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