xref: /OK3568_Linux_fs/kernel/scripts/dtc/yamltree.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0-or-later
2*4882a593Smuzhiyun /*
3*4882a593Smuzhiyun  * (C) Copyright Linaro, Ltd. 2018
4*4882a593Smuzhiyun  * (C) Copyright Arm Holdings.  2017
5*4882a593Smuzhiyun  * (C) Copyright David Gibson <dwg@au1.ibm.com>, IBM Corporation.  2005.
6*4882a593Smuzhiyun  */
7*4882a593Smuzhiyun 
8*4882a593Smuzhiyun #include <stdlib.h>
9*4882a593Smuzhiyun #include <yaml.h>
10*4882a593Smuzhiyun #include "dtc.h"
11*4882a593Smuzhiyun #include "srcpos.h"
12*4882a593Smuzhiyun 
13*4882a593Smuzhiyun char *yaml_error_name[] = {
14*4882a593Smuzhiyun 	[YAML_NO_ERROR] = "no error",
15*4882a593Smuzhiyun 	[YAML_MEMORY_ERROR] = "memory error",
16*4882a593Smuzhiyun 	[YAML_READER_ERROR] = "reader error",
17*4882a593Smuzhiyun 	[YAML_SCANNER_ERROR] = "scanner error",
18*4882a593Smuzhiyun 	[YAML_PARSER_ERROR] = "parser error",
19*4882a593Smuzhiyun 	[YAML_COMPOSER_ERROR] = "composer error",
20*4882a593Smuzhiyun 	[YAML_WRITER_ERROR] = "writer error",
21*4882a593Smuzhiyun 	[YAML_EMITTER_ERROR] = "emitter error",
22*4882a593Smuzhiyun };
23*4882a593Smuzhiyun 
24*4882a593Smuzhiyun #define yaml_emitter_emit_or_die(emitter, event) (			\
25*4882a593Smuzhiyun {									\
26*4882a593Smuzhiyun 	if (!yaml_emitter_emit(emitter, event))				\
27*4882a593Smuzhiyun 		die("yaml '%s': %s in %s, line %i\n",			\
28*4882a593Smuzhiyun 		    yaml_error_name[(emitter)->error], 			\
29*4882a593Smuzhiyun 		    (emitter)->problem, __func__, __LINE__);		\
30*4882a593Smuzhiyun })
31*4882a593Smuzhiyun 
yaml_propval_int(yaml_emitter_t * emitter,struct marker * markers,char * data,int len,int width)32*4882a593Smuzhiyun static void yaml_propval_int(yaml_emitter_t *emitter, struct marker *markers, char *data, int len, int width)
33*4882a593Smuzhiyun {
34*4882a593Smuzhiyun 	yaml_event_t event;
35*4882a593Smuzhiyun 	void *tag;
36*4882a593Smuzhiyun 	int off, start_offset = markers->offset;
37*4882a593Smuzhiyun 
38*4882a593Smuzhiyun 	switch(width) {
39*4882a593Smuzhiyun 		case 1: tag = "!u8"; break;
40*4882a593Smuzhiyun 		case 2: tag = "!u16"; break;
41*4882a593Smuzhiyun 		case 4: tag = "!u32"; break;
42*4882a593Smuzhiyun 		case 8: tag = "!u64"; break;
43*4882a593Smuzhiyun 		default:
44*4882a593Smuzhiyun 			die("Invalid width %i", width);
45*4882a593Smuzhiyun 	}
46*4882a593Smuzhiyun 	assert(len % width == 0);
47*4882a593Smuzhiyun 
48*4882a593Smuzhiyun 	yaml_sequence_start_event_initialize(&event, NULL,
49*4882a593Smuzhiyun 		(yaml_char_t *)tag, width == 4, YAML_FLOW_SEQUENCE_STYLE);
50*4882a593Smuzhiyun 	yaml_emitter_emit_or_die(emitter, &event);
51*4882a593Smuzhiyun 
52*4882a593Smuzhiyun 	for (off = 0; off < len; off += width) {
53*4882a593Smuzhiyun 		char buf[32];
54*4882a593Smuzhiyun 		struct marker *m;
55*4882a593Smuzhiyun 		bool is_phandle = false;
56*4882a593Smuzhiyun 
57*4882a593Smuzhiyun 		switch(width) {
58*4882a593Smuzhiyun 		case 1:
59*4882a593Smuzhiyun 			sprintf(buf, "0x%"PRIx8, *(uint8_t*)(data + off));
60*4882a593Smuzhiyun 			break;
61*4882a593Smuzhiyun 		case 2:
62*4882a593Smuzhiyun 			sprintf(buf, "0x%"PRIx16, dtb_ld16(data + off));
63*4882a593Smuzhiyun 			break;
64*4882a593Smuzhiyun 		case 4:
65*4882a593Smuzhiyun 			sprintf(buf, "0x%"PRIx32, dtb_ld32(data + off));
66*4882a593Smuzhiyun 			m = markers;
67*4882a593Smuzhiyun 			is_phandle = false;
68*4882a593Smuzhiyun 			for_each_marker_of_type(m, REF_PHANDLE) {
69*4882a593Smuzhiyun 				if (m->offset == (start_offset + off)) {
70*4882a593Smuzhiyun 					is_phandle = true;
71*4882a593Smuzhiyun 					break;
72*4882a593Smuzhiyun 				}
73*4882a593Smuzhiyun 			}
74*4882a593Smuzhiyun 			break;
75*4882a593Smuzhiyun 		case 8:
76*4882a593Smuzhiyun 			sprintf(buf, "0x%"PRIx64, dtb_ld64(data + off));
77*4882a593Smuzhiyun 			break;
78*4882a593Smuzhiyun 		}
79*4882a593Smuzhiyun 
80*4882a593Smuzhiyun 		if (is_phandle)
81*4882a593Smuzhiyun 			yaml_scalar_event_initialize(&event, NULL,
82*4882a593Smuzhiyun 				(yaml_char_t*)"!phandle", (yaml_char_t *)buf,
83*4882a593Smuzhiyun 				strlen(buf), 0, 0, YAML_PLAIN_SCALAR_STYLE);
84*4882a593Smuzhiyun 		else
85*4882a593Smuzhiyun 			yaml_scalar_event_initialize(&event, NULL,
86*4882a593Smuzhiyun 				(yaml_char_t*)YAML_INT_TAG, (yaml_char_t *)buf,
87*4882a593Smuzhiyun 				strlen(buf), 1, 1, YAML_PLAIN_SCALAR_STYLE);
88*4882a593Smuzhiyun 		yaml_emitter_emit_or_die(emitter, &event);
89*4882a593Smuzhiyun 	}
90*4882a593Smuzhiyun 
91*4882a593Smuzhiyun 	yaml_sequence_end_event_initialize(&event);
92*4882a593Smuzhiyun 	yaml_emitter_emit_or_die(emitter, &event);
93*4882a593Smuzhiyun }
94*4882a593Smuzhiyun 
yaml_propval_string(yaml_emitter_t * emitter,char * str,int len)95*4882a593Smuzhiyun static void yaml_propval_string(yaml_emitter_t *emitter, char *str, int len)
96*4882a593Smuzhiyun {
97*4882a593Smuzhiyun 	yaml_event_t event;
98*4882a593Smuzhiyun 	int i;
99*4882a593Smuzhiyun 
100*4882a593Smuzhiyun 	assert(str[len-1] == '\0');
101*4882a593Smuzhiyun 
102*4882a593Smuzhiyun 	/* Make sure the entire string is in the lower 7-bit ascii range */
103*4882a593Smuzhiyun 	for (i = 0; i < len; i++)
104*4882a593Smuzhiyun 		assert(isascii(str[i]));
105*4882a593Smuzhiyun 
106*4882a593Smuzhiyun 	yaml_scalar_event_initialize(&event, NULL,
107*4882a593Smuzhiyun 		(yaml_char_t *)YAML_STR_TAG, (yaml_char_t*)str,
108*4882a593Smuzhiyun 		len-1, 0, 1, YAML_DOUBLE_QUOTED_SCALAR_STYLE);
109*4882a593Smuzhiyun 	yaml_emitter_emit_or_die(emitter, &event);
110*4882a593Smuzhiyun }
111*4882a593Smuzhiyun 
yaml_propval(yaml_emitter_t * emitter,struct property * prop)112*4882a593Smuzhiyun static void yaml_propval(yaml_emitter_t *emitter, struct property *prop)
113*4882a593Smuzhiyun {
114*4882a593Smuzhiyun 	yaml_event_t event;
115*4882a593Smuzhiyun 	int len = prop->val.len;
116*4882a593Smuzhiyun 	struct marker *m = prop->val.markers;
117*4882a593Smuzhiyun 
118*4882a593Smuzhiyun 	/* Emit the property name */
119*4882a593Smuzhiyun 	yaml_scalar_event_initialize(&event, NULL,
120*4882a593Smuzhiyun 		(yaml_char_t *)YAML_STR_TAG, (yaml_char_t*)prop->name,
121*4882a593Smuzhiyun 		strlen(prop->name), 1, 1, YAML_PLAIN_SCALAR_STYLE);
122*4882a593Smuzhiyun 	yaml_emitter_emit_or_die(emitter, &event);
123*4882a593Smuzhiyun 
124*4882a593Smuzhiyun 	/* Boolean properties are easiest to deal with. Length is zero, so just emit 'true' */
125*4882a593Smuzhiyun 	if (len == 0) {
126*4882a593Smuzhiyun 		yaml_scalar_event_initialize(&event, NULL,
127*4882a593Smuzhiyun 			(yaml_char_t *)YAML_BOOL_TAG,
128*4882a593Smuzhiyun 			(yaml_char_t*)"true",
129*4882a593Smuzhiyun 			strlen("true"), 1, 0, YAML_PLAIN_SCALAR_STYLE);
130*4882a593Smuzhiyun 		yaml_emitter_emit_or_die(emitter, &event);
131*4882a593Smuzhiyun 		return;
132*4882a593Smuzhiyun 	}
133*4882a593Smuzhiyun 
134*4882a593Smuzhiyun 	if (!m)
135*4882a593Smuzhiyun 		die("No markers present in property '%s' value\n", prop->name);
136*4882a593Smuzhiyun 
137*4882a593Smuzhiyun 	yaml_sequence_start_event_initialize(&event, NULL,
138*4882a593Smuzhiyun 		(yaml_char_t *)YAML_SEQ_TAG, 1, YAML_FLOW_SEQUENCE_STYLE);
139*4882a593Smuzhiyun 	yaml_emitter_emit_or_die(emitter, &event);
140*4882a593Smuzhiyun 
141*4882a593Smuzhiyun 	for_each_marker(m) {
142*4882a593Smuzhiyun 		int chunk_len;
143*4882a593Smuzhiyun 		char *data = &prop->val.val[m->offset];
144*4882a593Smuzhiyun 
145*4882a593Smuzhiyun 		if (m->type < TYPE_UINT8)
146*4882a593Smuzhiyun 			continue;
147*4882a593Smuzhiyun 
148*4882a593Smuzhiyun 		chunk_len = type_marker_length(m) ? : len;
149*4882a593Smuzhiyun 		assert(chunk_len > 0);
150*4882a593Smuzhiyun 		len -= chunk_len;
151*4882a593Smuzhiyun 
152*4882a593Smuzhiyun 		switch(m->type) {
153*4882a593Smuzhiyun 		case TYPE_UINT16:
154*4882a593Smuzhiyun 			yaml_propval_int(emitter, m, data, chunk_len, 2);
155*4882a593Smuzhiyun 			break;
156*4882a593Smuzhiyun 		case TYPE_UINT32:
157*4882a593Smuzhiyun 			yaml_propval_int(emitter, m, data, chunk_len, 4);
158*4882a593Smuzhiyun 			break;
159*4882a593Smuzhiyun 		case TYPE_UINT64:
160*4882a593Smuzhiyun 			yaml_propval_int(emitter, m, data, chunk_len, 8);
161*4882a593Smuzhiyun 			break;
162*4882a593Smuzhiyun 		case TYPE_STRING:
163*4882a593Smuzhiyun 			yaml_propval_string(emitter, data, chunk_len);
164*4882a593Smuzhiyun 			break;
165*4882a593Smuzhiyun 		default:
166*4882a593Smuzhiyun 			yaml_propval_int(emitter, m, data, chunk_len, 1);
167*4882a593Smuzhiyun 			break;
168*4882a593Smuzhiyun 		}
169*4882a593Smuzhiyun 	}
170*4882a593Smuzhiyun 
171*4882a593Smuzhiyun 	yaml_sequence_end_event_initialize(&event);
172*4882a593Smuzhiyun 	yaml_emitter_emit_or_die(emitter, &event);
173*4882a593Smuzhiyun }
174*4882a593Smuzhiyun 
175*4882a593Smuzhiyun 
yaml_tree(struct node * tree,yaml_emitter_t * emitter)176*4882a593Smuzhiyun static void yaml_tree(struct node *tree, yaml_emitter_t *emitter)
177*4882a593Smuzhiyun {
178*4882a593Smuzhiyun 	struct property *prop;
179*4882a593Smuzhiyun 	struct node *child;
180*4882a593Smuzhiyun 	yaml_event_t event;
181*4882a593Smuzhiyun 
182*4882a593Smuzhiyun 	if (tree->deleted)
183*4882a593Smuzhiyun 		return;
184*4882a593Smuzhiyun 
185*4882a593Smuzhiyun 	yaml_mapping_start_event_initialize(&event, NULL,
186*4882a593Smuzhiyun 		(yaml_char_t *)YAML_MAP_TAG, 1, YAML_ANY_MAPPING_STYLE);
187*4882a593Smuzhiyun 	yaml_emitter_emit_or_die(emitter, &event);
188*4882a593Smuzhiyun 
189*4882a593Smuzhiyun 	for_each_property(tree, prop)
190*4882a593Smuzhiyun 		yaml_propval(emitter, prop);
191*4882a593Smuzhiyun 
192*4882a593Smuzhiyun 	/* Loop over all the children, emitting them into the map */
193*4882a593Smuzhiyun 	for_each_child(tree, child) {
194*4882a593Smuzhiyun 		yaml_scalar_event_initialize(&event, NULL,
195*4882a593Smuzhiyun 			(yaml_char_t *)YAML_STR_TAG, (yaml_char_t*)child->name,
196*4882a593Smuzhiyun 			strlen(child->name), 1, 0, YAML_PLAIN_SCALAR_STYLE);
197*4882a593Smuzhiyun 		yaml_emitter_emit_or_die(emitter, &event);
198*4882a593Smuzhiyun 		yaml_tree(child, emitter);
199*4882a593Smuzhiyun 	}
200*4882a593Smuzhiyun 
201*4882a593Smuzhiyun 	yaml_mapping_end_event_initialize(&event);
202*4882a593Smuzhiyun 	yaml_emitter_emit_or_die(emitter, &event);
203*4882a593Smuzhiyun }
204*4882a593Smuzhiyun 
dt_to_yaml(FILE * f,struct dt_info * dti)205*4882a593Smuzhiyun void dt_to_yaml(FILE *f, struct dt_info *dti)
206*4882a593Smuzhiyun {
207*4882a593Smuzhiyun 	yaml_emitter_t emitter;
208*4882a593Smuzhiyun 	yaml_event_t event;
209*4882a593Smuzhiyun 
210*4882a593Smuzhiyun 	yaml_emitter_initialize(&emitter);
211*4882a593Smuzhiyun 	yaml_emitter_set_output_file(&emitter, f);
212*4882a593Smuzhiyun 	yaml_stream_start_event_initialize(&event, YAML_UTF8_ENCODING);
213*4882a593Smuzhiyun 	yaml_emitter_emit_or_die(&emitter, &event);
214*4882a593Smuzhiyun 
215*4882a593Smuzhiyun 	yaml_document_start_event_initialize(&event, NULL, NULL, NULL, 0);
216*4882a593Smuzhiyun 	yaml_emitter_emit_or_die(&emitter, &event);
217*4882a593Smuzhiyun 
218*4882a593Smuzhiyun 	yaml_sequence_start_event_initialize(&event, NULL, (yaml_char_t *)YAML_SEQ_TAG, 1, YAML_ANY_SEQUENCE_STYLE);
219*4882a593Smuzhiyun 	yaml_emitter_emit_or_die(&emitter, &event);
220*4882a593Smuzhiyun 
221*4882a593Smuzhiyun 	yaml_tree(dti->dt, &emitter);
222*4882a593Smuzhiyun 
223*4882a593Smuzhiyun 	yaml_sequence_end_event_initialize(&event);
224*4882a593Smuzhiyun 	yaml_emitter_emit_or_die(&emitter, &event);
225*4882a593Smuzhiyun 
226*4882a593Smuzhiyun 	yaml_document_end_event_initialize(&event, 0);
227*4882a593Smuzhiyun 	yaml_emitter_emit_or_die(&emitter, &event);
228*4882a593Smuzhiyun 
229*4882a593Smuzhiyun 	yaml_stream_end_event_initialize(&event);
230*4882a593Smuzhiyun 	yaml_emitter_emit_or_die(&emitter, &event);
231*4882a593Smuzhiyun 
232*4882a593Smuzhiyun 	yaml_emitter_delete(&emitter);
233*4882a593Smuzhiyun }
234