summaryrefslogtreecommitdiffstats
path: root/meta-ti-extras/recipes/dtc/dtc/0003-dtc-Plugin-and-fixup-support.patch
diff options
context:
space:
mode:
Diffstat (limited to 'meta-ti-extras/recipes/dtc/dtc/0003-dtc-Plugin-and-fixup-support.patch')
-rw-r--r--meta-ti-extras/recipes/dtc/dtc/0003-dtc-Plugin-and-fixup-support.patch635
1 files changed, 0 insertions, 635 deletions
diff --git a/meta-ti-extras/recipes/dtc/dtc/0003-dtc-Plugin-and-fixup-support.patch b/meta-ti-extras/recipes/dtc/dtc/0003-dtc-Plugin-and-fixup-support.patch
deleted file mode 100644
index 69451b8..0000000
--- a/meta-ti-extras/recipes/dtc/dtc/0003-dtc-Plugin-and-fixup-support.patch
+++ /dev/null
@@ -1,635 +0,0 @@
1From 10e5b09069bb7d5b9c4b1aced82b7b20cd06dd65 Mon Sep 17 00:00:00 2001
2From: Pantelis Antoniou <pantelis.antoniou@konsulko.com>
3Date: Tue, 21 Oct 2014 22:07:16 +0300
4Subject: [PATCH] dtc: Plugin and fixup support
5
6This patch enable the generation of symbols & local fixup information
7for trees compiled with the -@ (--symbols) option.
8
9Using this patch labels in the tree and their users emit information
10in __symbols__ and __local_fixups__ nodes.
11
12The __fixups__ node make possible the dynamic resolution of phandle
13references which are present in the plugin tree but lie in the
14tree that are applying the overlay against.
15
16Signed-off-by: Pantelis Antoniou <pantelis.antoniou@konsulko.com>
17Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
18Signed-off-by: Jan Luebbe <jlu@pengutronix.de>
19---
20 Documentation/manual.txt | 16 ++++
21 checks.c | 8 +-
22 dtc-lexer.l | 5 ++
23 dtc-parser.y | 45 ++++++++--
24 dtc.c | 23 +++++-
25 dtc.h | 29 ++++++-
26 flattree.c | 2 +-
27 fstree.c | 2 +-
28 livetree.c | 209 ++++++++++++++++++++++++++++++++++++++++++++++-
29 treesource.c | 1 +
30 10 files changed, 327 insertions(+), 13 deletions(-)
31
32diff --git a/Documentation/manual.txt b/Documentation/manual.txt
33index f64c4f4..63066ec 100644
34--- a/Documentation/manual.txt
35+++ b/Documentation/manual.txt
36@@ -126,6 +126,20 @@ Options:
37 Make space for <number> reserve map entries
38 Relevant for dtb and asm output only.
39
40+ -@
41+ Generates a __symbols__ node at the root node of the resulting blob
42+ for any node labels used, and for any local references using phandles
43+ it also generates a __local_fixups__ node that tracks them.
44+
45+ When using the /plugin/ tag all unresolved label references to
46+ be tracked in the __fixups__ node, making dynamic resolution possible.
47+
48+ -A
49+ Generate automatically aliases for all node labels. This is similar to
50+ the -@ option (the __symbols__ node contain identical information) but
51+ the semantics are slightly different since no phandles are automatically
52+ generated for labeled nodes.
53+
54 -S <bytes>
55 Ensure the blob at least <bytes> long, adding additional
56 space if needed.
57@@ -160,6 +174,8 @@ Here is a very rough overview of the layout of a DTS source file:
58
59 devicetree: '/' nodedef
60
61+ plugindecl: '/' 'plugin' '/' ';'
62+
63 nodedef: '{' list_of_property list_of_subnode '}' ';'
64
65 property: label PROPNAME '=' propdata ';'
66diff --git a/checks.c b/checks.c
67index 386f956..3d4c3c6 100644
68--- a/checks.c
69+++ b/checks.c
70@@ -490,8 +490,12 @@ static void fixup_phandle_references(struct check *c, struct node *dt,
71
72 refnode = get_node_by_ref(dt, m->ref);
73 if (! refnode) {
74- FAIL(c, "Reference to non-existent node or label \"%s\"\n",
75- m->ref);
76+ if (!(tree_get_versionflags(dt) & VF_PLUGIN))
77+ FAIL(c, "Reference to non-existent node or "
78+ "label \"%s\"\n", m->ref);
79+ else /* mark the entry as unresolved */
80+ *((cell_t *)(prop->val.val + m->offset)) =
81+ cpu_to_fdt32(0xffffffff);
82 continue;
83 }
84
85diff --git a/dtc-lexer.l b/dtc-lexer.l
86index 790fbf6..40bbc87 100644
87--- a/dtc-lexer.l
88+++ b/dtc-lexer.l
89@@ -121,6 +121,11 @@ static void lexical_error(const char *fmt, ...);
90 return DT_V1;
91 }
92
93+<*>"/plugin/" {
94+ DPRINT("Keyword: /plugin/\n");
95+ return DT_PLUGIN;
96+ }
97+
98 <*>"/memreserve/" {
99 DPRINT("Keyword: /memreserve/\n");
100 BEGIN_DEFAULT();
101diff --git a/dtc-parser.y b/dtc-parser.y
102index 000873f..2890c1c 100644
103--- a/dtc-parser.y
104+++ b/dtc-parser.y
105@@ -19,6 +19,7 @@
106 */
107 %{
108 #include <stdio.h>
109+#include <inttypes.h>
110
111 #include "dtc.h"
112 #include "srcpos.h"
113@@ -33,6 +34,7 @@ extern void yyerror(char const *s);
114
115 extern struct boot_info *the_boot_info;
116 extern bool treesource_error;
117+extern unsigned int the_versionflags;
118 %}
119
120 %union {
121@@ -52,9 +54,11 @@ extern bool treesource_error;
122 struct node *nodelist;
123 struct reserve_info *re;
124 uint64_t integer;
125+ unsigned int flags;
126 }
127
128 %token DT_V1
129+%token DT_PLUGIN
130 %token DT_MEMRESERVE
131 %token DT_LSHIFT DT_RSHIFT DT_LE DT_GE DT_EQ DT_NE DT_AND DT_OR
132 %token DT_BITS
133@@ -71,6 +75,8 @@ extern bool treesource_error;
134
135 %type <data> propdata
136 %type <data> propdataprefix
137+%type <flags> versioninfo
138+%type <flags> plugindecl
139 %type <re> memreserve
140 %type <re> memreserves
141 %type <array> arrayprefix
142@@ -101,13 +107,33 @@ extern bool treesource_error;
143 %%
144
145 sourcefile:
146- DT_V1 ';' memreserves devicetree
147+ versioninfo ';' memreserves devicetree
148 {
149- the_boot_info = build_boot_info($3, $4,
150+ the_boot_info = build_boot_info($1, $3, $4,
151 guess_boot_cpuid($4));
152 }
153 ;
154
155+versioninfo:
156+ DT_V1 plugindecl
157+ {
158+ the_versionflags |= VF_DT_V1 | $2;
159+ $$ = the_versionflags;
160+ }
161+ ;
162+
163+plugindecl:
164+ DT_PLUGIN
165+ {
166+ the_versionflags |= VF_PLUGIN;
167+ $$ = VF_PLUGIN;
168+ }
169+ | /* empty */
170+ {
171+ $$ = 0;
172+ }
173+ ;
174+
175 memreserves:
176 /* empty */
177 {
178@@ -156,10 +182,14 @@ devicetree:
179 {
180 struct node *target = get_node_by_ref($1, $2);
181
182- if (target)
183+ if (target) {
184 merge_nodes(target, $3);
185- else
186- ERROR(&@2, "Label or path %s not found", $2);
187+ } else {
188+ if (the_versionflags & VF_PLUGIN)
189+ add_orphan_node($1, $3, $2);
190+ else
191+ ERROR(&@2, "Label or path %s not found", $2);
192+ }
193 $$ = $1;
194 }
195 | devicetree DT_DEL_NODE DT_REF ';'
196@@ -174,6 +204,11 @@ devicetree:
197
198 $$ = $1;
199 }
200+ | /* empty */
201+ {
202+ /* build empty node */
203+ $$ = name_node(build_node(NULL, NULL), "");
204+ }
205 ;
206
207 nodedef:
208diff --git a/dtc.c b/dtc.c
209index 63c2c9c..a25f852 100644
210--- a/dtc.c
211+++ b/dtc.c
212@@ -31,6 +31,8 @@ int reservenum; /* Number of memory reservation slots */
213 int minsize; /* Minimum blob size */
214 int padsize; /* Additional padding to blob */
215 int phandle_format = PHANDLE_BOTH; /* Use linux,phandle or phandle properties */
216+int symbol_fixup_support;
217+int auto_label_aliases;
218
219 static void fill_fullpaths(struct node *tree, const char *prefix)
220 {
221@@ -53,7 +55,7 @@ static void fill_fullpaths(struct node *tree, const char *prefix)
222 #define FDT_VERSION(version) _FDT_VERSION(version)
223 #define _FDT_VERSION(version) #version
224 static const char usage_synopsis[] = "dtc [options] <input file>";
225-static const char usage_short_opts[] = "qI:O:o:V:d:R:S:p:fb:i:H:sW:E:hv";
226+static const char usage_short_opts[] = "qI:O:o:V:d:R:S:p:fb:i:H:sW:E:@Ahv";
227 static struct option const usage_long_opts[] = {
228 {"quiet", no_argument, NULL, 'q'},
229 {"in-format", a_argument, NULL, 'I'},
230@@ -71,6 +73,8 @@ static struct option const usage_long_opts[] = {
231 {"phandle", a_argument, NULL, 'H'},
232 {"warning", a_argument, NULL, 'W'},
233 {"error", a_argument, NULL, 'E'},
234+ {"symbols", no_argument, NULL, '@'},
235+ {"auto-alias", no_argument, NULL, 'A'},
236 {"help", no_argument, NULL, 'h'},
237 {"version", no_argument, NULL, 'v'},
238 {NULL, no_argument, NULL, 0x0},
239@@ -101,6 +105,8 @@ static const char * const usage_opts_help[] = {
240 "\t\tboth - Both \"linux,phandle\" and \"phandle\" properties",
241 "\n\tEnable/disable warnings (prefix with \"no-\")",
242 "\n\tEnable/disable errors (prefix with \"no-\")",
243+ "\n\tEnable symbols/fixup support",
244+ "\n\tEnable auto-alias of labels",
245 "\n\tPrint this help and exit",
246 "\n\tPrint version and exit",
247 NULL,
248@@ -237,7 +243,12 @@ int main(int argc, char *argv[])
249 case 'E':
250 parse_checks_option(false, true, optarg);
251 break;
252-
253+ case '@':
254+ symbol_fixup_support = 1;
255+ break;
256+ case 'A':
257+ auto_label_aliases = 1;
258+ break;
259 case 'h':
260 usage(NULL);
261 default:
262@@ -295,6 +306,14 @@ int main(int argc, char *argv[])
263 fill_fullpaths(bi->dt, "");
264 process_checks(force, bi);
265
266+ if (auto_label_aliases)
267+ generate_label_tree(bi->dt, "aliases", false);
268+
269+ if (symbol_fixup_support) {
270+ generate_label_tree(bi->dt, "__symbols__", true);
271+ generate_fixups_tree(bi->dt);
272+ }
273+
274 if (sort)
275 sort_tree(bi);
276
277diff --git a/dtc.h b/dtc.h
278index 9d7f2d6..392cde7 100644
279--- a/dtc.h
280+++ b/dtc.h
281@@ -54,6 +54,12 @@ extern int reservenum; /* Number of memory reservation slots */
282 extern int minsize; /* Minimum blob size */
283 extern int padsize; /* Additional padding to blob */
284 extern int phandle_format; /* Use linux,phandle or phandle properties */
285+extern int symbol_fixup_support;/* enable symbols & fixup support */
286+extern int auto_label_aliases; /* auto generate labels -> aliases */
287+
288+/*
289+ * Tree source globals
290+ */
291
292 #define PHANDLE_LEGACY 0x1
293 #define PHANDLE_EPAPR 0x2
294@@ -158,6 +164,9 @@ struct node {
295 int addr_cells, size_cells;
296
297 struct label *labels;
298+
299+ /* only for the root (parent == NULL) */
300+ struct boot_info *bi;
301 };
302
303 #define for_each_label_withdel(l0, l) \
304@@ -194,6 +203,7 @@ struct node *build_node_delete(void);
305 struct node *name_node(struct node *node, char *name);
306 struct node *chain_node(struct node *first, struct node *list);
307 struct node *merge_nodes(struct node *old_node, struct node *new_node);
308+void add_orphan_node(struct node *old_node, struct node *new_node, char *ref);
309
310 void add_property(struct node *node, struct property *prop);
311 void delete_property_by_name(struct node *node, char *name);
312@@ -201,6 +211,8 @@ void delete_property(struct property *prop);
313 void add_child(struct node *parent, struct node *child);
314 void delete_node_by_name(struct node *parent, char *name);
315 void delete_node(struct node *node);
316+struct property *append_to_property(struct node *node,
317+ char *name, const void *data, int len);
318
319 const char *get_unitname(struct node *node);
320 struct property *get_property(struct node *node, const char *propname);
321@@ -236,14 +248,29 @@ struct reserve_info *add_reserve_entry(struct reserve_info *list,
322
323
324 struct boot_info {
325+ unsigned int versionflags;
326 struct reserve_info *reservelist;
327 struct node *dt; /* the device tree */
328 uint32_t boot_cpuid_phys;
329 };
330
331-struct boot_info *build_boot_info(struct reserve_info *reservelist,
332+/* version flags definitions */
333+#define VF_DT_V1 0x0001 /* /dts-v1/ */
334+#define VF_PLUGIN 0x0002 /* /plugin/ */
335+
336+static inline unsigned int tree_get_versionflags(struct node *dt)
337+{
338+ if (!dt || !dt->bi)
339+ return 0;
340+ return dt->bi->versionflags;
341+}
342+
343+struct boot_info *build_boot_info(unsigned int versionflags,
344+ struct reserve_info *reservelist,
345 struct node *tree, uint32_t boot_cpuid_phys);
346 void sort_tree(struct boot_info *bi);
347+void generate_label_tree(struct node *dt, char *gen_node_name, bool allocph);
348+void generate_fixups_tree(struct node *dt);
349
350 /* Checks */
351
352diff --git a/flattree.c b/flattree.c
353index 64ed375..4fe64d4 100644
354--- a/flattree.c
355+++ b/flattree.c
356@@ -930,5 +930,5 @@ struct boot_info *dt_from_blob(const char *fname)
357
358 fclose(f);
359
360- return build_boot_info(reservelist, tree, boot_cpuid_phys);
361+ return build_boot_info(VF_DT_V1, reservelist, tree, boot_cpuid_phys);
362 }
363diff --git a/fstree.c b/fstree.c
364index 6d1beec..54f520b 100644
365--- a/fstree.c
366+++ b/fstree.c
367@@ -86,6 +86,6 @@ struct boot_info *dt_from_fs(const char *dirname)
368 tree = read_fstree(dirname);
369 tree = name_node(tree, "");
370
371- return build_boot_info(NULL, tree, guess_boot_cpuid(tree));
372+ return build_boot_info(VF_DT_V1, NULL, tree, guess_boot_cpuid(tree));
373 }
374
375diff --git a/livetree.c b/livetree.c
376index e229b84..3eab9e2 100644
377--- a/livetree.c
378+++ b/livetree.c
379@@ -216,6 +216,31 @@ struct node *merge_nodes(struct node *old_node, struct node *new_node)
380 return old_node;
381 }
382
383+void add_orphan_node(struct node *dt, struct node *new_node, char *ref)
384+{
385+ static unsigned int next_orphan_fragment = 0;
386+ struct node *node = xmalloc(sizeof(*node));
387+ struct property *p;
388+ struct data d = empty_data;
389+ char *name;
390+
391+ memset(node, 0, sizeof(*node));
392+
393+ d = data_add_marker(d, REF_PHANDLE, ref);
394+ d = data_append_integer(d, 0xffffffff, 32);
395+
396+ p = build_property("target", d);
397+ add_property(node, p);
398+
399+ xasprintf(&name, "fragment@%u",
400+ next_orphan_fragment++);
401+ name_node(node, name);
402+ name_node(new_node, "__overlay__");
403+
404+ add_child(dt, node);
405+ add_child(node, new_node);
406+}
407+
408 struct node *chain_node(struct node *first, struct node *list)
409 {
410 assert(first->next_sibling == NULL);
411@@ -296,6 +321,24 @@ void delete_node(struct node *node)
412 delete_labels(&node->labels);
413 }
414
415+struct property *append_to_property(struct node *node,
416+ char *name, const void *data, int len)
417+{
418+ struct data d;
419+ struct property *p;
420+
421+ p = get_property(node, name);
422+ if (p) {
423+ d = data_append_data(p->val, data, len);
424+ p->val = d;
425+ } else {
426+ d = data_append_data(empty_data, data, len);
427+ p = build_property(name, d);
428+ add_property(node, p);
429+ }
430+ return p;
431+}
432+
433 struct reserve_info *build_reserve_entry(uint64_t address, uint64_t size)
434 {
435 struct reserve_info *new = xmalloc(sizeof(*new));
436@@ -335,15 +378,19 @@ struct reserve_info *add_reserve_entry(struct reserve_info *list,
437 return list;
438 }
439
440-struct boot_info *build_boot_info(struct reserve_info *reservelist,
441+struct boot_info *build_boot_info(unsigned int versionflags,
442+ struct reserve_info *reservelist,
443 struct node *tree, uint32_t boot_cpuid_phys)
444 {
445 struct boot_info *bi;
446
447 bi = xmalloc(sizeof(*bi));
448+ bi->versionflags = versionflags;
449 bi->reservelist = reservelist;
450 bi->dt = tree;
451 bi->boot_cpuid_phys = boot_cpuid_phys;
452+ /* link back */
453+ tree->bi = bi;
454
455 return bi;
456 }
457@@ -709,3 +756,163 @@ void sort_tree(struct boot_info *bi)
458 sort_reserve_entries(bi);
459 sort_node(bi->dt);
460 }
461+
462+/* utility helper to avoid code duplication */
463+static struct node *build_and_name_child_node(struct node *parent, char *name)
464+{
465+ struct node *node;
466+
467+ node = build_node(NULL, NULL);
468+ name_node(node, xstrdup(name));
469+ add_child(parent, node);
470+
471+ return node;
472+}
473+
474+static void generate_label_tree_internal(struct node *dt, struct node *node,
475+ struct node *an, bool allocph)
476+{
477+ struct node *c;
478+ struct property *p;
479+ struct label *l;
480+
481+ /* if if there are labels */
482+ if (node->labels) {
483+ /* now add the label in the node */
484+ for_each_label(node->labels, l) {
485+ /* check whether the label already exists */
486+ p = get_property(an, l->label);
487+ if (p) {
488+ fprintf(stderr, "WARNING: label %s already"
489+ " exists in /%s", l->label,
490+ an->name);
491+ continue;
492+ }
493+
494+ /* insert it */
495+ p = build_property(l->label,
496+ data_copy_escape_string(node->fullpath,
497+ strlen(node->fullpath)));
498+ add_property(an, p);
499+ }
500+
501+ /* force allocation of a phandle for this node */
502+ if (allocph)
503+ (void)get_node_phandle(dt, node);
504+ }
505+
506+ for_each_child(node, c)
507+ generate_label_tree_internal(dt, c, an, allocph);
508+}
509+
510+void generate_label_tree(struct node *dt, char *gen_node_name, bool allocph)
511+{
512+ struct node *an;
513+
514+ an = build_and_name_child_node(dt, gen_node_name);
515+ if (!an)
516+ die("Could not build label node /%s\n", gen_node_name);
517+
518+ generate_label_tree_internal(dt, dt, an, allocph);
519+}
520+
521+static char *fixups_name = "__fixups__";
522+static char *local_fixups_name = "__local_fixups__";
523+
524+static void add_fixup_entry(struct node *dt, struct node *node,
525+ struct property *prop, struct marker *m)
526+{
527+ struct node *fn; /* fixup node */
528+ char *entry;
529+
530+ /* m->ref can only be a REF_PHANDLE, but check anyway */
531+ assert(m->type == REF_PHANDLE);
532+
533+ /* fn is the node we're putting entries in */
534+ fn = get_subnode(dt, fixups_name);
535+ assert(fn != NULL);
536+
537+ /* there shouldn't be any ':' in the arguments */
538+ if (strchr(node->fullpath, ':') || strchr(prop->name, ':'))
539+ die("arguments should not contain ':'\n");
540+
541+ xasprintf(&entry, "%s:%s:%u",
542+ node->fullpath, prop->name, m->offset);
543+ append_to_property(fn, m->ref, entry, strlen(entry) + 1);
544+}
545+
546+static void add_local_fixup_entry(struct node *dt, struct node *node,
547+ struct property *prop, struct marker *m,
548+ struct node *refnode)
549+{
550+ struct node *lfn, *wn, *nwn; /* local fixup node, walk node, new */
551+ uint32_t value_32;
552+ char *s, *e, *comp;
553+ int len;
554+
555+ /* fn is the node we're putting entries in */
556+ lfn = get_subnode(dt, local_fixups_name);
557+ assert(lfn != NULL);
558+
559+ /* walk the path components creating nodes if they don't exist */
560+ comp = xmalloc(strlen(node->fullpath) + 1);
561+ /* start skipping the first / */
562+ s = node->fullpath + 1;
563+ wn = lfn;
564+ while (*s) {
565+ /* retrieve path component */
566+ e = strchr(s, '/');
567+ if (e == NULL)
568+ e = s + strlen(s);
569+ len = e - s;
570+ memcpy(comp, s, len);
571+ comp[len] = '\0';
572+
573+ /* if no node exists, create it */
574+ nwn = get_subnode(wn, comp);
575+ if (!nwn)
576+ nwn = build_and_name_child_node(wn, comp);
577+ wn = nwn;
578+
579+ /* last path component */
580+ if (!*e)
581+ break;
582+
583+ /* next path component */
584+ s = e + 1;
585+ }
586+ free(comp);
587+
588+ value_32 = cpu_to_fdt32(m->offset);
589+ append_to_property(wn, prop->name, &value_32, sizeof(value_32));
590+}
591+
592+static void generate_fixups_tree_internal(struct node *dt, struct node *node)
593+{
594+ struct node *c;
595+ struct property *prop;
596+ struct marker *m;
597+ struct node *refnode;
598+
599+ for_each_property(node, prop) {
600+ m = prop->val.markers;
601+ for_each_marker_of_type(m, REF_PHANDLE) {
602+ refnode = get_node_by_ref(dt, m->ref);
603+ if (!refnode)
604+ add_fixup_entry(dt, node, prop, m);
605+ else
606+ add_local_fixup_entry(dt, node, prop, m,
607+ refnode);
608+ }
609+ }
610+
611+ for_each_child(node, c)
612+ generate_fixups_tree_internal(dt, c);
613+}
614+
615+void generate_fixups_tree(struct node *dt)
616+{
617+ build_and_name_child_node(dt, fixups_name);
618+ build_and_name_child_node(dt, local_fixups_name);
619+ generate_fixups_tree_internal(dt, dt);
620+}
621diff --git a/treesource.c b/treesource.c
622index a55d1d1..2539a57 100644
623--- a/treesource.c
624+++ b/treesource.c
625@@ -27,6 +27,7 @@ extern YYLTYPE yylloc;
626
627 struct boot_info *the_boot_info;
628 bool treesource_error;
629+unsigned int the_versionflags;
630
631 struct boot_info *dt_from_source(const char *fname)
632 {
633--
6341.9.1
635