diff -r ffa851df0825 -r 2fb8b9db1c86 symbian-qemu-0.9.1-12/dtc-trunk/ftdump.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/symbian-qemu-0.9.1-12/dtc-trunk/ftdump.c Fri Jul 31 15:01:17 2009 +0100 @@ -0,0 +1,229 @@ +/* + * ftdump.c - Contributed by Pantelis Antoniou + */ + +#include +#include +#include +#include +#include + +#include +#include +#include + +#define ALIGN(x, a) (((x) + ((a) - 1)) & ~((a) - 1)) +#define PALIGN(p, a) ((void *)(ALIGN((unsigned long)(p), (a)))) +#define GET_CELL(p) (p += 4, *((uint32_t *)(p-4))) + +static int is_printable_string(const void *data, int len) +{ + const char *s = data; + const char *ss; + + /* zero length is not */ + if (len == 0) + return 0; + + /* must terminate with zero */ + if (s[len - 1] != '\0') + return 0; + + ss = s; + while (*s && isprint(*s)) + s++; + + /* not zero, or not done yet */ + if (*s != '\0' || (s + 1 - ss) < len) + return 0; + + return 1; +} + +static void print_data(const void *data, int len) +{ + int i; + const uint8_t *s; + + /* no data, don't print */ + if (len == 0) + return; + + if (is_printable_string(data, len)) { + printf(" = \"%s\"", (const char *)data); + } else if ((len % 4) == 0) { + printf(" = <"); + for (i = 0; i < len; i += 4) + printf("%08x%s", *((const uint32_t *)data + i), + i < (len - 4) ? " " : ""); + printf(">"); + } else { + printf(" = ["); + for (i = 0, s = data; i < len; i++) + printf("%02x%s", s[i], i < len - 1 ? " " : ""); + printf("]"); + } +} + +static void dump_blob(void *blob) +{ + struct fdt_header *bph = blob; + 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_str = fdt32_to_cpu(bph->off_dt_strings); + struct fdt_reserve_entry *p_rsvmap = + (struct fdt_reserve_entry *)((char *)blob + off_mem_rsvmap); + char *p_struct = (char *)blob + off_dt; + char *p_strings = (char *)blob + off_str; + uint32_t version = fdt32_to_cpu(bph->version); + uint32_t totalsize = fdt32_to_cpu(bph->totalsize); + uint32_t tag; + char *p; + char *s, *t; + int depth, sz, shift; + int i; + uint64_t addr, size; + + depth = 0; + shift = 4; + + printf("// magic:\t\t0x%x\n", fdt32_to_cpu(bph->magic)); + printf("// totalsize:\t\t0x%x (%d)\n", totalsize, totalsize); + printf("// off_dt_struct:\t0x%x\n", off_dt); + printf("// off_dt_strings:\t0x%x\n", off_str); + printf("// off_mem_rsvmap:\t0x%x\n", off_mem_rsvmap); + printf("// version:\t\t%d\n", version); + printf("// last_comp_version:\t%d\n", + fdt32_to_cpu(bph->last_comp_version)); + if (version >= 2) + printf("// boot_cpuid_phys:\t0x%x\n", + fdt32_to_cpu(bph->boot_cpuid_phys)); + + if (version >= 3) + printf("// size_dt_strings:\t0x%x\n", + fdt32_to_cpu(bph->size_dt_strings)); + if (version >= 17) + printf("// size_dt_struct:\t0x%x\n", + fdt32_to_cpu(bph->size_dt_struct)); + printf("\n"); + + for (i = 0; ; i++) { + addr = fdt64_to_cpu(p_rsvmap[i].address); + size = fdt64_to_cpu(p_rsvmap[i].size); + if (addr == 0 && size == 0) + break; + + printf("/memreserve/ %llx %llx;\n", + (unsigned long long)addr, (unsigned long long)size); + } + + p = p_struct; + while ((tag = fdt32_to_cpu(GET_CELL(p))) != FDT_END) { + + /* printf("tag: 0x%08x (%d)\n", tag, p - p_struct); */ + + if (tag == FDT_BEGIN_NODE) { + s = p; + p = PALIGN(p + strlen(s) + 1, 4); + + if (*s == '\0') + s = "/"; + + printf("%*s%s {\n", depth * shift, "", s); + + depth++; + continue; + } + + if (tag == FDT_END_NODE) { + depth--; + + printf("%*s};\n", depth * shift, ""); + continue; + } + + if (tag == FDT_NOP) { + printf("%*s// [NOP]\n", depth * shift, ""); + continue; + } + + if (tag != FDT_PROP) { + fprintf(stderr, "%*s ** Unknown tag 0x%08x\n", depth * shift, "", tag); + break; + } + sz = fdt32_to_cpu(GET_CELL(p)); + s = p_strings + fdt32_to_cpu(GET_CELL(p)); + if (version < 16 && sz >= 8) + p = PALIGN(p, 8); + t = p; + + p = PALIGN(p + sz, 4); + + printf("%*s%s", depth * shift, "", s); + print_data(t, sz); + printf(";\n"); + } +} + +static void __attribute__ ((noreturn)) usage(int error) +{ + FILE *f = error ? stderr : stdout; + fprintf(f, "Usage:\n"); + fprintf(f, "\tftdump [options] \n"); + fprintf(f, "\nOptions:\n"); + fprintf(f, "\t-h\n"); + fprintf(f, "\t\tThis help text\n"); + fprintf(f, "\t-v\n"); + fprintf(f, "\t\tPrint ftdump version and exit\n"); + fprintf(f, "\n"); + fprintf(f, "Report bugs to %s\n", BUG_URL); + exit(error ? 3 : 0); +} + +int main(int argc, char *argv[]) +{ + static const struct option longopts[] = { + {"help", no_argument, NULL, 'h'}, + {"version", no_argument, NULL, 'v'}, + {NULL, 0, NULL, 0} + }; + int opt; + FILE *fp; + char buf[16384]; /* 16k max */ + int size; + + while ((opt = getopt_long(argc, argv, "hv", + longopts, NULL)) != EOF) { + switch (opt) { + case 'h': + usage(0); + case 'v': + printf("Version: %s\n", DTC_VERSION); + exit(0); + default: + usage(1); + } + } + + if (argc != optind + 1) { + usage(1); + } + + fp = fopen(argv[optind], "rb"); + if (fp == NULL) { + fprintf(stderr, "unable to open %s\n", argv[1]); + return 10; + } + + size = fread(buf, 1, sizeof(buf), fp); + if (size == sizeof(buf)) { /* too large */ + fprintf(stderr, "file too large\n"); + return 10; + } + + dump_blob(buf); + + fclose(fp); + + return 0; +}