hc
2024-01-05 071106ecf68c401173c58808b1cf5f68cc50d390
kernel/scripts/dtc/treesource.c
....@@ -1,21 +1,6 @@
1
+// SPDX-License-Identifier: GPL-2.0-or-later
12 /*
23 * (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
194 */
205
216 #include "dtc.h"
....@@ -61,24 +46,18 @@
6146 || strchr("\a\b\t\n\v\f\r", c));
6247 }
6348
64
-static void write_propval_string(FILE *f, struct data val)
49
+static void write_propval_string(FILE *f, const char *s, size_t len)
6550 {
66
- const char *str = val.val;
67
- int i;
68
- struct marker *m = val.markers;
51
+ const char *end = s + len - 1;
6952
70
- assert(str[val.len-1] == '\0');
53
+ if (!len)
54
+ return;
7155
72
- while (m && (m->offset == 0)) {
73
- if (m->type == LABEL)
74
- fprintf(f, "%s: ", m->ref);
75
- m = m->next;
76
- }
56
+ assert(*end == '\0');
57
+
7758 fprintf(f, "\"");
78
-
79
- for (i = 0; i < (val.len-1); i++) {
80
- char c = str[i];
81
-
59
+ while (s < end) {
60
+ char c = *s++;
8261 switch (c) {
8362 case '\a':
8463 fprintf(f, "\\a");
....@@ -108,91 +87,80 @@
10887 fprintf(f, "\\\"");
10988 break;
11089 case '\0':
111
- fprintf(f, "\", ");
112
- while (m && (m->offset <= (i + 1))) {
113
- if (m->type == LABEL) {
114
- assert(m->offset == (i+1));
115
- fprintf(f, "%s: ", m->ref);
116
- }
117
- m = m->next;
118
- }
119
- fprintf(f, "\"");
90
+ fprintf(f, "\\0");
12091 break;
12192 default:
12293 if (isprint((unsigned char)c))
12394 fprintf(f, "%c", c);
12495 else
125
- fprintf(f, "\\x%02hhx", c);
96
+ fprintf(f, "\\x%02"PRIx8, c);
12697 }
12798 }
12899 fprintf(f, "\"");
129
-
130
- /* Wrap up any labels at the end of the value */
131
- for_each_marker_of_type(m, LABEL) {
132
- assert (m->offset == val.len);
133
- fprintf(f, " %s:", m->ref);
134
- }
135100 }
136101
137
-static void write_propval_cells(FILE *f, struct data val)
102
+static void write_propval_int(FILE *f, const char *p, size_t len, size_t width)
138103 {
139
- void *propend = val.val + val.len;
140
- fdt32_t *cp = (fdt32_t *)val.val;
141
- struct marker *m = val.markers;
104
+ const char *end = p + len;
105
+ assert(len % width == 0);
142106
143
- fprintf(f, "<");
144
- for (;;) {
145
- while (m && (m->offset <= ((char *)cp - val.val))) {
146
- if (m->type == LABEL) {
147
- assert(m->offset == ((char *)cp - val.val));
148
- fprintf(f, "%s: ", m->ref);
149
- }
150
- m = m->next;
151
- }
152
-
153
- fprintf(f, "0x%x", fdt32_to_cpu(*cp++));
154
- if ((void *)cp >= propend)
107
+ for (; p < end; p += width) {
108
+ switch (width) {
109
+ case 1:
110
+ fprintf(f, "%02"PRIx8, *(const uint8_t*)p);
155111 break;
156
- fprintf(f, " ");
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);
157124 }
158
-
159
- /* Wrap up any labels at the end of the value */
160
- for_each_marker_of_type(m, LABEL) {
161
- assert (m->offset == val.len);
162
- fprintf(f, " %s:", m->ref);
163
- }
164
- fprintf(f, ">");
165125 }
166126
167
-static void write_propval_bytes(FILE *f, struct data val)
127
+static bool has_data_type_information(struct marker *m)
168128 {
169
- void *propend = val.val + val.len;
170
- const char *bp = val.val;
171
- struct marker *m = val.markers;
172
-
173
- fprintf(f, "[");
174
- for (;;) {
175
- while (m && (m->offset == (bp-val.val))) {
176
- if (m->type == LABEL)
177
- fprintf(f, "%s: ", m->ref);
178
- m = m->next;
179
- }
180
-
181
- fprintf(f, "%02hhx", (unsigned char)(*bp++));
182
- if ((const void *)bp >= propend)
183
- break;
184
- fprintf(f, " ");
185
- }
186
-
187
- /* Wrap up any labels at the end of the value */
188
- for_each_marker_of_type(m, LABEL) {
189
- assert (m->offset == val.len);
190
- fprintf(f, " %s:", m->ref);
191
- }
192
- fprintf(f, "]");
129
+ return m->type >= TYPE_UINT8;
193130 }
194131
195
-static void write_propval(FILE *f, struct property *prop)
132
+static struct marker *next_type_marker(struct marker *m)
133
+{
134
+ while (m && !has_data_type_information(m))
135
+ m = m->next;
136
+ return m;
137
+}
138
+
139
+size_t type_marker_length(struct marker *m)
140
+{
141
+ struct marker *next = next_type_marker(m->next);
142
+
143
+ if (next)
144
+ return next->offset - m->offset;
145
+ return 0;
146
+}
147
+
148
+static const char *delim_start[] = {
149
+ [TYPE_UINT8] = "[",
150
+ [TYPE_UINT16] = "/bits/ 16 <",
151
+ [TYPE_UINT32] = "<",
152
+ [TYPE_UINT64] = "/bits/ 64 <",
153
+ [TYPE_STRING] = "",
154
+};
155
+static const char *delim_end[] = {
156
+ [TYPE_UINT8] = "]",
157
+ [TYPE_UINT16] = ">",
158
+ [TYPE_UINT32] = ">",
159
+ [TYPE_UINT64] = ">",
160
+ [TYPE_STRING] = "",
161
+};
162
+
163
+static enum markertype guess_value_type(struct property *prop)
196164 {
197165 int len = prop->val.len;
198166 const char *p = prop->val.val;
....@@ -200,11 +168,6 @@
200168 int nnotstring = 0, nnul = 0;
201169 int nnotstringlbl = 0, nnotcelllbl = 0;
202170 int i;
203
-
204
- if (len == 0) {
205
- fprintf(f, ";\n");
206
- return;
207
- }
208171
209172 for (i = 0; i < len; i++) {
210173 if (! isstring(p[i]))
....@@ -220,17 +183,99 @@
220183 nnotcelllbl++;
221184 }
222185
223
- fprintf(f, " = ");
224
- if ((p[len-1] == '\0') && (nnotstring == 0) && (nnul < (len-nnul))
186
+ if ((p[len-1] == '\0') && (nnotstring == 0) && (nnul <= (len-nnul))
225187 && (nnotstringlbl == 0)) {
226
- write_propval_string(f, prop->val);
188
+ return TYPE_STRING;
227189 } else if (((len % sizeof(cell_t)) == 0) && (nnotcelllbl == 0)) {
228
- write_propval_cells(f, prop->val);
229
- } else {
230
- write_propval_bytes(f, prop->val);
190
+ return TYPE_UINT32;
231191 }
232192
233
- fprintf(f, ";\n");
193
+ return TYPE_UINT8;
194
+}
195
+
196
+static void write_propval(FILE *f, struct property *prop)
197
+{
198
+ size_t len = prop->val.len;
199
+ struct marker *m = prop->val.markers;
200
+ struct marker dummy_marker;
201
+ enum markertype emit_type = TYPE_NONE;
202
+ char *srcstr;
203
+
204
+ if (len == 0) {
205
+ fprintf(f, ";");
206
+ if (annotate) {
207
+ srcstr = srcpos_string_first(prop->srcpos, annotate);
208
+ if (srcstr) {
209
+ fprintf(f, " /* %s */", srcstr);
210
+ free(srcstr);
211
+ }
212
+ }
213
+ fprintf(f, "\n");
214
+ return;
215
+ }
216
+
217
+ fprintf(f, " =");
218
+
219
+ if (!next_type_marker(m)) {
220
+ /* data type information missing, need to guess */
221
+ dummy_marker.type = guess_value_type(prop);
222
+ dummy_marker.next = prop->val.markers;
223
+ dummy_marker.offset = 0;
224
+ dummy_marker.ref = NULL;
225
+ m = &dummy_marker;
226
+ }
227
+
228
+ for_each_marker(m) {
229
+ size_t chunk_len = (m->next ? m->next->offset : len) - m->offset;
230
+ size_t data_len = type_marker_length(m) ? : len - m->offset;
231
+ const char *p = &prop->val.val[m->offset];
232
+
233
+ if (has_data_type_information(m)) {
234
+ emit_type = m->type;
235
+ fprintf(f, " %s", delim_start[emit_type]);
236
+ } else if (m->type == LABEL)
237
+ fprintf(f, " %s:", m->ref);
238
+ else if (m->offset)
239
+ fputc(' ', f);
240
+
241
+ if (emit_type == TYPE_NONE) {
242
+ assert(chunk_len == 0);
243
+ continue;
244
+ }
245
+
246
+ switch(emit_type) {
247
+ case TYPE_UINT16:
248
+ write_propval_int(f, p, chunk_len, 2);
249
+ break;
250
+ case TYPE_UINT32:
251
+ write_propval_int(f, p, chunk_len, 4);
252
+ break;
253
+ case TYPE_UINT64:
254
+ write_propval_int(f, p, chunk_len, 8);
255
+ break;
256
+ case TYPE_STRING:
257
+ write_propval_string(f, p, chunk_len);
258
+ break;
259
+ default:
260
+ write_propval_int(f, p, chunk_len, 1);
261
+ }
262
+
263
+ if (chunk_len == data_len) {
264
+ size_t pos = m->offset + chunk_len;
265
+ fprintf(f, pos == len ? "%s" : "%s,",
266
+ delim_end[emit_type] ? : "");
267
+ emit_type = TYPE_NONE;
268
+ }
269
+ }
270
+ fprintf(f, ";");
271
+ if (annotate) {
272
+ srcstr = srcpos_string_first(prop->srcpos, annotate);
273
+ if (srcstr) {
274
+ fprintf(f, " /* %s */", srcstr);
275
+ free(srcstr);
276
+ }
277
+ }
278
+ fprintf(f, "\n");
234279 }
235280
236281 static void write_tree_source_node(FILE *f, struct node *tree, int level)
....@@ -238,14 +283,24 @@
238283 struct property *prop;
239284 struct node *child;
240285 struct label *l;
286
+ char *srcstr;
241287
242288 write_prefix(f, level);
243289 for_each_label(tree->labels, l)
244290 fprintf(f, "%s: ", l->label);
245291 if (tree->name && (*tree->name))
246
- fprintf(f, "%s {\n", tree->name);
292
+ fprintf(f, "%s {", tree->name);
247293 else
248
- fprintf(f, "/ {\n");
294
+ fprintf(f, "/ {");
295
+
296
+ if (annotate) {
297
+ srcstr = srcpos_string_first(tree->srcpos, annotate);
298
+ if (srcstr) {
299
+ fprintf(f, " /* %s */", srcstr);
300
+ free(srcstr);
301
+ }
302
+ }
303
+ fprintf(f, "\n");
249304
250305 for_each_property(tree, prop) {
251306 write_prefix(f, level+1);
....@@ -259,9 +314,16 @@
259314 write_tree_source_node(f, child, level+1);
260315 }
261316 write_prefix(f, level);
262
- fprintf(f, "};\n");
317
+ fprintf(f, "};");
318
+ if (annotate) {
319
+ srcstr = srcpos_string_last(tree->srcpos, annotate);
320
+ if (srcstr) {
321
+ fprintf(f, " /* %s */", srcstr);
322
+ free(srcstr);
323
+ }
324
+ }
325
+ fprintf(f, "\n");
263326 }
264
-
265327
266328 void dt_to_source(FILE *f, struct dt_info *dti)
267329 {
....@@ -281,4 +343,3 @@
281343
282344 write_tree_source_node(f, dti->dt, 0);
283345 }
284
-