2 * (C) Copyright David Gibson <dwg@au1.ibm.com>, IBM Corporation. 2005.
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License as
7 * published by the Free Software Foundation; either version 2 of the
8 * License, or (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
25 * Tree building functions
28 void add_label(struct label
**labels
, char *label
)
32 /* Make sure the label isn't already there */
33 for_each_label_withdel(*labels
, new)
34 if (streq(new->label
, label
)) {
39 new = xmalloc(sizeof(*new));
40 memset(new, 0, sizeof(*new));
46 void delete_labels(struct label
**labels
)
50 for_each_label(*labels
, label
)
54 struct property
*build_property(char *name
, struct data val
,
55 struct srcpos
*srcpos
)
57 struct property
*new = xmalloc(sizeof(*new));
59 memset(new, 0, sizeof(*new));
63 new->srcpos
= srcpos_copy(srcpos
);
68 struct property
*build_property_delete(char *name
)
70 struct property
*new = xmalloc(sizeof(*new));
72 memset(new, 0, sizeof(*new));
80 struct property
*chain_property(struct property
*first
, struct property
*list
)
82 assert(first
->next
== NULL
);
88 struct property
*reverse_properties(struct property
*first
)
90 struct property
*p
= first
;
91 struct property
*head
= NULL
;
92 struct property
*next
;
103 struct node
*build_node(struct property
*proplist
, struct node
*children
,
104 struct srcpos
*srcpos
)
106 struct node
*new = xmalloc(sizeof(*new));
109 memset(new, 0, sizeof(*new));
111 new->proplist
= reverse_properties(proplist
);
112 new->children
= children
;
113 new->srcpos
= srcpos_copy(srcpos
);
115 for_each_child(new, child
) {
122 struct node
*build_node_delete(struct srcpos
*srcpos
)
124 struct node
*new = xmalloc(sizeof(*new));
126 memset(new, 0, sizeof(*new));
129 new->srcpos
= srcpos_copy(srcpos
);
134 struct node
*name_node(struct node
*node
, char *name
)
136 assert(node
->name
== NULL
);
143 struct node
*omit_node_if_unused(struct node
*node
)
145 node
->omit_if_unused
= 1;
150 struct node
*reference_node(struct node
*node
)
152 node
->is_referenced
= 1;
157 struct node
*merge_nodes(struct node
*old_node
, struct node
*new_node
)
159 struct property
*new_prop
, *old_prop
;
160 struct node
*new_child
, *old_child
;
163 old_node
->deleted
= 0;
165 /* Add new node labels to old node */
166 for_each_label_withdel(new_node
->labels
, l
)
167 add_label(&old_node
->labels
, l
->label
);
169 /* Move properties from the new node to the old node. If there
170 * is a collision, replace the old value with the new */
171 while (new_node
->proplist
) {
172 /* Pop the property off the list */
173 new_prop
= new_node
->proplist
;
174 new_node
->proplist
= new_prop
->next
;
175 new_prop
->next
= NULL
;
177 if (new_prop
->deleted
) {
178 delete_property_by_name(old_node
, new_prop
->name
);
183 /* Look for a collision, set new value if there is */
184 for_each_property_withdel(old_node
, old_prop
) {
185 if (streq(old_prop
->name
, new_prop
->name
)) {
186 /* Add new labels to old property */
187 for_each_label_withdel(new_prop
->labels
, l
)
188 add_label(&old_prop
->labels
, l
->label
);
190 old_prop
->val
= new_prop
->val
;
191 old_prop
->deleted
= 0;
192 free(old_prop
->srcpos
);
193 old_prop
->srcpos
= new_prop
->srcpos
;
200 /* if no collision occurred, add property to the old node. */
202 add_property(old_node
, new_prop
);
205 /* Move the override child nodes into the primary node. If
206 * there is a collision, then merge the nodes. */
207 while (new_node
->children
) {
208 /* Pop the child node off the list */
209 new_child
= new_node
->children
;
210 new_node
->children
= new_child
->next_sibling
;
211 new_child
->parent
= NULL
;
212 new_child
->next_sibling
= NULL
;
214 if (new_child
->deleted
) {
215 delete_node_by_name(old_node
, new_child
->name
);
220 /* Search for a collision. Merge if there is */
221 for_each_child_withdel(old_node
, old_child
) {
222 if (streq(old_child
->name
, new_child
->name
)) {
223 merge_nodes(old_child
, new_child
);
229 /* if no collision occurred, add child to the old node. */
231 add_child(old_node
, new_child
);
234 old_node
->srcpos
= srcpos_extend(old_node
->srcpos
, new_node
->srcpos
);
236 /* The new node contents are now merged into the old node. Free
243 struct node
* add_orphan_node(struct node
*dt
, struct node
*new_node
, char *ref
)
245 static unsigned int next_orphan_fragment
= 0;
248 struct data d
= empty_data
;
252 d
= data_append_data(d
, ref
, strlen(ref
) + 1);
254 p
= build_property("target-path", d
, NULL
);
256 d
= data_add_marker(d
, REF_PHANDLE
, ref
);
257 d
= data_append_integer(d
, 0xffffffff, 32);
259 p
= build_property("target", d
, NULL
);
262 xasprintf(&name
, "fragment@%u",
263 next_orphan_fragment
++);
264 name_node(new_node
, "__overlay__");
265 node
= build_node(p
, new_node
, NULL
);
266 name_node(node
, name
);
272 struct node
*chain_node(struct node
*first
, struct node
*list
)
274 assert(first
->next_sibling
== NULL
);
276 first
->next_sibling
= list
;
280 void add_property(struct node
*node
, struct property
*prop
)
293 void delete_property_by_name(struct node
*node
, char *name
)
295 struct property
*prop
= node
->proplist
;
298 if (streq(prop
->name
, name
)) {
299 delete_property(prop
);
306 void delete_property(struct property
*prop
)
309 delete_labels(&prop
->labels
);
312 void add_child(struct node
*parent
, struct node
*child
)
316 child
->next_sibling
= NULL
;
317 child
->parent
= parent
;
319 p
= &parent
->children
;
321 p
= &((*p
)->next_sibling
);
326 void delete_node_by_name(struct node
*parent
, char *name
)
328 struct node
*node
= parent
->children
;
331 if (streq(node
->name
, name
)) {
335 node
= node
->next_sibling
;
339 void delete_node(struct node
*node
)
341 struct property
*prop
;
345 for_each_child(node
, child
)
347 for_each_property(node
, prop
)
348 delete_property(prop
);
349 delete_labels(&node
->labels
);
352 void append_to_property(struct node
*node
,
353 char *name
, const void *data
, int len
)
358 p
= get_property(node
, name
);
360 d
= data_append_data(p
->val
, data
, len
);
363 d
= data_append_data(empty_data
, data
, len
);
364 p
= build_property(name
, d
, NULL
);
365 add_property(node
, p
);
369 struct reserve_info
*build_reserve_entry(uint64_t address
, uint64_t size
)
371 struct reserve_info
*new = xmalloc(sizeof(*new));
373 memset(new, 0, sizeof(*new));
375 new->address
= address
;
381 struct reserve_info
*chain_reserve_entry(struct reserve_info
*first
,
382 struct reserve_info
*list
)
384 assert(first
->next
== NULL
);
390 struct reserve_info
*add_reserve_entry(struct reserve_info
*list
,
391 struct reserve_info
*new)
393 struct reserve_info
*last
;
400 for (last
= list
; last
->next
; last
= last
->next
)
408 struct dt_info
*build_dt_info(unsigned int dtsflags
,
409 struct reserve_info
*reservelist
,
410 struct node
*tree
, uint32_t boot_cpuid_phys
)
414 dti
= xmalloc(sizeof(*dti
));
415 dti
->dtsflags
= dtsflags
;
416 dti
->reservelist
= reservelist
;
418 dti
->boot_cpuid_phys
= boot_cpuid_phys
;
424 * Tree accessor functions
427 const char *get_unitname(struct node
*node
)
429 if (node
->name
[node
->basenamelen
] == '\0')
432 return node
->name
+ node
->basenamelen
+ 1;
435 struct property
*get_property(struct node
*node
, const char *propname
)
437 struct property
*prop
;
439 for_each_property(node
, prop
)
440 if (streq(prop
->name
, propname
))
446 cell_t
propval_cell(struct property
*prop
)
448 assert(prop
->val
.len
== sizeof(cell_t
));
449 return fdt32_to_cpu(*((fdt32_t
*)prop
->val
.val
));
452 cell_t
propval_cell_n(struct property
*prop
, int n
)
454 assert(prop
->val
.len
/ sizeof(cell_t
) >= n
);
455 return fdt32_to_cpu(*((fdt32_t
*)prop
->val
.val
+ n
));
458 struct property
*get_property_by_label(struct node
*tree
, const char *label
,
461 struct property
*prop
;
466 for_each_property(tree
, prop
) {
469 for_each_label(prop
->labels
, l
)
470 if (streq(l
->label
, label
))
474 for_each_child(tree
, c
) {
475 prop
= get_property_by_label(c
, label
, node
);
484 struct marker
*get_marker_label(struct node
*tree
, const char *label
,
485 struct node
**node
, struct property
**prop
)
493 for_each_property(tree
, p
) {
496 for_each_marker_of_type(m
, LABEL
)
497 if (streq(m
->ref
, label
))
501 for_each_child(tree
, c
) {
502 m
= get_marker_label(c
, label
, node
, prop
);
512 struct node
*get_subnode(struct node
*node
, const char *nodename
)
516 for_each_child(node
, child
)
517 if (streq(child
->name
, nodename
))
523 struct node
*get_node_by_path(struct node
*tree
, const char *path
)
528 if (!path
|| ! (*path
)) {
534 while (path
[0] == '/')
537 p
= strchr(path
, '/');
539 for_each_child(tree
, child
) {
540 if (p
&& (strlen(child
->name
) == p
-path
) &&
541 strprefixeq(path
, p
- path
, child
->name
))
542 return get_node_by_path(child
, p
+1);
543 else if (!p
&& streq(path
, child
->name
))
550 struct node
*get_node_by_label(struct node
*tree
, const char *label
)
552 struct node
*child
, *node
;
555 assert(label
&& (strlen(label
) > 0));
557 for_each_label(tree
->labels
, l
)
558 if (streq(l
->label
, label
))
561 for_each_child(tree
, child
) {
562 node
= get_node_by_label(child
, label
);
570 struct node
*get_node_by_phandle(struct node
*tree
, cell_t phandle
)
572 struct node
*child
, *node
;
574 if ((phandle
== 0) || (phandle
== -1)) {
575 assert(generate_fixups
);
579 if (tree
->phandle
== phandle
) {
585 for_each_child(tree
, child
) {
586 node
= get_node_by_phandle(child
, phandle
);
594 struct node
*get_node_by_ref(struct node
*tree
, const char *ref
)
598 else if (ref
[0] == '/')
599 return get_node_by_path(tree
, ref
);
601 return get_node_by_label(tree
, ref
);
604 cell_t
get_node_phandle(struct node
*root
, struct node
*node
)
606 static cell_t phandle
= 1; /* FIXME: ick, static local */
607 struct data d
= empty_data
;
609 if ((node
->phandle
!= 0) && (node
->phandle
!= -1))
610 return node
->phandle
;
612 while (get_node_by_phandle(root
, phandle
))
615 node
->phandle
= phandle
;
617 d
= data_add_marker(d
, TYPE_UINT32
, NULL
);
618 d
= data_append_cell(d
, phandle
);
620 if (!get_property(node
, "linux,phandle")
621 && (phandle_format
& PHANDLE_LEGACY
))
622 add_property(node
, build_property("linux,phandle", d
, NULL
));
624 if (!get_property(node
, "phandle")
625 && (phandle_format
& PHANDLE_EPAPR
))
626 add_property(node
, build_property("phandle", d
, NULL
));
628 /* If the node *does* have a phandle property, we must
629 * be dealing with a self-referencing phandle, which will be
630 * fixed up momentarily in the caller */
632 return node
->phandle
;
635 uint32_t guess_boot_cpuid(struct node
*tree
)
637 struct node
*cpus
, *bootcpu
;
638 struct property
*reg
;
640 cpus
= get_node_by_path(tree
, "/cpus");
645 bootcpu
= cpus
->children
;
649 reg
= get_property(bootcpu
, "reg");
650 if (!reg
|| (reg
->val
.len
!= sizeof(uint32_t)))
653 /* FIXME: Sanity check node? */
655 return propval_cell(reg
);
658 static int cmp_reserve_info(const void *ax
, const void *bx
)
660 const struct reserve_info
*a
, *b
;
662 a
= *((const struct reserve_info
* const *)ax
);
663 b
= *((const struct reserve_info
* const *)bx
);
665 if (a
->address
< b
->address
)
667 else if (a
->address
> b
->address
)
669 else if (a
->size
< b
->size
)
671 else if (a
->size
> b
->size
)
677 static void sort_reserve_entries(struct dt_info
*dti
)
679 struct reserve_info
*ri
, **tbl
;
682 for (ri
= dti
->reservelist
;
690 tbl
= xmalloc(n
* sizeof(*tbl
));
692 for (ri
= dti
->reservelist
;
697 qsort(tbl
, n
, sizeof(*tbl
), cmp_reserve_info
);
699 dti
->reservelist
= tbl
[0];
700 for (i
= 0; i
< (n
-1); i
++)
701 tbl
[i
]->next
= tbl
[i
+1];
702 tbl
[n
-1]->next
= NULL
;
707 static int cmp_prop(const void *ax
, const void *bx
)
709 const struct property
*a
, *b
;
711 a
= *((const struct property
* const *)ax
);
712 b
= *((const struct property
* const *)bx
);
714 return strcmp(a
->name
, b
->name
);
717 static void sort_properties(struct node
*node
)
720 struct property
*prop
, **tbl
;
722 for_each_property_withdel(node
, prop
)
728 tbl
= xmalloc(n
* sizeof(*tbl
));
730 for_each_property_withdel(node
, prop
)
733 qsort(tbl
, n
, sizeof(*tbl
), cmp_prop
);
735 node
->proplist
= tbl
[0];
736 for (i
= 0; i
< (n
-1); i
++)
737 tbl
[i
]->next
= tbl
[i
+1];
738 tbl
[n
-1]->next
= NULL
;
743 static int cmp_subnode(const void *ax
, const void *bx
)
745 const struct node
*a
, *b
;
747 a
= *((const struct node
* const *)ax
);
748 b
= *((const struct node
* const *)bx
);
750 return strcmp(a
->name
, b
->name
);
753 static void sort_subnodes(struct node
*node
)
756 struct node
*subnode
, **tbl
;
758 for_each_child_withdel(node
, subnode
)
764 tbl
= xmalloc(n
* sizeof(*tbl
));
766 for_each_child_withdel(node
, subnode
)
769 qsort(tbl
, n
, sizeof(*tbl
), cmp_subnode
);
771 node
->children
= tbl
[0];
772 for (i
= 0; i
< (n
-1); i
++)
773 tbl
[i
]->next_sibling
= tbl
[i
+1];
774 tbl
[n
-1]->next_sibling
= NULL
;
779 static void sort_node(struct node
*node
)
783 sort_properties(node
);
785 for_each_child_withdel(node
, c
)
789 void sort_tree(struct dt_info
*dti
)
791 sort_reserve_entries(dti
);
795 /* utility helper to avoid code duplication */
796 static struct node
*build_and_name_child_node(struct node
*parent
, char *name
)
800 node
= build_node(NULL
, NULL
, NULL
);
801 name_node(node
, xstrdup(name
));
802 add_child(parent
, node
);
807 static struct node
*build_root_node(struct node
*dt
, char *name
)
811 an
= get_subnode(dt
, name
);
813 an
= build_and_name_child_node(dt
, name
);
816 die("Could not build root node /%s\n", name
);
821 static bool any_label_tree(struct dt_info
*dti
, struct node
*node
)
828 for_each_child(node
, c
)
829 if (any_label_tree(dti
, c
))
835 static void generate_label_tree_internal(struct dt_info
*dti
,
836 struct node
*an
, struct node
*node
,
839 struct node
*dt
= dti
->dt
;
844 /* if there are labels */
847 /* now add the label in the node */
848 for_each_label(node
->labels
, l
) {
850 /* check whether the label already exists */
851 p
= get_property(an
, l
->label
);
853 fprintf(stderr
, "WARNING: label %s already"
854 " exists in /%s", l
->label
,
860 p
= build_property(l
->label
,
861 data_copy_mem(node
->fullpath
,
862 strlen(node
->fullpath
) + 1),
867 /* force allocation of a phandle for this node */
869 (void)get_node_phandle(dt
, node
);
872 for_each_child(node
, c
)
873 generate_label_tree_internal(dti
, an
, c
, allocph
);
876 static bool any_fixup_tree(struct dt_info
*dti
, struct node
*node
)
879 struct property
*prop
;
882 for_each_property(node
, prop
) {
883 m
= prop
->val
.markers
;
884 for_each_marker_of_type(m
, REF_PHANDLE
) {
885 if (!get_node_by_ref(dti
->dt
, m
->ref
))
890 for_each_child(node
, c
) {
891 if (any_fixup_tree(dti
, c
))
898 static void add_fixup_entry(struct dt_info
*dti
, struct node
*fn
,
899 struct node
*node
, struct property
*prop
,
904 /* m->ref can only be a REF_PHANDLE, but check anyway */
905 assert(m
->type
== REF_PHANDLE
);
907 /* there shouldn't be any ':' in the arguments */
908 if (strchr(node
->fullpath
, ':') || strchr(prop
->name
, ':'))
909 die("arguments should not contain ':'\n");
911 xasprintf(&entry
, "%s:%s:%u",
912 node
->fullpath
, prop
->name
, m
->offset
);
913 append_to_property(fn
, m
->ref
, entry
, strlen(entry
) + 1);
918 static void generate_fixups_tree_internal(struct dt_info
*dti
,
922 struct node
*dt
= dti
->dt
;
924 struct property
*prop
;
926 struct node
*refnode
;
928 for_each_property(node
, prop
) {
929 m
= prop
->val
.markers
;
930 for_each_marker_of_type(m
, REF_PHANDLE
) {
931 refnode
= get_node_by_ref(dt
, m
->ref
);
933 add_fixup_entry(dti
, fn
, node
, prop
, m
);
937 for_each_child(node
, c
)
938 generate_fixups_tree_internal(dti
, fn
, c
);
941 static bool any_local_fixup_tree(struct dt_info
*dti
, struct node
*node
)
944 struct property
*prop
;
947 for_each_property(node
, prop
) {
948 m
= prop
->val
.markers
;
949 for_each_marker_of_type(m
, REF_PHANDLE
) {
950 if (get_node_by_ref(dti
->dt
, m
->ref
))
955 for_each_child(node
, c
) {
956 if (any_local_fixup_tree(dti
, c
))
963 static void add_local_fixup_entry(struct dt_info
*dti
,
964 struct node
*lfn
, struct node
*node
,
965 struct property
*prop
, struct marker
*m
,
966 struct node
*refnode
)
968 struct node
*wn
, *nwn
; /* local fixup node, walk node, new */
973 /* walk back retreiving depth */
975 for (wn
= node
; wn
; wn
= wn
->parent
)
978 /* allocate name array */
979 compp
= xmalloc(sizeof(*compp
) * depth
);
981 /* store names in the array */
982 for (wn
= node
, i
= depth
- 1; wn
; wn
= wn
->parent
, i
--)
985 /* walk the path components creating nodes if they don't exist */
986 for (wn
= lfn
, i
= 1; i
< depth
; i
++, wn
= nwn
) {
987 /* if no node exists, create it */
988 nwn
= get_subnode(wn
, compp
[i
]);
990 nwn
= build_and_name_child_node(wn
, compp
[i
]);
995 value_32
= cpu_to_fdt32(m
->offset
);
996 append_to_property(wn
, prop
->name
, &value_32
, sizeof(value_32
));
999 static void generate_local_fixups_tree_internal(struct dt_info
*dti
,
1003 struct node
*dt
= dti
->dt
;
1005 struct property
*prop
;
1007 struct node
*refnode
;
1009 for_each_property(node
, prop
) {
1010 m
= prop
->val
.markers
;
1011 for_each_marker_of_type(m
, REF_PHANDLE
) {
1012 refnode
= get_node_by_ref(dt
, m
->ref
);
1014 add_local_fixup_entry(dti
, lfn
, node
, prop
, m
, refnode
);
1018 for_each_child(node
, c
)
1019 generate_local_fixups_tree_internal(dti
, lfn
, c
);
1022 void generate_label_tree(struct dt_info
*dti
, char *name
, bool allocph
)
1024 if (!any_label_tree(dti
, dti
->dt
))
1026 generate_label_tree_internal(dti
, build_root_node(dti
->dt
, name
),
1030 void generate_fixups_tree(struct dt_info
*dti
, char *name
)
1032 if (!any_fixup_tree(dti
, dti
->dt
))
1034 generate_fixups_tree_internal(dti
, build_root_node(dti
->dt
, name
),
1038 void generate_local_fixups_tree(struct dt_info
*dti
, char *name
)
1040 if (!any_local_fixup_tree(dti
, dti
->dt
))
1042 generate_local_fixups_tree_internal(dti
, build_root_node(dti
->dt
, name
),