xref: /openbmc/linux/scripts/dtc/treesource.c (revision 15d90a6a)
1 /*
2  * (C) Copyright David Gibson <dwg@au1.ibm.com>, IBM Corporation.  2005.
3  *
4  *
5  * This program is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU General Public License as
7  * published by the Free Software Foundation; either version 2 of the
8  * License, or (at your option) any later version.
9  *
10  *  This program is distributed in the hope that it will be useful,
11  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
12  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  *  General Public License for more details.
14  *
15  *  You should have received a copy of the GNU General Public License
16  *  along with this program; if not, write to the Free Software
17  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307
18  *                                                                   USA
19  */
20 
21 #include "dtc.h"
22 #include "srcpos.h"
23 
24 extern FILE *yyin;
25 extern int yyparse(void);
26 extern YYLTYPE yylloc;
27 
28 struct dt_info *parser_output;
29 bool treesource_error;
30 
31 struct dt_info *dt_from_source(const char *fname)
32 {
33 	parser_output = NULL;
34 	treesource_error = false;
35 
36 	srcfile_push(fname);
37 	yyin = current_srcfile->f;
38 	yylloc.file = current_srcfile;
39 
40 	if (yyparse() != 0)
41 		die("Unable to parse input tree\n");
42 
43 	if (treesource_error)
44 		die("Syntax error parsing input tree\n");
45 
46 	return parser_output;
47 }
48 
49 static void write_prefix(FILE *f, int level)
50 {
51 	int i;
52 
53 	for (i = 0; i < level; i++)
54 		fputc('\t', f);
55 }
56 
57 static bool isstring(char c)
58 {
59 	return (isprint((unsigned char)c)
60 		|| (c == '\0')
61 		|| strchr("\a\b\t\n\v\f\r", c));
62 }
63 
64 static void write_propval_string(FILE *f, const char *s, size_t len)
65 {
66 	const char *end = s + len - 1;
67 
68 	if (!len)
69 		return;
70 
71 	assert(*end == '\0');
72 
73 	fprintf(f, "\"");
74 	while (s < end) {
75 		char c = *s++;
76 		switch (c) {
77 		case '\a':
78 			fprintf(f, "\\a");
79 			break;
80 		case '\b':
81 			fprintf(f, "\\b");
82 			break;
83 		case '\t':
84 			fprintf(f, "\\t");
85 			break;
86 		case '\n':
87 			fprintf(f, "\\n");
88 			break;
89 		case '\v':
90 			fprintf(f, "\\v");
91 			break;
92 		case '\f':
93 			fprintf(f, "\\f");
94 			break;
95 		case '\r':
96 			fprintf(f, "\\r");
97 			break;
98 		case '\\':
99 			fprintf(f, "\\\\");
100 			break;
101 		case '\"':
102 			fprintf(f, "\\\"");
103 			break;
104 		case '\0':
105 			fprintf(f, "\\0");
106 			break;
107 		default:
108 			if (isprint((unsigned char)c))
109 				fprintf(f, "%c", c);
110 			else
111 				fprintf(f, "\\x%02"PRIx8, c);
112 		}
113 	}
114 	fprintf(f, "\"");
115 }
116 
117 static void write_propval_int(FILE *f, const char *p, size_t len, size_t width)
118 {
119 	const char *end = p + len;
120 	assert(len % width == 0);
121 
122 	for (; p < end; p += width) {
123 		switch (width) {
124 		case 1:
125 			fprintf(f, "%02"PRIx8, *(const uint8_t*)p);
126 			break;
127 		case 2:
128 			fprintf(f, "0x%02"PRIx16, fdt16_to_cpu(*(const fdt16_t*)p));
129 			break;
130 		case 4:
131 			fprintf(f, "0x%02"PRIx32, fdt32_to_cpu(*(const fdt32_t*)p));
132 			break;
133 		case 8:
134 			fprintf(f, "0x%02"PRIx64, fdt64_to_cpu(*(const fdt64_t*)p));
135 			break;
136 		}
137 		if (p + width < end)
138 			fputc(' ', f);
139 	}
140 }
141 
142 static bool has_data_type_information(struct marker *m)
143 {
144 	return m->type >= TYPE_UINT8;
145 }
146 
147 static struct marker *next_type_marker(struct marker *m)
148 {
149 	while (m && !has_data_type_information(m))
150 		m = m->next;
151 	return m;
152 }
153 
154 size_t type_marker_length(struct marker *m)
155 {
156 	struct marker *next = next_type_marker(m->next);
157 
158 	if (next)
159 		return next->offset - m->offset;
160 	return 0;
161 }
162 
163 static const char *delim_start[] = {
164 	[TYPE_UINT8] = "[",
165 	[TYPE_UINT16] = "/bits/ 16 <",
166 	[TYPE_UINT32] = "<",
167 	[TYPE_UINT64] = "/bits/ 64 <",
168 	[TYPE_STRING] = "",
169 };
170 static const char *delim_end[] = {
171 	[TYPE_UINT8] = "]",
172 	[TYPE_UINT16] = ">",
173 	[TYPE_UINT32] = ">",
174 	[TYPE_UINT64] = ">",
175 	[TYPE_STRING] = "",
176 };
177 
178 static enum markertype guess_value_type(struct property *prop)
179 {
180 	int len = prop->val.len;
181 	const char *p = prop->val.val;
182 	struct marker *m = prop->val.markers;
183 	int nnotstring = 0, nnul = 0;
184 	int nnotstringlbl = 0, nnotcelllbl = 0;
185 	int i;
186 
187 	for (i = 0; i < len; i++) {
188 		if (! isstring(p[i]))
189 			nnotstring++;
190 		if (p[i] == '\0')
191 			nnul++;
192 	}
193 
194 	for_each_marker_of_type(m, LABEL) {
195 		if ((m->offset > 0) && (prop->val.val[m->offset - 1] != '\0'))
196 			nnotstringlbl++;
197 		if ((m->offset % sizeof(cell_t)) != 0)
198 			nnotcelllbl++;
199 	}
200 
201 	if ((p[len-1] == '\0') && (nnotstring == 0) && (nnul < (len-nnul))
202 	    && (nnotstringlbl == 0)) {
203 		return TYPE_STRING;
204 	} else if (((len % sizeof(cell_t)) == 0) && (nnotcelllbl == 0)) {
205 		return TYPE_UINT32;
206 	}
207 
208 	return TYPE_UINT8;
209 }
210 
211 static void write_propval(FILE *f, struct property *prop)
212 {
213 	size_t len = prop->val.len;
214 	struct marker *m = prop->val.markers;
215 	struct marker dummy_marker;
216 	enum markertype emit_type = TYPE_NONE;
217 	char *srcstr;
218 
219 	if (len == 0) {
220 		fprintf(f, ";");
221 		if (annotate) {
222 			srcstr = srcpos_string_first(prop->srcpos, annotate);
223 			if (srcstr) {
224 				fprintf(f, " /* %s */", srcstr);
225 				free(srcstr);
226 			}
227 		}
228 		fprintf(f, "\n");
229 		return;
230 	}
231 
232 	fprintf(f, " =");
233 
234 	if (!next_type_marker(m)) {
235 		/* data type information missing, need to guess */
236 		dummy_marker.type = guess_value_type(prop);
237 		dummy_marker.next = prop->val.markers;
238 		dummy_marker.offset = 0;
239 		dummy_marker.ref = NULL;
240 		m = &dummy_marker;
241 	}
242 
243 	for_each_marker(m) {
244 		size_t chunk_len = (m->next ? m->next->offset : len) - m->offset;
245 		size_t data_len = type_marker_length(m) ? : len - m->offset;
246 		const char *p = &prop->val.val[m->offset];
247 
248 		if (has_data_type_information(m)) {
249 			emit_type = m->type;
250 			fprintf(f, " %s", delim_start[emit_type]);
251 		} else if (m->type == LABEL)
252 			fprintf(f, " %s:", m->ref);
253 		else if (m->offset)
254 			fputc(' ', f);
255 
256 		if (emit_type == TYPE_NONE) {
257 			assert(chunk_len == 0);
258 			continue;
259 		}
260 
261 		switch(emit_type) {
262 		case TYPE_UINT16:
263 			write_propval_int(f, p, chunk_len, 2);
264 			break;
265 		case TYPE_UINT32:
266 			write_propval_int(f, p, chunk_len, 4);
267 			break;
268 		case TYPE_UINT64:
269 			write_propval_int(f, p, chunk_len, 8);
270 			break;
271 		case TYPE_STRING:
272 			write_propval_string(f, p, chunk_len);
273 			break;
274 		default:
275 			write_propval_int(f, p, chunk_len, 1);
276 		}
277 
278 		if (chunk_len == data_len) {
279 			size_t pos = m->offset + chunk_len;
280 			fprintf(f, pos == len ? "%s" : "%s,",
281 			        delim_end[emit_type] ? : "");
282 			emit_type = TYPE_NONE;
283 		}
284 	}
285 	fprintf(f, ";");
286 	if (annotate) {
287 		srcstr = srcpos_string_first(prop->srcpos, annotate);
288 		if (srcstr) {
289 			fprintf(f, " /* %s */", srcstr);
290 			free(srcstr);
291 		}
292 	}
293 	fprintf(f, "\n");
294 }
295 
296 static void write_tree_source_node(FILE *f, struct node *tree, int level)
297 {
298 	struct property *prop;
299 	struct node *child;
300 	struct label *l;
301 	char *srcstr;
302 
303 	write_prefix(f, level);
304 	for_each_label(tree->labels, l)
305 		fprintf(f, "%s: ", l->label);
306 	if (tree->name && (*tree->name))
307 		fprintf(f, "%s {", tree->name);
308 	else
309 		fprintf(f, "/ {");
310 
311 	if (annotate) {
312 		srcstr = srcpos_string_first(tree->srcpos, annotate);
313 		if (srcstr) {
314 			fprintf(f, " /* %s */", srcstr);
315 			free(srcstr);
316 		}
317 	}
318 	fprintf(f, "\n");
319 
320 	for_each_property(tree, prop) {
321 		write_prefix(f, level+1);
322 		for_each_label(prop->labels, l)
323 			fprintf(f, "%s: ", l->label);
324 		fprintf(f, "%s", prop->name);
325 		write_propval(f, prop);
326 	}
327 	for_each_child(tree, child) {
328 		fprintf(f, "\n");
329 		write_tree_source_node(f, child, level+1);
330 	}
331 	write_prefix(f, level);
332 	fprintf(f, "};");
333 	if (annotate) {
334 		srcstr = srcpos_string_last(tree->srcpos, annotate);
335 		if (srcstr) {
336 			fprintf(f, " /* %s */", srcstr);
337 			free(srcstr);
338 		}
339 	}
340 	fprintf(f, "\n");
341 }
342 
343 void dt_to_source(FILE *f, struct dt_info *dti)
344 {
345 	struct reserve_info *re;
346 
347 	fprintf(f, "/dts-v1/;\n\n");
348 
349 	for (re = dti->reservelist; re; re = re->next) {
350 		struct label *l;
351 
352 		for_each_label(re->labels, l)
353 			fprintf(f, "%s: ", l->label);
354 		fprintf(f, "/memreserve/\t0x%016llx 0x%016llx;\n",
355 			(unsigned long long)re->address,
356 			(unsigned long long)re->size);
357 	}
358 
359 	write_tree_source_node(f, dti->dt, 0);
360 }
361