1/* 2 * fdtdump.c - Contributed by Pantelis Antoniou <pantelis.antoniou AT gmail.com> 3 */ 4 5#include <stdint.h> 6#include <stdio.h> 7#include <stdlib.h> 8#include <string.h> 9#include <ctype.h> 10 11#include <fdt.h> 12#include <libfdt_env.h> 13 14#include "util.h" 15 16#define ALIGN(x, a) (((x) + ((a) - 1)) & ~((a) - 1)) 17#define PALIGN(p, a) ((void *)(ALIGN((unsigned long)(p), (a)))) 18#define GET_CELL(p) (p += 4, *((const uint32_t *)(p-4))) 19 20static void print_data(const char *data, int len) 21{ 22 int i; 23 const char *p = data; 24 25 /* no data, don't print */ 26 if (len == 0) 27 return; 28 29 if (util_is_printable_string(data, len)) { 30 printf(" = \"%s\"", (const char *)data); 31 } else if ((len % 4) == 0) { 32 printf(" = <"); 33 for (i = 0; i < len; i += 4) 34 printf("0x%08x%s", fdt32_to_cpu(GET_CELL(p)), 35 i < (len - 4) ? " " : ""); 36 printf(">"); 37 } else { 38 printf(" = ["); 39 for (i = 0; i < len; i++) 40 printf("%02x%s", *p++, i < len - 1 ? " " : ""); 41 printf("]"); 42 } 43} 44 45static void dump_blob(void *blob) 46{ 47 struct fdt_header *bph = blob; 48 uint32_t off_mem_rsvmap = fdt32_to_cpu(bph->off_mem_rsvmap); 49 uint32_t off_dt = fdt32_to_cpu(bph->off_dt_struct); 50 uint32_t off_str = fdt32_to_cpu(bph->off_dt_strings); 51 struct fdt_reserve_entry *p_rsvmap = 52 (struct fdt_reserve_entry *)((char *)blob + off_mem_rsvmap); 53 const char *p_struct = (const char *)blob + off_dt; 54 const char *p_strings = (const char *)blob + off_str; 55 uint32_t version = fdt32_to_cpu(bph->version); 56 uint32_t totalsize = fdt32_to_cpu(bph->totalsize); 57 uint32_t tag; 58 const char *p, *s, *t; 59 int depth, sz, shift; 60 int i; 61 uint64_t addr, size; 62 63 depth = 0; 64 shift = 4; 65 66 printf("/dts-v1/;\n"); 67 printf("// magic:\t\t0x%x\n", fdt32_to_cpu(bph->magic)); 68 printf("// totalsize:\t\t0x%x (%d)\n", totalsize, totalsize); 69 printf("// off_dt_struct:\t0x%x\n", off_dt); 70 printf("// off_dt_strings:\t0x%x\n", off_str); 71 printf("// off_mem_rsvmap:\t0x%x\n", off_mem_rsvmap); 72 printf("// version:\t\t%d\n", version); 73 printf("// last_comp_version:\t%d\n", 74 fdt32_to_cpu(bph->last_comp_version)); 75 if (version >= 2) 76 printf("// boot_cpuid_phys:\t0x%x\n", 77 fdt32_to_cpu(bph->boot_cpuid_phys)); 78 79 if (version >= 3) 80 printf("// size_dt_strings:\t0x%x\n", 81 fdt32_to_cpu(bph->size_dt_strings)); 82 if (version >= 17) 83 printf("// size_dt_struct:\t0x%x\n", 84 fdt32_to_cpu(bph->size_dt_struct)); 85 printf("\n"); 86 87 for (i = 0; ; i++) { 88 addr = fdt64_to_cpu(p_rsvmap[i].address); 89 size = fdt64_to_cpu(p_rsvmap[i].size); 90 if (addr == 0 && size == 0) 91 break; 92 93 printf("/memreserve/ %llx %llx;\n", 94 (unsigned long long)addr, (unsigned long long)size); 95 } 96 97 p = p_struct; 98 while ((tag = fdt32_to_cpu(GET_CELL(p))) != FDT_END) { 99 100 /* printf("tag: 0x%08x (%d)\n", tag, p - p_struct); */ 101 102 if (tag == FDT_BEGIN_NODE) { 103 s = p; 104 p = PALIGN(p + strlen(s) + 1, 4); 105 106 if (*s == '\0') 107 s = "/"; 108 109 printf("%*s%s {\n", depth * shift, "", s); 110 111 depth++; 112 continue; 113 } 114 115 if (tag == FDT_END_NODE) { 116 depth--; 117 118 printf("%*s};\n", depth * shift, ""); 119 continue; 120 } 121 122 if (tag == FDT_NOP) { 123 printf("%*s// [NOP]\n", depth * shift, ""); 124 continue; 125 } 126 127 if (tag != FDT_PROP) { 128 fprintf(stderr, "%*s ** Unknown tag 0x%08x\n", depth * shift, "", tag); 129 break; 130 } 131 sz = fdt32_to_cpu(GET_CELL(p)); 132 s = p_strings + fdt32_to_cpu(GET_CELL(p)); 133 if (version < 16 && sz >= 8) 134 p = PALIGN(p, 8); 135 t = p; 136 137 p = PALIGN(p + sz, 4); 138 139 printf("%*s%s", depth * shift, "", s); 140 print_data(t, sz); 141 printf(";\n"); 142 } 143} 144 145 146int main(int argc, char *argv[]) 147{ 148 char *buf; 149 150 if (argc < 2) { 151 fprintf(stderr, "supply input filename\n"); 152 return 5; 153 } 154 155 buf = utilfdt_read(argv[1]); 156 if (buf) 157 dump_blob(buf); 158 else 159 return 10; 160 161 return 0; 162} 163