1204431Sraj/*
2204431Sraj * (C) Copyright David Gibson <dwg@au1.ibm.com>, IBM Corporation.  2005.
3204431Sraj *
4204431Sraj *
5204431Sraj * This program is free software; you can redistribute it and/or
6204431Sraj * modify it under the terms of the GNU General Public License as
7204431Sraj * published by the Free Software Foundation; either version 2 of the
8204431Sraj * License, or (at your option) any later version.
9204431Sraj *
10204431Sraj *  This program is distributed in the hope that it will be useful,
11204431Sraj *  but WITHOUT ANY WARRANTY; without even the implied warranty of
12204431Sraj *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13204431Sraj *  General Public License for more details.
14204431Sraj *
15204431Sraj *  You should have received a copy of the GNU General Public License
16204431Sraj *  along with this program; if not, write to the Free Software
17204431Sraj *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307
18204431Sraj *                                                                   USA
19204431Sraj */
20204431Sraj
21204431Sraj#include "dtc.h"
22204431Sraj#include "srcpos.h"
23204431Sraj
24204431Srajextern FILE *yyin;
25204431Srajextern int yyparse(void);
26204431Sraj
27204431Srajstruct boot_info *the_boot_info;
28204431Srajint treesource_error;
29204431Sraj
30204431Srajstruct boot_info *dt_from_source(const char *fname)
31204431Sraj{
32204431Sraj	the_boot_info = NULL;
33204431Sraj	treesource_error = 0;
34204431Sraj
35204431Sraj	srcpos_file = dtc_open_file(fname, NULL);
36204431Sraj	yyin = srcpos_file->file;
37204431Sraj
38204431Sraj	if (yyparse() != 0)
39204431Sraj		die("Unable to parse input tree\n");
40204431Sraj
41204431Sraj	if (treesource_error)
42204431Sraj		die("Syntax error parsing input tree\n");
43204431Sraj
44204431Sraj	return the_boot_info;
45204431Sraj}
46204431Sraj
47204431Srajstatic void write_prefix(FILE *f, int level)
48204431Sraj{
49204431Sraj	int i;
50204431Sraj
51204431Sraj	for (i = 0; i < level; i++)
52204431Sraj		fputc('\t', f);
53204431Sraj}
54204431Sraj
55204433Srajstatic int isstring(char c)
56204431Sraj{
57204431Sraj	return (isprint(c)
58204431Sraj		|| (c == '\0')
59204431Sraj		|| strchr("\a\b\t\n\v\f\r", c));
60204431Sraj}
61204431Sraj
62204431Srajstatic void write_propval_string(FILE *f, struct data val)
63204431Sraj{
64204431Sraj	const char *str = val.val;
65204431Sraj	int i;
66204431Sraj	struct marker *m = val.markers;
67204431Sraj
68204431Sraj	assert(str[val.len-1] == '\0');
69204431Sraj
70204433Sraj	while (m && (m->offset == 0)) {
71204433Sraj		if (m->type == LABEL)
72204433Sraj			fprintf(f, "%s: ", m->ref);
73204433Sraj		m = m->next;
74204433Sraj	}
75204433Sraj	fprintf(f, "\"");
76204433Sraj
77204431Sraj	for (i = 0; i < (val.len-1); i++) {
78204431Sraj		char c = str[i];
79204431Sraj
80204431Sraj		switch (c) {
81204431Sraj		case '\a':
82204431Sraj			fprintf(f, "\\a");
83204431Sraj			break;
84204431Sraj		case '\b':
85204431Sraj			fprintf(f, "\\b");
86204431Sraj			break;
87204431Sraj		case '\t':
88204431Sraj			fprintf(f, "\\t");
89204431Sraj			break;
90204431Sraj		case '\n':
91204431Sraj			fprintf(f, "\\n");
92204431Sraj			break;
93204431Sraj		case '\v':
94204431Sraj			fprintf(f, "\\v");
95204431Sraj			break;
96204431Sraj		case '\f':
97204431Sraj			fprintf(f, "\\f");
98204431Sraj			break;
99204431Sraj		case '\r':
100204431Sraj			fprintf(f, "\\r");
101204431Sraj			break;
102204431Sraj		case '\\':
103204431Sraj			fprintf(f, "\\\\");
104204431Sraj			break;
105204431Sraj		case '\"':
106204431Sraj			fprintf(f, "\\\"");
107204431Sraj			break;
108204431Sraj		case '\0':
109204431Sraj			fprintf(f, "\", ");
110204433Sraj			while (m && (m->offset < i)) {
111204433Sraj				if (m->type == LABEL) {
112204433Sraj					assert(m->offset == (i+1));
113204433Sraj					fprintf(f, "%s: ", m->ref);
114204433Sraj				}
115204433Sraj				m = m->next;
116204433Sraj			}
117204433Sraj			fprintf(f, "\"");
118204431Sraj			break;
119204431Sraj		default:
120204431Sraj			if (isprint(c))
121204431Sraj				fprintf(f, "%c", c);
122204431Sraj			else
123204431Sraj				fprintf(f, "\\x%02hhx", c);
124204431Sraj		}
125204431Sraj	}
126204431Sraj	fprintf(f, "\"");
127204431Sraj
128204431Sraj	/* Wrap up any labels at the end of the value */
129204431Sraj	for_each_marker_of_type(m, LABEL) {
130204431Sraj		assert (m->offset == val.len);
131204431Sraj		fprintf(f, " %s:", m->ref);
132204431Sraj	}
133204431Sraj}
134204431Sraj
135204431Srajstatic void write_propval_cells(FILE *f, struct data val)
136204431Sraj{
137204431Sraj	void *propend = val.val + val.len;
138204431Sraj	cell_t *cp = (cell_t *)val.val;
139204431Sraj	struct marker *m = val.markers;
140204431Sraj
141204431Sraj	fprintf(f, "<");
142204431Sraj	for (;;) {
143204431Sraj		while (m && (m->offset <= ((char *)cp - val.val))) {
144204431Sraj			if (m->type == LABEL) {
145204431Sraj				assert(m->offset == ((char *)cp - val.val));
146204431Sraj				fprintf(f, "%s: ", m->ref);
147204431Sraj			}
148204431Sraj			m = m->next;
149204431Sraj		}
150204431Sraj
151204431Sraj		fprintf(f, "0x%x", fdt32_to_cpu(*cp++));
152204431Sraj		if ((void *)cp >= propend)
153204431Sraj			break;
154204431Sraj		fprintf(f, " ");
155204431Sraj	}
156204431Sraj
157204431Sraj	/* Wrap up any labels at the end of the value */
158204431Sraj	for_each_marker_of_type(m, LABEL) {
159204431Sraj		assert (m->offset == val.len);
160204431Sraj		fprintf(f, " %s:", m->ref);
161204431Sraj	}
162204431Sraj	fprintf(f, ">");
163204431Sraj}
164204431Sraj
165204431Srajstatic void write_propval_bytes(FILE *f, struct data val)
166204431Sraj{
167204431Sraj	void *propend = val.val + val.len;
168204431Sraj	const char *bp = val.val;
169204431Sraj	struct marker *m = val.markers;
170204431Sraj
171204431Sraj	fprintf(f, "[");
172204431Sraj	for (;;) {
173204431Sraj		while (m && (m->offset == (bp-val.val))) {
174204431Sraj			if (m->type == LABEL)
175204431Sraj				fprintf(f, "%s: ", m->ref);
176204431Sraj			m = m->next;
177204431Sraj		}
178204431Sraj
179204431Sraj		fprintf(f, "%02hhx", *bp++);
180204431Sraj		if ((const void *)bp >= propend)
181204431Sraj			break;
182204431Sraj		fprintf(f, " ");
183204431Sraj	}
184204431Sraj
185204431Sraj	/* Wrap up any labels at the end of the value */
186204431Sraj	for_each_marker_of_type(m, LABEL) {
187204431Sraj		assert (m->offset == val.len);
188204431Sraj		fprintf(f, " %s:", m->ref);
189204431Sraj	}
190204431Sraj	fprintf(f, "]");
191204431Sraj}
192204431Sraj
193204431Srajstatic void write_propval(FILE *f, struct property *prop)
194204431Sraj{
195204431Sraj	int len = prop->val.len;
196204431Sraj	const char *p = prop->val.val;
197204431Sraj	struct marker *m = prop->val.markers;
198204431Sraj	int nnotstring = 0, nnul = 0;
199204431Sraj	int nnotstringlbl = 0, nnotcelllbl = 0;
200204431Sraj	int i;
201204431Sraj
202204431Sraj	if (len == 0) {
203204431Sraj		fprintf(f, ";\n");
204204431Sraj		return;
205204431Sraj	}
206204431Sraj
207204431Sraj	for (i = 0; i < len; i++) {
208204431Sraj		if (! isstring(p[i]))
209204431Sraj			nnotstring++;
210204431Sraj		if (p[i] == '\0')
211204431Sraj			nnul++;
212204431Sraj	}
213204431Sraj
214204431Sraj	for_each_marker_of_type(m, LABEL) {
215204431Sraj		if ((m->offset > 0) && (prop->val.val[m->offset - 1] != '\0'))
216204431Sraj			nnotstringlbl++;
217204431Sraj		if ((m->offset % sizeof(cell_t)) != 0)
218204431Sraj			nnotcelllbl++;
219204431Sraj	}
220204431Sraj
221204431Sraj	fprintf(f, " = ");
222204431Sraj	if ((p[len-1] == '\0') && (nnotstring == 0) && (nnul < (len-nnul))
223204431Sraj	    && (nnotstringlbl == 0)) {
224204431Sraj		write_propval_string(f, prop->val);
225204431Sraj	} else if (((len % sizeof(cell_t)) == 0) && (nnotcelllbl == 0)) {
226204431Sraj		write_propval_cells(f, prop->val);
227204431Sraj	} else {
228204431Sraj		write_propval_bytes(f, prop->val);
229204431Sraj	}
230204431Sraj
231204431Sraj	fprintf(f, ";\n");
232204431Sraj}
233204431Sraj
234204431Srajstatic void write_tree_source_node(FILE *f, struct node *tree, int level)
235204431Sraj{
236204431Sraj	struct property *prop;
237204431Sraj	struct node *child;
238204431Sraj
239204431Sraj	write_prefix(f, level);
240204431Sraj	if (tree->label)
241204431Sraj		fprintf(f, "%s: ", tree->label);
242204431Sraj	if (tree->name && (*tree->name))
243204431Sraj		fprintf(f, "%s {\n", tree->name);
244204431Sraj	else
245204431Sraj		fprintf(f, "/ {\n");
246204431Sraj
247204431Sraj	for_each_property(tree, prop) {
248204431Sraj		write_prefix(f, level+1);
249204431Sraj		if (prop->label)
250204431Sraj			fprintf(f, "%s: ", prop->label);
251204431Sraj		fprintf(f, "%s", prop->name);
252204431Sraj		write_propval(f, prop);
253204431Sraj	}
254204431Sraj	for_each_child(tree, child) {
255204431Sraj		fprintf(f, "\n");
256204431Sraj		write_tree_source_node(f, child, level+1);
257204431Sraj	}
258204431Sraj	write_prefix(f, level);
259204431Sraj	fprintf(f, "};\n");
260204431Sraj}
261204431Sraj
262204431Sraj
263204431Srajvoid dt_to_source(FILE *f, struct boot_info *bi)
264204431Sraj{
265204431Sraj	struct reserve_info *re;
266204431Sraj
267204431Sraj	fprintf(f, "/dts-v1/;\n\n");
268204431Sraj
269204431Sraj	for (re = bi->reservelist; re; re = re->next) {
270204431Sraj		if (re->label)
271204431Sraj			fprintf(f, "%s: ", re->label);
272204431Sraj		fprintf(f, "/memreserve/\t0x%016llx 0x%016llx;\n",
273204431Sraj			(unsigned long long)re->re.address,
274204431Sraj			(unsigned long long)re->re.size);
275204431Sraj	}
276204431Sraj
277204431Sraj	write_tree_source_node(f, bi->dt, 0);
278204431Sraj}
279204431Sraj
280