blob: 605d303c47a41f007aa7b6db50f2a7c8d6d09bc9 [file] [log] [blame]
b.liue9582032025-04-17 19:18:16 +08001From 5f84cb93eef9f8a8ff7f49d593893f252744d0fe Mon Sep 17 00:00:00 2001
2From: Pantelis Antoniou <pantelis.antoniou@konsulko.com>
3Date: Wed, 26 Aug 2015 18:28:08 +0300
4Subject: [PATCH] scripts/dtc: Update to version with overlays
5
6Update to mainline dtc with overlay support
7
8Signed-off-by: Pantelis Antoniou <pantelis.antoniou@konsulko.com>
9---
10 checks.c | 20 +++++-
11 dtc-lexer.l | 5 ++
12 dtc-parser.y | 54 ++++++++++++++--
13 dtc.c | 83 ++++++++++++++++++++++--
14 dtc.h | 13 +++-
15 livetree.c | 202 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
16 treesource.c | 3 +
17 util.c | 2 +-
18 8 files changed, 367 insertions(+), 15 deletions(-)
19
20diff --git a/checks.c b/checks.c
21index 3bf0fa4..af25c2b 100644
22--- a/checks.c
23+++ b/checks.c
24@@ -465,8 +465,12 @@ static void fixup_phandle_references(struct check *c, struct node *dt,
25
26 refnode = get_node_by_ref(dt, m->ref);
27 if (! refnode) {
28- FAIL(c, "Reference to non-existent node or label \"%s\"\n",
29- m->ref);
30+ if (!source_is_plugin)
31+ FAIL(c, "Reference to non-existent node or "
32+ "label \"%s\"\n", m->ref);
33+ else /* mark the entry as unresolved */
34+ *((cell_t *)(prop->val.val + m->offset)) =
35+ cpu_to_fdt32(0xffffffff);
36 continue;
37 }
38
39@@ -559,7 +563,7 @@ static void check_reg_format(struct check *c, struct node *dt,
40 size_cells = node_size_cells(node->parent);
41 entrylen = (addr_cells + size_cells) * sizeof(cell_t);
42
43- if ((prop->val.len % entrylen) != 0)
44+ if (!entrylen || (prop->val.len % entrylen) != 0)
45 FAIL(c, "\"reg\" property in %s has invalid length (%d bytes) "
46 "(#address-cells == %d, #size-cells == %d)",
47 node->fullpath, prop->val.len, addr_cells, size_cells);
48@@ -651,6 +655,15 @@ static void check_obsolete_chosen_interrupt_controller(struct check *c,
49 }
50 TREE_WARNING(obsolete_chosen_interrupt_controller, NULL);
51
52+static void check_deprecated_plugin_syntax(struct check *c,
53+ struct node *dt)
54+{
55+ if (deprecated_plugin_syntax_warning)
56+ FAIL(c, "Use '/dts-v1/ /plugin/'; syntax. /dts-v1/; /plugin/; "
57+ "is going to be removed in next versions");
58+}
59+TREE_WARNING(deprecated_plugin_syntax, NULL);
60+
61 static struct check *check_table[] = {
62 &duplicate_node_names, &duplicate_property_names,
63 &node_name_chars, &node_name_format, &property_name_chars,
64@@ -668,6 +681,7 @@ static struct check *check_table[] = {
65
66 &avoid_default_addr_size,
67 &obsolete_chosen_interrupt_controller,
68+ &deprecated_plugin_syntax,
69
70 &always_fail,
71 };
72diff --git a/dtc-lexer.l b/dtc-lexer.l
73index 0ee1caf..dd44ba2 100644
74--- a/dtc-lexer.l
75+++ b/dtc-lexer.l
76@@ -113,6 +113,11 @@ static void lexical_error(const char *fmt, ...);
77 return DT_V1;
78 }
79
80+<*>"/plugin/" {
81+ DPRINT("Keyword: /plugin/\n");
82+ return DT_PLUGIN;
83+ }
84+
85 <*>"/memreserve/" {
86 DPRINT("Keyword: /memreserve/\n");
87 BEGIN_DEFAULT();
88diff --git a/dtc-parser.y b/dtc-parser.y
89index ea57e0a..7d9652d 100644
90--- a/dtc-parser.y
91+++ b/dtc-parser.y
92@@ -19,6 +19,7 @@
93 */
94 %{
95 #include <stdio.h>
96+#include <inttypes.h>
97
98 #include "dtc.h"
99 #include "srcpos.h"
100@@ -52,9 +53,11 @@ extern bool treesource_error;
101 struct node *nodelist;
102 struct reserve_info *re;
103 uint64_t integer;
104+ bool is_plugin;
105 }
106
107 %token DT_V1
108+%token DT_PLUGIN
109 %token DT_MEMRESERVE
110 %token DT_LSHIFT DT_RSHIFT DT_LE DT_GE DT_EQ DT_NE DT_AND DT_OR
111 %token DT_BITS
112@@ -71,6 +74,7 @@ extern bool treesource_error;
113
114 %type <data> propdata
115 %type <data> propdataprefix
116+%type <is_plugin> plugindecl
117 %type <re> memreserve
118 %type <re> memreserves
119 %type <array> arrayprefix
120@@ -101,10 +105,39 @@ extern bool treesource_error;
121 %%
122
123 sourcefile:
124- DT_V1 ';' memreserves devicetree
125+ basesource
126+ | pluginsource
127+ ;
128+
129+basesource:
130+ DT_V1 ';' plugindecl memreserves devicetree
131+ {
132+ source_is_plugin = $3;
133+ if (source_is_plugin)
134+ deprecated_plugin_syntax_warning = true;
135+ the_boot_info = build_boot_info($4, $5,
136+ guess_boot_cpuid($5));
137+ }
138+ ;
139+
140+plugindecl:
141+ /* empty */
142+ {
143+ $$ = false;
144+ }
145+ | DT_PLUGIN ';'
146+ {
147+ $$ = true;
148+ }
149+ ;
150+
151+pluginsource:
152+ DT_V1 DT_PLUGIN ';' memreserves devicetree
153 {
154- the_boot_info = build_boot_info($3, $4,
155- guess_boot_cpuid($4));
156+ source_is_plugin = true;
157+ deprecated_plugin_syntax_warning = false;
158+ the_boot_info = build_boot_info($4, $5,
159+ guess_boot_cpuid($5));
160 }
161 ;
162
163@@ -144,10 +177,14 @@ devicetree:
164 {
165 struct node *target = get_node_by_ref($1, $2);
166
167- if (target)
168+ if (target) {
169 merge_nodes(target, $3);
170- else
171- ERROR(&@2, "Label or path %s not found", $2);
172+ } else {
173+ if (symbol_fixup_support)
174+ add_orphan_node($1, $3, $2);
175+ else
176+ ERROR(&@2, "Label or path %s not found", $2);
177+ }
178 $$ = $1;
179 }
180 | devicetree DT_DEL_NODE DT_REF ';'
181@@ -162,6 +199,11 @@ devicetree:
182
183 $$ = $1;
184 }
185+ | /* empty */
186+ {
187+ /* build empty node */
188+ $$ = name_node(build_node(NULL, NULL), "");
189+ }
190 ;
191
192 nodedef:
193diff --git a/dtc.c b/dtc.c
194index 8c4add6..ee37be9 100644
195--- a/dtc.c
196+++ b/dtc.c
197@@ -18,6 +18,8 @@
198 * USA
199 */
200
201+#include <sys/stat.h>
202+
203 #include "dtc.h"
204 #include "srcpos.h"
205
206@@ -29,6 +31,8 @@ int reservenum; /* Number of memory reservation slots */
207 int minsize; /* Minimum blob size */
208 int padsize; /* Additional padding to blob */
209 int phandle_format = PHANDLE_BOTH; /* Use linux,phandle or phandle properties */
210+int symbol_fixup_support;
211+int auto_label_aliases;
212
213 static void fill_fullpaths(struct node *tree, const char *prefix)
214 {
215@@ -51,7 +55,7 @@ static void fill_fullpaths(struct node *tree, const char *prefix)
216 #define FDT_VERSION(version) _FDT_VERSION(version)
217 #define _FDT_VERSION(version) #version
218 static const char usage_synopsis[] = "dtc [options] <input file>";
219-static const char usage_short_opts[] = "qI:O:o:V:d:R:S:p:fb:i:H:sW:E:hv";
220+static const char usage_short_opts[] = "qI:O:o:V:d:R:S:p:fb:i:H:sW:E:@Ahv";
221 static struct option const usage_long_opts[] = {
222 {"quiet", no_argument, NULL, 'q'},
223 {"in-format", a_argument, NULL, 'I'},
224@@ -69,6 +73,8 @@ static struct option const usage_long_opts[] = {
225 {"phandle", a_argument, NULL, 'H'},
226 {"warning", a_argument, NULL, 'W'},
227 {"error", a_argument, NULL, 'E'},
228+ {"symbols", no_argument, NULL, '@'},
229+ {"auto-alias", no_argument, NULL, 'A'},
230 {"help", no_argument, NULL, 'h'},
231 {"version", no_argument, NULL, 'v'},
232 {NULL, no_argument, NULL, 0x0},
233@@ -99,16 +105,63 @@ static const char * const usage_opts_help[] = {
234 "\t\tboth - Both \"linux,phandle\" and \"phandle\" properties",
235 "\n\tEnable/disable warnings (prefix with \"no-\")",
236 "\n\tEnable/disable errors (prefix with \"no-\")",
237+ "\n\tEnable symbols/fixup support",
238+ "\n\tEnable auto-alias of labels",
239 "\n\tPrint this help and exit",
240 "\n\tPrint version and exit",
241 NULL,
242 };
243
244+static const char *guess_type_by_name(const char *fname, const char *fallback)
245+{
246+ const char *s;
247+
248+ s = strrchr(fname, '.');
249+ if (s == NULL)
250+ return fallback;
251+ if (!strcasecmp(s, ".dts"))
252+ return "dts";
253+ if (!strcasecmp(s, ".dtb"))
254+ return "dtb";
255+ return fallback;
256+}
257+
258+static const char *guess_input_format(const char *fname, const char *fallback)
259+{
260+ struct stat statbuf;
261+ uint32_t magic;
262+ FILE *f;
263+
264+ if (stat(fname, &statbuf) != 0)
265+ return fallback;
266+
267+ if (S_ISDIR(statbuf.st_mode))
268+ return "fs";
269+
270+ if (!S_ISREG(statbuf.st_mode))
271+ return fallback;
272+
273+ f = fopen(fname, "r");
274+ if (f == NULL)
275+ return fallback;
276+ if (fread(&magic, 4, 1, f) != 1) {
277+ fclose(f);
278+ return fallback;
279+ }
280+ fclose(f);
281+
282+ magic = fdt32_to_cpu(magic);
283+ if (magic == FDT_MAGIC)
284+ return "dtb";
285+
286+ return guess_type_by_name(fname, fallback);
287+}
288+
289 int main(int argc, char *argv[])
290 {
291 struct boot_info *bi;
292- const char *inform = "dts";
293- const char *outform = "dts";
294+ const char *inform = NULL;
295+ const char *outform = NULL;
296 const char *outname = "-";
297 const char *depname = NULL;
298 bool force = false, sort = false;
299@@ -186,7 +239,12 @@ int main(int argc, char *argv[])
300 case 'E':
301 parse_checks_option(false, true, optarg);
302 break;
303-
304+ case '@':
305+ symbol_fixup_support = 1;
306+ break;
307+ case 'A':
308+ auto_label_aliases = 1;
309+ break;
310 case 'h':
311 usage(NULL);
312 default:
313@@ -213,6 +271,17 @@ int main(int argc, char *argv[])
314 fprintf(depfile, "%s:", outname);
315 }
316
317+ if (inform == NULL)
318+ inform = guess_input_format(arg, "dts");
319+ if (outform == NULL) {
320+ outform = guess_type_by_name(outname, NULL);
321+ if (outform == NULL) {
322+ if (streq(inform, "dts"))
323+ outform = "dtb";
324+ else
325+ outform = "dts";
326+ }
327+ }
328 if (streq(inform, "dts"))
329 bi = dt_from_source(arg);
330 else if (streq(inform, "fs"))
331@@ -236,6 +305,12 @@ int main(int argc, char *argv[])
332 if (sort)
333 sort_tree(bi);
334
335+ if (symbol_fixup_support || auto_label_aliases)
336+ generate_label_node(bi->dt, bi->dt);
337+
338+ if (symbol_fixup_support)
339+ generate_fixups_node(bi->dt, bi->dt);
340+
341 if (streq(outname, "-")) {
342 outf = stdout;
343 } else {
344diff --git a/dtc.h b/dtc.h
345index 56212c8..d025111 100644
346--- a/dtc.h
347+++ b/dtc.h
348@@ -20,7 +20,7 @@
349 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
350 * USA
351 */
352-
353+#define _GNU_SOURCE
354 #include <stdio.h>
355 #include <string.h>
356 #include <stdlib.h>
357@@ -54,6 +54,14 @@ extern int reservenum; /* Number of memory reservation slots */
358 extern int minsize; /* Minimum blob size */
359 extern int padsize; /* Additional padding to blob */
360 extern int phandle_format; /* Use linux,phandle or phandle properties */
361+extern int symbol_fixup_support;/* enable symbols & fixup support */
362+extern int auto_label_aliases; /* auto generate labels -> aliases */
363+
364+/*
365+ * Tree source globals
366+ */
367+extern bool source_is_plugin;
368+extern bool deprecated_plugin_syntax_warning;
369
370 #define PHANDLE_LEGACY 0x1
371 #define PHANDLE_EPAPR 0x2
372@@ -194,6 +202,7 @@ struct node *build_node_delete(void);
373 struct node *name_node(struct node *node, char *name);
374 struct node *chain_node(struct node *first, struct node *list);
375 struct node *merge_nodes(struct node *old_node, struct node *new_node);
376+void add_orphan_node(struct node *old_node, struct node *new_node, char *ref);
377
378 void add_property(struct node *node, struct property *prop);
379 void delete_property_by_name(struct node *node, char *name);
380@@ -244,6 +253,8 @@ struct boot_info {
381 struct boot_info *build_boot_info(struct reserve_info *reservelist,
382 struct node *tree, uint32_t boot_cpuid_phys);
383 void sort_tree(struct boot_info *bi);
384+void generate_label_node(struct node *node, struct node *dt);
385+void generate_fixups_node(struct node *node, struct node *dt);
386
387 /* Checks */
388
389diff --git a/livetree.c b/livetree.c
390index e229b84..1ef9fc4 100644
391--- a/livetree.c
392+++ b/livetree.c
393@@ -216,6 +216,34 @@ struct node *merge_nodes(struct node *old_node, struct node *new_node)
394 return old_node;
395 }
396
397+void add_orphan_node(struct node *dt, struct node *new_node, char *ref)
398+{
399+ static unsigned int next_orphan_fragment = 0;
400+ struct node *ovl = xmalloc(sizeof(*ovl));
401+ struct property *p;
402+ struct data d = empty_data;
403+ char *name;
404+ int ret;
405+
406+ memset(ovl, 0, sizeof(*ovl));
407+
408+ d = data_add_marker(d, REF_PHANDLE, ref);
409+ d = data_append_integer(d, 0xffffffff, 32);
410+
411+ p = build_property("target", d);
412+ add_property(ovl, p);
413+
414+ ret = asprintf(&name, "fragment@%u",
415+ next_orphan_fragment++);
416+ if (ret == -1)
417+ die("asprintf() failed\n");
418+ name_node(ovl, name);
419+ name_node(new_node, "__overlay__");
420+
421+ add_child(dt, ovl);
422+ add_child(ovl, new_node);
423+}
424+
425 struct node *chain_node(struct node *first, struct node *list)
426 {
427 assert(first->next_sibling == NULL);
428@@ -709,3 +737,177 @@ void sort_tree(struct boot_info *bi)
429 sort_reserve_entries(bi);
430 sort_node(bi->dt);
431 }
432+
433+void generate_label_node(struct node *node, struct node *dt)
434+{
435+ struct node *c, *an;
436+ struct property *p;
437+ struct label *l;
438+ int has_label;
439+ char *gen_node_name;
440+
441+ if (auto_label_aliases)
442+ gen_node_name = "aliases";
443+ else
444+ gen_node_name = "__symbols__";
445+
446+ /* Make sure the label isn't already there */
447+ has_label = 0;
448+ for_each_label(node->labels, l) {
449+ has_label = 1;
450+ break;
451+ }
452+
453+ if (has_label) {
454+
455+ /* an is the aliases/__symbols__ node */
456+ an = get_subnode(dt, gen_node_name);
457+ /* if no node exists, create it */
458+ if (!an) {
459+ an = build_node(NULL, NULL);
460+ name_node(an, gen_node_name);
461+ add_child(dt, an);
462+ }
463+
464+ /* now add the label in the node */
465+ for_each_label(node->labels, l) {
466+ /* check whether the label already exists */
467+ p = get_property(an, l->label);
468+ if (p) {
469+ fprintf(stderr, "WARNING: label %s already"
470+ " exists in /%s", l->label,
471+ gen_node_name);
472+ continue;
473+ }
474+
475+ /* insert it */
476+ p = build_property(l->label,
477+ data_copy_escape_string(node->fullpath,
478+ strlen(node->fullpath)));
479+ add_property(an, p);
480+ }
481+
482+ /* force allocation of a phandle for this node */
483+ if (symbol_fixup_support)
484+ (void)get_node_phandle(dt, node);
485+ }
486+
487+ for_each_child(node, c)
488+ generate_label_node(c, dt);
489+}
490+
491+static void add_fixup_entry(struct node *dt, struct node *node,
492+ struct property *prop, struct marker *m)
493+{
494+ struct node *fn; /* local fixup node */
495+ struct property *p;
496+ char *fixups_name = "__fixups__";
497+ struct data d;
498+ char *entry;
499+ int ret;
500+
501+ /* fn is the node we're putting entries in */
502+ fn = get_subnode(dt, fixups_name);
503+ /* if no node exists, create it */
504+ if (!fn) {
505+ fn = build_node(NULL, NULL);
506+ name_node(fn, fixups_name);
507+ add_child(dt, fn);
508+ }
509+
510+ ret = asprintf(&entry, "%s:%s:%u",
511+ node->fullpath, prop->name, m->offset);
512+ if (ret == -1)
513+ die("asprintf() failed\n");
514+
515+ p = get_property(fn, m->ref);
516+ d = data_append_data(p ? p->val : empty_data, entry, strlen(entry) + 1);
517+ if (!p)
518+ add_property(fn, build_property(m->ref, d));
519+ else
520+ p->val = d;
521+}
522+
523+static void add_local_fixup_entry(struct node *dt, struct node *node,
524+ struct property *prop, struct marker *m,
525+ struct node *refnode)
526+{
527+ struct node *lfn, *wn, *nwn; /* local fixup node, walk node, new */
528+ struct property *p;
529+ struct data d;
530+ char *local_fixups_name = "__local_fixups__";
531+ char *s, *e, *comp;
532+ int len;
533+
534+ /* fn is the node we're putting entries in */
535+ lfn = get_subnode(dt, local_fixups_name);
536+ /* if no node exists, create it */
537+ if (!lfn) {
538+ lfn = build_node(NULL, NULL);
539+ name_node(lfn, local_fixups_name);
540+ add_child(dt, lfn);
541+ }
542+
543+ /* walk the path components creating nodes if they don't exist */
544+ comp = NULL;
545+ /* start skipping the first / */
546+ s = node->fullpath + 1;
547+ wn = lfn;
548+ while (*s) {
549+ /* retrieve path component */
550+ e = strchr(s, '/');
551+ if (e == NULL)
552+ e = s + strlen(s);
553+ len = e - s;
554+ comp = xrealloc(comp, len + 1);
555+ memcpy(comp, s, len);
556+ comp[len] = '\0';
557+
558+ /* if no node exists, create it */
559+ nwn = get_subnode(wn, comp);
560+ if (!nwn) {
561+ nwn = build_node(NULL, NULL);
562+ name_node(nwn, strdup(comp));
563+ add_child(wn, nwn);
564+ }
565+ wn = nwn;
566+
567+ /* last path component */
568+ if (!*e)
569+ break;
570+
571+ /* next path component */
572+ s = e + 1;
573+ }
574+ free(comp);
575+
576+ p = get_property(wn, prop->name);
577+ d = data_append_cell(p ? p->val : empty_data, (cell_t)m->offset);
578+ if (!p)
579+ add_property(wn, build_property(prop->name, d));
580+ else
581+ p->val = d;
582+}
583+
584+void generate_fixups_node(struct node *node, struct node *dt)
585+{
586+ struct node *c;
587+ struct property *prop;
588+ struct marker *m;
589+ struct node *refnode;
590+
591+ for_each_property(node, prop) {
592+ m = prop->val.markers;
593+ for_each_marker_of_type(m, REF_PHANDLE) {
594+ refnode = get_node_by_ref(dt, m->ref);
595+ if (!refnode)
596+ add_fixup_entry(dt, node, prop, m);
597+ else
598+ add_local_fixup_entry(dt, node, prop, m,
599+ refnode);
600+ }
601+ }
602+
603+ for_each_child(node, c)
604+ generate_fixups_node(c, dt);
605+}
606diff --git a/treesource.c b/treesource.c
607index a55d1d1..e1d6657 100644
608--- a/treesource.c
609+++ b/treesource.c
610@@ -28,6 +28,9 @@ extern YYLTYPE yylloc;
611 struct boot_info *the_boot_info;
612 bool treesource_error;
613
614+bool source_is_plugin;
615+bool deprecated_plugin_syntax_warning;
616+
617 struct boot_info *dt_from_source(const char *fname)
618 {
619 the_boot_info = NULL;
620diff --git a/util.c b/util.c
621index 9d65226..cbb945b 100644
622--- a/util.c
623+++ b/util.c
624@@ -349,7 +349,6 @@ int utilfdt_decode_type(const char *fmt, int *type, int *size)
625 void utilfdt_print_data(const char *data, int len)
626 {
627 int i;
628- const char *p = data;
629 const char *s;
630
631 /* no data, don't print */
632@@ -376,6 +375,7 @@ void utilfdt_print_data(const char *data, int len)
633 i < (len - 1) ? " " : "");
634 printf(">");
635 } else {
636+ const unsigned char *p = (const unsigned char *)data;
637 printf(" = [");
638 for (i = 0; i < len; i++)
639 printf("%02x%s", *p++, i < len - 1 ? " " : "");
640--
6412.7.0
642