]> CyberLeo.Net >> Repos - FreeBSD/releng/9.2.git/blob - contrib/dtc/ftdump.c
- Copy stable/9 to releng/9.2 as part of the 9.2-RELEASE cycle.
[FreeBSD/releng/9.2.git] / contrib / dtc / ftdump.c
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
20 static 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
44 static 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
69 static 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
170 int 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 }