diff options
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.patch | 635 |
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 @@ | |||
1 | From 10e5b09069bb7d5b9c4b1aced82b7b20cd06dd65 Mon Sep 17 00:00:00 2001 | ||
2 | From: Pantelis Antoniou <pantelis.antoniou@konsulko.com> | ||
3 | Date: Tue, 21 Oct 2014 22:07:16 +0300 | ||
4 | Subject: [PATCH] dtc: Plugin and fixup support | ||
5 | |||
6 | This patch enable the generation of symbols & local fixup information | ||
7 | for trees compiled with the -@ (--symbols) option. | ||
8 | |||
9 | Using this patch labels in the tree and their users emit information | ||
10 | in __symbols__ and __local_fixups__ nodes. | ||
11 | |||
12 | The __fixups__ node make possible the dynamic resolution of phandle | ||
13 | references which are present in the plugin tree but lie in the | ||
14 | tree that are applying the overlay against. | ||
15 | |||
16 | Signed-off-by: Pantelis Antoniou <pantelis.antoniou@konsulko.com> | ||
17 | Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de> | ||
18 | Signed-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 | |||
32 | diff --git a/Documentation/manual.txt b/Documentation/manual.txt | ||
33 | index 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 ';' | ||
66 | diff --git a/checks.c b/checks.c | ||
67 | index 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 | |||
85 | diff --git a/dtc-lexer.l b/dtc-lexer.l | ||
86 | index 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(); | ||
101 | diff --git a/dtc-parser.y b/dtc-parser.y | ||
102 | index 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: | ||
208 | diff --git a/dtc.c b/dtc.c | ||
209 | index 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 | |||
277 | diff --git a/dtc.h b/dtc.h | ||
278 | index 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 | |||
352 | diff --git a/flattree.c b/flattree.c | ||
353 | index 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 | } | ||
363 | diff --git a/fstree.c b/fstree.c | ||
364 | index 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 | |||
375 | diff --git a/livetree.c b/livetree.c | ||
376 | index 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 | +} | ||
621 | diff --git a/treesource.c b/treesource.c | ||
622 | index 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 | -- | ||
634 | 1.9.1 | ||
635 | |||