1 // SPDX-License-Identifier: GPL-2.0-or-later
3 * (C) Copyright David Gibson <dwg@au1.ibm.com>, IBM Corporation. 2005.
10 * Tree building functions
13 void add_label(struct label
**labels
, char *label
)
17 /* Make sure the label isn't already there */
18 for_each_label_withdel(*labels
, new)
19 if (streq(new->label
, label
)) {
24 new = xmalloc(sizeof(*new));
25 memset(new, 0, sizeof(*new));
31 void delete_labels(struct label
**labels
)
35 for_each_label(*labels
, label
)
39 struct property
*build_property(const char *name
, struct data val
,
40 struct srcpos
*srcpos
)
42 struct property
*new = xmalloc(sizeof(*new));
44 memset(new, 0, sizeof(*new));
46 new->name
= xstrdup(name
);
48 new->srcpos
= srcpos_copy(srcpos
);
53 struct property
*build_property_delete(const char *name
)
55 struct property
*new = xmalloc(sizeof(*new));
57 memset(new, 0, sizeof(*new));
59 new->name
= xstrdup(name
);
65 struct property
*chain_property(struct property
*first
, struct property
*list
)
67 assert(first
->next
== NULL
);
73 struct property
*reverse_properties(struct property
*first
)
75 struct property
*p
= first
;
76 struct property
*head
= NULL
;
77 struct property
*next
;
88 struct node
*build_node(struct property
*proplist
, struct node
*children
,
89 struct srcpos
*srcpos
)
91 struct node
*new = xmalloc(sizeof(*new));
94 memset(new, 0, sizeof(*new));
96 new->proplist
= reverse_properties(proplist
);
97 new->children
= children
;
98 new->srcpos
= srcpos_copy(srcpos
);
100 for_each_child(new, child
) {
107 struct node
*build_node_delete(struct srcpos
*srcpos
)
109 struct node
*new = xmalloc(sizeof(*new));
111 memset(new, 0, sizeof(*new));
114 new->srcpos
= srcpos_copy(srcpos
);
119 struct node
*name_node(struct node
*node
, const char *name
)
121 assert(node
->name
== NULL
);
123 node
->name
= xstrdup(name
);
128 struct node
*omit_node_if_unused(struct node
*node
)
130 node
->omit_if_unused
= 1;
135 struct node
*reference_node(struct node
*node
)
137 node
->is_referenced
= 1;
142 struct node
*merge_nodes(struct node
*old_node
, struct node
*new_node
)
144 struct property
*new_prop
, *old_prop
;
145 struct node
*new_child
, *old_child
;
148 old_node
->deleted
= 0;
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
);
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
;
162 if (new_prop
->deleted
) {
163 delete_property_by_name(old_node
, new_prop
->name
);
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
);
175 old_prop
->val
= new_prop
->val
;
176 old_prop
->deleted
= 0;
177 free(old_prop
->srcpos
);
178 old_prop
->srcpos
= new_prop
->srcpos
;
185 /* if no collision occurred, add property to the old node. */
187 add_property(old_node
, new_prop
);
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
;
199 if (new_child
->deleted
) {
200 delete_node_by_name(old_node
, new_child
->name
);
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
);
214 /* if no collision occurred, add child to the old node. */
216 add_child(old_node
, new_child
);
219 old_node
->srcpos
= srcpos_extend(old_node
->srcpos
, new_node
->srcpos
);
221 /* The new node contents are now merged into the old node. Free
228 struct node
* add_orphan_node(struct node
*dt
, struct node
*new_node
, char *ref
)
230 static unsigned int next_orphan_fragment
= 0;
233 struct data d
= empty_data
;
237 d
= data_add_marker(d
, TYPE_STRING
, ref
);
238 d
= data_append_data(d
, ref
, strlen(ref
) + 1);
240 p
= build_property("target-path", d
, NULL
);
242 d
= data_add_marker(d
, REF_PHANDLE
, ref
);
243 d
= data_append_integer(d
, 0xffffffff, 32);
245 p
= build_property("target", d
, NULL
);
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
);
259 struct node
*chain_node(struct node
*first
, struct node
*list
)
261 assert(first
->next_sibling
== NULL
);
263 first
->next_sibling
= list
;
267 void add_property(struct node
*node
, struct property
*prop
)
280 void delete_property_by_name(struct node
*node
, char *name
)
282 struct property
*prop
= node
->proplist
;
285 if (streq(prop
->name
, name
)) {
286 delete_property(prop
);
293 void delete_property(struct property
*prop
)
296 delete_labels(&prop
->labels
);
299 void add_child(struct node
*parent
, struct node
*child
)
303 child
->next_sibling
= NULL
;
304 child
->parent
= parent
;
306 p
= &parent
->children
;
308 p
= &((*p
)->next_sibling
);
313 void delete_node_by_name(struct node
*parent
, char *name
)
315 struct node
*node
= parent
->children
;
318 if (streq(node
->name
, name
)) {
322 node
= node
->next_sibling
;
326 void delete_node(struct node
*node
)
328 struct property
*prop
;
332 for_each_child(node
, child
)
334 for_each_property(node
, prop
)
335 delete_property(prop
);
336 delete_labels(&node
->labels
);
339 void append_to_property(struct node
*node
,
340 char *name
, const void *data
, int len
,
341 enum markertype type
)
346 p
= get_property(node
, name
);
348 d
= data_add_marker(p
->val
, type
, name
);
349 d
= data_append_data(d
, data
, len
);
352 d
= data_add_marker(empty_data
, type
, name
);
353 d
= data_append_data(d
, data
, len
);
354 p
= build_property(name
, d
, NULL
);
355 add_property(node
, p
);
359 struct reserve_info
*build_reserve_entry(uint64_t address
, uint64_t size
)
361 struct reserve_info
*new = xmalloc(sizeof(*new));
363 memset(new, 0, sizeof(*new));
365 new->address
= address
;
371 struct reserve_info
*chain_reserve_entry(struct reserve_info
*first
,
372 struct reserve_info
*list
)
374 assert(first
->next
== NULL
);
380 struct reserve_info
*add_reserve_entry(struct reserve_info
*list
,
381 struct reserve_info
*new)
383 struct reserve_info
*last
;
390 for (last
= list
; last
->next
; last
= last
->next
)
398 struct dt_info
*build_dt_info(unsigned int dtsflags
,
399 struct reserve_info
*reservelist
,
400 struct node
*tree
, uint32_t boot_cpuid_phys
)
404 dti
= xmalloc(sizeof(*dti
));
405 dti
->dtsflags
= dtsflags
;
406 dti
->reservelist
= reservelist
;
408 dti
->boot_cpuid_phys
= boot_cpuid_phys
;
414 * Tree accessor functions
417 const char *get_unitname(struct node
*node
)
419 if (node
->name
[node
->basenamelen
] == '\0')
422 return node
->name
+ node
->basenamelen
+ 1;
425 struct property
*get_property(struct node
*node
, const char *propname
)
427 struct property
*prop
;
429 for_each_property(node
, prop
)
430 if (streq(prop
->name
, propname
))
436 cell_t
propval_cell(struct property
*prop
)
438 assert(prop
->val
.len
== sizeof(cell_t
));
439 return fdt32_to_cpu(*((fdt32_t
*)prop
->val
.val
));
442 cell_t
propval_cell_n(struct property
*prop
, unsigned int n
)
444 assert(prop
->val
.len
/ sizeof(cell_t
) > n
);
445 return fdt32_to_cpu(*((fdt32_t
*)prop
->val
.val
+ n
));
448 struct property
*get_property_by_label(struct node
*tree
, const char *label
,
451 struct property
*prop
;
456 for_each_property(tree
, prop
) {
459 for_each_label(prop
->labels
, l
)
460 if (streq(l
->label
, label
))
464 for_each_child(tree
, c
) {
465 prop
= get_property_by_label(c
, label
, node
);
474 struct marker
*get_marker_label(struct node
*tree
, const char *label
,
475 struct node
**node
, struct property
**prop
)
483 for_each_property(tree
, p
) {
486 for_each_marker_of_type(m
, LABEL
)
487 if (streq(m
->ref
, label
))
491 for_each_child(tree
, c
) {
492 m
= get_marker_label(c
, label
, node
, prop
);
502 struct node
*get_subnode(struct node
*node
, const char *nodename
)
506 for_each_child(node
, child
)
507 if (streq(child
->name
, nodename
))
513 struct node
*get_node_by_path(struct node
*tree
, const char *path
)
518 if (!path
|| ! (*path
)) {
524 while (path
[0] == '/')
527 p
= strchr(path
, '/');
529 for_each_child(tree
, child
) {
530 if (p
&& strprefixeq(path
, (size_t)(p
- path
), child
->name
))
531 return get_node_by_path(child
, p
+1);
532 else if (!p
&& streq(path
, child
->name
))
539 struct node
*get_node_by_label(struct node
*tree
, const char *label
)
541 struct node
*child
, *node
;
544 assert(label
&& (strlen(label
) > 0));
546 for_each_label(tree
->labels
, l
)
547 if (streq(l
->label
, label
))
550 for_each_child(tree
, child
) {
551 node
= get_node_by_label(child
, label
);
559 struct node
*get_node_by_phandle(struct node
*tree
, cell_t phandle
)
561 struct node
*child
, *node
;
563 if (!phandle_is_valid(phandle
)) {
564 assert(generate_fixups
);
568 if (tree
->phandle
== phandle
) {
574 for_each_child(tree
, child
) {
575 node
= get_node_by_phandle(child
, phandle
);
583 struct node
*get_node_by_ref(struct node
*tree
, const char *ref
)
585 struct node
*target
= tree
;
586 const char *label
= NULL
, *path
= NULL
;
597 const char *slash
= strchr(label
, '/');
601 buf
= xstrndup(label
, slash
- label
);
606 target
= get_node_by_label(tree
, label
);
615 target
= get_node_by_path(target
, path
);
620 static void add_phandle_property(struct node
*node
,
621 const char *name
, int format
)
625 if (!(phandle_format
& format
))
627 if (get_property(node
, name
))
630 d
= data_add_marker(empty_data
, TYPE_UINT32
, NULL
);
631 d
= data_append_cell(d
, node
->phandle
);
633 add_property(node
, build_property(name
, d
, NULL
));
636 cell_t
get_node_phandle(struct node
*root
, struct node
*node
)
638 static cell_t phandle
= 1; /* FIXME: ick, static local */
640 if (phandle_is_valid(node
->phandle
))
641 return node
->phandle
;
643 while (get_node_by_phandle(root
, phandle
))
646 node
->phandle
= phandle
;
648 add_phandle_property(node
, "linux,phandle", PHANDLE_LEGACY
);
649 add_phandle_property(node
, "phandle", PHANDLE_EPAPR
);
651 /* If the node *does* have a phandle property, we must
652 * be dealing with a self-referencing phandle, which will be
653 * fixed up momentarily in the caller */
655 return node
->phandle
;
658 uint32_t guess_boot_cpuid(struct node
*tree
)
660 struct node
*cpus
, *bootcpu
;
661 struct property
*reg
;
663 cpus
= get_node_by_path(tree
, "/cpus");
668 bootcpu
= cpus
->children
;
672 reg
= get_property(bootcpu
, "reg");
673 if (!reg
|| (reg
->val
.len
!= sizeof(uint32_t)))
676 /* FIXME: Sanity check node? */
678 return propval_cell(reg
);
681 static int cmp_reserve_info(const void *ax
, const void *bx
)
683 const struct reserve_info
*a
, *b
;
685 a
= *((const struct reserve_info
* const *)ax
);
686 b
= *((const struct reserve_info
* const *)bx
);
688 if (a
->address
< b
->address
)
690 else if (a
->address
> b
->address
)
692 else if (a
->size
< b
->size
)
694 else if (a
->size
> b
->size
)
700 static void sort_reserve_entries(struct dt_info
*dti
)
702 struct reserve_info
*ri
, **tbl
;
705 for (ri
= dti
->reservelist
;
713 tbl
= xmalloc(n
* sizeof(*tbl
));
715 for (ri
= dti
->reservelist
;
720 qsort(tbl
, n
, sizeof(*tbl
), cmp_reserve_info
);
722 dti
->reservelist
= tbl
[0];
723 for (i
= 0; i
< (n
-1); i
++)
724 tbl
[i
]->next
= tbl
[i
+1];
725 tbl
[n
-1]->next
= NULL
;
730 static int cmp_prop(const void *ax
, const void *bx
)
732 const struct property
*a
, *b
;
734 a
= *((const struct property
* const *)ax
);
735 b
= *((const struct property
* const *)bx
);
737 return strcmp(a
->name
, b
->name
);
740 static void sort_properties(struct node
*node
)
743 struct property
*prop
, **tbl
;
745 for_each_property_withdel(node
, prop
)
751 tbl
= xmalloc(n
* sizeof(*tbl
));
753 for_each_property_withdel(node
, prop
)
756 qsort(tbl
, n
, sizeof(*tbl
), cmp_prop
);
758 node
->proplist
= tbl
[0];
759 for (i
= 0; i
< (n
-1); i
++)
760 tbl
[i
]->next
= tbl
[i
+1];
761 tbl
[n
-1]->next
= NULL
;
766 static int cmp_subnode(const void *ax
, const void *bx
)
768 const struct node
*a
, *b
;
770 a
= *((const struct node
* const *)ax
);
771 b
= *((const struct node
* const *)bx
);
773 return strcmp(a
->name
, b
->name
);
776 static void sort_subnodes(struct node
*node
)
779 struct node
*subnode
, **tbl
;
781 for_each_child_withdel(node
, subnode
)
787 tbl
= xmalloc(n
* sizeof(*tbl
));
789 for_each_child_withdel(node
, subnode
)
792 qsort(tbl
, n
, sizeof(*tbl
), cmp_subnode
);
794 node
->children
= tbl
[0];
795 for (i
= 0; i
< (n
-1); i
++)
796 tbl
[i
]->next_sibling
= tbl
[i
+1];
797 tbl
[n
-1]->next_sibling
= NULL
;
802 static void sort_node(struct node
*node
)
806 sort_properties(node
);
808 for_each_child_withdel(node
, c
)
812 void sort_tree(struct dt_info
*dti
)
814 sort_reserve_entries(dti
);
818 /* utility helper to avoid code duplication */
819 static struct node
*build_and_name_child_node(struct node
*parent
, const char *name
)
823 node
= build_node(NULL
, NULL
, NULL
);
824 name_node(node
, name
);
825 add_child(parent
, node
);
830 static struct node
*build_root_node(struct node
*dt
, const char *name
)
834 an
= get_subnode(dt
, name
);
836 an
= build_and_name_child_node(dt
, name
);
839 die("Could not build root node /%s\n", name
);
844 static bool any_label_tree(struct dt_info
*dti
, struct node
*node
)
851 for_each_child(node
, c
)
852 if (any_label_tree(dti
, c
))
858 static void generate_label_tree_internal(struct dt_info
*dti
,
859 struct node
*an
, struct node
*node
,
862 struct node
*dt
= dti
->dt
;
867 /* if there are labels */
870 /* now add the label in the node */
871 for_each_label(node
->labels
, l
) {
873 /* check whether the label already exists */
874 p
= get_property(an
, l
->label
);
876 fprintf(stderr
, "WARNING: label %s already"
877 " exists in /%s", l
->label
,
883 p
= build_property(l
->label
,
884 data_copy_escape_string(node
->fullpath
,
885 strlen(node
->fullpath
)),
890 /* force allocation of a phandle for this node */
892 (void)get_node_phandle(dt
, node
);
895 for_each_child(node
, c
)
896 generate_label_tree_internal(dti
, an
, c
, allocph
);
899 static bool any_fixup_tree(struct dt_info
*dti
, struct node
*node
)
902 struct property
*prop
;
905 for_each_property(node
, prop
) {
906 m
= prop
->val
.markers
;
907 for_each_marker_of_type(m
, REF_PHANDLE
) {
908 if (!get_node_by_ref(dti
->dt
, m
->ref
))
913 for_each_child(node
, c
) {
914 if (any_fixup_tree(dti
, c
))
921 static void add_fixup_entry(struct dt_info
*dti
, struct node
*fn
,
922 struct node
*node
, struct property
*prop
,
927 /* m->ref can only be a REF_PHANDLE, but check anyway */
928 assert(m
->type
== REF_PHANDLE
);
930 /* The format only permits fixups for references to label, not
931 * references to path */
932 if (strchr(m
->ref
, '/'))
933 die("Can't generate fixup for reference to path &{%s}\n",
936 /* there shouldn't be any ':' in the arguments */
937 if (strchr(node
->fullpath
, ':') || strchr(prop
->name
, ':'))
938 die("arguments should not contain ':'\n");
940 xasprintf(&entry
, "%s:%s:%u",
941 node
->fullpath
, prop
->name
, m
->offset
);
942 append_to_property(fn
, m
->ref
, entry
, strlen(entry
) + 1, TYPE_STRING
);
947 static void generate_fixups_tree_internal(struct dt_info
*dti
,
951 struct node
*dt
= dti
->dt
;
953 struct property
*prop
;
955 struct node
*refnode
;
957 for_each_property(node
, prop
) {
958 m
= prop
->val
.markers
;
959 for_each_marker_of_type(m
, REF_PHANDLE
) {
960 refnode
= get_node_by_ref(dt
, m
->ref
);
962 add_fixup_entry(dti
, fn
, node
, prop
, m
);
966 for_each_child(node
, c
)
967 generate_fixups_tree_internal(dti
, fn
, c
);
970 static bool any_local_fixup_tree(struct dt_info
*dti
, struct node
*node
)
973 struct property
*prop
;
976 for_each_property(node
, prop
) {
977 m
= prop
->val
.markers
;
978 for_each_marker_of_type(m
, REF_PHANDLE
) {
979 if (get_node_by_ref(dti
->dt
, m
->ref
))
984 for_each_child(node
, c
) {
985 if (any_local_fixup_tree(dti
, c
))
992 static void add_local_fixup_entry(struct dt_info
*dti
,
993 struct node
*lfn
, struct node
*node
,
994 struct property
*prop
, struct marker
*m
,
995 struct node
*refnode
)
997 struct node
*wn
, *nwn
; /* local fixup node, walk node, new */
1002 /* walk back retrieving depth */
1004 for (wn
= node
; wn
; wn
= wn
->parent
)
1007 /* allocate name array */
1008 compp
= xmalloc(sizeof(*compp
) * depth
);
1010 /* store names in the array */
1011 for (wn
= node
, i
= depth
- 1; wn
; wn
= wn
->parent
, i
--)
1012 compp
[i
] = wn
->name
;
1014 /* walk the path components creating nodes if they don't exist */
1015 for (wn
= lfn
, i
= 1; i
< depth
; i
++, wn
= nwn
) {
1016 /* if no node exists, create it */
1017 nwn
= get_subnode(wn
, compp
[i
]);
1019 nwn
= build_and_name_child_node(wn
, compp
[i
]);
1024 value_32
= cpu_to_fdt32(m
->offset
);
1025 append_to_property(wn
, prop
->name
, &value_32
, sizeof(value_32
), TYPE_UINT32
);
1028 static void generate_local_fixups_tree_internal(struct dt_info
*dti
,
1032 struct node
*dt
= dti
->dt
;
1034 struct property
*prop
;
1036 struct node
*refnode
;
1038 for_each_property(node
, prop
) {
1039 m
= prop
->val
.markers
;
1040 for_each_marker_of_type(m
, REF_PHANDLE
) {
1041 refnode
= get_node_by_ref(dt
, m
->ref
);
1043 add_local_fixup_entry(dti
, lfn
, node
, prop
, m
, refnode
);
1047 for_each_child(node
, c
)
1048 generate_local_fixups_tree_internal(dti
, lfn
, c
);
1051 void generate_label_tree(struct dt_info
*dti
, const char *name
, bool allocph
)
1053 if (!any_label_tree(dti
, dti
->dt
))
1055 generate_label_tree_internal(dti
, build_root_node(dti
->dt
, name
),
1059 void generate_fixups_tree(struct dt_info
*dti
, const char *name
)
1061 if (!any_fixup_tree(dti
, dti
->dt
))
1063 generate_fixups_tree_internal(dti
, build_root_node(dti
->dt
, name
),
1067 void generate_local_fixups_tree(struct dt_info
*dti
, const char *name
)
1069 if (!any_local_fixup_tree(dti
, dti
->dt
))
1071 generate_local_fixups_tree_internal(dti
, build_root_node(dti
->dt
, name
),