1204431Sraj/*
2204431Sraj * ftdump.c - Contributed by Pantelis Antoniou <pantelis.antoniou AT gmail.com>
3204431Sraj */
4204431Sraj
5204431Sraj#include <stdint.h>
6204431Sraj#include <stdio.h>
7204433Sraj#include <stdlib.h>
8204431Sraj#include <string.h>
9204431Sraj#include <ctype.h>
10204431Sraj
11204431Sraj#include <fdt.h>
12204431Sraj#include <libfdt_env.h>
13204431Sraj
14204433Sraj#define FTDUMP_BUF_SIZE	65536
15204433Sraj
16204431Sraj#define ALIGN(x, a)	(((x) + ((a) - 1)) & ~((a) - 1))
17204431Sraj#define PALIGN(p, a)	((void *)(ALIGN((unsigned long)(p), (a))))
18204433Sraj#define GET_CELL(p)	(p += 4, *((const uint32_t *)(p-4)))
19204431Sraj
20204431Srajstatic int is_printable_string(const void *data, int len)
21204431Sraj{
22204431Sraj	const char *s = data;
23204431Sraj	const char *ss;
24204431Sraj
25204431Sraj	/* zero length is not */
26204431Sraj	if (len == 0)
27204431Sraj		return 0;
28204431Sraj
29204431Sraj	/* must terminate with zero */
30204431Sraj	if (s[len - 1] != '\0')
31204431Sraj		return 0;
32204431Sraj
33204431Sraj	ss = s;
34204431Sraj	while (*s && isprint(*s))
35204431Sraj		s++;
36204431Sraj
37204431Sraj	/* not zero, or not done yet */
38204431Sraj	if (*s != '\0' || (s + 1 - ss) < len)
39204431Sraj		return 0;
40204431Sraj
41204431Sraj	return 1;
42204431Sraj}
43204431Sraj
44204433Srajstatic void print_data(const char *data, int len)
45204431Sraj{
46204431Sraj	int i;
47204433Sraj	const char *p = data;
48204431Sraj
49204431Sraj	/* no data, don't print */
50204431Sraj	if (len == 0)
51204431Sraj		return;
52204431Sraj
53204431Sraj	if (is_printable_string(data, len)) {
54204431Sraj		printf(" = \"%s\"", (const char *)data);
55204431Sraj	} else if ((len % 4) == 0) {
56204431Sraj		printf(" = <");
57204431Sraj		for (i = 0; i < len; i += 4)
58204433Sraj			printf("0x%08x%s", fdt32_to_cpu(GET_CELL(p)),
59204431Sraj			       i < (len - 4) ? " " : "");
60204431Sraj		printf(">");
61204431Sraj	} else {
62204431Sraj		printf(" = [");
63204433Sraj		for (i = 0; i < len; i++)
64204433Sraj			printf("%02x%s", *p++, i < len - 1 ? " " : "");
65204431Sraj		printf("]");
66204431Sraj	}
67204431Sraj}
68204431Sraj
69204431Srajstatic void dump_blob(void *blob)
70204431Sraj{
71204431Sraj	struct fdt_header *bph = blob;
72204431Sraj	uint32_t off_mem_rsvmap = fdt32_to_cpu(bph->off_mem_rsvmap);
73204431Sraj	uint32_t off_dt = fdt32_to_cpu(bph->off_dt_struct);
74204431Sraj	uint32_t off_str = fdt32_to_cpu(bph->off_dt_strings);
75204431Sraj	struct fdt_reserve_entry *p_rsvmap =
76204431Sraj		(struct fdt_reserve_entry *)((char *)blob + off_mem_rsvmap);
77204433Sraj	const char *p_struct = (const char *)blob + off_dt;
78204433Sraj	const char *p_strings = (const char *)blob + off_str;
79204431Sraj	uint32_t version = fdt32_to_cpu(bph->version);
80204431Sraj	uint32_t totalsize = fdt32_to_cpu(bph->totalsize);
81204431Sraj	uint32_t tag;
82204433Sraj	const char *p, *s, *t;
83204431Sraj	int depth, sz, shift;
84204431Sraj	int i;
85204431Sraj	uint64_t addr, size;
86204431Sraj
87204431Sraj	depth = 0;
88204431Sraj	shift = 4;
89204431Sraj
90204433Sraj	printf("/dts-v1/;\n");
91204431Sraj	printf("// magic:\t\t0x%x\n", fdt32_to_cpu(bph->magic));
92204431Sraj	printf("// totalsize:\t\t0x%x (%d)\n", totalsize, totalsize);
93204431Sraj	printf("// off_dt_struct:\t0x%x\n", off_dt);
94204431Sraj	printf("// off_dt_strings:\t0x%x\n", off_str);
95204431Sraj	printf("// off_mem_rsvmap:\t0x%x\n", off_mem_rsvmap);
96204431Sraj	printf("// version:\t\t%d\n", version);
97204431Sraj	printf("// last_comp_version:\t%d\n",
98204431Sraj	       fdt32_to_cpu(bph->last_comp_version));
99204431Sraj	if (version >= 2)
100204431Sraj		printf("// boot_cpuid_phys:\t0x%x\n",
101204431Sraj		       fdt32_to_cpu(bph->boot_cpuid_phys));
102204431Sraj
103204431Sraj	if (version >= 3)
104204431Sraj		printf("// size_dt_strings:\t0x%x\n",
105204431Sraj		       fdt32_to_cpu(bph->size_dt_strings));
106204431Sraj	if (version >= 17)
107204431Sraj		printf("// size_dt_struct:\t0x%x\n",
108204431Sraj		       fdt32_to_cpu(bph->size_dt_struct));
109204431Sraj	printf("\n");
110204431Sraj
111204431Sraj	for (i = 0; ; i++) {
112204431Sraj		addr = fdt64_to_cpu(p_rsvmap[i].address);
113204431Sraj		size = fdt64_to_cpu(p_rsvmap[i].size);
114204431Sraj		if (addr == 0 && size == 0)
115204431Sraj			break;
116204431Sraj
117204431Sraj		printf("/memreserve/ %llx %llx;\n",
118204431Sraj		       (unsigned long long)addr, (unsigned long long)size);
119204431Sraj	}
120204431Sraj
121204431Sraj	p = p_struct;
122204431Sraj	while ((tag = fdt32_to_cpu(GET_CELL(p))) != FDT_END) {
123204431Sraj
124204431Sraj		/* printf("tag: 0x%08x (%d)\n", tag, p - p_struct); */
125204431Sraj
126204431Sraj		if (tag == FDT_BEGIN_NODE) {
127204431Sraj			s = p;
128204431Sraj			p = PALIGN(p + strlen(s) + 1, 4);
129204431Sraj
130204431Sraj			if (*s == '\0')
131204431Sraj				s = "/";
132204431Sraj
133204431Sraj			printf("%*s%s {\n", depth * shift, "", s);
134204431Sraj
135204431Sraj			depth++;
136204431Sraj			continue;
137204431Sraj		}
138204431Sraj
139204431Sraj		if (tag == FDT_END_NODE) {
140204431Sraj			depth--;
141204431Sraj
142204431Sraj			printf("%*s};\n", depth * shift, "");
143204431Sraj			continue;
144204431Sraj		}
145204431Sraj
146204431Sraj		if (tag == FDT_NOP) {
147204431Sraj			printf("%*s// [NOP]\n", depth * shift, "");
148204431Sraj			continue;
149204431Sraj		}
150204431Sraj
151204431Sraj		if (tag != FDT_PROP) {
152204431Sraj			fprintf(stderr, "%*s ** Unknown tag 0x%08x\n", depth * shift, "", tag);
153204431Sraj			break;
154204431Sraj		}
155204431Sraj		sz = fdt32_to_cpu(GET_CELL(p));
156204431Sraj		s = p_strings + fdt32_to_cpu(GET_CELL(p));
157204431Sraj		if (version < 16 && sz >= 8)
158204431Sraj			p = PALIGN(p, 8);
159204431Sraj		t = p;
160204431Sraj
161204431Sraj		p = PALIGN(p + sz, 4);
162204431Sraj
163204431Sraj		printf("%*s%s", depth * shift, "", s);
164204431Sraj		print_data(t, sz);
165204431Sraj		printf(";\n");
166204431Sraj	}
167204431Sraj}
168204431Sraj
169204431Sraj
170204431Srajint main(int argc, char *argv[])
171204431Sraj{
172204431Sraj	FILE *fp;
173204433Sraj	char *buf;
174204431Sraj	int size;
175204431Sraj
176204431Sraj	if (argc < 2) {
177204431Sraj		fprintf(stderr, "supply input filename\n");
178204431Sraj		return 5;
179204431Sraj	}
180204431Sraj
181204433Sraj	if (strcmp(argv[1], "-") == 0) {
182204433Sraj		fp = stdin;
183204433Sraj	} else {
184204433Sraj		fp = fopen(argv[1], "rb");
185204433Sraj		if (fp == NULL) {
186204433Sraj			fprintf(stderr, "unable to open %s\n", argv[1]);
187204433Sraj			return 10;
188204433Sraj		}
189204433Sraj	}
190204433Sraj
191204433Sraj	buf = malloc(FTDUMP_BUF_SIZE);
192204433Sraj	if (!buf) {
193204433Sraj		fprintf(stderr, "Couldn't allocate %d byte buffer\n", FTDUMP_BUF_SIZE);
194204431Sraj		return 10;
195204431Sraj	}
196204431Sraj
197204433Sraj	size = fread(buf, 1, FTDUMP_BUF_SIZE, fp);
198204433Sraj	if (size == FTDUMP_BUF_SIZE) {
199204433Sraj		fprintf(stderr, "file too large (maximum is %d bytes)\n", FTDUMP_BUF_SIZE);
200204431Sraj		return 10;
201204431Sraj	}
202204431Sraj
203204431Sraj	dump_blob(buf);
204204431Sraj
205204431Sraj	fclose(fp);
206204431Sraj
207204431Sraj	return 0;
208204431Sraj}
209