Merge tag 'fuse-update-6.6' of git://git.kernel.org/pub/scm/linux/kernel/git/mszeredi...
[platform/kernel/linux-starfive.git] / scripts / dtc / treesource.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
9 extern FILE *yyin;
10 extern int yyparse(void);
11 extern YYLTYPE yylloc;
12
13 struct dt_info *parser_output;
14 bool treesource_error;
15
16 struct 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
34 static 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
42 static 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
49 static 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
102 static 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
127 static const char *delim_start[] = {
128         [TYPE_UINT8] = "[",
129         [TYPE_UINT16] = "/bits/ 16 <",
130         [TYPE_UINT32] = "<",
131         [TYPE_UINT64] = "/bits/ 64 <",
132         [TYPE_STRING] = "",
133 };
134 static const char *delim_end[] = {
135         [TYPE_UINT8] = "]",
136         [TYPE_UINT16] = ">",
137         [TYPE_UINT32] = ">",
138         [TYPE_UINT64] = ">",
139         [TYPE_STRING] = "",
140 };
141
142 static enum markertype guess_value_type(struct property *prop)
143 {
144         int len = prop->val.len;
145         const char *p = prop->val.val;
146         struct marker *m = prop->val.markers;
147         int nnotstring = 0, nnul = 0;
148         int nnotstringlbl = 0, nnotcelllbl = 0;
149         int i;
150
151         for (i = 0; i < len; i++) {
152                 if (! isstring(p[i]))
153                         nnotstring++;
154                 if (p[i] == '\0')
155                         nnul++;
156         }
157
158         for_each_marker_of_type(m, LABEL) {
159                 if ((m->offset > 0) && (prop->val.val[m->offset - 1] != '\0'))
160                         nnotstringlbl++;
161                 if ((m->offset % sizeof(cell_t)) != 0)
162                         nnotcelllbl++;
163         }
164
165         if ((p[len-1] == '\0') && (nnotstring == 0) && (nnul <= (len-nnul))
166             && (nnotstringlbl == 0)) {
167                 return TYPE_STRING;
168         } else if (((len % sizeof(cell_t)) == 0) && (nnotcelllbl == 0)) {
169                 return TYPE_UINT32;
170         }
171
172         return TYPE_UINT8;
173 }
174
175 static void write_propval(FILE *f, struct property *prop)
176 {
177         size_t len = prop->val.len;
178         struct marker *m = prop->val.markers;
179         struct marker dummy_marker;
180         enum markertype emit_type = TYPE_NONE;
181         char *srcstr;
182
183         if (len == 0) {
184                 fprintf(f, ";");
185                 if (annotate) {
186                         srcstr = srcpos_string_first(prop->srcpos, annotate);
187                         if (srcstr) {
188                                 fprintf(f, " /* %s */", srcstr);
189                                 free(srcstr);
190                         }
191                 }
192                 fprintf(f, "\n");
193                 return;
194         }
195
196         fprintf(f, " =");
197
198         if (!next_type_marker(m)) {
199                 /* data type information missing, need to guess */
200                 dummy_marker.type = guess_value_type(prop);
201                 dummy_marker.next = prop->val.markers;
202                 dummy_marker.offset = 0;
203                 dummy_marker.ref = NULL;
204                 m = &dummy_marker;
205         }
206
207         for_each_marker(m) {
208                 size_t chunk_len = (m->next ? m->next->offset : len) - m->offset;
209                 size_t data_len = type_marker_length(m) ? : len - m->offset;
210                 const char *p = &prop->val.val[m->offset];
211                 struct marker *m_phandle;
212
213                 if (is_type_marker(m->type)) {
214                         emit_type = m->type;
215                         fprintf(f, " %s", delim_start[emit_type]);
216                 } else if (m->type == LABEL)
217                         fprintf(f, " %s:", m->ref);
218
219                 if (emit_type == TYPE_NONE || chunk_len == 0)
220                         continue;
221
222                 switch(emit_type) {
223                 case TYPE_UINT16:
224                         write_propval_int(f, p, chunk_len, 2);
225                         break;
226                 case TYPE_UINT32:
227                         m_phandle = prop->val.markers;
228                         for_each_marker_of_type(m_phandle, REF_PHANDLE)
229                                 if (m->offset == m_phandle->offset)
230                                         break;
231
232                         if (m_phandle) {
233                                 if (m_phandle->ref[0] == '/')
234                                         fprintf(f, "&{%s}", m_phandle->ref);
235                                 else
236                                         fprintf(f, "&%s", m_phandle->ref);
237                                 if (chunk_len > 4) {
238                                         fputc(' ', f);
239                                         write_propval_int(f, p + 4, chunk_len - 4, 4);
240                                 }
241                         } else {
242                                 write_propval_int(f, p, chunk_len, 4);
243                         }
244                         break;
245                 case TYPE_UINT64:
246                         write_propval_int(f, p, chunk_len, 8);
247                         break;
248                 case TYPE_STRING:
249                         write_propval_string(f, p, chunk_len);
250                         break;
251                 default:
252                         write_propval_int(f, p, chunk_len, 1);
253                 }
254
255                 if (chunk_len == data_len) {
256                         size_t pos = m->offset + chunk_len;
257                         fprintf(f, pos == len ? "%s" : "%s,",
258                                 delim_end[emit_type] ? : "");
259                         emit_type = TYPE_NONE;
260                 }
261         }
262         fprintf(f, ";");
263         if (annotate) {
264                 srcstr = srcpos_string_first(prop->srcpos, annotate);
265                 if (srcstr) {
266                         fprintf(f, " /* %s */", srcstr);
267                         free(srcstr);
268                 }
269         }
270         fprintf(f, "\n");
271 }
272
273 static void write_tree_source_node(FILE *f, struct node *tree, int level)
274 {
275         struct property *prop;
276         struct node *child;
277         struct label *l;
278         char *srcstr;
279
280         write_prefix(f, level);
281         for_each_label(tree->labels, l)
282                 fprintf(f, "%s: ", l->label);
283         if (tree->name && (*tree->name))
284                 fprintf(f, "%s {", tree->name);
285         else
286                 fprintf(f, "/ {");
287
288         if (annotate) {
289                 srcstr = srcpos_string_first(tree->srcpos, annotate);
290                 if (srcstr) {
291                         fprintf(f, " /* %s */", srcstr);
292                         free(srcstr);
293                 }
294         }
295         fprintf(f, "\n");
296
297         for_each_property(tree, prop) {
298                 write_prefix(f, level+1);
299                 for_each_label(prop->labels, l)
300                         fprintf(f, "%s: ", l->label);
301                 fprintf(f, "%s", prop->name);
302                 write_propval(f, prop);
303         }
304         for_each_child(tree, child) {
305                 fprintf(f, "\n");
306                 write_tree_source_node(f, child, level+1);
307         }
308         write_prefix(f, level);
309         fprintf(f, "};");
310         if (annotate) {
311                 srcstr = srcpos_string_last(tree->srcpos, annotate);
312                 if (srcstr) {
313                         fprintf(f, " /* %s */", srcstr);
314                         free(srcstr);
315                 }
316         }
317         fprintf(f, "\n");
318 }
319
320 void dt_to_source(FILE *f, struct dt_info *dti)
321 {
322         struct reserve_info *re;
323
324         fprintf(f, "/dts-v1/;\n\n");
325
326         for (re = dti->reservelist; re; re = re->next) {
327                 struct label *l;
328
329                 for_each_label(re->labels, l)
330                         fprintf(f, "%s: ", l->label);
331                 fprintf(f, "/memreserve/\t0x%016llx 0x%016llx;\n",
332                         (unsigned long long)re->address,
333                         (unsigned long long)re->size);
334         }
335
336         write_tree_source_node(f, dti->dt, 0);
337 }