1/* 2 * ftdump.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#define FTDUMP_BUF_SIZE 65536 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 int is_printable_string(const void *data, int len) 21{ 22 const char *s = data; 23 const char *ss; 24 25 /* zero length is not */ 26 if (len == 0) 27 return 0; 28 29 /* must terminate with zero */ 30 if (s[len - 1] != '\0') 31 return 0; 32 33 ss = s; 34 while (*s && isprint(*s)) 35 s++; 36 37 /* not zero, or not done yet */ 38 if (*s != '\0' || (s + 1 - ss) < len) 39 return 0; 40 41 return 1; 42} 43 44static void print_data(const char *data, int len) 45{ 46 int i; 47 const char *p = data; 48 49 /* no data, don't print */ 50 if (len == 0) 51 return; 52 53 if (is_printable_string(data, len)) { 54 printf(" = \"%s\"", (const char *)data); 55 } else if ((len % 4) == 0) { 56 printf(" = <"); 57 for (i = 0; i < len; i += 4) 58 printf("0x%08x%s", fdt32_to_cpu(GET_CELL(p)), 59 i < (len - 4) ? " " : ""); 60 printf(">"); 61 } else { 62 printf(" = ["); 63 for (i = 0; i < len; i++) 64 printf("%02x%s", *p++, i < len - 1 ? " " : ""); 65 printf("]"); 66 } 67} 68 69static void dump_blob(void *blob) 70{ 71 struct fdt_header *bph = blob; 72 uint32_t off_mem_rsvmap = fdt32_to_cpu(bph->off_mem_rsvmap); 73 uint32_t off_dt = fdt32_to_cpu(bph->off_dt_struct); 74 uint32_t off_str = fdt32_to_cpu(bph->off_dt_strings); 75 struct fdt_reserve_entry *p_rsvmap = 76 (struct fdt_reserve_entry *)((char *)blob + off_mem_rsvmap); 77 const char *p_struct = (const char *)blob + off_dt; 78 const char *p_strings = (const char *)blob + off_str; 79 uint32_t version = fdt32_to_cpu(bph->version); 80 uint32_t totalsize = fdt32_to_cpu(bph->totalsize); 81 uint32_t tag; 82 const char *p, *s, *t; 83 int depth, sz, shift; 84 int i; 85 uint64_t addr, size; 86 87 depth = 0; 88 shift = 4; 89 90 printf("/dts-v1/;\n"); 91 printf("// magic:\t\t0x%x\n", fdt32_to_cpu(bph->magic)); 92 printf("// totalsize:\t\t0x%x (%d)\n", totalsize, totalsize); 93 printf("// off_dt_struct:\t0x%x\n", off_dt); 94 printf("// off_dt_strings:\t0x%x\n", off_str); 95 printf("// off_mem_rsvmap:\t0x%x\n", off_mem_rsvmap); 96 printf("// version:\t\t%d\n", version); 97 printf("// last_comp_version:\t%d\n", 98 fdt32_to_cpu(bph->last_comp_version)); 99 if (version >= 2) 100 printf("// boot_cpuid_phys:\t0x%x\n", 101 fdt32_to_cpu(bph->boot_cpuid_phys)); 102 103 if (version >= 3) 104 printf("// size_dt_strings:\t0x%x\n", 105 fdt32_to_cpu(bph->size_dt_strings)); 106 if (version >= 17) 107 printf("// size_dt_struct:\t0x%x\n", 108 fdt32_to_cpu(bph->size_dt_struct)); 109 printf("\n"); 110 111 for (i = 0; ; i++) { 112 addr = fdt64_to_cpu(p_rsvmap[i].address); 113 size = fdt64_to_cpu(p_rsvmap[i].size); 114 if (addr == 0 && size == 0) 115 break; 116 117 printf("/memreserve/ %llx %llx;\n", 118 (unsigned long long)addr, (unsigned long long)size); 119 } 120 121 p = p_struct; 122 while ((tag = fdt32_to_cpu(GET_CELL(p))) != FDT_END) { 123 124 /* printf("tag: 0x%08x (%d)\n", tag, p - p_struct); */ 125 126 if (tag == FDT_BEGIN_NODE) { 127 s = p; 128 p = PALIGN(p + strlen(s) + 1, 4); 129 130 if (*s == '\0') 131 s = "/"; 132 133 printf("%*s%s {\n", depth * shift, "", s); 134 135 depth++; 136 continue; 137 } 138 139 if (tag == FDT_END_NODE) { 140 depth--; 141 142 printf("%*s};\n", depth * shift, ""); 143 continue; 144 } 145 146 if (tag == FDT_NOP) { 147 printf("%*s// [NOP]\n", depth * shift, ""); 148 continue; 149 } 150 151 if (tag != FDT_PROP) { 152 fprintf(stderr, "%*s ** Unknown tag 0x%08x\n", depth * shift, "", tag); 153 break; 154 } 155 sz = fdt32_to_cpu(GET_CELL(p)); 156 s = p_strings + fdt32_to_cpu(GET_CELL(p)); 157 if (version < 16 && sz >= 8) 158 p = PALIGN(p, 8); 159 t = p; 160 161 p = PALIGN(p + sz, 4); 162 163 printf("%*s%s", depth * shift, "", s); 164 print_data(t, sz); 165 printf(";\n"); 166 } 167} 168 169 170int main(int argc, char *argv[]) 171{ 172 FILE *fp; 173 char *buf; 174 int size; 175 176 if (argc < 2) { 177 fprintf(stderr, "supply input filename\n"); 178 return 5; 179 } 180 181 if (strcmp(argv[1], "-") == 0) { 182 fp = stdin; 183 } else { 184 fp = fopen(argv[1], "rb"); 185 if (fp == NULL) { 186 fprintf(stderr, "unable to open %s\n", argv[1]); 187 return 10; 188 } 189 } 190 191 buf = malloc(FTDUMP_BUF_SIZE); 192 if (!buf) { 193 fprintf(stderr, "Couldn't allocate %d byte buffer\n", FTDUMP_BUF_SIZE); 194 return 10; 195 } 196 197 size = fread(buf, 1, FTDUMP_BUF_SIZE, fp); 198 if (size == FTDUMP_BUF_SIZE) { 199 fprintf(stderr, "file too large (maximum is %d bytes)\n", FTDUMP_BUF_SIZE); 200 return 10; 201 } 202 203 dump_blob(buf); 204 205 fclose(fp); 206 207 return 0; 208} 209