blob: 53343d7afaf0ae306ce9466f4d11b3624f09d356 [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);
Kumar Gala501e21c2007-12-04 10:33:20 -060090 uint32_t totalsize = be32_to_cpu(bph->totalsize);
David Gibsonb2543fc2005-08-29 14:58:27 +100091 uint32_t tag;
92 char *p;
93 char *s, *t;
94 int depth, sz, shift;
95 int i;
96 uint64_t addr, size;
97
98 depth = 0;
99 shift = 4;
100
101 printf("// Version 0x%x tree\n", version);
Kumar Gala501e21c2007-12-04 10:33:20 -0600102 printf("// Totalsize 0x%x(%d)\n", totalsize, totalsize);
David Gibsonb2543fc2005-08-29 14:58:27 +1000103 for (i = 0; ; i++) {
104 addr = be64_to_cpu(p_rsvmap[i].address);
105 size = be64_to_cpu(p_rsvmap[i].size);
106 if (addr == 0 && size == 0)
107 break;
108
109 printf("/memreserve/ %llx %llx;\n",
110 (unsigned long long)addr, (unsigned long long)size);
111 }
112
113 p = p_struct;
David Gibsonfb7c7ac2007-09-26 13:11:05 +1000114 while ((tag = be32_to_cpu(GET_CELL(p))) != FDT_END) {
David Gibsonb2543fc2005-08-29 14:58:27 +1000115
116 /* printf("tag: 0x%08x (%d)\n", tag, p - p_struct); */
117
David Gibsonfb7c7ac2007-09-26 13:11:05 +1000118 if (tag == FDT_BEGIN_NODE) {
David Gibsonb2543fc2005-08-29 14:58:27 +1000119 s = p;
120 p = PALIGN(p + strlen(s) + 1, 4);
121
122 if (*s == '\0')
123 s = "/";
124
125 printf("%*s%s {\n", depth * shift, "", s);
126
127 depth++;
128 continue;
129 }
130
David Gibsonfb7c7ac2007-09-26 13:11:05 +1000131 if (tag == FDT_END_NODE) {
David Gibsonb2543fc2005-08-29 14:58:27 +1000132 depth--;
133
134 printf("%*s};\n", depth * shift, "");
135 continue;
136 }
137
David Gibsonfb7c7ac2007-09-26 13:11:05 +1000138 if (tag == FDT_NOP) {
David Gibsonb2543fc2005-08-29 14:58:27 +1000139 printf("%*s// [NOP]\n", depth * shift, "");
140 continue;
141 }
142
David Gibsonfb7c7ac2007-09-26 13:11:05 +1000143 if (tag != FDT_PROP) {
David Gibsonb2543fc2005-08-29 14:58:27 +1000144 fprintf(stderr, "%*s ** Unknown tag 0x%08x\n", depth * shift, "", tag);
145 break;
146 }
Ed Swarthout00143002007-03-14 17:33:19 -0500147 sz = be32_to_cpu(GET_CELL(p));
David Gibsonb2543fc2005-08-29 14:58:27 +1000148 s = p_strings + be32_to_cpu(GET_CELL(p));
David Gibson46c88df2007-03-14 11:02:40 +1100149 if (version < 16 && sz >= 8)
David Gibsonb2543fc2005-08-29 14:58:27 +1000150 p = PALIGN(p, 8);
151 t = p;
152
153 p = PALIGN(p + sz, 4);
154
155 printf("%*s%s", depth * shift, "", s);
156 print_data(t, sz);
157 printf(";\n");
158 }
159}
160
161
162int main(int argc, char *argv[])
163{
164 FILE *fp;
165 char buf[16384]; /* 16k max */
166 int size;
167
168 if (argc < 2) {
169 fprintf(stderr, "supply input filename\n");
170 return 5;
171 }
172
173 fp = fopen(argv[1], "rb");
174 if (fp == NULL) {
175 fprintf(stderr, "unable to open %s\n", argv[1]);
176 return 10;
177 }
178
179 size = fread(buf, 1, sizeof(buf), fp);
180 if (size == sizeof(buf)) { /* too large */
181 fprintf(stderr, "file too large\n");
182 return 10;
183 }
184
185 dump_blob(buf);
186
187 fclose(fp);
188
189 return 0;
190}