mirror of
https://github.com/dgibson/dtc.git
synced 2025-10-13 16:27:39 -04:00
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:
parent
4ad49c3a9c
commit
8ec013ae63
1 changed files with 37 additions and 4 deletions
41
fdtdump.c
41
fdtdump.c
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue