blob: 577c2cfc98ae8caa03ac31833edd84f7f522e3c7 [file] [log] [blame]
David Gibsonb2543fc2005-08-29 14:58:27 +10001/*
2 * ftdump.c - Contributed by Pantelis Antoniou <pantelis.antoniou AT gmail.com>
3 */
4
5#include <stdint.h>
6#include <stdio.h>
7#include <string.h>
8#include <ctype.h>
9#include <netinet/in.h>
10#include <byteswap.h>
11
David Gibsonfb7c7ac2007-09-26 13:11:05 +100012#include <fdt.h>
David Gibsonb2543fc2005-08-29 14:58:27 +100013
14#define cpu_to_be16(x) htons(x)
15#define be16_to_cpu(x) ntohs(x)
16
17#define cpu_to_be32(x) htonl(x)
18#define be32_to_cpu(x) ntohl(x)
19
20#if __BYTE_ORDER == __BIG_ENDIAN
21#define cpu_to_be64(x) (x)
22#define be64_to_cpu(x) (x)
23#else
24#define cpu_to_be64(x) bswap_64(x)
25#define be64_to_cpu(x) bswap_64(x)
26#endif
27
28#define ALIGN(x, a) (((x) + ((a) - 1)) & ~((a) - 1))
29#define PALIGN(p, a) ((void *)(ALIGN((unsigned long)(p), (a))))
30#define GET_CELL(p) (p += 4, *((uint32_t *)(p-4)))
31
32static int is_printable_string(const void *data, int len)
33{
34 const char *s = data;
35 const char *ss;
36
37 /* zero length is not */
38 if (len == 0)
39 return 0;
40
41 /* must terminate with zero */
42 if (s[len - 1] != '\0')
43 return 0;
44
45 ss = s;
46 while (*s && isprint(*s))
47 s++;
48
49 /* not zero, or not done yet */
50 if (*s != '\0' || (s + 1 - ss) < len)
51 return 0;
52
53 return 1;
54}
55
56static void print_data(const void *data, int len)
57{
58 int i;
59 const uint8_t *s;
60
61 /* no data, don't print */
62 if (len == 0)
63 return;
64
65 if (is_printable_string(data, len)) {
66 printf(" = \"%s\"", (char *)data);
67 } else if ((len % 4) == 0) {
68 printf(" = <");
69 for (i = 0; i < len; i += 4)
70 printf("%08x%s", *((uint32_t *)data + i),
71 i < (len - 4) ? " " : "");
72 printf(">");
73 } else {
74 printf(" = [");
75 for (i = 0, s = data; i < len; i++)
76 printf("%02x%s", s[i], i < len - 1 ? " " : "");
77 printf("]");
78 }
79}
80
81static void dump_blob(void *blob)
82{
David Gibsonfb7c7ac2007-09-26 13:11:05 +100083 struct fdt_header *bph = blob;
84 struct fdt_reserve_entry *p_rsvmap =
85 (struct fdt_reserve_entry *)(blob
86 + be32_to_cpu(bph->off_mem_rsvmap));
David Gibsonb2543fc2005-08-29 14:58:27 +100087 char *p_struct = blob + be32_to_cpu(bph->off_dt_struct);
88 char *p_strings = blob + be32_to_cpu(bph->off_dt_strings);
89 uint32_t version = be32_to_cpu(bph->version);
90 uint32_t tag;
91 char *p;
92 char *s, *t;
93 int depth, sz, shift;
94 int i;
95 uint64_t addr, size;
96
97 depth = 0;
98 shift = 4;
99
100 printf("// Version 0x%x tree\n", version);
101 for (i = 0; ; i++) {
102 addr = be64_to_cpu(p_rsvmap[i].address);
103 size = be64_to_cpu(p_rsvmap[i].size);
104 if (addr == 0 && size == 0)
105 break;
106
107 printf("/memreserve/ %llx %llx;\n",
108 (unsigned long long)addr, (unsigned long long)size);
109 }
110
111 p = p_struct;
David Gibsonfb7c7ac2007-09-26 13:11:05 +1000112 while ((tag = be32_to_cpu(GET_CELL(p))) != FDT_END) {
David Gibsonb2543fc2005-08-29 14:58:27 +1000113
114 /* printf("tag: 0x%08x (%d)\n", tag, p - p_struct); */
115
David Gibsonfb7c7ac2007-09-26 13:11:05 +1000116 if (tag == FDT_BEGIN_NODE) {
David Gibsonb2543fc2005-08-29 14:58:27 +1000117 s = p;
118 p = PALIGN(p + strlen(s) + 1, 4);
119
120 if (*s == '\0')
121 s = "/";
122
123 printf("%*s%s {\n", depth * shift, "", s);
124
125 depth++;
126 continue;
127 }
128
David Gibsonfb7c7ac2007-09-26 13:11:05 +1000129 if (tag == FDT_END_NODE) {
David Gibsonb2543fc2005-08-29 14:58:27 +1000130 depth--;
131
132 printf("%*s};\n", depth * shift, "");
133 continue;
134 }
135
David Gibsonfb7c7ac2007-09-26 13:11:05 +1000136 if (tag == FDT_NOP) {
David Gibsonb2543fc2005-08-29 14:58:27 +1000137 printf("%*s// [NOP]\n", depth * shift, "");
138 continue;
139 }
140
David Gibsonfb7c7ac2007-09-26 13:11:05 +1000141 if (tag != FDT_PROP) {
David Gibsonb2543fc2005-08-29 14:58:27 +1000142 fprintf(stderr, "%*s ** Unknown tag 0x%08x\n", depth * shift, "", tag);
143 break;
144 }
Ed Swarthout00143002007-03-14 17:33:19 -0500145 sz = be32_to_cpu(GET_CELL(p));
David Gibsonb2543fc2005-08-29 14:58:27 +1000146 s = p_strings + be32_to_cpu(GET_CELL(p));
David Gibson46c88df2007-03-14 11:02:40 +1100147 if (version < 16 && sz >= 8)
David Gibsonb2543fc2005-08-29 14:58:27 +1000148 p = PALIGN(p, 8);
149 t = p;
150
151 p = PALIGN(p + sz, 4);
152
153 printf("%*s%s", depth * shift, "", s);
154 print_data(t, sz);
155 printf(";\n");
156 }
157}
158
159
160int main(int argc, char *argv[])
161{
162 FILE *fp;
163 char buf[16384]; /* 16k max */
164 int size;
165
166 if (argc < 2) {
167 fprintf(stderr, "supply input filename\n");
168 return 5;
169 }
170
171 fp = fopen(argv[1], "rb");
172 if (fp == NULL) {
173 fprintf(stderr, "unable to open %s\n", argv[1]);
174 return 10;
175 }
176
177 size = fread(buf, 1, sizeof(buf), fp);
178 if (size == sizeof(buf)) { /* too large */
179 fprintf(stderr, "file too large\n");
180 return 10;
181 }
182
183 dump_blob(buf);
184
185 fclose(fp);
186
187 return 0;
188}