forked from len0rd/rockbox
nwztools: various fix and enhancements
Change-Id: Iaa89df27b7a0c4eb9fc6603c431de3d1fe791fa1
This commit is contained in:
parent
6d04ed343c
commit
99f20b85f6
4 changed files with 71 additions and 17 deletions
|
@ -32,9 +32,10 @@
|
||||||
#include "nvp.h"
|
#include "nvp.h"
|
||||||
|
|
||||||
bool g_debug = false;
|
bool g_debug = false;
|
||||||
char *g_out_prefix = NULL;
|
static char *g_out_prefix = NULL;
|
||||||
FILE *g_in_file = NULL;
|
static FILE *g_in_file = NULL;
|
||||||
bool g_force = false;
|
bool g_force = false;
|
||||||
|
static int g_nvp_node = -1;
|
||||||
|
|
||||||
#define let_the_force_flow(x) do { if(!g_force) return x; } while(0)
|
#define let_the_force_flow(x) do { if(!g_force) return x; } while(0)
|
||||||
#define continue_the_force(x) if(x) let_the_force_flow(x)
|
#define continue_the_force(x) if(x) let_the_force_flow(x)
|
||||||
|
@ -164,15 +165,52 @@ static int do_emmc(void)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int do_nvp_extract(void)
|
||||||
|
{
|
||||||
|
if(!g_out_prefix)
|
||||||
|
{
|
||||||
|
cprintf(GREY, "You must specify an output prefix to extract a NVP node\n");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
if(!nvp_is_valid_node(g_nvp_node))
|
||||||
|
{
|
||||||
|
cprintf(GREY, "Invalid NVP node %d\n", g_nvp_node);
|
||||||
|
return 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
FILE *f = fopen(g_out_prefix, "wb");
|
||||||
|
if(!f)
|
||||||
|
{
|
||||||
|
cprintf(GREY, "Cannot open output file: %m\n");
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
int size = nvp_get_node_size(g_nvp_node);
|
||||||
|
void *buffer = malloc(size);
|
||||||
|
int ret = nvp_read_node(g_nvp_node, 0, buffer, size);
|
||||||
|
if(ret < 0)
|
||||||
|
cprintf(GREY, "NVP read error: %d\n", ret);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
cprintf(YELLOW, "%d ", ret);
|
||||||
|
cprintf(GREEN, "bytes written\n");
|
||||||
|
fwrite(buffer, 1, ret, f);
|
||||||
|
}
|
||||||
|
free(buffer);
|
||||||
|
fclose(f);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static void usage(void)
|
static void usage(void)
|
||||||
{
|
{
|
||||||
printf("Usage: emmctool [options] img\n");
|
printf("Usage: emmctool [options] img\n");
|
||||||
printf("Options:\n");
|
printf("Options:\n");
|
||||||
printf(" -o <prefix>\tSet output prefix\n");
|
printf(" -o <prefix>\t\tSet output prefix\n");
|
||||||
printf(" -f/--force\tForce to continue on errors\n");
|
printf(" -f/--force\t\tForce to continue on errors\n");
|
||||||
printf(" -?/--help\tDisplay this message\n");
|
printf(" -?/--help\t\tDisplay this message\n");
|
||||||
printf(" -d/--debug\tDisplay debug messages\n");
|
printf(" -d/--debug\t\tDisplay debug messages\n");
|
||||||
printf(" -c/--no-color\tDisable color output\n");
|
printf(" -c/--no-color\t\tDisable color output\n");
|
||||||
|
printf(" -e/--nvp-ex <node>\tExtract a NVP node\n");
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -186,10 +224,11 @@ int main(int argc, char **argv)
|
||||||
{"debug", no_argument, 0, 'd'},
|
{"debug", no_argument, 0, 'd'},
|
||||||
{"no-color", no_argument, 0, 'c'},
|
{"no-color", no_argument, 0, 'c'},
|
||||||
{"force", no_argument, 0, 'f'},
|
{"force", no_argument, 0, 'f'},
|
||||||
|
{"nvp-ex", required_argument, 0, 'e'},
|
||||||
{0, 0, 0, 0}
|
{0, 0, 0, 0}
|
||||||
};
|
};
|
||||||
|
|
||||||
int c = getopt_long(argc, argv, "?dcfo:", long_options, NULL);
|
int c = getopt_long(argc, argv, "?dcfo:e:", long_options, NULL);
|
||||||
if(c == -1)
|
if(c == -1)
|
||||||
break;
|
break;
|
||||||
switch(c)
|
switch(c)
|
||||||
|
@ -211,6 +250,9 @@ int main(int argc, char **argv)
|
||||||
case 'o':
|
case 'o':
|
||||||
g_out_prefix = optarg;
|
g_out_prefix = optarg;
|
||||||
break;
|
break;
|
||||||
|
case 'e':
|
||||||
|
g_nvp_node = strtoul(optarg, NULL, 0);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
abort();
|
abort();
|
||||||
}
|
}
|
||||||
|
@ -232,6 +274,8 @@ int main(int argc, char **argv)
|
||||||
int ret = nvp_init(EMMC_NVP_SIZE, &nvp_read, g_debug);
|
int ret = nvp_init(EMMC_NVP_SIZE, &nvp_read, g_debug);
|
||||||
if(ret) return ret;
|
if(ret) return ret;
|
||||||
ret = do_emmc();
|
ret = do_emmc();
|
||||||
|
if(ret == 0 && g_nvp_node >= 0)
|
||||||
|
ret = do_nvp_extract();
|
||||||
|
|
||||||
fclose(g_in_file);
|
fclose(g_in_file);
|
||||||
|
|
||||||
|
|
|
@ -279,6 +279,7 @@ int nvp_read_data(int shadow, int area, int zone, int offset, void *buf, int siz
|
||||||
{
|
{
|
||||||
int large = nvp_area_info[area].kind == NVP_AREA_LARGE_KIND;
|
int large = nvp_area_info[area].kind == NVP_AREA_LARGE_KIND;
|
||||||
int unit_size = large ? NVP_LARGE_AREA_SIZE : NVP_SMALL_AREA_SIZE;
|
int unit_size = large ? NVP_LARGE_AREA_SIZE : NVP_SMALL_AREA_SIZE;
|
||||||
|
int read_size = 0;
|
||||||
|
|
||||||
while(size > 0)
|
while(size > 0)
|
||||||
{
|
{
|
||||||
|
@ -288,17 +289,23 @@ int nvp_read_data(int shadow, int area, int zone, int offset, void *buf, int siz
|
||||||
nvp_get_cluster_number(shadow, area, zone, index) :
|
nvp_get_cluster_number(shadow, area, zone, index) :
|
||||||
nvp_get_sector_number(shadow, area, zone, index);
|
nvp_get_sector_number(shadow, area, zone, index);
|
||||||
if(sec_cluster == 0)
|
if(sec_cluster == 0)
|
||||||
return -1;
|
break;
|
||||||
//cprintf(GREY, "[sec_cluster=%d]", sec_cluster);
|
|
||||||
int read = MIN(size, unit_size - unit_offset);
|
int read = MIN(size, unit_size - unit_offset);
|
||||||
|
//cprintf(GREY, "[sec_cluster=%d read=%d]", sec_cluster, read);
|
||||||
int ret = nvp_read(sec_cluster * unit_size, read, buf);
|
int ret = nvp_read(sec_cluster * unit_size, read, buf);
|
||||||
if(ret)
|
if(ret)
|
||||||
return ret;
|
return ret;
|
||||||
buf += read;
|
buf += read;
|
||||||
offset += read;
|
offset += read;
|
||||||
size -= read;
|
size -= read;
|
||||||
|
read_size += read;
|
||||||
}
|
}
|
||||||
return 0;
|
return read_size;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool nvp_is_valid_node(int node)
|
||||||
|
{
|
||||||
|
return node >= 0 && node < nr_nodes && node_info[node].area != -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct nvp_node_info_t nvp_get_node_info(int node)
|
struct nvp_node_info_t nvp_get_node_info(int node)
|
||||||
|
@ -527,16 +534,18 @@ int nvp_info(void)
|
||||||
cprintf_field(" Zone ", "%s", zones[j].name);
|
cprintf_field(" Zone ", "%s", zones[j].name);
|
||||||
cprintf(BLUE, " ->");
|
cprintf(BLUE, " ->");
|
||||||
uint8_t buf[0x20];
|
uint8_t buf[0x20];
|
||||||
int ret = nvp_read_data(0, i, j, 0, buf, MIN(0x20, zones[j].size));
|
int sz = 0x20;
|
||||||
if(ret)
|
int ret = nvp_read_data(0, i, j, 0, buf, MIN(sz, zones[j].size));
|
||||||
|
if(ret <= 0)
|
||||||
{
|
{
|
||||||
cprintf(RED, " No data\n");
|
cprintf(RED, " No data\n");
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
for(int i = 0; i < MIN(0x20, zones[j].size); i++)
|
sz = MIN(sz, ret);
|
||||||
|
for(int i = 0; i < MIN(sz, zones[j].size); i++)
|
||||||
cprintf(YELLOW, " %02x", buf[i]);
|
cprintf(YELLOW, " %02x", buf[i]);
|
||||||
cprintf(BLUE, " -> ");
|
cprintf(BLUE, " -> ");
|
||||||
for(int i = 0; i < MIN(0x20, zones[j].size); i++)
|
for(int i = 0; i < MIN(sz, zones[j].size); i++)
|
||||||
cprintf(YELLOW, "%c", isprint(buf[i]) ? buf[i] : '.');
|
cprintf(YELLOW, "%c", isprint(buf[i]) ? buf[i] : '.');
|
||||||
printf("\n");
|
printf("\n");
|
||||||
}
|
}
|
||||||
|
|
|
@ -74,6 +74,7 @@ extern struct nvp_area_info_entry_t nvp_area_info[NVP_NR_AREAS];
|
||||||
typedef int (*nvp_read_fn_t)(uint32_t offset, uint32_t size, void *buf);
|
typedef int (*nvp_read_fn_t)(uint32_t offset, uint32_t size, void *buf);
|
||||||
|
|
||||||
int nvp_init(int nvp_size, nvp_read_fn_t read, bool debug);
|
int nvp_init(int nvp_size, nvp_read_fn_t read, bool debug);
|
||||||
|
bool nvp_is_valid_node(int node);
|
||||||
struct nvp_node_info_t nvp_get_node_info(int node);
|
struct nvp_node_info_t nvp_get_node_info(int node);
|
||||||
int nvp_get_node_size(int node);
|
int nvp_get_node_size(int node);
|
||||||
const char *nvp_get_node_name(int node);
|
const char *nvp_get_node_name(int node);
|
||||||
|
@ -88,6 +89,7 @@ int nvp_get_sector_status(int sector);
|
||||||
int nvp_set_sector_status(int sector, int status);
|
int nvp_set_sector_status(int sector, int status);
|
||||||
int nvp_get_cluster_number(int shadow, int area, int zone, int index);
|
int nvp_get_cluster_number(int shadow, int area, int zone, int index);
|
||||||
int nvp_get_sector_number(int shadow, int area, int zone, int index);
|
int nvp_get_sector_number(int shadow, int area, int zone, int index);
|
||||||
|
/* returns amount of read data or -1 */
|
||||||
int nvp_read_data(int shadow, int area, int zone, int offset, void *buffer, int size);
|
int nvp_read_data(int shadow, int area, int zone, int offset, void *buffer, int size);
|
||||||
|
|
||||||
#endif /* __NVP_H__ */
|
#endif /* __NVP_H__ */
|
||||||
|
|
|
@ -393,8 +393,7 @@ int get_dnk_nvp(int argc, char **argv)
|
||||||
printf("Node usage: <node>\n");
|
printf("Node usage: <node>\n");
|
||||||
printf("Nodes:\n");
|
printf("Nodes:\n");
|
||||||
for(unsigned i = 0; i < NR_NVP_PROPS; i++)
|
for(unsigned i = 0; i < NR_NVP_PROPS; i++)
|
||||||
printf(" %s\t%s", nvp_prop_list[i].name, nvp_prop_list[i].desc);
|
printf(" %s\t%s\n", nvp_prop_list[i].name, nvp_prop_list[i].desc);
|
||||||
printf("\n");
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue