File Index
Files and directories
Sign in
FILE

treesource.c

File preview with syntax highlighting.

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