1 /* $NetBSD: livetree.c,v 1.1.1.3 2019/12/22 12:34:03 skrll Exp $ */
2
3 // SPDX-License-Identifier: GPL-2.0-or-later
4 /*
5 * (C) Copyright David Gibson <dwg@au1.ibm.com>, IBM Corporation. 2005.
6 */
7
8 #include "dtc.h"
9 #include "srcpos.h"
10
11 /*
12 * Tree building functions
13 */
14
add_label(struct label ** labels,char * label)15 void add_label(struct label **labels, char *label)
16 {
17 struct label *new;
18
19 /* Make sure the label isn't already there */
20 for_each_label_withdel(*labels, new)
21 if (streq(new->label, label)) {
22 new->deleted = 0;
23 return;
24 }
25
26 new = xmalloc(sizeof(*new));
27 memset(new, 0, sizeof(*new));
28 new->label = label;
29 new->next = *labels;
30 *labels = new;
31 }
32
delete_labels(struct label ** labels)33 void delete_labels(struct label **labels)
34 {
35 struct label *label;
36
37 for_each_label(*labels, label)
38 label->deleted = 1;
39 }
40
build_property(char * name,struct data val,struct srcpos * srcpos)41 struct property *build_property(char *name, struct data val,
42 struct srcpos *srcpos)
43 {
44 struct property *new = xmalloc(sizeof(*new));
45
46 memset(new, 0, sizeof(*new));
47
48 new->name = name;
49 new->val = val;
50 new->srcpos = srcpos_copy(srcpos);
51
52 return new;
53 }
54
build_property_delete(char * name)55 struct property *build_property_delete(char *name)
56 {
57 struct property *new = xmalloc(sizeof(*new));
58
59 memset(new, 0, sizeof(*new));
60
61 new->name = name;
62 new->deleted = 1;
63
64 return new;
65 }
66
chain_property(struct property * first,struct property * list)67 struct property *chain_property(struct property *first, struct property *list)
68 {
69 assert(first->next == NULL);
70
71 first->next = list;
72 return first;
73 }
74
reverse_properties(struct property * first)75 struct property *reverse_properties(struct property *first)
76 {
77 struct property *p = first;
78 struct property *head = NULL;
79 struct property *next;
80
81 while (p) {
82 next = p->next;
83 p->next = head;
84 head = p;
85 p = next;
86 }
87 return head;
88 }
89
build_node(struct property * proplist,struct node * children,struct srcpos * srcpos)90 struct node *build_node(struct property *proplist, struct node *children,
91 struct srcpos *srcpos)
92 {
93 struct node *new = xmalloc(sizeof(*new));
94 struct node *child;
95
96 memset(new, 0, sizeof(*new));
97
98 new->proplist = reverse_properties(proplist);
99 new->children = children;
100 new->srcpos = srcpos_copy(srcpos);
101
102 for_each_child(new, child) {
103 child->parent = new;
104 }
105
106 return new;
107 }
108
build_node_delete(struct srcpos * srcpos)109 struct node *build_node_delete(struct srcpos *srcpos)
110 {
111 struct node *new = xmalloc(sizeof(*new));
112
113 memset(new, 0, sizeof(*new));
114
115 new->deleted = 1;
116 new->srcpos = srcpos_copy(srcpos);
117
118 return new;
119 }
120
name_node(struct node * node,char * name)121 struct node *name_node(struct node *node, char *name)
122 {
123 assert(node->name == NULL);
124
125 node->name = name;
126
127 return node;
128 }
129
omit_node_if_unused(struct node * node)130 struct node *omit_node_if_unused(struct node *node)
131 {
132 node->omit_if_unused = 1;
133
134 return node;
135 }
136
reference_node(struct node * node)137 struct node *reference_node(struct node *node)
138 {
139 node->is_referenced = 1;
140
141 return node;
142 }
143
merge_nodes(struct node * old_node,struct node * new_node)144 struct node *merge_nodes(struct node *old_node, struct node *new_node)
145 {
146 struct property *new_prop, *old_prop;
147 struct node *new_child, *old_child;
148 struct label *l;
149
150 old_node->deleted = 0;
151
152 /* Add new node labels to old node */
153 for_each_label_withdel(new_node->labels, l)
154 add_label(&old_node->labels, l->label);
155
156 /* Move properties from the new node to the old node. If there
157 * is a collision, replace the old value with the new */
158 while (new_node->proplist) {
159 /* Pop the property off the list */
160 new_prop = new_node->proplist;
161 new_node->proplist = new_prop->next;
162 new_prop->next = NULL;
163
164 if (new_prop->deleted) {
165 delete_property_by_name(old_node, new_prop->name);
166 free(new_prop);
167 continue;
168 }
169
170 /* Look for a collision, set new value if there is */
171 for_each_property_withdel(old_node, old_prop) {
172 if (streq(old_prop->name, new_prop->name)) {
173 /* Add new labels to old property */
174 for_each_label_withdel(new_prop->labels, l)
175 add_label(&old_prop->labels, l->label);
176
177 old_prop->val = new_prop->val;
178 old_prop->deleted = 0;
179 free(old_prop->srcpos);
180 old_prop->srcpos = new_prop->srcpos;
181 free(new_prop);
182 new_prop = NULL;
183 break;
184 }
185 }
186
187 /* if no collision occurred, add property to the old node. */
188 if (new_prop)
189 add_property(old_node, new_prop);
190 }
191
192 /* Move the override child nodes into the primary node. If
193 * there is a collision, then merge the nodes. */
194 while (new_node->children) {
195 /* Pop the child node off the list */
196 new_child = new_node->children;
197 new_node->children = new_child->next_sibling;
198 new_child->parent = NULL;
199 new_child->next_sibling = NULL;
200
201 if (new_child->deleted) {
202 delete_node_by_name(old_node, new_child->name);
203 free(new_child);
204 continue;
205 }
206
207 /* Search for a collision. Merge if there is */
208 for_each_child_withdel(old_node, old_child) {
209 if (streq(old_child->name, new_child->name)) {
210 merge_nodes(old_child, new_child);
211 new_child = NULL;
212 break;
213 }
214 }
215
216 /* if no collision occurred, add child to the old node. */
217 if (new_child)
218 add_child(old_node, new_child);
219 }
220
221 old_node->srcpos = srcpos_extend(old_node->srcpos, new_node->srcpos);
222
223 /* The new node contents are now merged into the old node. Free
224 * the new node. */
225 free(new_node);
226
227 return old_node;
228 }
229
add_orphan_node(struct node * dt,struct node * new_node,char * ref)230 struct node * add_orphan_node(struct node *dt, struct node *new_node, char *ref)
231 {
232 static unsigned int next_orphan_fragment = 0;
233 struct node *node;
234 struct property *p;
235 struct data d = empty_data;
236 char *name;
237
238 if (ref[0] == '/') {
239 d = data_add_marker(d, TYPE_STRING, ref);
240 d = data_append_data(d, ref, strlen(ref) + 1);
241
242 p = build_property("target-path", d, NULL);
243 } else {
244 d = data_add_marker(d, REF_PHANDLE, ref);
245 d = data_append_integer(d, 0xffffffff, 32);
246
247 p = build_property("target", d, NULL);
248 }
249
250 xasprintf(&name, "fragment@%u",
251 next_orphan_fragment++);
252 name_node(new_node, "__overlay__");
253 node = build_node(p, new_node, NULL);
254 name_node(node, name);
255
256 add_child(dt, node);
257 return dt;
258 }
259
chain_node(struct node * first,struct node * list)260 struct node *chain_node(struct node *first, struct node *list)
261 {
262 assert(first->next_sibling == NULL);
263
264 first->next_sibling = list;
265 return first;
266 }
267
add_property(struct node * node,struct property * prop)268 void add_property(struct node *node, struct property *prop)
269 {
270 struct property **p;
271
272 prop->next = NULL;
273
274 p = &node->proplist;
275 while (*p)
276 p = &((*p)->next);
277
278 *p = prop;
279 }
280
delete_property_by_name(struct node * node,char * name)281 void delete_property_by_name(struct node *node, char *name)
282 {
283 struct property *prop = node->proplist;
284
285 while (prop) {
286 if (streq(prop->name, name)) {
287 delete_property(prop);
288 return;
289 }
290 prop = prop->next;
291 }
292 }
293
delete_property(struct property * prop)294 void delete_property(struct property *prop)
295 {
296 prop->deleted = 1;
297 delete_labels(&prop->labels);
298 }
299
add_child(struct node * parent,struct node * child)300 void add_child(struct node *parent, struct node *child)
301 {
302 struct node **p;
303
304 child->next_sibling = NULL;
305 child->parent = parent;
306
307 p = &parent->children;
308 while (*p)
309 p = &((*p)->next_sibling);
310
311 *p = child;
312 }
313
delete_node_by_name(struct node * parent,char * name)314 void delete_node_by_name(struct node *parent, char *name)
315 {
316 struct node *node = parent->children;
317
318 while (node) {
319 if (streq(node->name, name)) {
320 delete_node(node);
321 return;
322 }
323 node = node->next_sibling;
324 }
325 }
326
delete_node(struct node * node)327 void delete_node(struct node *node)
328 {
329 struct property *prop;
330 struct node *child;
331
332 node->deleted = 1;
333 for_each_child(node, child)
334 delete_node(child);
335 for_each_property(node, prop)
336 delete_property(prop);
337 delete_labels(&node->labels);
338 }
339
append_to_property(struct node * node,char * name,const void * data,int len,enum markertype type)340 void append_to_property(struct node *node,
341 char *name, const void *data, int len,
342 enum markertype type)
343 {
344 struct data d;
345 struct property *p;
346
347 p = get_property(node, name);
348 if (p) {
349 d = data_add_marker(p->val, type, name);
350 d = data_append_data(d, data, len);
351 p->val = d;
352 } else {
353 d = data_add_marker(empty_data, type, name);
354 d = data_append_data(d, data, len);
355 p = build_property(name, d, NULL);
356 add_property(node, p);
357 }
358 }
359
build_reserve_entry(uint64_t address,uint64_t size)360 struct reserve_info *build_reserve_entry(uint64_t address, uint64_t size)
361 {
362 struct reserve_info *new = xmalloc(sizeof(*new));
363
364 memset(new, 0, sizeof(*new));
365
366 new->address = address;
367 new->size = size;
368
369 return new;
370 }
371
chain_reserve_entry(struct reserve_info * first,struct reserve_info * list)372 struct reserve_info *chain_reserve_entry(struct reserve_info *first,
373 struct reserve_info *list)
374 {
375 assert(first->next == NULL);
376
377 first->next = list;
378 return first;
379 }
380
add_reserve_entry(struct reserve_info * list,struct reserve_info * new)381 struct reserve_info *add_reserve_entry(struct reserve_info *list,
382 struct reserve_info *new)
383 {
384 struct reserve_info *last;
385
386 new->next = NULL;
387
388 if (! list)
389 return new;
390
391 for (last = list; last->next; last = last->next)
392 ;
393
394 last->next = new;
395
396 return list;
397 }
398
build_dt_info(unsigned int dtsflags,struct reserve_info * reservelist,struct node * tree,uint32_t boot_cpuid_phys)399 struct dt_info *build_dt_info(unsigned int dtsflags,
400 struct reserve_info *reservelist,
401 struct node *tree, uint32_t boot_cpuid_phys)
402 {
403 struct dt_info *dti;
404
405 dti = xmalloc(sizeof(*dti));
406 dti->dtsflags = dtsflags;
407 dti->reservelist = reservelist;
408 dti->dt = tree;
409 dti->boot_cpuid_phys = boot_cpuid_phys;
410
411 return dti;
412 }
413
414 /*
415 * Tree accessor functions
416 */
417
get_unitname(struct node * node)418 const char *get_unitname(struct node *node)
419 {
420 if (node->name[node->basenamelen] == '\0')
421 return "";
422 else
423 return node->name + node->basenamelen + 1;
424 }
425
get_property(struct node * node,const char * propname)426 struct property *get_property(struct node *node, const char *propname)
427 {
428 struct property *prop;
429
430 for_each_property(node, prop)
431 if (streq(prop->name, propname))
432 return prop;
433
434 return NULL;
435 }
436
propval_cell(struct property * prop)437 cell_t propval_cell(struct property *prop)
438 {
439 assert(prop->val.len == sizeof(cell_t));
440 return fdt32_to_cpu(*((fdt32_t *)prop->val.val));
441 }
442
propval_cell_n(struct property * prop,int n)443 cell_t propval_cell_n(struct property *prop, int n)
444 {
445 assert(prop->val.len / sizeof(cell_t) >= n);
446 return fdt32_to_cpu(*((fdt32_t *)prop->val.val + n));
447 }
448
get_property_by_label(struct node * tree,const char * label,struct node ** node)449 struct property *get_property_by_label(struct node *tree, const char *label,
450 struct node **node)
451 {
452 struct property *prop;
453 struct node *c;
454
455 *node = tree;
456
457 for_each_property(tree, prop) {
458 struct label *l;
459
460 for_each_label(prop->labels, l)
461 if (streq(l->label, label))
462 return prop;
463 }
464
465 for_each_child(tree, c) {
466 prop = get_property_by_label(c, label, node);
467 if (prop)
468 return prop;
469 }
470
471 *node = NULL;
472 return NULL;
473 }
474
get_marker_label(struct node * tree,const char * label,struct node ** node,struct property ** prop)475 struct marker *get_marker_label(struct node *tree, const char *label,
476 struct node **node, struct property **prop)
477 {
478 struct marker *m;
479 struct property *p;
480 struct node *c;
481
482 *node = tree;
483
484 for_each_property(tree, p) {
485 *prop = p;
486 m = p->val.markers;
487 for_each_marker_of_type(m, LABEL)
488 if (streq(m->ref, label))
489 return m;
490 }
491
492 for_each_child(tree, c) {
493 m = get_marker_label(c, label, node, prop);
494 if (m)
495 return m;
496 }
497
498 *prop = NULL;
499 *node = NULL;
500 return NULL;
501 }
502
get_subnode(struct node * node,const char * nodename)503 struct node *get_subnode(struct node *node, const char *nodename)
504 {
505 struct node *child;
506
507 for_each_child(node, child)
508 if (streq(child->name, nodename))
509 return child;
510
511 return NULL;
512 }
513
get_node_by_path(struct node * tree,const char * path)514 struct node *get_node_by_path(struct node *tree, const char *path)
515 {
516 const char *p;
517 struct node *child;
518
519 if (!path || ! (*path)) {
520 if (tree->deleted)
521 return NULL;
522 return tree;
523 }
524
525 while (path[0] == '/')
526 path++;
527
528 p = strchr(path, '/');
529
530 for_each_child(tree, child) {
531 if (p && strprefixeq(path, p - path, child->name))
532 return get_node_by_path(child, p+1);
533 else if (!p && streq(path, child->name))
534 return child;
535 }
536
537 return NULL;
538 }
539
get_node_by_label(struct node * tree,const char * label)540 struct node *get_node_by_label(struct node *tree, const char *label)
541 {
542 struct node *child, *node;
543 struct label *l;
544
545 assert(label && (strlen(label) > 0));
546
547 for_each_label(tree->labels, l)
548 if (streq(l->label, label))
549 return tree;
550
551 for_each_child(tree, child) {
552 node = get_node_by_label(child, label);
553 if (node)
554 return node;
555 }
556
557 return NULL;
558 }
559
get_node_by_phandle(struct node * tree,cell_t phandle)560 struct node *get_node_by_phandle(struct node *tree, cell_t phandle)
561 {
562 struct node *child, *node;
563
564 if ((phandle == 0) || (phandle == -1)) {
565 assert(generate_fixups);
566 return NULL;
567 }
568
569 if (tree->phandle == phandle) {
570 if (tree->deleted)
571 return NULL;
572 return tree;
573 }
574
575 for_each_child(tree, child) {
576 node = get_node_by_phandle(child, phandle);
577 if (node)
578 return node;
579 }
580
581 return NULL;
582 }
583
get_node_by_ref(struct node * tree,const char * ref)584 struct node *get_node_by_ref(struct node *tree, const char *ref)
585 {
586 if (streq(ref, "/"))
587 return tree;
588 else if (ref[0] == '/')
589 return get_node_by_path(tree, ref);
590 else
591 return get_node_by_label(tree, ref);
592 }
593
get_node_phandle(struct node * root,struct node * node)594 cell_t get_node_phandle(struct node *root, struct node *node)
595 {
596 static cell_t phandle = 1; /* FIXME: ick, static local */
597 struct data d = empty_data;
598
599 if ((node->phandle != 0) && (node->phandle != -1))
600 return node->phandle;
601
602 while (get_node_by_phandle(root, phandle))
603 phandle++;
604
605 node->phandle = phandle;
606
607 d = data_add_marker(d, TYPE_UINT32, NULL);
608 d = data_append_cell(d, phandle);
609
610 if (!get_property(node, "linux,phandle")
611 && (phandle_format & PHANDLE_LEGACY))
612 add_property(node, build_property("linux,phandle", d, NULL));
613
614 if (!get_property(node, "phandle")
615 && (phandle_format & PHANDLE_EPAPR))
616 add_property(node, build_property("phandle", d, NULL));
617
618 /* If the node *does* have a phandle property, we must
619 * be dealing with a self-referencing phandle, which will be
620 * fixed up momentarily in the caller */
621
622 return node->phandle;
623 }
624
guess_boot_cpuid(struct node * tree)625 uint32_t guess_boot_cpuid(struct node *tree)
626 {
627 struct node *cpus, *bootcpu;
628 struct property *reg;
629
630 cpus = get_node_by_path(tree, "/cpus");
631 if (!cpus)
632 return 0;
633
634
635 bootcpu = cpus->children;
636 if (!bootcpu)
637 return 0;
638
639 reg = get_property(bootcpu, "reg");
640 if (!reg || (reg->val.len != sizeof(uint32_t)))
641 return 0;
642
643 /* FIXME: Sanity check node? */
644
645 return propval_cell(reg);
646 }
647
cmp_reserve_info(const void * ax,const void * bx)648 static int cmp_reserve_info(const void *ax, const void *bx)
649 {
650 const struct reserve_info *a, *b;
651
652 a = *((const struct reserve_info * const *)ax);
653 b = *((const struct reserve_info * const *)bx);
654
655 if (a->address < b->address)
656 return -1;
657 else if (a->address > b->address)
658 return 1;
659 else if (a->size < b->size)
660 return -1;
661 else if (a->size > b->size)
662 return 1;
663 else
664 return 0;
665 }
666
sort_reserve_entries(struct dt_info * dti)667 static void sort_reserve_entries(struct dt_info *dti)
668 {
669 struct reserve_info *ri, **tbl;
670 int n = 0, i = 0;
671
672 for (ri = dti->reservelist;
673 ri;
674 ri = ri->next)
675 n++;
676
677 if (n == 0)
678 return;
679
680 tbl = xmalloc(n * sizeof(*tbl));
681
682 for (ri = dti->reservelist;
683 ri;
684 ri = ri->next)
685 tbl[i++] = ri;
686
687 qsort(tbl, n, sizeof(*tbl), cmp_reserve_info);
688
689 dti->reservelist = tbl[0];
690 for (i = 0; i < (n-1); i++)
691 tbl[i]->next = tbl[i+1];
692 tbl[n-1]->next = NULL;
693
694 free(tbl);
695 }
696
cmp_prop(const void * ax,const void * bx)697 static int cmp_prop(const void *ax, const void *bx)
698 {
699 const struct property *a, *b;
700
701 a = *((const struct property * const *)ax);
702 b = *((const struct property * const *)bx);
703
704 return strcmp(a->name, b->name);
705 }
706
sort_properties(struct node * node)707 static void sort_properties(struct node *node)
708 {
709 int n = 0, i = 0;
710 struct property *prop, **tbl;
711
712 for_each_property_withdel(node, prop)
713 n++;
714
715 if (n == 0)
716 return;
717
718 tbl = xmalloc(n * sizeof(*tbl));
719
720 for_each_property_withdel(node, prop)
721 tbl[i++] = prop;
722
723 qsort(tbl, n, sizeof(*tbl), cmp_prop);
724
725 node->proplist = tbl[0];
726 for (i = 0; i < (n-1); i++)
727 tbl[i]->next = tbl[i+1];
728 tbl[n-1]->next = NULL;
729
730 free(tbl);
731 }
732
cmp_subnode(const void * ax,const void * bx)733 static int cmp_subnode(const void *ax, const void *bx)
734 {
735 const struct node *a, *b;
736
737 a = *((const struct node * const *)ax);
738 b = *((const struct node * const *)bx);
739
740 return strcmp(a->name, b->name);
741 }
742
sort_subnodes(struct node * node)743 static void sort_subnodes(struct node *node)
744 {
745 int n = 0, i = 0;
746 struct node *subnode, **tbl;
747
748 for_each_child_withdel(node, subnode)
749 n++;
750
751 if (n == 0)
752 return;
753
754 tbl = xmalloc(n * sizeof(*tbl));
755
756 for_each_child_withdel(node, subnode)
757 tbl[i++] = subnode;
758
759 qsort(tbl, n, sizeof(*tbl), cmp_subnode);
760
761 node->children = tbl[0];
762 for (i = 0; i < (n-1); i++)
763 tbl[i]->next_sibling = tbl[i+1];
764 tbl[n-1]->next_sibling = NULL;
765
766 free(tbl);
767 }
768
sort_node(struct node * node)769 static void sort_node(struct node *node)
770 {
771 struct node *c;
772
773 sort_properties(node);
774 sort_subnodes(node);
775 for_each_child_withdel(node, c)
776 sort_node(c);
777 }
778
sort_tree(struct dt_info * dti)779 void sort_tree(struct dt_info *dti)
780 {
781 sort_reserve_entries(dti);
782 sort_node(dti->dt);
783 }
784
785 /* utility helper to avoid code duplication */
build_and_name_child_node(struct node * parent,char * name)786 static struct node *build_and_name_child_node(struct node *parent, char *name)
787 {
788 struct node *node;
789
790 node = build_node(NULL, NULL, NULL);
791 name_node(node, xstrdup(name));
792 add_child(parent, node);
793
794 return node;
795 }
796
build_root_node(struct node * dt,char * name)797 static struct node *build_root_node(struct node *dt, char *name)
798 {
799 struct node *an;
800
801 an = get_subnode(dt, name);
802 if (!an)
803 an = build_and_name_child_node(dt, name);
804
805 if (!an)
806 die("Could not build root node /%s\n", name);
807
808 return an;
809 }
810
any_label_tree(struct dt_info * dti,struct node * node)811 static bool any_label_tree(struct dt_info *dti, struct node *node)
812 {
813 struct node *c;
814
815 if (node->labels)
816 return true;
817
818 for_each_child(node, c)
819 if (any_label_tree(dti, c))
820 return true;
821
822 return false;
823 }
824
generate_label_tree_internal(struct dt_info * dti,struct node * an,struct node * node,bool allocph)825 static void generate_label_tree_internal(struct dt_info *dti,
826 struct node *an, struct node *node,
827 bool allocph)
828 {
829 struct node *dt = dti->dt;
830 struct node *c;
831 struct property *p;
832 struct label *l;
833
834 /* if there are labels */
835 if (node->labels) {
836
837 /* now add the label in the node */
838 for_each_label(node->labels, l) {
839
840 /* check whether the label already exists */
841 p = get_property(an, l->label);
842 if (p) {
843 fprintf(stderr, "WARNING: label %s already"
844 " exists in /%s", l->label,
845 an->name);
846 continue;
847 }
848
849 /* insert it */
850 p = build_property(l->label,
851 data_copy_escape_string(node->fullpath,
852 strlen(node->fullpath)),
853 NULL);
854 add_property(an, p);
855 }
856
857 /* force allocation of a phandle for this node */
858 if (allocph)
859 (void)get_node_phandle(dt, node);
860 }
861
862 for_each_child(node, c)
863 generate_label_tree_internal(dti, an, c, allocph);
864 }
865
any_fixup_tree(struct dt_info * dti,struct node * node)866 static bool any_fixup_tree(struct dt_info *dti, struct node *node)
867 {
868 struct node *c;
869 struct property *prop;
870 struct marker *m;
871
872 for_each_property(node, prop) {
873 m = prop->val.markers;
874 for_each_marker_of_type(m, REF_PHANDLE) {
875 if (!get_node_by_ref(dti->dt, m->ref))
876 return true;
877 }
878 }
879
880 for_each_child(node, c) {
881 if (any_fixup_tree(dti, c))
882 return true;
883 }
884
885 return false;
886 }
887
add_fixup_entry(struct dt_info * dti,struct node * fn,struct node * node,struct property * prop,struct marker * m)888 static void add_fixup_entry(struct dt_info *dti, struct node *fn,
889 struct node *node, struct property *prop,
890 struct marker *m)
891 {
892 char *entry;
893
894 /* m->ref can only be a REF_PHANDLE, but check anyway */
895 assert(m->type == REF_PHANDLE);
896
897 /* there shouldn't be any ':' in the arguments */
898 if (strchr(node->fullpath, ':') || strchr(prop->name, ':'))
899 die("arguments should not contain ':'\n");
900
901 xasprintf(&entry, "%s:%s:%u",
902 node->fullpath, prop->name, m->offset);
903 append_to_property(fn, m->ref, entry, strlen(entry) + 1, TYPE_STRING);
904
905 free(entry);
906 }
907
generate_fixups_tree_internal(struct dt_info * dti,struct node * fn,struct node * node)908 static void generate_fixups_tree_internal(struct dt_info *dti,
909 struct node *fn,
910 struct node *node)
911 {
912 struct node *dt = dti->dt;
913 struct node *c;
914 struct property *prop;
915 struct marker *m;
916 struct node *refnode;
917
918 for_each_property(node, prop) {
919 m = prop->val.markers;
920 for_each_marker_of_type(m, REF_PHANDLE) {
921 refnode = get_node_by_ref(dt, m->ref);
922 if (!refnode)
923 add_fixup_entry(dti, fn, node, prop, m);
924 }
925 }
926
927 for_each_child(node, c)
928 generate_fixups_tree_internal(dti, fn, c);
929 }
930
any_local_fixup_tree(struct dt_info * dti,struct node * node)931 static bool any_local_fixup_tree(struct dt_info *dti, struct node *node)
932 {
933 struct node *c;
934 struct property *prop;
935 struct marker *m;
936
937 for_each_property(node, prop) {
938 m = prop->val.markers;
939 for_each_marker_of_type(m, REF_PHANDLE) {
940 if (get_node_by_ref(dti->dt, m->ref))
941 return true;
942 }
943 }
944
945 for_each_child(node, c) {
946 if (any_local_fixup_tree(dti, c))
947 return true;
948 }
949
950 return false;
951 }
952
add_local_fixup_entry(struct dt_info * dti,struct node * lfn,struct node * node,struct property * prop,struct marker * m,struct node * refnode)953 static void add_local_fixup_entry(struct dt_info *dti,
954 struct node *lfn, struct node *node,
955 struct property *prop, struct marker *m,
956 struct node *refnode)
957 {
958 struct node *wn, *nwn; /* local fixup node, walk node, new */
959 fdt32_t value_32;
960 char **compp;
961 int i, depth;
962
963 /* walk back retrieving depth */
964 depth = 0;
965 for (wn = node; wn; wn = wn->parent)
966 depth++;
967
968 /* allocate name array */
969 compp = xmalloc(sizeof(*compp) * depth);
970
971 /* store names in the array */
972 for (wn = node, i = depth - 1; wn; wn = wn->parent, i--)
973 compp[i] = wn->name;
974
975 /* walk the path components creating nodes if they don't exist */
976 for (wn = lfn, i = 1; i < depth; i++, wn = nwn) {
977 /* if no node exists, create it */
978 nwn = get_subnode(wn, compp[i]);
979 if (!nwn)
980 nwn = build_and_name_child_node(wn, compp[i]);
981 }
982
983 free(compp);
984
985 value_32 = cpu_to_fdt32(m->offset);
986 append_to_property(wn, prop->name, &value_32, sizeof(value_32), TYPE_UINT32);
987 }
988
generate_local_fixups_tree_internal(struct dt_info * dti,struct node * lfn,struct node * node)989 static void generate_local_fixups_tree_internal(struct dt_info *dti,
990 struct node *lfn,
991 struct node *node)
992 {
993 struct node *dt = dti->dt;
994 struct node *c;
995 struct property *prop;
996 struct marker *m;
997 struct node *refnode;
998
999 for_each_property(node, prop) {
1000 m = prop->val.markers;
1001 for_each_marker_of_type(m, REF_PHANDLE) {
1002 refnode = get_node_by_ref(dt, m->ref);
1003 if (refnode)
1004 add_local_fixup_entry(dti, lfn, node, prop, m, refnode);
1005 }
1006 }
1007
1008 for_each_child(node, c)
1009 generate_local_fixups_tree_internal(dti, lfn, c);
1010 }
1011
generate_label_tree(struct dt_info * dti,char * name,bool allocph)1012 void generate_label_tree(struct dt_info *dti, char *name, bool allocph)
1013 {
1014 if (!any_label_tree(dti, dti->dt))
1015 return;
1016 generate_label_tree_internal(dti, build_root_node(dti->dt, name),
1017 dti->dt, allocph);
1018 }
1019
generate_fixups_tree(struct dt_info * dti,char * name)1020 void generate_fixups_tree(struct dt_info *dti, char *name)
1021 {
1022 if (!any_fixup_tree(dti, dti->dt))
1023 return;
1024 generate_fixups_tree_internal(dti, build_root_node(dti->dt, name),
1025 dti->dt);
1026 }
1027
generate_local_fixups_tree(struct dt_info * dti,char * name)1028 void generate_local_fixups_tree(struct dt_info *dti, char *name)
1029 {
1030 if (!any_local_fixup_tree(dti, dti->dt))
1031 return;
1032 generate_local_fixups_tree_internal(dti, build_root_node(dti->dt, name),
1033 dti->dt);
1034 }
1035