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
24 * Tree building functions
27 void add_label(struct label
**labels
, char *label
)
31 /* Make sure the label isn't already there */
32 for_each_label_withdel(*labels
, new)
33 if (streq(new->label
, label
)) {
38 new = xmalloc(sizeof(*new));
39 memset(new, 0, sizeof(*new));
45 void delete_labels(struct label
**labels
)
49 for_each_label(*labels
, label
)
53 struct property
*build_property(char *name
, struct data val
)
55 struct property
*new = xmalloc(sizeof(*new));
57 memset(new, 0, sizeof(*new));
65 struct property
*build_property_delete(char *name
)
67 struct property
*new = xmalloc(sizeof(*new));
69 memset(new, 0, sizeof(*new));
77 struct property
*chain_property(struct property
*first
, struct property
*list
)
79 assert(first
->next
== NULL
);
85 struct property
*reverse_properties(struct property
*first
)
87 struct property
*p
= first
;
88 struct property
*head
= NULL
;
89 struct property
*next
;
100 struct node
*build_node(struct property
*proplist
, struct node
*children
)
102 struct node
*new = xmalloc(sizeof(*new));
105 memset(new, 0, sizeof(*new));
107 new->proplist
= reverse_properties(proplist
);
108 new->children
= children
;
110 for_each_child(new, child
) {
117 struct node
*build_node_delete(void)
119 struct node
*new = xmalloc(sizeof(*new));
121 memset(new, 0, sizeof(*new));
128 struct node
*name_node(struct node
*node
, char *name
)
130 assert(node
->name
== NULL
);
137 struct node
*merge_nodes(struct node
*old_node
, struct node
*new_node
)
139 struct property
*new_prop
, *old_prop
;
140 struct node
*new_child
, *old_child
;
143 old_node
->deleted
= 0;
145 /* Add new node labels to old node */
146 for_each_label_withdel(new_node
->labels
, l
)
147 add_label(&old_node
->labels
, l
->label
);
149 /* Move properties from the new node to the old node. If there
150 * is a collision, replace the old value with the new */
151 while (new_node
->proplist
) {
152 /* Pop the property off the list */
153 new_prop
= new_node
->proplist
;
154 new_node
->proplist
= new_prop
->next
;
155 new_prop
->next
= NULL
;
157 if (new_prop
->deleted
) {
158 delete_property_by_name(old_node
, new_prop
->name
);
163 /* Look for a collision, set new value if there is */
164 for_each_property_withdel(old_node
, old_prop
) {
165 if (streq(old_prop
->name
, new_prop
->name
)) {
166 /* Add new labels to old property */
167 for_each_label_withdel(new_prop
->labels
, l
)
168 add_label(&old_prop
->labels
, l
->label
);
170 old_prop
->val
= new_prop
->val
;
171 old_prop
->deleted
= 0;
178 /* if no collision occurred, add property to the old node. */
180 add_property(old_node
, new_prop
);
183 /* Move the override child nodes into the primary node. If
184 * there is a collision, then merge the nodes. */
185 while (new_node
->children
) {
186 /* Pop the child node off the list */
187 new_child
= new_node
->children
;
188 new_node
->children
= new_child
->next_sibling
;
189 new_child
->parent
= NULL
;
190 new_child
->next_sibling
= NULL
;
192 if (new_child
->deleted
) {
193 delete_node_by_name(old_node
, new_child
->name
);
198 /* Search for a collision. Merge if there is */
199 for_each_child_withdel(old_node
, old_child
) {
200 if (streq(old_child
->name
, new_child
->name
)) {
201 merge_nodes(old_child
, new_child
);
207 /* if no collision occurred, add child to the old node. */
209 add_child(old_node
, new_child
);
212 /* The new node contents are now merged into the old node. Free
219 struct node
*chain_node(struct node
*first
, struct node
*list
)
221 assert(first
->next_sibling
== NULL
);
223 first
->next_sibling
= list
;
227 void add_property(struct node
*node
, struct property
*prop
)
240 void delete_property_by_name(struct node
*node
, char *name
)
242 struct property
*prop
= node
->proplist
;
245 if (streq(prop
->name
, name
)) {
246 delete_property(prop
);
253 void delete_property(struct property
*prop
)
256 delete_labels(&prop
->labels
);
259 void add_child(struct node
*parent
, struct node
*child
)
263 child
->next_sibling
= NULL
;
264 child
->parent
= parent
;
266 p
= &parent
->children
;
268 p
= &((*p
)->next_sibling
);
273 void delete_node_by_name(struct node
*parent
, char *name
)
275 struct node
*node
= parent
->children
;
278 if (streq(node
->name
, name
)) {
282 node
= node
->next_sibling
;
286 void delete_node(struct node
*node
)
288 struct property
*prop
;
292 for_each_child(node
, child
)
294 for_each_property(node
, prop
)
295 delete_property(prop
);
296 delete_labels(&node
->labels
);
299 void append_to_property(struct node
*node
,
300 char *name
, const void *data
, int len
)
305 p
= get_property(node
, name
);
307 d
= data_append_data(p
->val
, data
, len
);
310 d
= data_append_data(empty_data
, data
, len
);
311 p
= build_property(name
, d
);
312 add_property(node
, p
);
316 struct reserve_info
*build_reserve_entry(uint64_t address
, uint64_t size
)
318 struct reserve_info
*new = xmalloc(sizeof(*new));
320 memset(new, 0, sizeof(*new));
322 new->address
= address
;
328 struct reserve_info
*chain_reserve_entry(struct reserve_info
*first
,
329 struct reserve_info
*list
)
331 assert(first
->next
== NULL
);
337 struct reserve_info
*add_reserve_entry(struct reserve_info
*list
,
338 struct reserve_info
*new)
340 struct reserve_info
*last
;
347 for (last
= list
; last
->next
; last
= last
->next
)
355 struct dt_info
*build_dt_info(unsigned int dtsflags
,
356 struct reserve_info
*reservelist
,
357 struct node
*tree
, uint32_t boot_cpuid_phys
)
361 dti
= xmalloc(sizeof(*dti
));
362 dti
->dtsflags
= dtsflags
;
363 dti
->reservelist
= reservelist
;
365 dti
->boot_cpuid_phys
= boot_cpuid_phys
;
371 * Tree accessor functions
374 const char *get_unitname(struct node
*node
)
376 if (node
->name
[node
->basenamelen
] == '\0')
379 return node
->name
+ node
->basenamelen
+ 1;
382 struct property
*get_property(struct node
*node
, const char *propname
)
384 struct property
*prop
;
386 for_each_property(node
, prop
)
387 if (streq(prop
->name
, propname
))
393 cell_t
propval_cell(struct property
*prop
)
395 assert(prop
->val
.len
== sizeof(cell_t
));
396 return fdt32_to_cpu(*((fdt32_t
*)prop
->val
.val
));
399 struct property
*get_property_by_label(struct node
*tree
, const char *label
,
402 struct property
*prop
;
407 for_each_property(tree
, prop
) {
410 for_each_label(prop
->labels
, l
)
411 if (streq(l
->label
, label
))
415 for_each_child(tree
, c
) {
416 prop
= get_property_by_label(c
, label
, node
);
425 struct marker
*get_marker_label(struct node
*tree
, const char *label
,
426 struct node
**node
, struct property
**prop
)
434 for_each_property(tree
, p
) {
437 for_each_marker_of_type(m
, LABEL
)
438 if (streq(m
->ref
, label
))
442 for_each_child(tree
, c
) {
443 m
= get_marker_label(c
, label
, node
, prop
);
453 struct node
*get_subnode(struct node
*node
, const char *nodename
)
457 for_each_child(node
, child
)
458 if (streq(child
->name
, nodename
))
464 struct node
*get_node_by_path(struct node
*tree
, const char *path
)
469 if (!path
|| ! (*path
)) {
475 while (path
[0] == '/')
478 p
= strchr(path
, '/');
480 for_each_child(tree
, child
) {
481 if (p
&& strneq(path
, child
->name
, p
-path
))
482 return get_node_by_path(child
, p
+1);
483 else if (!p
&& streq(path
, child
->name
))
490 struct node
*get_node_by_label(struct node
*tree
, const char *label
)
492 struct node
*child
, *node
;
495 assert(label
&& (strlen(label
) > 0));
497 for_each_label(tree
->labels
, l
)
498 if (streq(l
->label
, label
))
501 for_each_child(tree
, child
) {
502 node
= get_node_by_label(child
, label
);
510 struct node
*get_node_by_phandle(struct node
*tree
, cell_t phandle
)
512 struct node
*child
, *node
;
514 assert((phandle
!= 0) && (phandle
!= -1));
516 if (tree
->phandle
== phandle
) {
522 for_each_child(tree
, child
) {
523 node
= get_node_by_phandle(child
, phandle
);
531 struct node
*get_node_by_ref(struct node
*tree
, const char *ref
)
535 else if (ref
[0] == '/')
536 return get_node_by_path(tree
, ref
);
538 return get_node_by_label(tree
, ref
);
541 cell_t
get_node_phandle(struct node
*root
, struct node
*node
)
543 static cell_t phandle
= 1; /* FIXME: ick, static local */
545 if ((node
->phandle
!= 0) && (node
->phandle
!= -1))
546 return node
->phandle
;
548 while (get_node_by_phandle(root
, phandle
))
551 node
->phandle
= phandle
;
553 if (!get_property(node
, "linux,phandle")
554 && (phandle_format
& PHANDLE_LEGACY
))
556 build_property("linux,phandle",
557 data_append_cell(empty_data
, phandle
)));
559 if (!get_property(node
, "phandle")
560 && (phandle_format
& PHANDLE_EPAPR
))
562 build_property("phandle",
563 data_append_cell(empty_data
, phandle
)));
565 /* If the node *does* have a phandle property, we must
566 * be dealing with a self-referencing phandle, which will be
567 * fixed up momentarily in the caller */
569 return node
->phandle
;
572 uint32_t guess_boot_cpuid(struct node
*tree
)
574 struct node
*cpus
, *bootcpu
;
575 struct property
*reg
;
577 cpus
= get_node_by_path(tree
, "/cpus");
582 bootcpu
= cpus
->children
;
586 reg
= get_property(bootcpu
, "reg");
587 if (!reg
|| (reg
->val
.len
!= sizeof(uint32_t)))
590 /* FIXME: Sanity check node? */
592 return propval_cell(reg
);
595 static int cmp_reserve_info(const void *ax
, const void *bx
)
597 const struct reserve_info
*a
, *b
;
599 a
= *((const struct reserve_info
* const *)ax
);
600 b
= *((const struct reserve_info
* const *)bx
);
602 if (a
->address
< b
->address
)
604 else if (a
->address
> b
->address
)
606 else if (a
->size
< b
->size
)
608 else if (a
->size
> b
->size
)
614 static void sort_reserve_entries(struct dt_info
*dti
)
616 struct reserve_info
*ri
, **tbl
;
619 for (ri
= dti
->reservelist
;
627 tbl
= xmalloc(n
* sizeof(*tbl
));
629 for (ri
= dti
->reservelist
;
634 qsort(tbl
, n
, sizeof(*tbl
), cmp_reserve_info
);
636 dti
->reservelist
= tbl
[0];
637 for (i
= 0; i
< (n
-1); i
++)
638 tbl
[i
]->next
= tbl
[i
+1];
639 tbl
[n
-1]->next
= NULL
;
644 static int cmp_prop(const void *ax
, const void *bx
)
646 const struct property
*a
, *b
;
648 a
= *((const struct property
* const *)ax
);
649 b
= *((const struct property
* const *)bx
);
651 return strcmp(a
->name
, b
->name
);
654 static void sort_properties(struct node
*node
)
657 struct property
*prop
, **tbl
;
659 for_each_property_withdel(node
, prop
)
665 tbl
= xmalloc(n
* sizeof(*tbl
));
667 for_each_property_withdel(node
, prop
)
670 qsort(tbl
, n
, sizeof(*tbl
), cmp_prop
);
672 node
->proplist
= tbl
[0];
673 for (i
= 0; i
< (n
-1); i
++)
674 tbl
[i
]->next
= tbl
[i
+1];
675 tbl
[n
-1]->next
= NULL
;
680 static int cmp_subnode(const void *ax
, const void *bx
)
682 const struct node
*a
, *b
;
684 a
= *((const struct node
* const *)ax
);
685 b
= *((const struct node
* const *)bx
);
687 return strcmp(a
->name
, b
->name
);
690 static void sort_subnodes(struct node
*node
)
693 struct node
*subnode
, **tbl
;
695 for_each_child_withdel(node
, subnode
)
701 tbl
= xmalloc(n
* sizeof(*tbl
));
703 for_each_child_withdel(node
, subnode
)
706 qsort(tbl
, n
, sizeof(*tbl
), cmp_subnode
);
708 node
->children
= tbl
[0];
709 for (i
= 0; i
< (n
-1); i
++)
710 tbl
[i
]->next_sibling
= tbl
[i
+1];
711 tbl
[n
-1]->next_sibling
= NULL
;
716 static void sort_node(struct node
*node
)
720 sort_properties(node
);
722 for_each_child_withdel(node
, c
)
726 void sort_tree(struct dt_info
*dti
)
728 sort_reserve_entries(dti
);
732 /* utility helper to avoid code duplication */
733 static struct node
*build_and_name_child_node(struct node
*parent
, char *name
)
737 node
= build_node(NULL
, NULL
);
738 name_node(node
, xstrdup(name
));
739 add_child(parent
, node
);
744 static struct node
*build_root_node(struct node
*dt
, char *name
)
748 an
= get_subnode(dt
, name
);
750 an
= build_and_name_child_node(dt
, name
);
753 die("Could not build root node /%s\n", name
);
758 static bool any_label_tree(struct dt_info
*dti
, struct node
*node
)
765 for_each_child(node
, c
)
766 if (any_label_tree(dti
, c
))
772 static void generate_label_tree_internal(struct dt_info
*dti
,
773 struct node
*an
, struct node
*node
,
776 struct node
*dt
= dti
->dt
;
781 /* if there are labels */
784 /* now add the label in the node */
785 for_each_label(node
->labels
, l
) {
787 /* check whether the label already exists */
788 p
= get_property(an
, l
->label
);
790 fprintf(stderr
, "WARNING: label %s already"
791 " exists in /%s", l
->label
,
797 p
= build_property(l
->label
,
798 data_copy_mem(node
->fullpath
,
799 strlen(node
->fullpath
) + 1));
803 /* force allocation of a phandle for this node */
805 (void)get_node_phandle(dt
, node
);
808 for_each_child(node
, c
)
809 generate_label_tree_internal(dti
, an
, c
, allocph
);
812 static bool any_fixup_tree(struct dt_info
*dti
, struct node
*node
)
815 struct property
*prop
;
818 for_each_property(node
, prop
) {
819 m
= prop
->val
.markers
;
820 for_each_marker_of_type(m
, REF_PHANDLE
) {
821 if (!get_node_by_ref(dti
->dt
, m
->ref
))
826 for_each_child(node
, c
) {
827 if (any_fixup_tree(dti
, c
))
834 static void add_fixup_entry(struct dt_info
*dti
, struct node
*fn
,
835 struct node
*node
, struct property
*prop
,
840 /* m->ref can only be a REF_PHANDLE, but check anyway */
841 assert(m
->type
== REF_PHANDLE
);
843 /* there shouldn't be any ':' in the arguments */
844 if (strchr(node
->fullpath
, ':') || strchr(prop
->name
, ':'))
845 die("arguments should not contain ':'\n");
847 xasprintf(&entry
, "%s:%s:%u",
848 node
->fullpath
, prop
->name
, m
->offset
);
849 append_to_property(fn
, m
->ref
, entry
, strlen(entry
) + 1);
854 static void generate_fixups_tree_internal(struct dt_info
*dti
,
858 struct node
*dt
= dti
->dt
;
860 struct property
*prop
;
862 struct node
*refnode
;
864 for_each_property(node
, prop
) {
865 m
= prop
->val
.markers
;
866 for_each_marker_of_type(m
, REF_PHANDLE
) {
867 refnode
= get_node_by_ref(dt
, m
->ref
);
869 add_fixup_entry(dti
, fn
, node
, prop
, m
);
873 for_each_child(node
, c
)
874 generate_fixups_tree_internal(dti
, fn
, c
);
877 static bool any_local_fixup_tree(struct dt_info
*dti
, struct node
*node
)
880 struct property
*prop
;
883 for_each_property(node
, prop
) {
884 m
= prop
->val
.markers
;
885 for_each_marker_of_type(m
, REF_PHANDLE
) {
886 if (get_node_by_ref(dti
->dt
, m
->ref
))
891 for_each_child(node
, c
) {
892 if (any_local_fixup_tree(dti
, c
))
899 static void add_local_fixup_entry(struct dt_info
*dti
,
900 struct node
*lfn
, struct node
*node
,
901 struct property
*prop
, struct marker
*m
,
902 struct node
*refnode
)
904 struct node
*wn
, *nwn
; /* local fixup node, walk node, new */
909 /* walk back retreiving depth */
911 for (wn
= node
; wn
; wn
= wn
->parent
)
914 /* allocate name array */
915 compp
= xmalloc(sizeof(*compp
) * depth
);
917 /* store names in the array */
918 for (wn
= node
, i
= depth
- 1; wn
; wn
= wn
->parent
, i
--)
921 /* walk the path components creating nodes if they don't exist */
922 for (wn
= lfn
, i
= 1; i
< depth
; i
++, wn
= nwn
) {
923 /* if no node exists, create it */
924 nwn
= get_subnode(wn
, compp
[i
]);
926 nwn
= build_and_name_child_node(wn
, compp
[i
]);
931 value_32
= cpu_to_fdt32(m
->offset
);
932 append_to_property(wn
, prop
->name
, &value_32
, sizeof(value_32
));
935 static void generate_local_fixups_tree_internal(struct dt_info
*dti
,
939 struct node
*dt
= dti
->dt
;
941 struct property
*prop
;
943 struct node
*refnode
;
945 for_each_property(node
, prop
) {
946 m
= prop
->val
.markers
;
947 for_each_marker_of_type(m
, REF_PHANDLE
) {
948 refnode
= get_node_by_ref(dt
, m
->ref
);
950 add_local_fixup_entry(dti
, lfn
, node
, prop
, m
, refnode
);
954 for_each_child(node
, c
)
955 generate_local_fixups_tree_internal(dti
, lfn
, c
);
958 void generate_label_tree(struct dt_info
*dti
, char *name
, bool allocph
)
960 if (!any_label_tree(dti
, dti
->dt
))
962 generate_label_tree_internal(dti
, build_root_node(dti
->dt
, name
),
966 void generate_fixups_tree(struct dt_info
*dti
, char *name
)
968 if (!any_fixup_tree(dti
, dti
->dt
))
970 generate_fixups_tree_internal(dti
, build_root_node(dti
->dt
, name
),
974 void generate_local_fixups_tree(struct dt_info
*dti
, char *name
)
976 if (!any_local_fixup_tree(dti
, dti
->dt
))
978 generate_local_fixups_tree_internal(dti
, build_root_node(dti
->dt
, name
),