fdtdump: add a debug mode

When hacking raw fdt files, it's useful to know the actual offsets into
the file each node appears.  Add a --debug mode that includes this.

Signed-off-by: Mike Frysinger <vapier@gentoo.org>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
This commit is contained in:
Mike Frysinger 2013-04-15 22:13:17 -04:00 committed by David Gibson
parent 4ad49c3a9c
commit 8ec013ae63

View file

@ -19,8 +19,29 @@
#define PALIGN(p, a) ((void *)(ALIGN((unsigned long)(p), (a)))) #define PALIGN(p, a) ((void *)(ALIGN((unsigned long)(p), (a))))
#define GET_CELL(p) (p += 4, *((const uint32_t *)(p-4))) #define GET_CELL(p) (p += 4, *((const uint32_t *)(p-4)))
static void dump_blob(void *blob) static const char *tagname(uint32_t tag)
{ {
static const char * const names[] = {
#define TN(t) [t] #t
TN(FDT_BEGIN_NODE),
TN(FDT_END_NODE),
TN(FDT_PROP),
TN(FDT_NOP),
TN(FDT_END),
#undef TN
};
if (tag < ARRAY_SIZE(names))
if (names[tag])
return names[tag];
return "FDT_???";
}
#define dumpf(fmt, args...) \
do { if (debug) printf("// " fmt, ## args); } while (0)
static void dump_blob(void *blob, bool debug)
{
uintptr_t blob_off = (uintptr_t)blob;
struct fdt_header *bph = blob; struct fdt_header *bph = blob;
uint32_t off_mem_rsvmap = fdt32_to_cpu(bph->off_mem_rsvmap); uint32_t off_mem_rsvmap = fdt32_to_cpu(bph->off_mem_rsvmap);
uint32_t off_dt = fdt32_to_cpu(bph->off_dt_struct); uint32_t off_dt = fdt32_to_cpu(bph->off_dt_struct);
@ -74,7 +95,8 @@ static void dump_blob(void *blob)
p = p_struct; p = p_struct;
while ((tag = fdt32_to_cpu(GET_CELL(p))) != FDT_END) { while ((tag = fdt32_to_cpu(GET_CELL(p))) != FDT_END) {
/* printf("tag: 0x%08x (%d)\n", tag, p - p_struct); */ dumpf("%04zx: tag: 0x%08x (%s)\n",
(uintptr_t)p - blob_off - 4, tag, tagname(tag));
if (tag == FDT_BEGIN_NODE) { if (tag == FDT_BEGIN_NODE) {
s = p; s = p;
@ -113,6 +135,8 @@ static void dump_blob(void *blob)
p = PALIGN(p + sz, 4); p = PALIGN(p + sz, 4);
dumpf("%04zx: string: %s\n", (uintptr_t)s - blob_off, s);
dumpf("%04zx: value\n", (uintptr_t)t - blob_off);
printf("%*s%s", depth * shift, "", s); printf("%*s%s", depth * shift, "", s);
utilfdt_print_data(t, sz); utilfdt_print_data(t, sz);
printf(";\n"); printf(";\n");
@ -121,12 +145,14 @@ static void dump_blob(void *blob)
/* Usage related data. */ /* Usage related data. */
static const char usage_synopsis[] = "fdtdump [options] <file>"; static const char usage_synopsis[] = "fdtdump [options] <file>";
static const char usage_short_opts[] = "s" USAGE_COMMON_SHORT_OPTS; static const char usage_short_opts[] = "ds" USAGE_COMMON_SHORT_OPTS;
static struct option const usage_long_opts[] = { static struct option const usage_long_opts[] = {
{"debug", no_argument, NULL, 'd'},
{"scan", no_argument, NULL, 's'}, {"scan", no_argument, NULL, 's'},
USAGE_COMMON_LONG_OPTS USAGE_COMMON_LONG_OPTS
}; };
static const char * const usage_opts_help[] = { static const char * const usage_opts_help[] = {
"Dump debug information while decoding the file",
"Scan for an embedded fdt in file", "Scan for an embedded fdt in file",
USAGE_COMMON_OPTS_HELP USAGE_COMMON_OPTS_HELP
}; };
@ -136,6 +162,7 @@ int main(int argc, char *argv[])
int opt; int opt;
const char *file; const char *file;
char *buf; char *buf;
bool debug = false;
bool scan = false; bool scan = false;
off_t len; off_t len;
@ -143,6 +170,9 @@ int main(int argc, char *argv[])
switch (opt) { switch (opt) {
case_USAGE_COMMON_FLAGS case_USAGE_COMMON_FLAGS
case 'd':
debug = true;
break;
case 's': case 's':
scan = true; scan = true;
break; break;
@ -179,6 +209,9 @@ int main(int argc, char *argv[])
fdt_off_dt_struct(p) < this_len && fdt_off_dt_struct(p) < this_len &&
fdt_off_dt_strings(p) < this_len) fdt_off_dt_strings(p) < this_len)
break; break;
if (debug)
printf("%s: skipping fdt magic at offset %#zx\n",
file, p - buf);
} }
++p; ++p;
} }
@ -188,7 +221,7 @@ int main(int argc, char *argv[])
buf = p; buf = p;
} }
dump_blob(buf); dump_blob(buf, debug);
return 0; return 0;
} }