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 /*
10 * Tree building functions
11 */
12
add_label(struct label ** labels,char * label)13 void add_label(struct label **labels, char *label)
14 {
15 struct label *new;
16
17 /* Make sure the label isn't already there */
18 for_each_label_withdel(*labels, new)
19 if (streq(new->label, label)) {
20 new->deleted = 0;
21 return;
22 }
23
24 new = xmalloc(sizeof(*new));
25 memset(new, 0, sizeof(*new));
26 new->label = label;
27 new->next = *labels;
28 *labels = new;
29 }
30
delete_labels(struct label ** labels)31 void delete_labels(struct label **labels)
32 {
33 struct label *label;
34
35 for_each_label(*labels, label)
36 label->deleted = 1;
37 }
38
build_property(const char * name,struct data val,struct srcpos * srcpos)39 struct property *build_property(const char *name, struct data val,
40 struct srcpos *srcpos)
41 {
42 struct property *new = xmalloc(sizeof(*new));
43
44 memset(new, 0, sizeof(*new));
45
46 new->name = xstrdup(name);
47 new->val = val;
48 new->srcpos = srcpos_copy(srcpos);
49
50 return new;
51 }
52
build_property_delete(const char * name)53 struct property *build_property_delete(const char *name)
54 {
55 struct property *new = xmalloc(sizeof(*new));
56
57 memset(new, 0, sizeof(*new));
58
59 new->name = xstrdup(name);
60 new->deleted = 1;
61
62 return new;
63 }
64
chain_property(struct property * first,struct property * list)65 struct property *chain_property(struct property *first, struct property *list)
66 {
67 assert(first->next == NULL);
68
69 first->next = list;
70 return first;
71 }
72
reverse_properties(struct property * first)73 struct property *reverse_properties(struct property *first)
74 {
75 struct property *p = first;
76 struct property *head = NULL;
77 struct property *next;
78
79 while (p) {
80 next = p->next;
81 p->next = head;
82 head = p;
83 p = next;
84 }
85 return head;
86 }
87
build_node(struct property * proplist,struct node * children,struct srcpos * srcpos)88 struct node *build_node(struct property *proplist, struct node *children,
89 struct srcpos *srcpos)
90 {
91 struct node *new = xmalloc(sizeof(*new));
92 struct node *child;
93
94 memset(new, 0, sizeof(*new));
95
96 new->proplist = reverse_properties(proplist);
97 new->children = children;
98 new->srcpos = srcpos_copy(srcpos);
99
100 for_each_child(new, child) {
101 child->parent = new;
102 }
103
104 return new;
105 }
106
build_node_delete(struct srcpos * srcpos)107 struct node *build_node_delete(struct srcpos *srcpos)
108 {
109 struct node *new = xmalloc(sizeof(*new));
110
111 memset(new, 0, sizeof(*new));
112
113 new->deleted = 1;
114 new->srcpos = srcpos_copy(srcpos);
115
116 return new;
117 }
118
name_node(struct node * node,const char * name)119 struct node *name_node(struct node *node, const char *name)
120 {
121 assert(node->name == NULL);
122
123 node->name = xstrdup(name);
124
125 return node;
126 }
127
omit_node_if_unused(struct node * node)128 struct node *omit_node_if_unused(struct node *node)
129 {
130 node->omit_if_unused = 1;
131
132 return node;
133 }
134
reference_node(struct node * node)135 struct node *reference_node(struct node *node)
136 {
137 node->is_referenced = 1;
138
139 return node;
140 }
141
merge_nodes(struct node * old_node,struct node * new_node)142 struct node *merge_nodes(struct node *old_node, struct node *new_node)
143 {
144 struct property *new_prop, *old_prop;
145 struct node *new_child, *old_child;
146 struct label *l;
147
148 old_node->deleted = 0;
149
150 /* Add new node labels to old node */
151 for_each_label_withdel(new_node->labels, l)
152 add_label(&old_node->labels, l->label);
153
154 /* Move properties from the new node to the old node. If there
155 * is a collision, replace the old value with the new */
156 while (new_node->proplist) {
157 /* Pop the property off the list */
158 new_prop = new_node->proplist;
159 new_node->proplist = new_prop->next;
160 new_prop->next = NULL;
161
162 if (new_prop->deleted) {
163 delete_property_by_name(old_node, new_prop->name);
164 free(new_prop);
165 continue;
166 }
167
168 /* Look for a collision, set new value if there is */
169 for_each_property_withdel(old_node, old_prop) {
170 if (streq(old_prop->name, new_prop->name)) {
171 /* Add new labels to old property */
172 for_each_label_withdel(new_prop->labels, l)
173 add_label(&old_prop->labels, l->label);
174
175 old_prop->val = new_prop->val;
176 old_prop->deleted = 0;
177 srcpos_free(old_prop->srcpos);
178 old_prop->srcpos = new_prop->srcpos;
179 free(new_prop);
180 new_prop = NULL;
181 break;
182 }
183 }
184
185 /* if no collision occurred, add property to the old node. */
186 if (new_prop)
187 add_property(old_node, new_prop);
188 }
189
190 /* Move the override child nodes into the primary node. If
191 * there is a collision, then merge the nodes. */
192 while (new_node->children) {
193 /* Pop the child node off the list */
194 new_child = new_node->children;
195 new_node->children = new_child->next_sibling;
196 new_child->parent = NULL;
197 new_child->next_sibling = NULL;
198
199 if (new_child->deleted) {
200 delete_node_by_name(old_node, new_child->name);
201 free(new_child);
202 continue;
203 }
204
205 /* Search for a collision. Merge if there is */
206 for_each_child_withdel(old_node, old_child) {
207 if (streq(old_child->name, new_child->name)) {
208 merge_nodes(old_child, new_child);
209 new_child = NULL;
210 break;
211 }
212 }
213
214 /* if no collision occurred, add child to the old node. */
215 if (new_child)
216 add_child(old_node, new_child);
217 }
218
219 old_node->srcpos = srcpos_extend(old_node->srcpos, new_node->srcpos);
220
221 /* The new node contents are now merged into the old node. Free
222 * the new node. */
223 free(new_node);
224
225 return old_node;
226 }
227
add_orphan_node(struct node * dt,struct node * new_node,char * ref)228 struct node * add_orphan_node(struct node *dt, struct node *new_node, char *ref)
229 {
230 static unsigned int next_orphan_fragment = 0;
231 struct node *node;
232 struct property *p;
233 struct data d = empty_data;
234 char *name;
235
236 if (ref[0] == '/') {
237 d = data_add_marker(d, TYPE_STRING, ref);
238 d = data_append_data(d, ref, strlen(ref) + 1);
239
240 p = build_property("target-path", d, NULL);
241 } else {
242 d = data_add_marker(d, REF_PHANDLE, ref);
243 d = data_append_integer(d, 0xffffffff, 32);
244
245 p = build_property("target", d, NULL);
246 }
247
248 xasprintf(&name, "fragment@%u",
249 next_orphan_fragment++);
250 name_node(new_node, "__overlay__");
251 node = build_node(p, new_node, NULL);
252 name_node(node, name);
253 free(name);
254
255 add_child(dt, node);
256 return dt;
257 }
258
chain_node(struct node * first,struct node * list)259 struct node *chain_node(struct node *first, struct node *list)
260 {
261 assert(first->next_sibling == NULL);
262
263 first->next_sibling = list;
264 return first;
265 }
266
add_property(struct node * node,struct property * prop)267 void add_property(struct node *node, struct property *prop)
268 {
269 struct property **p;
270
271 prop->next = NULL;
272
273 p = &node->proplist;
274 while (*p)
275 p = &((*p)->next);
276
277 *p = prop;
278 }
279
delete_property_by_name(struct node * node,char * name)280 void delete_property_by_name(struct node *node, char *name)
281 {
282 struct property *prop = node->proplist;
283
284 while (prop) {
285 if (streq(prop->name, name)) {
286 delete_property(prop);
287 return;
288 }
289 prop = prop->next;
290 }
291 }
292
delete_property(struct property * prop)293 void delete_property(struct property *prop)
294 {
295 prop->deleted = 1;
296 delete_labels(&prop->labels);
297 }
298
add_child(struct node * parent,struct node * child)299 void add_child(struct node *parent, struct node *child)
300 {
301 struct node **p;
302
303 child->next_sibling = NULL;
304 child->parent = parent;
305
306 p = &parent->children;
307 while (*p)
308 p = &((*p)->next_sibling);
309
310 *p = child;
311 }
312
delete_node_by_name(struct node * parent,char * name)313 void delete_node_by_name(struct node *parent, char *name)
314 {
315 struct node *node = parent->children;
316
317 while (node) {
318 if (streq(node->name, name)) {
319 delete_node(node);
320 return;
321 }
322 node = node->next_sibling;
323 }
324 }
325
delete_node(struct node * node)326 void delete_node(struct node *node)
327 {
328 struct property *prop;
329 struct node *child;
330
331 node->deleted = 1;
332 for_each_child(node, child)
333 delete_node(child);
334 for_each_property(node, prop)
335 delete_property(prop);
336 delete_labels(&node->labels);
337 }
338
append_to_property(struct node * node,char * name,const void * data,int len,enum markertype type)339 void append_to_property(struct node *node,
340 char *name, const void *data, int len,
341 enum markertype type)
342 {
343 struct property *p;
344
345 p = get_property(node, name);
346 if (!p) {
347 p = build_property(name, empty_data, NULL);
348 add_property(node, p);
349 }
350
351 p->val = data_add_marker(p->val, type, name);
352 p->val = data_append_data(p->val, data, len);
353 }
354
append_unique_str_to_property(struct node * node,char * name,const char * data,int len)355 static int append_unique_str_to_property(struct node *node,
356 char *name, const char *data, int len)
357 {
358 struct property *p;
359
360 p = get_property(node, name);
361 if (p) {
362 const char *s;
363
364 if (p->val.len && p->val.val[p->val.len - 1] != '\0')
365 /* The current content doesn't look like a string */
366 return -1;
367
368 for (s = p->val.val; s < p->val.val + p->val.len; s = strchr(s, '\0') + 1) {
369 if (strcmp(data, s) == 0)
370 /* data already contained in node.name */
371 return 0;
372 }
373 } else {
374 p = build_property(name, empty_data, NULL);
375 add_property(node, p);
376 }
377
378 p->val = data_add_marker(p->val, TYPE_STRING, name);
379 p->val = data_append_data(p->val, data, len);
380
381 return 0;
382 }
383
append_unique_u32_to_property(struct node * node,char * name,fdt32_t value)384 static int append_unique_u32_to_property(struct node *node, char *name, fdt32_t value)
385 {
386 struct property *p;
387
388 p = get_property(node, name);
389 if (p) {
390 const fdt32_t *v, *val_end = (const fdt32_t *)p->val.val + p->val.len / 4;
391
392 if (p->val.len % 4 != 0)
393 /* The current content doesn't look like a u32 array */
394 return -1;
395
396 for (v = (const void *)p->val.val; v < val_end; v++) {
397 if (*v == value)
398 /* value already contained */
399 return 0;
400 }
401 } else {
402 p = build_property(name, empty_data, NULL);
403 add_property(node, p);
404 }
405
406 p->val = data_add_marker(p->val, TYPE_UINT32, name);
407 p->val = data_append_data(p->val, &value, 4);
408
409 return 0;
410 }
411
build_reserve_entry(uint64_t address,uint64_t size)412 struct reserve_info *build_reserve_entry(uint64_t address, uint64_t size)
413 {
414 struct reserve_info *new = xmalloc(sizeof(*new));
415
416 memset(new, 0, sizeof(*new));
417
418 new->address = address;
419 new->size = size;
420
421 return new;
422 }
423
chain_reserve_entry(struct reserve_info * first,struct reserve_info * list)424 struct reserve_info *chain_reserve_entry(struct reserve_info *first,
425 struct reserve_info *list)
426 {
427 assert(first->next == NULL);
428
429 first->next = list;
430 return first;
431 }
432
add_reserve_entry(struct reserve_info * list,struct reserve_info * new)433 struct reserve_info *add_reserve_entry(struct reserve_info *list,
434 struct reserve_info *new)
435 {
436 struct reserve_info *last;
437
438 new->next = NULL;
439
440 if (! list)
441 return new;
442
443 for (last = list; last->next; last = last->next)
444 ;
445
446 last->next = new;
447
448 return list;
449 }
450
build_dt_info(unsigned int dtsflags,struct reserve_info * reservelist,struct node * tree,uint32_t boot_cpuid_phys)451 struct dt_info *build_dt_info(unsigned int dtsflags,
452 struct reserve_info *reservelist,
453 struct node *tree, uint32_t boot_cpuid_phys)
454 {
455 struct dt_info *dti;
456
457 dti = xmalloc(sizeof(*dti));
458 dti->dtsflags = dtsflags;
459 dti->reservelist = reservelist;
460 dti->dt = tree;
461 dti->boot_cpuid_phys = boot_cpuid_phys;
462
463 return dti;
464 }
465
466 /*
467 * Tree accessor functions
468 */
469
get_unitname(struct node * node)470 const char *get_unitname(struct node *node)
471 {
472 if (node->name[node->basenamelen] == '\0')
473 return "";
474 else
475 return node->name + node->basenamelen + 1;
476 }
477
get_property(struct node * node,const char * propname)478 struct property *get_property(struct node *node, const char *propname)
479 {
480 struct property *prop;
481
482 for_each_property(node, prop)
483 if (streq(prop->name, propname))
484 return prop;
485
486 return NULL;
487 }
488
propval_cell(struct property * prop)489 cell_t propval_cell(struct property *prop)
490 {
491 assert(prop->val.len == sizeof(cell_t));
492 return fdt32_to_cpu(*((fdt32_t *)prop->val.val));
493 }
494
propval_cell_n(struct property * prop,unsigned int n)495 cell_t propval_cell_n(struct property *prop, unsigned int n)
496 {
497 assert(prop->val.len / sizeof(cell_t) > n);
498 return fdt32_to_cpu(*((fdt32_t *)prop->val.val + n));
499 }
500
get_property_by_label(struct node * tree,const char * label,struct node ** node)501 struct property *get_property_by_label(struct node *tree, const char *label,
502 struct node **node)
503 {
504 struct property *prop;
505 struct node *c;
506
507 *node = tree;
508
509 for_each_property(tree, prop) {
510 struct label *l;
511
512 for_each_label(prop->labels, l)
513 if (streq(l->label, label))
514 return prop;
515 }
516
517 for_each_child(tree, c) {
518 prop = get_property_by_label(c, label, node);
519 if (prop)
520 return prop;
521 }
522
523 *node = NULL;
524 return NULL;
525 }
526
get_marker_label(struct node * tree,const char * label,struct node ** node,struct property ** prop)527 struct marker *get_marker_label(struct node *tree, const char *label,
528 struct node **node, struct property **prop)
529 {
530 struct marker *m;
531 struct property *p;
532 struct node *c;
533
534 *node = tree;
535
536 for_each_property(tree, p) {
537 *prop = p;
538 m = p->val.markers;
539 for_each_marker_of_type(m, LABEL)
540 if (streq(m->ref, label))
541 return m;
542 }
543
544 for_each_child(tree, c) {
545 m = get_marker_label(c, label, node, prop);
546 if (m)
547 return m;
548 }
549
550 *prop = NULL;
551 *node = NULL;
552 return NULL;
553 }
554
get_subnode(struct node * node,const char * nodename)555 struct node *get_subnode(struct node *node, const char *nodename)
556 {
557 struct node *child;
558
559 for_each_child(node, child)
560 if (streq(child->name, nodename) && !child->deleted)
561 return child;
562
563 return NULL;
564 }
565
get_node_by_path(struct node * tree,const char * path)566 struct node *get_node_by_path(struct node *tree, const char *path)
567 {
568 const char *p;
569 struct node *child;
570
571 if (!path || ! (*path)) {
572 if (tree->deleted)
573 return NULL;
574 return tree;
575 }
576
577 while (path[0] == '/')
578 path++;
579
580 p = strchr(path, '/');
581
582 for_each_child(tree, child) {
583 if (p && strprefixeq(path, (size_t)(p - path), child->name))
584 return get_node_by_path(child, p+1);
585 else if (!p && streq(path, child->name))
586 return child;
587 }
588
589 return NULL;
590 }
591
get_node_by_label(struct node * tree,const char * label)592 struct node *get_node_by_label(struct node *tree, const char *label)
593 {
594 struct node *child, *node;
595 struct label *l;
596
597 assert(label && (strlen(label) > 0));
598
599 for_each_label(tree->labels, l)
600 if (streq(l->label, label))
601 return tree;
602
603 for_each_child(tree, child) {
604 node = get_node_by_label(child, label);
605 if (node)
606 return node;
607 }
608
609 return NULL;
610 }
611
get_node_by_phandle(struct node * tree,cell_t phandle)612 struct node *get_node_by_phandle(struct node *tree, cell_t phandle)
613 {
614 struct node *child, *node;
615
616 if (!phandle_is_valid(phandle)) {
617 assert(generate_fixups);
618 return NULL;
619 }
620
621 if (tree->phandle == phandle) {
622 if (tree->deleted)
623 return NULL;
624 return tree;
625 }
626
627 for_each_child(tree, child) {
628 node = get_node_by_phandle(child, phandle);
629 if (node)
630 return node;
631 }
632
633 return NULL;
634 }
635
get_node_by_ref(struct node * tree,const char * ref)636 struct node *get_node_by_ref(struct node *tree, const char *ref)
637 {
638 struct node *target = tree;
639 const char *label = NULL, *path = NULL;
640
641 if (streq(ref, "/"))
642 return tree;
643
644 if (ref[0] == '/')
645 path = ref;
646 else
647 label = ref;
648
649 if (label) {
650 const char *slash = strchr(label, '/');
651 char *buf = NULL;
652
653 if (slash) {
654 buf = xstrndup(label, slash - label);
655 label = buf;
656 path = slash + 1;
657 }
658
659 target = get_node_by_label(tree, label);
660
661 free(buf);
662
663 if (!target)
664 return NULL;
665 }
666
667 if (path)
668 target = get_node_by_path(target, path);
669
670 return target;
671 }
672
add_phandle_property(struct node * node,const char * name,int format)673 static void add_phandle_property(struct node *node,
674 const char *name, int format)
675 {
676 struct data d;
677
678 if (!(phandle_format & format))
679 return;
680 if (get_property(node, name))
681 return;
682
683 d = data_add_marker(empty_data, TYPE_UINT32, NULL);
684 d = data_append_cell(d, node->phandle);
685
686 add_property(node, build_property(name, d, NULL));
687 }
688
get_node_phandle(struct node * root,struct node * node)689 cell_t get_node_phandle(struct node *root, struct node *node)
690 {
691 static cell_t phandle = 1; /* FIXME: ick, static local */
692
693 if (phandle_is_valid(node->phandle))
694 return node->phandle;
695
696 while (get_node_by_phandle(root, phandle))
697 phandle++;
698
699 node->phandle = phandle;
700
701 add_phandle_property(node, "linux,phandle", PHANDLE_LEGACY);
702 add_phandle_property(node, "phandle", PHANDLE_EPAPR);
703
704 /* If the node *does* have a phandle property, we must
705 * be dealing with a self-referencing phandle, which will be
706 * fixed up momentarily in the caller */
707
708 return node->phandle;
709 }
710
guess_boot_cpuid(struct node * tree)711 uint32_t guess_boot_cpuid(struct node *tree)
712 {
713 struct node *cpus, *bootcpu;
714 struct property *reg;
715
716 cpus = get_node_by_path(tree, "/cpus");
717 if (!cpus)
718 return 0;
719
720
721 bootcpu = cpus->children;
722 if (!bootcpu)
723 return 0;
724
725 reg = get_property(bootcpu, "reg");
726 if (!reg || (reg->val.len != sizeof(uint32_t)))
727 return 0;
728
729 /* FIXME: Sanity check node? */
730
731 return propval_cell(reg);
732 }
733
cmp_reserve_info(const void * ax,const void * bx)734 static int cmp_reserve_info(const void *ax, const void *bx)
735 {
736 const struct reserve_info *a, *b;
737
738 a = *((const struct reserve_info * const *)ax);
739 b = *((const struct reserve_info * const *)bx);
740
741 if (a->address < b->address)
742 return -1;
743 else if (a->address > b->address)
744 return 1;
745 else if (a->size < b->size)
746 return -1;
747 else if (a->size > b->size)
748 return 1;
749 else
750 return 0;
751 }
752
sort_reserve_entries(struct dt_info * dti)753 static void sort_reserve_entries(struct dt_info *dti)
754 {
755 struct reserve_info *ri, **tbl;
756 int n = 0, i = 0;
757
758 for (ri = dti->reservelist;
759 ri;
760 ri = ri->next)
761 n++;
762
763 if (n == 0)
764 return;
765
766 tbl = xmalloc(n * sizeof(*tbl));
767
768 for (ri = dti->reservelist;
769 ri;
770 ri = ri->next)
771 tbl[i++] = ri;
772
773 qsort(tbl, n, sizeof(*tbl), cmp_reserve_info);
774
775 dti->reservelist = tbl[0];
776 for (i = 0; i < (n-1); i++)
777 tbl[i]->next = tbl[i+1];
778 tbl[n-1]->next = NULL;
779
780 free(tbl);
781 }
782
cmp_prop(const void * ax,const void * bx)783 static int cmp_prop(const void *ax, const void *bx)
784 {
785 const struct property *a, *b;
786
787 a = *((const struct property * const *)ax);
788 b = *((const struct property * const *)bx);
789
790 return strcmp(a->name, b->name);
791 }
792
sort_properties(struct node * node)793 static void sort_properties(struct node *node)
794 {
795 int n = 0, i = 0;
796 struct property *prop, **tbl;
797
798 for_each_property_withdel(node, prop)
799 n++;
800
801 if (n == 0)
802 return;
803
804 tbl = xmalloc(n * sizeof(*tbl));
805
806 for_each_property_withdel(node, prop)
807 tbl[i++] = prop;
808
809 qsort(tbl, n, sizeof(*tbl), cmp_prop);
810
811 node->proplist = tbl[0];
812 for (i = 0; i < (n-1); i++)
813 tbl[i]->next = tbl[i+1];
814 tbl[n-1]->next = NULL;
815
816 free(tbl);
817 }
818
cmp_subnode(const void * ax,const void * bx)819 static int cmp_subnode(const void *ax, const void *bx)
820 {
821 const struct node *a, *b;
822
823 a = *((const struct node * const *)ax);
824 b = *((const struct node * const *)bx);
825
826 return strcmp(a->name, b->name);
827 }
828
sort_subnodes(struct node * node)829 static void sort_subnodes(struct node *node)
830 {
831 int n = 0, i = 0;
832 struct node *subnode, **tbl;
833
834 for_each_child_withdel(node, subnode)
835 n++;
836
837 if (n == 0)
838 return;
839
840 tbl = xmalloc(n * sizeof(*tbl));
841
842 for_each_child_withdel(node, subnode)
843 tbl[i++] = subnode;
844
845 qsort(tbl, n, sizeof(*tbl), cmp_subnode);
846
847 node->children = tbl[0];
848 for (i = 0; i < (n-1); i++)
849 tbl[i]->next_sibling = tbl[i+1];
850 tbl[n-1]->next_sibling = NULL;
851
852 free(tbl);
853 }
854
sort_node(struct node * node)855 static void sort_node(struct node *node)
856 {
857 struct node *c;
858
859 sort_properties(node);
860 sort_subnodes(node);
861 for_each_child_withdel(node, c)
862 sort_node(c);
863 }
864
sort_tree(struct dt_info * dti)865 void sort_tree(struct dt_info *dti)
866 {
867 sort_reserve_entries(dti);
868 sort_node(dti->dt);
869 }
870
871 /* utility helper to avoid code duplication */
build_and_name_child_node(struct node * parent,const char * name)872 static struct node *build_and_name_child_node(struct node *parent, const char *name)
873 {
874 struct node *node;
875
876 node = build_node(NULL, NULL, NULL);
877 name_node(node, name);
878 add_child(parent, node);
879
880 return node;
881 }
882
build_root_node(struct node * dt,const char * name)883 static struct node *build_root_node(struct node *dt, const char *name)
884 {
885 struct node *an;
886
887 an = get_subnode(dt, name);
888 if (!an)
889 an = build_and_name_child_node(dt, name);
890
891 if (!an)
892 die("Could not build root node /%s\n", name);
893
894 return an;
895 }
896
any_label_tree(struct dt_info * dti,struct node * node)897 static bool any_label_tree(struct dt_info *dti, struct node *node)
898 {
899 struct node *c;
900
901 if (node->labels)
902 return true;
903
904 for_each_child(node, c)
905 if (any_label_tree(dti, c))
906 return true;
907
908 return false;
909 }
910
generate_label_tree_internal(struct dt_info * dti,struct node * an,struct node * node,bool allocph)911 static void generate_label_tree_internal(struct dt_info *dti,
912 struct node *an, struct node *node,
913 bool allocph)
914 {
915 struct node *dt = dti->dt;
916 struct node *c;
917 struct property *p;
918 struct label *l;
919
920 /* if there are labels */
921 if (node->labels) {
922
923 /* now add the label in the node */
924 for_each_label(node->labels, l) {
925
926 /* check whether the label already exists */
927 p = get_property(an, l->label);
928 if (p) {
929 fprintf(stderr, "WARNING: label %s already"
930 " exists in /%s", l->label,
931 an->name);
932 continue;
933 }
934
935 /* insert it */
936 p = build_property(l->label,
937 data_copy_escape_string(node->fullpath,
938 strlen(node->fullpath)),
939 NULL);
940 add_property(an, p);
941 }
942
943 /* force allocation of a phandle for this node */
944 if (allocph)
945 (void)get_node_phandle(dt, node);
946 }
947
948 for_each_child(node, c)
949 generate_label_tree_internal(dti, an, c, allocph);
950 }
951
any_fixup_tree(struct dt_info * dti,struct node * node)952 static bool any_fixup_tree(struct dt_info *dti, struct node *node)
953 {
954 struct node *c;
955 struct property *prop;
956 struct marker *m;
957
958 for_each_property(node, prop) {
959 m = prop->val.markers;
960 for_each_marker_of_type(m, REF_PHANDLE) {
961 if (!get_node_by_ref(dti->dt, m->ref))
962 return true;
963 }
964 }
965
966 for_each_child(node, c) {
967 if (any_fixup_tree(dti, c))
968 return true;
969 }
970
971 return false;
972 }
973
add_fixup_entry(struct dt_info * dti,struct node * fn,struct node * node,struct property * prop,struct marker * m)974 static int add_fixup_entry(struct dt_info *dti, struct node *fn,
975 struct node *node, struct property *prop,
976 struct marker *m)
977 {
978 char *entry;
979 int ret;
980
981 /* m->ref can only be a REF_PHANDLE, but check anyway */
982 assert(m->type == REF_PHANDLE);
983
984 /* The format only permits fixups for references to label, not
985 * references to path */
986 if (strchr(m->ref, '/'))
987 die("Can't generate fixup for reference to path &{%s}\n",
988 m->ref);
989
990 /* there shouldn't be any ':' in the arguments */
991 if (strchr(node->fullpath, ':') || strchr(prop->name, ':'))
992 die("arguments should not contain ':'\n");
993
994 xasprintf(&entry, "%s:%s:%u",
995 node->fullpath, prop->name, m->offset);
996 ret = append_unique_str_to_property(fn, m->ref, entry, strlen(entry) + 1);
997
998 free(entry);
999
1000 return ret;
1001 }
1002
generate_fixups_tree_internal(struct dt_info * dti,struct node * fn,struct node * node)1003 static int generate_fixups_tree_internal(struct dt_info *dti,
1004 struct node *fn,
1005 struct node *node)
1006 {
1007 struct node *dt = dti->dt;
1008 struct node *c;
1009 struct property *prop;
1010 struct marker *m;
1011 struct node *refnode;
1012 int ret = 0;
1013
1014 for_each_property(node, prop) {
1015 m = prop->val.markers;
1016 for_each_marker_of_type(m, REF_PHANDLE) {
1017 refnode = get_node_by_ref(dt, m->ref);
1018 if (!refnode)
1019 if (add_fixup_entry(dti, fn, node, prop, m))
1020 ret = -1;
1021 }
1022 }
1023
1024 for_each_child(node, c)
1025 if (generate_fixups_tree_internal(dti, fn, c))
1026 ret = -1;
1027
1028 return ret;
1029 }
1030
any_local_fixup_tree(struct dt_info * dti,struct node * node)1031 static bool any_local_fixup_tree(struct dt_info *dti, struct node *node)
1032 {
1033 struct node *c;
1034 struct property *prop;
1035 struct marker *m;
1036
1037 for_each_property(node, prop) {
1038 m = prop->val.markers;
1039 for_each_marker_of_type(m, REF_PHANDLE) {
1040 if (get_node_by_ref(dti->dt, m->ref))
1041 return true;
1042 }
1043 }
1044
1045 for_each_child(node, c) {
1046 if (any_local_fixup_tree(dti, c))
1047 return true;
1048 }
1049
1050 return false;
1051 }
1052
add_local_fixup_entry(struct dt_info * dti,struct node * lfn,struct node * node,struct property * prop,struct marker * m,struct node * refnode)1053 static int add_local_fixup_entry(struct dt_info *dti,
1054 struct node *lfn, struct node *node,
1055 struct property *prop, struct marker *m,
1056 struct node *refnode)
1057 {
1058 struct node *wn, *nwn; /* local fixup node, walk node, new */
1059 fdt32_t value_32;
1060 char **compp;
1061 int i, depth;
1062
1063 /* walk back retrieving depth */
1064 depth = 0;
1065 for (wn = node; wn; wn = wn->parent)
1066 depth++;
1067
1068 /* allocate name array */
1069 compp = xmalloc(sizeof(*compp) * depth);
1070
1071 /* store names in the array */
1072 for (wn = node, i = depth - 1; wn; wn = wn->parent, i--)
1073 compp[i] = wn->name;
1074
1075 /* walk the path components creating nodes if they don't exist */
1076 for (wn = lfn, i = 1; i < depth; i++, wn = nwn) {
1077 /* if no node exists, create it */
1078 nwn = build_root_node(wn, compp[i]);
1079 }
1080
1081 free(compp);
1082
1083 value_32 = cpu_to_fdt32(m->offset);
1084 return append_unique_u32_to_property(wn, prop->name, value_32);
1085 }
1086
generate_local_fixups_tree_internal(struct dt_info * dti,struct node * lfn,struct node * node)1087 static int generate_local_fixups_tree_internal(struct dt_info *dti,
1088 struct node *lfn,
1089 struct node *node)
1090 {
1091 struct node *dt = dti->dt;
1092 struct node *c;
1093 struct property *prop;
1094 struct marker *m;
1095 struct node *refnode;
1096 int ret = 0;
1097
1098 for_each_property(node, prop) {
1099 m = prop->val.markers;
1100 for_each_marker_of_type(m, REF_PHANDLE) {
1101 refnode = get_node_by_ref(dt, m->ref);
1102 if (refnode)
1103 if (add_local_fixup_entry(dti, lfn, node, prop, m, refnode))
1104 ret = -1;
1105 }
1106 }
1107
1108 for_each_child(node, c)
1109 if (generate_local_fixups_tree_internal(dti, lfn, c))
1110 ret = -1;
1111
1112 return ret;
1113 }
1114
generate_labels_from_tree(struct dt_info * dti,const char * name)1115 void generate_labels_from_tree(struct dt_info *dti, const char *name)
1116 {
1117 struct node *an;
1118 struct property *p;
1119
1120 an = get_subnode(dti->dt, name);
1121 if (!an)
1122 return;
1123
1124 for_each_property(an, p) {
1125 struct node *labeled_node;
1126
1127 labeled_node = get_node_by_path(dti->dt, p->val.val);
1128 if (labeled_node)
1129 add_label(&labeled_node->labels, p->name);
1130 else if (quiet < 1)
1131 fprintf(stderr, "Warning: Path %s referenced in property %s/%s missing",
1132 p->val.val, name, p->name);
1133 }
1134 }
1135
generate_label_tree(struct dt_info * dti,const char * name,bool allocph)1136 void generate_label_tree(struct dt_info *dti, const char *name, bool allocph)
1137 {
1138 if (!any_label_tree(dti, dti->dt))
1139 return;
1140 generate_label_tree_internal(dti, build_root_node(dti->dt, name),
1141 dti->dt, allocph);
1142 }
1143
generate_fixups_tree(struct dt_info * dti,const char * name)1144 void generate_fixups_tree(struct dt_info *dti, const char *name)
1145 {
1146 if (!any_fixup_tree(dti, dti->dt))
1147 return;
1148 if (generate_fixups_tree_internal(dti, build_root_node(dti->dt, name), dti->dt))
1149 fprintf(stderr,
1150 "Warning: Preexisting data in %s malformed, some content could not be added.\n",
1151 name);
1152 }
1153
fixup_phandles(struct dt_info * dti,const char * name)1154 void fixup_phandles(struct dt_info *dti, const char *name)
1155 {
1156 struct node *an;
1157 struct property *fp;
1158
1159 an = get_subnode(dti->dt, name);
1160 if (!an)
1161 return;
1162
1163 for_each_property(an, fp) {
1164 char *fnext = fp->val.val;
1165 char *fv;
1166 unsigned int fl;
1167
1168 while ((fl = fp->val.len - (fnext - fp->val.val))) {
1169 char *propname, *soffset;
1170 struct node *n;
1171 struct property *p;
1172 long offset;
1173
1174 fv = fnext;
1175 fnext = memchr(fv, 0, fl);
1176
1177 if (!fnext) {
1178 if (quiet < 1)
1179 fprintf(stderr, "Warning: Malformed fixup entry for label %s\n",
1180 fp->name);
1181 break;
1182 }
1183 fnext += 1;
1184
1185 propname = memchr(fv, ':', fnext - 1 - fv);
1186 if (!propname) {
1187 if (quiet < 1)
1188 fprintf(stderr, "Warning: Malformed fixup entry for label %s\n",
1189 fp->name);
1190 continue;
1191 }
1192 propname++;
1193
1194 soffset = memchr(propname, ':', fnext - 1 - propname);
1195 if (!soffset) {
1196 if (quiet < 1)
1197 fprintf(stderr, "Warning: Malformed fixup entry for label %s\n",
1198 fp->name);
1199 continue;
1200 }
1201 soffset++;
1202
1203 /*
1204 * temporarily modify the property to not have to create
1205 * a copy for the node path.
1206 */
1207 *(propname - 1) = '\0';
1208
1209 n = get_node_by_path(dti->dt, fv);
1210 if (!n && quiet < 1)
1211 fprintf(stderr, "Warning: Label %s references non-existing node %s\n",
1212 fp->name, fv);
1213
1214 *(propname - 1) = ':';
1215
1216 if (!n)
1217 continue;
1218
1219 /*
1220 * temporarily modify the property to not have to create
1221 * a copy for the property name.
1222 */
1223 *(soffset - 1) = '\0';
1224
1225 p = get_property(n, propname);
1226
1227 if (!p && quiet < 1)
1228 fprintf(stderr, "Warning: Label %s references non-existing property %s in node %s\n",
1229 fp->name, n->fullpath, propname);
1230
1231 *(soffset - 1) = ':';
1232
1233 if (!p)
1234 continue;
1235
1236 offset = strtol(soffset, NULL, 0);
1237 if (offset < 0 || offset + 4 > p->val.len) {
1238 if (quiet < 1)
1239 fprintf(stderr,
1240 "Warning: Label %s contains invalid offset for property %s in node %s\n",
1241 fp->name, p->name, n->fullpath);
1242 continue;
1243 }
1244
1245 property_add_marker(p, REF_PHANDLE, offset, fp->name);
1246 }
1247 }
1248 }
1249
generate_local_fixups_tree(struct dt_info * dti,const char * name)1250 void generate_local_fixups_tree(struct dt_info *dti, const char *name)
1251 {
1252 if (!any_local_fixup_tree(dti, dti->dt))
1253 return;
1254 if (generate_local_fixups_tree_internal(dti, build_root_node(dti->dt, name), dti->dt))
1255 fprintf(stderr,
1256 "Warning: Preexisting data in %s malformed, some content could not be added.\n",
1257 name);
1258 }
1259
local_fixup_phandles_node(struct dt_info * dti,struct node * lf,struct node * n)1260 static void local_fixup_phandles_node(struct dt_info *dti, struct node *lf, struct node *n)
1261 {
1262 struct property *lfp;
1263 struct node *lfsubnode;
1264
1265 for_each_property(lf, lfp) {
1266 struct property *p = get_property(n, lfp->name);
1267 fdt32_t *offsets = (fdt32_t *)lfp->val.val;
1268 size_t i;
1269
1270 if (!p) {
1271 if (quiet < 1)
1272 fprintf(stderr, "Warning: Property %s in %s referenced in __local_fixups__ missing\n",
1273 lfp->name, n->fullpath);
1274 continue;
1275 }
1276
1277 /*
1278 * Each property in the __local_fixups__ tree is a concatenation
1279 * of offsets, so it must be a multiple of sizeof(fdt32_t).
1280 */
1281 if (lfp->val.len % sizeof(fdt32_t)) {
1282 if (quiet < 1)
1283 fprintf(stderr, "Warning: property %s in /__local_fixups__%s malformed\n",
1284 lfp->name, n->fullpath);
1285 continue;
1286 }
1287
1288 for (i = 0; i < lfp->val.len / sizeof(fdt32_t); i++)
1289 add_phandle_marker(dti, p, dtb_ld32(offsets + i));
1290 }
1291
1292 for_each_child(lf, lfsubnode) {
1293 struct node *subnode = get_subnode(n, lfsubnode->name);
1294
1295 if (!subnode) {
1296 if (quiet < 1)
1297 fprintf(stderr, "Warning: node %s/%s referenced in __local_fixups__ missing\n",
1298 lfsubnode->name, n->fullpath);
1299 continue;
1300 }
1301
1302 local_fixup_phandles_node(dti, lfsubnode, subnode);
1303 }
1304 }
1305
local_fixup_phandles(struct dt_info * dti,const char * name)1306 void local_fixup_phandles(struct dt_info *dti, const char *name)
1307 {
1308 struct node *an;
1309
1310 an = get_subnode(dti->dt, name);
1311 if (!an)
1312 return;
1313
1314 local_fixup_phandles_node(dti, an, dti->dt);
1315 }
1316