112869ecdSRob Herring // SPDX-License-Identifier: GPL-2.0-or-later
29fffb55fSDavid Gibson /*
39fffb55fSDavid Gibson * (C) Copyright David Gibson <dwg@au1.ibm.com>, IBM Corporation. 2005.
49fffb55fSDavid Gibson */
59fffb55fSDavid Gibson
69fffb55fSDavid Gibson #include "dtc.h"
7c2e7075cSRob Herring #include "srcpos.h"
89fffb55fSDavid Gibson
99fffb55fSDavid Gibson /*
109fffb55fSDavid Gibson * Tree building functions
119fffb55fSDavid Gibson */
129fffb55fSDavid Gibson
add_label(struct label ** labels,char * label)13658f29a5SJohn Bonesio void add_label(struct label **labels, char *label)
14658f29a5SJohn Bonesio {
15658f29a5SJohn Bonesio struct label *new;
16658f29a5SJohn Bonesio
17658f29a5SJohn Bonesio /* Make sure the label isn't already there */
18cd296721SStephen Warren for_each_label_withdel(*labels, new)
19cd296721SStephen Warren if (streq(new->label, label)) {
20cd296721SStephen Warren new->deleted = 0;
21658f29a5SJohn Bonesio return;
22cd296721SStephen Warren }
23658f29a5SJohn Bonesio
24658f29a5SJohn Bonesio new = xmalloc(sizeof(*new));
25cd296721SStephen Warren memset(new, 0, sizeof(*new));
26658f29a5SJohn Bonesio new->label = label;
27658f29a5SJohn Bonesio new->next = *labels;
28658f29a5SJohn Bonesio *labels = new;
29658f29a5SJohn Bonesio }
30658f29a5SJohn Bonesio
delete_labels(struct label ** labels)31cd296721SStephen Warren void delete_labels(struct label **labels)
32cd296721SStephen Warren {
33cd296721SStephen Warren struct label *label;
34cd296721SStephen Warren
35cd296721SStephen Warren for_each_label(*labels, label)
36cd296721SStephen Warren label->deleted = 1;
37cd296721SStephen Warren }
38cd296721SStephen Warren
build_property(const char * name,struct data val,struct srcpos * srcpos)39*12d638f4SRob Herring (Arm) struct property *build_property(const char *name, struct data val,
40c2e7075cSRob Herring struct srcpos *srcpos)
419fffb55fSDavid Gibson {
429fffb55fSDavid Gibson struct property *new = xmalloc(sizeof(*new));
439fffb55fSDavid Gibson
44658f29a5SJohn Bonesio memset(new, 0, sizeof(*new));
45658f29a5SJohn Bonesio
46*12d638f4SRob Herring (Arm) new->name = xstrdup(name);
479fffb55fSDavid Gibson new->val = val;
48c2e7075cSRob Herring new->srcpos = srcpos_copy(srcpos);
499fffb55fSDavid Gibson
509fffb55fSDavid Gibson return new;
519fffb55fSDavid Gibson }
529fffb55fSDavid Gibson
build_property_delete(const char * name)53*12d638f4SRob Herring (Arm) struct property *build_property_delete(const char *name)
54cd296721SStephen Warren {
55cd296721SStephen Warren struct property *new = xmalloc(sizeof(*new));
56cd296721SStephen Warren
57cd296721SStephen Warren memset(new, 0, sizeof(*new));
58cd296721SStephen Warren
59*12d638f4SRob Herring (Arm) new->name = xstrdup(name);
60cd296721SStephen Warren new->deleted = 1;
61cd296721SStephen Warren
62cd296721SStephen Warren return new;
63cd296721SStephen Warren }
64cd296721SStephen Warren
chain_property(struct property * first,struct property * list)659fffb55fSDavid Gibson struct property *chain_property(struct property *first, struct property *list)
669fffb55fSDavid Gibson {
679fffb55fSDavid Gibson assert(first->next == NULL);
689fffb55fSDavid Gibson
699fffb55fSDavid Gibson first->next = list;
709fffb55fSDavid Gibson return first;
719fffb55fSDavid Gibson }
729fffb55fSDavid Gibson
reverse_properties(struct property * first)739fffb55fSDavid Gibson struct property *reverse_properties(struct property *first)
749fffb55fSDavid Gibson {
759fffb55fSDavid Gibson struct property *p = first;
769fffb55fSDavid Gibson struct property *head = NULL;
779fffb55fSDavid Gibson struct property *next;
789fffb55fSDavid Gibson
799fffb55fSDavid Gibson while (p) {
809fffb55fSDavid Gibson next = p->next;
819fffb55fSDavid Gibson p->next = head;
829fffb55fSDavid Gibson head = p;
839fffb55fSDavid Gibson p = next;
849fffb55fSDavid Gibson }
859fffb55fSDavid Gibson return head;
869fffb55fSDavid Gibson }
879fffb55fSDavid Gibson
build_node(struct property * proplist,struct node * children,struct srcpos * srcpos)88c2e7075cSRob Herring struct node *build_node(struct property *proplist, struct node *children,
89c2e7075cSRob Herring struct srcpos *srcpos)
909fffb55fSDavid Gibson {
919fffb55fSDavid Gibson struct node *new = xmalloc(sizeof(*new));
929fffb55fSDavid Gibson struct node *child;
939fffb55fSDavid Gibson
949fffb55fSDavid Gibson memset(new, 0, sizeof(*new));
959fffb55fSDavid Gibson
969fffb55fSDavid Gibson new->proplist = reverse_properties(proplist);
979fffb55fSDavid Gibson new->children = children;
98c2e7075cSRob Herring new->srcpos = srcpos_copy(srcpos);
999fffb55fSDavid Gibson
1009fffb55fSDavid Gibson for_each_child(new, child) {
1019fffb55fSDavid Gibson child->parent = new;
1029fffb55fSDavid Gibson }
1039fffb55fSDavid Gibson
1049fffb55fSDavid Gibson return new;
1059fffb55fSDavid Gibson }
1069fffb55fSDavid Gibson
build_node_delete(struct srcpos * srcpos)107c2e7075cSRob Herring struct node *build_node_delete(struct srcpos *srcpos)
108cd296721SStephen Warren {
109cd296721SStephen Warren struct node *new = xmalloc(sizeof(*new));
110cd296721SStephen Warren
111cd296721SStephen Warren memset(new, 0, sizeof(*new));
112cd296721SStephen Warren
113cd296721SStephen Warren new->deleted = 1;
114c2e7075cSRob Herring new->srcpos = srcpos_copy(srcpos);
115cd296721SStephen Warren
116cd296721SStephen Warren return new;
117cd296721SStephen Warren }
118cd296721SStephen Warren
name_node(struct node * node,const char * name)119*12d638f4SRob Herring (Arm) struct node *name_node(struct node *node, const char *name)
1209fffb55fSDavid Gibson {
1219fffb55fSDavid Gibson assert(node->name == NULL);
1229fffb55fSDavid Gibson
123*12d638f4SRob Herring (Arm) node->name = xstrdup(name);
1249fffb55fSDavid Gibson
1259fffb55fSDavid Gibson return node;
1269fffb55fSDavid Gibson }
1279fffb55fSDavid Gibson
omit_node_if_unused(struct node * node)12850aafd60SRob Herring struct node *omit_node_if_unused(struct node *node)
12950aafd60SRob Herring {
13050aafd60SRob Herring node->omit_if_unused = 1;
13150aafd60SRob Herring
13250aafd60SRob Herring return node;
13350aafd60SRob Herring }
13450aafd60SRob Herring
reference_node(struct node * node)13550aafd60SRob Herring struct node *reference_node(struct node *node)
13650aafd60SRob Herring {
13750aafd60SRob Herring node->is_referenced = 1;
13850aafd60SRob Herring
13950aafd60SRob Herring return node;
14050aafd60SRob Herring }
14150aafd60SRob Herring
merge_nodes(struct node * old_node,struct node * new_node)142658f29a5SJohn Bonesio struct node *merge_nodes(struct node *old_node, struct node *new_node)
143658f29a5SJohn Bonesio {
144658f29a5SJohn Bonesio struct property *new_prop, *old_prop;
145658f29a5SJohn Bonesio struct node *new_child, *old_child;
146658f29a5SJohn Bonesio struct label *l;
147658f29a5SJohn Bonesio
148cd296721SStephen Warren old_node->deleted = 0;
149cd296721SStephen Warren
150658f29a5SJohn Bonesio /* Add new node labels to old node */
151cd296721SStephen Warren for_each_label_withdel(new_node->labels, l)
152658f29a5SJohn Bonesio add_label(&old_node->labels, l->label);
153658f29a5SJohn Bonesio
154658f29a5SJohn Bonesio /* Move properties from the new node to the old node. If there
155658f29a5SJohn Bonesio * is a collision, replace the old value with the new */
156658f29a5SJohn Bonesio while (new_node->proplist) {
157658f29a5SJohn Bonesio /* Pop the property off the list */
158658f29a5SJohn Bonesio new_prop = new_node->proplist;
159658f29a5SJohn Bonesio new_node->proplist = new_prop->next;
160658f29a5SJohn Bonesio new_prop->next = NULL;
161658f29a5SJohn Bonesio
162cd296721SStephen Warren if (new_prop->deleted) {
163cd296721SStephen Warren delete_property_by_name(old_node, new_prop->name);
164cd296721SStephen Warren free(new_prop);
165cd296721SStephen Warren continue;
166cd296721SStephen Warren }
167cd296721SStephen Warren
168658f29a5SJohn Bonesio /* Look for a collision, set new value if there is */
169cd296721SStephen Warren for_each_property_withdel(old_node, old_prop) {
170658f29a5SJohn Bonesio if (streq(old_prop->name, new_prop->name)) {
171658f29a5SJohn Bonesio /* Add new labels to old property */
172cd296721SStephen Warren for_each_label_withdel(new_prop->labels, l)
173658f29a5SJohn Bonesio add_label(&old_prop->labels, l->label);
174658f29a5SJohn Bonesio
175658f29a5SJohn Bonesio old_prop->val = new_prop->val;
176cd296721SStephen Warren old_prop->deleted = 0;
177c2e7075cSRob Herring free(old_prop->srcpos);
178c2e7075cSRob Herring old_prop->srcpos = new_prop->srcpos;
179658f29a5SJohn Bonesio free(new_prop);
180658f29a5SJohn Bonesio new_prop = NULL;
181658f29a5SJohn Bonesio break;
182658f29a5SJohn Bonesio }
183658f29a5SJohn Bonesio }
184658f29a5SJohn Bonesio
185658f29a5SJohn Bonesio /* if no collision occurred, add property to the old node. */
186658f29a5SJohn Bonesio if (new_prop)
187658f29a5SJohn Bonesio add_property(old_node, new_prop);
188658f29a5SJohn Bonesio }
189658f29a5SJohn Bonesio
190658f29a5SJohn Bonesio /* Move the override child nodes into the primary node. If
191658f29a5SJohn Bonesio * there is a collision, then merge the nodes. */
192658f29a5SJohn Bonesio while (new_node->children) {
193658f29a5SJohn Bonesio /* Pop the child node off the list */
194658f29a5SJohn Bonesio new_child = new_node->children;
195658f29a5SJohn Bonesio new_node->children = new_child->next_sibling;
196658f29a5SJohn Bonesio new_child->parent = NULL;
197658f29a5SJohn Bonesio new_child->next_sibling = NULL;
198658f29a5SJohn Bonesio
199cd296721SStephen Warren if (new_child->deleted) {
200cd296721SStephen Warren delete_node_by_name(old_node, new_child->name);
201cd296721SStephen Warren free(new_child);
202cd296721SStephen Warren continue;
203cd296721SStephen Warren }
204cd296721SStephen Warren
205658f29a5SJohn Bonesio /* Search for a collision. Merge if there is */
206cd296721SStephen Warren for_each_child_withdel(old_node, old_child) {
207658f29a5SJohn Bonesio if (streq(old_child->name, new_child->name)) {
208658f29a5SJohn Bonesio merge_nodes(old_child, new_child);
209658f29a5SJohn Bonesio new_child = NULL;
210658f29a5SJohn Bonesio break;
211658f29a5SJohn Bonesio }
212658f29a5SJohn Bonesio }
213658f29a5SJohn Bonesio
2146f05afcbSRob Herring /* if no collision occurred, add child to the old node. */
215658f29a5SJohn Bonesio if (new_child)
216658f29a5SJohn Bonesio add_child(old_node, new_child);
217658f29a5SJohn Bonesio }
218658f29a5SJohn Bonesio
219c2e7075cSRob Herring old_node->srcpos = srcpos_extend(old_node->srcpos, new_node->srcpos);
220c2e7075cSRob Herring
221658f29a5SJohn Bonesio /* The new node contents are now merged into the old node. Free
222658f29a5SJohn Bonesio * the new node. */
223658f29a5SJohn Bonesio free(new_node);
224658f29a5SJohn Bonesio
225658f29a5SJohn Bonesio return old_node;
226658f29a5SJohn Bonesio }
227658f29a5SJohn Bonesio
add_orphan_node(struct node * dt,struct node * new_node,char * ref)2289130ba88SRob Herring struct node * add_orphan_node(struct node *dt, struct node *new_node, char *ref)
2294201d057SRob Herring {
2304201d057SRob Herring static unsigned int next_orphan_fragment = 0;
2314201d057SRob Herring struct node *node;
2324201d057SRob Herring struct property *p;
2334201d057SRob Herring struct data d = empty_data;
2344201d057SRob Herring char *name;
2354201d057SRob Herring
23650aafd60SRob Herring if (ref[0] == '/') {
2379bb9c6a1SRob Herring d = data_add_marker(d, TYPE_STRING, ref);
23850aafd60SRob Herring d = data_append_data(d, ref, strlen(ref) + 1);
23950aafd60SRob Herring
240c2e7075cSRob Herring p = build_property("target-path", d, NULL);
24150aafd60SRob Herring } else {
2424201d057SRob Herring d = data_add_marker(d, REF_PHANDLE, ref);
2434201d057SRob Herring d = data_append_integer(d, 0xffffffff, 32);
2444201d057SRob Herring
245c2e7075cSRob Herring p = build_property("target", d, NULL);
24650aafd60SRob Herring }
2474201d057SRob Herring
2484201d057SRob Herring xasprintf(&name, "fragment@%u",
2494201d057SRob Herring next_orphan_fragment++);
2504201d057SRob Herring name_node(new_node, "__overlay__");
251c2e7075cSRob Herring node = build_node(p, new_node, NULL);
2524201d057SRob Herring name_node(node, name);
253*12d638f4SRob Herring (Arm) free(name);
2544201d057SRob Herring
2554201d057SRob Herring add_child(dt, node);
2569130ba88SRob Herring return dt;
2574201d057SRob Herring }
2584201d057SRob Herring
chain_node(struct node * first,struct node * list)2599fffb55fSDavid Gibson struct node *chain_node(struct node *first, struct node *list)
2609fffb55fSDavid Gibson {
2619fffb55fSDavid Gibson assert(first->next_sibling == NULL);
2629fffb55fSDavid Gibson
2639fffb55fSDavid Gibson first->next_sibling = list;
2649fffb55fSDavid Gibson return first;
2659fffb55fSDavid Gibson }
2669fffb55fSDavid Gibson
add_property(struct node * node,struct property * prop)2679fffb55fSDavid Gibson void add_property(struct node *node, struct property *prop)
2689fffb55fSDavid Gibson {
2699fffb55fSDavid Gibson struct property **p;
2709fffb55fSDavid Gibson
2719fffb55fSDavid Gibson prop->next = NULL;
2729fffb55fSDavid Gibson
2739fffb55fSDavid Gibson p = &node->proplist;
2749fffb55fSDavid Gibson while (*p)
2759fffb55fSDavid Gibson p = &((*p)->next);
2769fffb55fSDavid Gibson
2779fffb55fSDavid Gibson *p = prop;
2789fffb55fSDavid Gibson }
2799fffb55fSDavid Gibson
delete_property_by_name(struct node * node,char * name)280cd296721SStephen Warren void delete_property_by_name(struct node *node, char *name)
281cd296721SStephen Warren {
282cd296721SStephen Warren struct property *prop = node->proplist;
283cd296721SStephen Warren
284cd296721SStephen Warren while (prop) {
28589d12310SRob Herring if (streq(prop->name, name)) {
286cd296721SStephen Warren delete_property(prop);
287cd296721SStephen Warren return;
288cd296721SStephen Warren }
289cd296721SStephen Warren prop = prop->next;
290cd296721SStephen Warren }
291cd296721SStephen Warren }
292cd296721SStephen Warren
delete_property(struct property * prop)293cd296721SStephen Warren void delete_property(struct property *prop)
294cd296721SStephen Warren {
295cd296721SStephen Warren prop->deleted = 1;
296cd296721SStephen Warren delete_labels(&prop->labels);
297cd296721SStephen Warren }
298cd296721SStephen Warren
add_child(struct node * parent,struct node * child)2999fffb55fSDavid Gibson void add_child(struct node *parent, struct node *child)
3009fffb55fSDavid Gibson {
3019fffb55fSDavid Gibson struct node **p;
3029fffb55fSDavid Gibson
3039fffb55fSDavid Gibson child->next_sibling = NULL;
3049fffb55fSDavid Gibson child->parent = parent;
3059fffb55fSDavid Gibson
3069fffb55fSDavid Gibson p = &parent->children;
3079fffb55fSDavid Gibson while (*p)
3089fffb55fSDavid Gibson p = &((*p)->next_sibling);
3099fffb55fSDavid Gibson
3109fffb55fSDavid Gibson *p = child;
3119fffb55fSDavid Gibson }
3129fffb55fSDavid Gibson
delete_node_by_name(struct node * parent,char * name)313cd296721SStephen Warren void delete_node_by_name(struct node *parent, char *name)
314cd296721SStephen Warren {
315cd296721SStephen Warren struct node *node = parent->children;
316cd296721SStephen Warren
317cd296721SStephen Warren while (node) {
31889d12310SRob Herring if (streq(node->name, name)) {
319cd296721SStephen Warren delete_node(node);
320cd296721SStephen Warren return;
321cd296721SStephen Warren }
322cd296721SStephen Warren node = node->next_sibling;
323cd296721SStephen Warren }
324cd296721SStephen Warren }
325cd296721SStephen Warren
delete_node(struct node * node)326cd296721SStephen Warren void delete_node(struct node *node)
327cd296721SStephen Warren {
328cd296721SStephen Warren struct property *prop;
329cd296721SStephen Warren struct node *child;
330cd296721SStephen Warren
331cd296721SStephen Warren node->deleted = 1;
332cd296721SStephen Warren for_each_child(node, child)
333cd296721SStephen Warren delete_node(child);
334cd296721SStephen Warren for_each_property(node, prop)
335cd296721SStephen Warren delete_property(prop);
336cd296721SStephen Warren delete_labels(&node->labels);
337cd296721SStephen Warren }
338cd296721SStephen Warren
append_to_property(struct node * node,char * name,const void * data,int len,enum markertype type)3396f05afcbSRob Herring void append_to_property(struct node *node,
3409bb9c6a1SRob Herring char *name, const void *data, int len,
3419bb9c6a1SRob Herring enum markertype type)
3426f05afcbSRob Herring {
3436f05afcbSRob Herring struct data d;
3446f05afcbSRob Herring struct property *p;
3456f05afcbSRob Herring
3466f05afcbSRob Herring p = get_property(node, name);
3476f05afcbSRob Herring if (p) {
3489bb9c6a1SRob Herring d = data_add_marker(p->val, type, name);
3499bb9c6a1SRob Herring d = data_append_data(d, data, len);
3506f05afcbSRob Herring p->val = d;
3516f05afcbSRob Herring } else {
3529bb9c6a1SRob Herring d = data_add_marker(empty_data, type, name);
3539bb9c6a1SRob Herring d = data_append_data(d, data, len);
354c2e7075cSRob Herring p = build_property(name, d, NULL);
3556f05afcbSRob Herring add_property(node, p);
3566f05afcbSRob Herring }
3576f05afcbSRob Herring }
3586f05afcbSRob Herring
build_reserve_entry(uint64_t address,uint64_t size)359658f29a5SJohn Bonesio struct reserve_info *build_reserve_entry(uint64_t address, uint64_t size)
3609fffb55fSDavid Gibson {
3619fffb55fSDavid Gibson struct reserve_info *new = xmalloc(sizeof(*new));
3629fffb55fSDavid Gibson
363658f29a5SJohn Bonesio memset(new, 0, sizeof(*new));
364658f29a5SJohn Bonesio
36589d12310SRob Herring new->address = address;
36689d12310SRob Herring new->size = size;
3679fffb55fSDavid Gibson
3689fffb55fSDavid Gibson return new;
3699fffb55fSDavid Gibson }
3709fffb55fSDavid Gibson
chain_reserve_entry(struct reserve_info * first,struct reserve_info * list)3719fffb55fSDavid Gibson struct reserve_info *chain_reserve_entry(struct reserve_info *first,
3729fffb55fSDavid Gibson struct reserve_info *list)
3739fffb55fSDavid Gibson {
3749fffb55fSDavid Gibson assert(first->next == NULL);
3759fffb55fSDavid Gibson
3769fffb55fSDavid Gibson first->next = list;
3779fffb55fSDavid Gibson return first;
3789fffb55fSDavid Gibson }
3799fffb55fSDavid Gibson
add_reserve_entry(struct reserve_info * list,struct reserve_info * new)3809fffb55fSDavid Gibson struct reserve_info *add_reserve_entry(struct reserve_info *list,
3819fffb55fSDavid Gibson struct reserve_info *new)
3829fffb55fSDavid Gibson {
3839fffb55fSDavid Gibson struct reserve_info *last;
3849fffb55fSDavid Gibson
3859fffb55fSDavid Gibson new->next = NULL;
3869fffb55fSDavid Gibson
3879fffb55fSDavid Gibson if (! list)
3889fffb55fSDavid Gibson return new;
3899fffb55fSDavid Gibson
3909fffb55fSDavid Gibson for (last = list; last->next; last = last->next)
3919fffb55fSDavid Gibson ;
3929fffb55fSDavid Gibson
3939fffb55fSDavid Gibson last->next = new;
3949fffb55fSDavid Gibson
3959fffb55fSDavid Gibson return list;
3969fffb55fSDavid Gibson }
3979fffb55fSDavid Gibson
build_dt_info(unsigned int dtsflags,struct reserve_info * reservelist,struct node * tree,uint32_t boot_cpuid_phys)3986f05afcbSRob Herring struct dt_info *build_dt_info(unsigned int dtsflags,
3996f05afcbSRob Herring struct reserve_info *reservelist,
4009fffb55fSDavid Gibson struct node *tree, uint32_t boot_cpuid_phys)
4019fffb55fSDavid Gibson {
4026f05afcbSRob Herring struct dt_info *dti;
4039fffb55fSDavid Gibson
4046f05afcbSRob Herring dti = xmalloc(sizeof(*dti));
4056f05afcbSRob Herring dti->dtsflags = dtsflags;
4066f05afcbSRob Herring dti->reservelist = reservelist;
4076f05afcbSRob Herring dti->dt = tree;
4086f05afcbSRob Herring dti->boot_cpuid_phys = boot_cpuid_phys;
4099fffb55fSDavid Gibson
4106f05afcbSRob Herring return dti;
4119fffb55fSDavid Gibson }
4129fffb55fSDavid Gibson
4139fffb55fSDavid Gibson /*
4149fffb55fSDavid Gibson * Tree accessor functions
4159fffb55fSDavid Gibson */
4169fffb55fSDavid Gibson
get_unitname(struct node * node)4179fffb55fSDavid Gibson const char *get_unitname(struct node *node)
4189fffb55fSDavid Gibson {
4199fffb55fSDavid Gibson if (node->name[node->basenamelen] == '\0')
4209fffb55fSDavid Gibson return "";
4219fffb55fSDavid Gibson else
4229fffb55fSDavid Gibson return node->name + node->basenamelen + 1;
4239fffb55fSDavid Gibson }
4249fffb55fSDavid Gibson
get_property(struct node * node,const char * propname)4259fffb55fSDavid Gibson struct property *get_property(struct node *node, const char *propname)
4269fffb55fSDavid Gibson {
4279fffb55fSDavid Gibson struct property *prop;
4289fffb55fSDavid Gibson
4299fffb55fSDavid Gibson for_each_property(node, prop)
4309fffb55fSDavid Gibson if (streq(prop->name, propname))
4319fffb55fSDavid Gibson return prop;
4329fffb55fSDavid Gibson
4339fffb55fSDavid Gibson return NULL;
4349fffb55fSDavid Gibson }
4359fffb55fSDavid Gibson
propval_cell(struct property * prop)4369fffb55fSDavid Gibson cell_t propval_cell(struct property *prop)
4379fffb55fSDavid Gibson {
4389fffb55fSDavid Gibson assert(prop->val.len == sizeof(cell_t));
43989d12310SRob Herring return fdt32_to_cpu(*((fdt32_t *)prop->val.val));
4409fffb55fSDavid Gibson }
4419fffb55fSDavid Gibson
propval_cell_n(struct property * prop,unsigned int n)44279edff12SRob Herring cell_t propval_cell_n(struct property *prop, unsigned int n)
4434201d057SRob Herring {
444*12d638f4SRob Herring (Arm) assert(prop->val.len / sizeof(cell_t) > n);
4454201d057SRob Herring return fdt32_to_cpu(*((fdt32_t *)prop->val.val + n));
4464201d057SRob Herring }
4474201d057SRob Herring
get_property_by_label(struct node * tree,const char * label,struct node ** node)448658f29a5SJohn Bonesio struct property *get_property_by_label(struct node *tree, const char *label,
449658f29a5SJohn Bonesio struct node **node)
450658f29a5SJohn Bonesio {
451658f29a5SJohn Bonesio struct property *prop;
452658f29a5SJohn Bonesio struct node *c;
453658f29a5SJohn Bonesio
454658f29a5SJohn Bonesio *node = tree;
455658f29a5SJohn Bonesio
456658f29a5SJohn Bonesio for_each_property(tree, prop) {
457658f29a5SJohn Bonesio struct label *l;
458658f29a5SJohn Bonesio
459658f29a5SJohn Bonesio for_each_label(prop->labels, l)
460658f29a5SJohn Bonesio if (streq(l->label, label))
461658f29a5SJohn Bonesio return prop;
462658f29a5SJohn Bonesio }
463658f29a5SJohn Bonesio
464658f29a5SJohn Bonesio for_each_child(tree, c) {
465658f29a5SJohn Bonesio prop = get_property_by_label(c, label, node);
466658f29a5SJohn Bonesio if (prop)
467658f29a5SJohn Bonesio return prop;
468658f29a5SJohn Bonesio }
469658f29a5SJohn Bonesio
470658f29a5SJohn Bonesio *node = NULL;
471658f29a5SJohn Bonesio return NULL;
472658f29a5SJohn Bonesio }
473658f29a5SJohn Bonesio
get_marker_label(struct node * tree,const char * label,struct node ** node,struct property ** prop)474658f29a5SJohn Bonesio struct marker *get_marker_label(struct node *tree, const char *label,
475658f29a5SJohn Bonesio struct node **node, struct property **prop)
476658f29a5SJohn Bonesio {
477658f29a5SJohn Bonesio struct marker *m;
478658f29a5SJohn Bonesio struct property *p;
479658f29a5SJohn Bonesio struct node *c;
480658f29a5SJohn Bonesio
481658f29a5SJohn Bonesio *node = tree;
482658f29a5SJohn Bonesio
483658f29a5SJohn Bonesio for_each_property(tree, p) {
484658f29a5SJohn Bonesio *prop = p;
485658f29a5SJohn Bonesio m = p->val.markers;
486658f29a5SJohn Bonesio for_each_marker_of_type(m, LABEL)
487658f29a5SJohn Bonesio if (streq(m->ref, label))
488658f29a5SJohn Bonesio return m;
489658f29a5SJohn Bonesio }
490658f29a5SJohn Bonesio
491658f29a5SJohn Bonesio for_each_child(tree, c) {
492658f29a5SJohn Bonesio m = get_marker_label(c, label, node, prop);
493658f29a5SJohn Bonesio if (m)
494658f29a5SJohn Bonesio return m;
495658f29a5SJohn Bonesio }
496658f29a5SJohn Bonesio
497658f29a5SJohn Bonesio *prop = NULL;
498658f29a5SJohn Bonesio *node = NULL;
499658f29a5SJohn Bonesio return NULL;
500658f29a5SJohn Bonesio }
501658f29a5SJohn Bonesio
get_subnode(struct node * node,const char * nodename)5029fffb55fSDavid Gibson struct node *get_subnode(struct node *node, const char *nodename)
5039fffb55fSDavid Gibson {
5049fffb55fSDavid Gibson struct node *child;
5059fffb55fSDavid Gibson
5069fffb55fSDavid Gibson for_each_child(node, child)
5079fffb55fSDavid Gibson if (streq(child->name, nodename))
5089fffb55fSDavid Gibson return child;
5099fffb55fSDavid Gibson
5109fffb55fSDavid Gibson return NULL;
5119fffb55fSDavid Gibson }
5129fffb55fSDavid Gibson
get_node_by_path(struct node * tree,const char * path)5139fffb55fSDavid Gibson struct node *get_node_by_path(struct node *tree, const char *path)
5149fffb55fSDavid Gibson {
5159fffb55fSDavid Gibson const char *p;
5169fffb55fSDavid Gibson struct node *child;
5179fffb55fSDavid Gibson
518cd296721SStephen Warren if (!path || ! (*path)) {
519cd296721SStephen Warren if (tree->deleted)
520cd296721SStephen Warren return NULL;
5219fffb55fSDavid Gibson return tree;
522cd296721SStephen Warren }
5239fffb55fSDavid Gibson
5249fffb55fSDavid Gibson while (path[0] == '/')
5259fffb55fSDavid Gibson path++;
5269fffb55fSDavid Gibson
5279fffb55fSDavid Gibson p = strchr(path, '/');
5289fffb55fSDavid Gibson
5299fffb55fSDavid Gibson for_each_child(tree, child) {
530a77725a9SRob Herring if (p && strprefixeq(path, (size_t)(p - path), child->name))
5319fffb55fSDavid Gibson return get_node_by_path(child, p+1);
5329fffb55fSDavid Gibson else if (!p && streq(path, child->name))
5339fffb55fSDavid Gibson return child;
5349fffb55fSDavid Gibson }
5359fffb55fSDavid Gibson
5369fffb55fSDavid Gibson return NULL;
5379fffb55fSDavid Gibson }
5389fffb55fSDavid Gibson
get_node_by_label(struct node * tree,const char * label)5399fffb55fSDavid Gibson struct node *get_node_by_label(struct node *tree, const char *label)
5409fffb55fSDavid Gibson {
5419fffb55fSDavid Gibson struct node *child, *node;
542658f29a5SJohn Bonesio struct label *l;
5439fffb55fSDavid Gibson
5449fffb55fSDavid Gibson assert(label && (strlen(label) > 0));
5459fffb55fSDavid Gibson
546658f29a5SJohn Bonesio for_each_label(tree->labels, l)
547658f29a5SJohn Bonesio if (streq(l->label, label))
5489fffb55fSDavid Gibson return tree;
5499fffb55fSDavid Gibson
5509fffb55fSDavid Gibson for_each_child(tree, child) {
5519fffb55fSDavid Gibson node = get_node_by_label(child, label);
5529fffb55fSDavid Gibson if (node)
5539fffb55fSDavid Gibson return node;
5549fffb55fSDavid Gibson }
5559fffb55fSDavid Gibson
5569fffb55fSDavid Gibson return NULL;
5579fffb55fSDavid Gibson }
5589fffb55fSDavid Gibson
get_node_by_phandle(struct node * tree,cell_t phandle)5599fffb55fSDavid Gibson struct node *get_node_by_phandle(struct node *tree, cell_t phandle)
5609fffb55fSDavid Gibson {
5619fffb55fSDavid Gibson struct node *child, *node;
5629fffb55fSDavid Gibson
563a77725a9SRob Herring if (!phandle_is_valid(phandle)) {
5649130ba88SRob Herring assert(generate_fixups);
5659130ba88SRob Herring return NULL;
5669130ba88SRob Herring }
5679fffb55fSDavid Gibson
568cd296721SStephen Warren if (tree->phandle == phandle) {
569cd296721SStephen Warren if (tree->deleted)
570cd296721SStephen Warren return NULL;
5719fffb55fSDavid Gibson return tree;
572cd296721SStephen Warren }
5739fffb55fSDavid Gibson
5749fffb55fSDavid Gibson for_each_child(tree, child) {
5759fffb55fSDavid Gibson node = get_node_by_phandle(child, phandle);
5769fffb55fSDavid Gibson if (node)
5779fffb55fSDavid Gibson return node;
5789fffb55fSDavid Gibson }
5799fffb55fSDavid Gibson
5809fffb55fSDavid Gibson return NULL;
5819fffb55fSDavid Gibson }
5829fffb55fSDavid Gibson
get_node_by_ref(struct node * tree,const char * ref)5839fffb55fSDavid Gibson struct node *get_node_by_ref(struct node *tree, const char *ref)
5849fffb55fSDavid Gibson {
585ea3723a5SRob Herring struct node *target = tree;
586ea3723a5SRob Herring const char *label = NULL, *path = NULL;
587ea3723a5SRob Herring
58847605971SRob Herring if (streq(ref, "/"))
58947605971SRob Herring return tree;
590ea3723a5SRob Herring
591ea3723a5SRob Herring if (ref[0] == '/')
592ea3723a5SRob Herring path = ref;
5939fffb55fSDavid Gibson else
594ea3723a5SRob Herring label = ref;
595ea3723a5SRob Herring
596ea3723a5SRob Herring if (label) {
597ea3723a5SRob Herring const char *slash = strchr(label, '/');
598ea3723a5SRob Herring char *buf = NULL;
599ea3723a5SRob Herring
600ea3723a5SRob Herring if (slash) {
601ea3723a5SRob Herring buf = xstrndup(label, slash - label);
602ea3723a5SRob Herring label = buf;
603ea3723a5SRob Herring path = slash + 1;
604ea3723a5SRob Herring }
605ea3723a5SRob Herring
606ea3723a5SRob Herring target = get_node_by_label(tree, label);
607ea3723a5SRob Herring
608ea3723a5SRob Herring free(buf);
609ea3723a5SRob Herring
610ea3723a5SRob Herring if (!target)
611ea3723a5SRob Herring return NULL;
612ea3723a5SRob Herring }
613ea3723a5SRob Herring
614ea3723a5SRob Herring if (path)
615ea3723a5SRob Herring target = get_node_by_path(target, path);
616ea3723a5SRob Herring
617ea3723a5SRob Herring return target;
6189fffb55fSDavid Gibson }
6199fffb55fSDavid Gibson
add_phandle_property(struct node * node,const char * name,int format)620*12d638f4SRob Herring (Arm) static void add_phandle_property(struct node *node,
621*12d638f4SRob Herring (Arm) const char *name, int format)
622*12d638f4SRob Herring (Arm) {
623*12d638f4SRob Herring (Arm) struct data d;
624*12d638f4SRob Herring (Arm)
625*12d638f4SRob Herring (Arm) if (!(phandle_format & format))
626*12d638f4SRob Herring (Arm) return;
627*12d638f4SRob Herring (Arm) if (get_property(node, name))
628*12d638f4SRob Herring (Arm) return;
629*12d638f4SRob Herring (Arm)
630*12d638f4SRob Herring (Arm) d = data_add_marker(empty_data, TYPE_UINT32, NULL);
631*12d638f4SRob Herring (Arm) d = data_append_cell(d, node->phandle);
632*12d638f4SRob Herring (Arm)
633*12d638f4SRob Herring (Arm) add_property(node, build_property(name, d, NULL));
634*12d638f4SRob Herring (Arm) }
635*12d638f4SRob Herring (Arm)
get_node_phandle(struct node * root,struct node * node)6369fffb55fSDavid Gibson cell_t get_node_phandle(struct node *root, struct node *node)
6379fffb55fSDavid Gibson {
6389fffb55fSDavid Gibson static cell_t phandle = 1; /* FIXME: ick, static local */
6399fffb55fSDavid Gibson
640a77725a9SRob Herring if (phandle_is_valid(node->phandle))
6419fffb55fSDavid Gibson return node->phandle;
6429fffb55fSDavid Gibson
6439fffb55fSDavid Gibson while (get_node_by_phandle(root, phandle))
6449fffb55fSDavid Gibson phandle++;
6459fffb55fSDavid Gibson
6469fffb55fSDavid Gibson node->phandle = phandle;
647658f29a5SJohn Bonesio
648*12d638f4SRob Herring (Arm) add_phandle_property(node, "linux,phandle", PHANDLE_LEGACY);
649*12d638f4SRob Herring (Arm) add_phandle_property(node, "phandle", PHANDLE_EPAPR);
650658f29a5SJohn Bonesio
651658f29a5SJohn Bonesio /* If the node *does* have a phandle property, we must
652658f29a5SJohn Bonesio * be dealing with a self-referencing phandle, which will be
653658f29a5SJohn Bonesio * fixed up momentarily in the caller */
6549fffb55fSDavid Gibson
6559fffb55fSDavid Gibson return node->phandle;
6569fffb55fSDavid Gibson }
657658f29a5SJohn Bonesio
guess_boot_cpuid(struct node * tree)658658f29a5SJohn Bonesio uint32_t guess_boot_cpuid(struct node *tree)
659658f29a5SJohn Bonesio {
660658f29a5SJohn Bonesio struct node *cpus, *bootcpu;
661658f29a5SJohn Bonesio struct property *reg;
662658f29a5SJohn Bonesio
663658f29a5SJohn Bonesio cpus = get_node_by_path(tree, "/cpus");
664658f29a5SJohn Bonesio if (!cpus)
665658f29a5SJohn Bonesio return 0;
666658f29a5SJohn Bonesio
667658f29a5SJohn Bonesio
668658f29a5SJohn Bonesio bootcpu = cpus->children;
669658f29a5SJohn Bonesio if (!bootcpu)
670658f29a5SJohn Bonesio return 0;
671658f29a5SJohn Bonesio
672658f29a5SJohn Bonesio reg = get_property(bootcpu, "reg");
673658f29a5SJohn Bonesio if (!reg || (reg->val.len != sizeof(uint32_t)))
674658f29a5SJohn Bonesio return 0;
675658f29a5SJohn Bonesio
676658f29a5SJohn Bonesio /* FIXME: Sanity check node? */
677658f29a5SJohn Bonesio
678658f29a5SJohn Bonesio return propval_cell(reg);
679658f29a5SJohn Bonesio }
680658f29a5SJohn Bonesio
cmp_reserve_info(const void * ax,const void * bx)681658f29a5SJohn Bonesio static int cmp_reserve_info(const void *ax, const void *bx)
682658f29a5SJohn Bonesio {
683658f29a5SJohn Bonesio const struct reserve_info *a, *b;
684658f29a5SJohn Bonesio
685658f29a5SJohn Bonesio a = *((const struct reserve_info * const *)ax);
686658f29a5SJohn Bonesio b = *((const struct reserve_info * const *)bx);
687658f29a5SJohn Bonesio
68889d12310SRob Herring if (a->address < b->address)
689658f29a5SJohn Bonesio return -1;
69089d12310SRob Herring else if (a->address > b->address)
691658f29a5SJohn Bonesio return 1;
69289d12310SRob Herring else if (a->size < b->size)
693658f29a5SJohn Bonesio return -1;
69489d12310SRob Herring else if (a->size > b->size)
695658f29a5SJohn Bonesio return 1;
696658f29a5SJohn Bonesio else
697658f29a5SJohn Bonesio return 0;
698658f29a5SJohn Bonesio }
699658f29a5SJohn Bonesio
sort_reserve_entries(struct dt_info * dti)7006f05afcbSRob Herring static void sort_reserve_entries(struct dt_info *dti)
701658f29a5SJohn Bonesio {
702658f29a5SJohn Bonesio struct reserve_info *ri, **tbl;
703658f29a5SJohn Bonesio int n = 0, i = 0;
704658f29a5SJohn Bonesio
7056f05afcbSRob Herring for (ri = dti->reservelist;
706658f29a5SJohn Bonesio ri;
707658f29a5SJohn Bonesio ri = ri->next)
708658f29a5SJohn Bonesio n++;
709658f29a5SJohn Bonesio
710658f29a5SJohn Bonesio if (n == 0)
711658f29a5SJohn Bonesio return;
712658f29a5SJohn Bonesio
713658f29a5SJohn Bonesio tbl = xmalloc(n * sizeof(*tbl));
714658f29a5SJohn Bonesio
7156f05afcbSRob Herring for (ri = dti->reservelist;
716658f29a5SJohn Bonesio ri;
717658f29a5SJohn Bonesio ri = ri->next)
718658f29a5SJohn Bonesio tbl[i++] = ri;
719658f29a5SJohn Bonesio
720658f29a5SJohn Bonesio qsort(tbl, n, sizeof(*tbl), cmp_reserve_info);
721658f29a5SJohn Bonesio
7226f05afcbSRob Herring dti->reservelist = tbl[0];
723658f29a5SJohn Bonesio for (i = 0; i < (n-1); i++)
724658f29a5SJohn Bonesio tbl[i]->next = tbl[i+1];
725658f29a5SJohn Bonesio tbl[n-1]->next = NULL;
726658f29a5SJohn Bonesio
727658f29a5SJohn Bonesio free(tbl);
728658f29a5SJohn Bonesio }
729658f29a5SJohn Bonesio
cmp_prop(const void * ax,const void * bx)730658f29a5SJohn Bonesio static int cmp_prop(const void *ax, const void *bx)
731658f29a5SJohn Bonesio {
732658f29a5SJohn Bonesio const struct property *a, *b;
733658f29a5SJohn Bonesio
734658f29a5SJohn Bonesio a = *((const struct property * const *)ax);
735658f29a5SJohn Bonesio b = *((const struct property * const *)bx);
736658f29a5SJohn Bonesio
737658f29a5SJohn Bonesio return strcmp(a->name, b->name);
738658f29a5SJohn Bonesio }
739658f29a5SJohn Bonesio
sort_properties(struct node * node)740658f29a5SJohn Bonesio static void sort_properties(struct node *node)
741658f29a5SJohn Bonesio {
742658f29a5SJohn Bonesio int n = 0, i = 0;
743658f29a5SJohn Bonesio struct property *prop, **tbl;
744658f29a5SJohn Bonesio
745cd296721SStephen Warren for_each_property_withdel(node, prop)
746658f29a5SJohn Bonesio n++;
747658f29a5SJohn Bonesio
748658f29a5SJohn Bonesio if (n == 0)
749658f29a5SJohn Bonesio return;
750658f29a5SJohn Bonesio
751658f29a5SJohn Bonesio tbl = xmalloc(n * sizeof(*tbl));
752658f29a5SJohn Bonesio
753cd296721SStephen Warren for_each_property_withdel(node, prop)
754658f29a5SJohn Bonesio tbl[i++] = prop;
755658f29a5SJohn Bonesio
756658f29a5SJohn Bonesio qsort(tbl, n, sizeof(*tbl), cmp_prop);
757658f29a5SJohn Bonesio
758658f29a5SJohn Bonesio node->proplist = tbl[0];
759658f29a5SJohn Bonesio for (i = 0; i < (n-1); i++)
760658f29a5SJohn Bonesio tbl[i]->next = tbl[i+1];
761658f29a5SJohn Bonesio tbl[n-1]->next = NULL;
762658f29a5SJohn Bonesio
763658f29a5SJohn Bonesio free(tbl);
764658f29a5SJohn Bonesio }
765658f29a5SJohn Bonesio
cmp_subnode(const void * ax,const void * bx)766658f29a5SJohn Bonesio static int cmp_subnode(const void *ax, const void *bx)
767658f29a5SJohn Bonesio {
768658f29a5SJohn Bonesio const struct node *a, *b;
769658f29a5SJohn Bonesio
770658f29a5SJohn Bonesio a = *((const struct node * const *)ax);
771658f29a5SJohn Bonesio b = *((const struct node * const *)bx);
772658f29a5SJohn Bonesio
773658f29a5SJohn Bonesio return strcmp(a->name, b->name);
774658f29a5SJohn Bonesio }
775658f29a5SJohn Bonesio
sort_subnodes(struct node * node)776658f29a5SJohn Bonesio static void sort_subnodes(struct node *node)
777658f29a5SJohn Bonesio {
778658f29a5SJohn Bonesio int n = 0, i = 0;
779658f29a5SJohn Bonesio struct node *subnode, **tbl;
780658f29a5SJohn Bonesio
781cd296721SStephen Warren for_each_child_withdel(node, subnode)
782658f29a5SJohn Bonesio n++;
783658f29a5SJohn Bonesio
784658f29a5SJohn Bonesio if (n == 0)
785658f29a5SJohn Bonesio return;
786658f29a5SJohn Bonesio
787658f29a5SJohn Bonesio tbl = xmalloc(n * sizeof(*tbl));
788658f29a5SJohn Bonesio
789cd296721SStephen Warren for_each_child_withdel(node, subnode)
790658f29a5SJohn Bonesio tbl[i++] = subnode;
791658f29a5SJohn Bonesio
792658f29a5SJohn Bonesio qsort(tbl, n, sizeof(*tbl), cmp_subnode);
793658f29a5SJohn Bonesio
794658f29a5SJohn Bonesio node->children = tbl[0];
795658f29a5SJohn Bonesio for (i = 0; i < (n-1); i++)
796658f29a5SJohn Bonesio tbl[i]->next_sibling = tbl[i+1];
797658f29a5SJohn Bonesio tbl[n-1]->next_sibling = NULL;
798658f29a5SJohn Bonesio
799658f29a5SJohn Bonesio free(tbl);
800658f29a5SJohn Bonesio }
801658f29a5SJohn Bonesio
sort_node(struct node * node)802658f29a5SJohn Bonesio static void sort_node(struct node *node)
803658f29a5SJohn Bonesio {
804658f29a5SJohn Bonesio struct node *c;
805658f29a5SJohn Bonesio
806658f29a5SJohn Bonesio sort_properties(node);
807658f29a5SJohn Bonesio sort_subnodes(node);
808cd296721SStephen Warren for_each_child_withdel(node, c)
809658f29a5SJohn Bonesio sort_node(c);
810658f29a5SJohn Bonesio }
811658f29a5SJohn Bonesio
sort_tree(struct dt_info * dti)8126f05afcbSRob Herring void sort_tree(struct dt_info *dti)
813658f29a5SJohn Bonesio {
8146f05afcbSRob Herring sort_reserve_entries(dti);
8156f05afcbSRob Herring sort_node(dti->dt);
8166f05afcbSRob Herring }
8176f05afcbSRob Herring
8186f05afcbSRob Herring /* utility helper to avoid code duplication */
build_and_name_child_node(struct node * parent,const char * name)819*12d638f4SRob Herring (Arm) static struct node *build_and_name_child_node(struct node *parent, const char *name)
8206f05afcbSRob Herring {
8216f05afcbSRob Herring struct node *node;
8226f05afcbSRob Herring
823c2e7075cSRob Herring node = build_node(NULL, NULL, NULL);
824*12d638f4SRob Herring (Arm) name_node(node, name);
8256f05afcbSRob Herring add_child(parent, node);
8266f05afcbSRob Herring
8276f05afcbSRob Herring return node;
8286f05afcbSRob Herring }
8296f05afcbSRob Herring
build_root_node(struct node * dt,const char * name)830*12d638f4SRob Herring (Arm) static struct node *build_root_node(struct node *dt, const char *name)
8316f05afcbSRob Herring {
8326f05afcbSRob Herring struct node *an;
8336f05afcbSRob Herring
8346f05afcbSRob Herring an = get_subnode(dt, name);
8356f05afcbSRob Herring if (!an)
8366f05afcbSRob Herring an = build_and_name_child_node(dt, name);
8376f05afcbSRob Herring
8386f05afcbSRob Herring if (!an)
8396f05afcbSRob Herring die("Could not build root node /%s\n", name);
8406f05afcbSRob Herring
8416f05afcbSRob Herring return an;
8426f05afcbSRob Herring }
8436f05afcbSRob Herring
any_label_tree(struct dt_info * dti,struct node * node)8446f05afcbSRob Herring static bool any_label_tree(struct dt_info *dti, struct node *node)
8456f05afcbSRob Herring {
8466f05afcbSRob Herring struct node *c;
8476f05afcbSRob Herring
8486f05afcbSRob Herring if (node->labels)
8496f05afcbSRob Herring return true;
8506f05afcbSRob Herring
8516f05afcbSRob Herring for_each_child(node, c)
8526f05afcbSRob Herring if (any_label_tree(dti, c))
8536f05afcbSRob Herring return true;
8546f05afcbSRob Herring
8556f05afcbSRob Herring return false;
8566f05afcbSRob Herring }
8576f05afcbSRob Herring
generate_label_tree_internal(struct dt_info * dti,struct node * an,struct node * node,bool allocph)8586f05afcbSRob Herring static void generate_label_tree_internal(struct dt_info *dti,
8596f05afcbSRob Herring struct node *an, struct node *node,
8606f05afcbSRob Herring bool allocph)
8616f05afcbSRob Herring {
8626f05afcbSRob Herring struct node *dt = dti->dt;
8636f05afcbSRob Herring struct node *c;
8646f05afcbSRob Herring struct property *p;
8656f05afcbSRob Herring struct label *l;
8666f05afcbSRob Herring
8676f05afcbSRob Herring /* if there are labels */
8686f05afcbSRob Herring if (node->labels) {
8696f05afcbSRob Herring
8706f05afcbSRob Herring /* now add the label in the node */
8716f05afcbSRob Herring for_each_label(node->labels, l) {
8726f05afcbSRob Herring
8736f05afcbSRob Herring /* check whether the label already exists */
8746f05afcbSRob Herring p = get_property(an, l->label);
8756f05afcbSRob Herring if (p) {
8766f05afcbSRob Herring fprintf(stderr, "WARNING: label %s already"
8776f05afcbSRob Herring " exists in /%s", l->label,
8786f05afcbSRob Herring an->name);
8796f05afcbSRob Herring continue;
8806f05afcbSRob Herring }
8816f05afcbSRob Herring
8826f05afcbSRob Herring /* insert it */
8836f05afcbSRob Herring p = build_property(l->label,
8849bb9c6a1SRob Herring data_copy_escape_string(node->fullpath,
8859bb9c6a1SRob Herring strlen(node->fullpath)),
886c2e7075cSRob Herring NULL);
8876f05afcbSRob Herring add_property(an, p);
8886f05afcbSRob Herring }
8896f05afcbSRob Herring
8906f05afcbSRob Herring /* force allocation of a phandle for this node */
8916f05afcbSRob Herring if (allocph)
8926f05afcbSRob Herring (void)get_node_phandle(dt, node);
8936f05afcbSRob Herring }
8946f05afcbSRob Herring
8956f05afcbSRob Herring for_each_child(node, c)
8966f05afcbSRob Herring generate_label_tree_internal(dti, an, c, allocph);
8976f05afcbSRob Herring }
8986f05afcbSRob Herring
any_fixup_tree(struct dt_info * dti,struct node * node)8996f05afcbSRob Herring static bool any_fixup_tree(struct dt_info *dti, struct node *node)
9006f05afcbSRob Herring {
9016f05afcbSRob Herring struct node *c;
9026f05afcbSRob Herring struct property *prop;
9036f05afcbSRob Herring struct marker *m;
9046f05afcbSRob Herring
9056f05afcbSRob Herring for_each_property(node, prop) {
9066f05afcbSRob Herring m = prop->val.markers;
9076f05afcbSRob Herring for_each_marker_of_type(m, REF_PHANDLE) {
9086f05afcbSRob Herring if (!get_node_by_ref(dti->dt, m->ref))
9096f05afcbSRob Herring return true;
9106f05afcbSRob Herring }
9116f05afcbSRob Herring }
9126f05afcbSRob Herring
9136f05afcbSRob Herring for_each_child(node, c) {
9146f05afcbSRob Herring if (any_fixup_tree(dti, c))
9156f05afcbSRob Herring return true;
9166f05afcbSRob Herring }
9176f05afcbSRob Herring
9186f05afcbSRob Herring return false;
9196f05afcbSRob Herring }
9206f05afcbSRob Herring
add_fixup_entry(struct dt_info * dti,struct node * fn,struct node * node,struct property * prop,struct marker * m)9216f05afcbSRob Herring static void add_fixup_entry(struct dt_info *dti, struct node *fn,
9226f05afcbSRob Herring struct node *node, struct property *prop,
9236f05afcbSRob Herring struct marker *m)
9246f05afcbSRob Herring {
9256f05afcbSRob Herring char *entry;
9266f05afcbSRob Herring
9276f05afcbSRob Herring /* m->ref can only be a REF_PHANDLE, but check anyway */
9286f05afcbSRob Herring assert(m->type == REF_PHANDLE);
9296f05afcbSRob Herring
930ea3723a5SRob Herring /* The format only permits fixups for references to label, not
931ea3723a5SRob Herring * references to path */
932ea3723a5SRob Herring if (strchr(m->ref, '/'))
933ea3723a5SRob Herring die("Can't generate fixup for reference to path &{%s}\n",
934ea3723a5SRob Herring m->ref);
935ea3723a5SRob Herring
9366f05afcbSRob Herring /* there shouldn't be any ':' in the arguments */
9376f05afcbSRob Herring if (strchr(node->fullpath, ':') || strchr(prop->name, ':'))
9386f05afcbSRob Herring die("arguments should not contain ':'\n");
9396f05afcbSRob Herring
9406f05afcbSRob Herring xasprintf(&entry, "%s:%s:%u",
9416f05afcbSRob Herring node->fullpath, prop->name, m->offset);
9429bb9c6a1SRob Herring append_to_property(fn, m->ref, entry, strlen(entry) + 1, TYPE_STRING);
94389d12310SRob Herring
94489d12310SRob Herring free(entry);
9456f05afcbSRob Herring }
9466f05afcbSRob Herring
generate_fixups_tree_internal(struct dt_info * dti,struct node * fn,struct node * node)9476f05afcbSRob Herring static void generate_fixups_tree_internal(struct dt_info *dti,
9486f05afcbSRob Herring struct node *fn,
9496f05afcbSRob Herring struct node *node)
9506f05afcbSRob Herring {
9516f05afcbSRob Herring struct node *dt = dti->dt;
9526f05afcbSRob Herring struct node *c;
9536f05afcbSRob Herring struct property *prop;
9546f05afcbSRob Herring struct marker *m;
9556f05afcbSRob Herring struct node *refnode;
9566f05afcbSRob Herring
9576f05afcbSRob Herring for_each_property(node, prop) {
9586f05afcbSRob Herring m = prop->val.markers;
9596f05afcbSRob Herring for_each_marker_of_type(m, REF_PHANDLE) {
9606f05afcbSRob Herring refnode = get_node_by_ref(dt, m->ref);
9616f05afcbSRob Herring if (!refnode)
9626f05afcbSRob Herring add_fixup_entry(dti, fn, node, prop, m);
9636f05afcbSRob Herring }
9646f05afcbSRob Herring }
9656f05afcbSRob Herring
9666f05afcbSRob Herring for_each_child(node, c)
9676f05afcbSRob Herring generate_fixups_tree_internal(dti, fn, c);
9686f05afcbSRob Herring }
9696f05afcbSRob Herring
any_local_fixup_tree(struct dt_info * dti,struct node * node)9706f05afcbSRob Herring static bool any_local_fixup_tree(struct dt_info *dti, struct node *node)
9716f05afcbSRob Herring {
9726f05afcbSRob Herring struct node *c;
9736f05afcbSRob Herring struct property *prop;
9746f05afcbSRob Herring struct marker *m;
9756f05afcbSRob Herring
9766f05afcbSRob Herring for_each_property(node, prop) {
9776f05afcbSRob Herring m = prop->val.markers;
9786f05afcbSRob Herring for_each_marker_of_type(m, REF_PHANDLE) {
9796f05afcbSRob Herring if (get_node_by_ref(dti->dt, m->ref))
9806f05afcbSRob Herring return true;
9816f05afcbSRob Herring }
9826f05afcbSRob Herring }
9836f05afcbSRob Herring
9846f05afcbSRob Herring for_each_child(node, c) {
9856f05afcbSRob Herring if (any_local_fixup_tree(dti, c))
9866f05afcbSRob Herring return true;
9876f05afcbSRob Herring }
9886f05afcbSRob Herring
9896f05afcbSRob Herring return false;
9906f05afcbSRob Herring }
9916f05afcbSRob Herring
add_local_fixup_entry(struct dt_info * dti,struct node * lfn,struct node * node,struct property * prop,struct marker * m,struct node * refnode)9926f05afcbSRob Herring static void add_local_fixup_entry(struct dt_info *dti,
9936f05afcbSRob Herring struct node *lfn, struct node *node,
9946f05afcbSRob Herring struct property *prop, struct marker *m,
9956f05afcbSRob Herring struct node *refnode)
9966f05afcbSRob Herring {
9976f05afcbSRob Herring struct node *wn, *nwn; /* local fixup node, walk node, new */
99889d12310SRob Herring fdt32_t value_32;
9996f05afcbSRob Herring char **compp;
10006f05afcbSRob Herring int i, depth;
10016f05afcbSRob Herring
10029bb9c6a1SRob Herring /* walk back retrieving depth */
10036f05afcbSRob Herring depth = 0;
10046f05afcbSRob Herring for (wn = node; wn; wn = wn->parent)
10056f05afcbSRob Herring depth++;
10066f05afcbSRob Herring
10076f05afcbSRob Herring /* allocate name array */
10086f05afcbSRob Herring compp = xmalloc(sizeof(*compp) * depth);
10096f05afcbSRob Herring
10106f05afcbSRob Herring /* store names in the array */
10116f05afcbSRob Herring for (wn = node, i = depth - 1; wn; wn = wn->parent, i--)
10126f05afcbSRob Herring compp[i] = wn->name;
10136f05afcbSRob Herring
10146f05afcbSRob Herring /* walk the path components creating nodes if they don't exist */
10156f05afcbSRob Herring for (wn = lfn, i = 1; i < depth; i++, wn = nwn) {
10166f05afcbSRob Herring /* if no node exists, create it */
10176f05afcbSRob Herring nwn = get_subnode(wn, compp[i]);
10186f05afcbSRob Herring if (!nwn)
10196f05afcbSRob Herring nwn = build_and_name_child_node(wn, compp[i]);
10206f05afcbSRob Herring }
10216f05afcbSRob Herring
10226f05afcbSRob Herring free(compp);
10236f05afcbSRob Herring
10246f05afcbSRob Herring value_32 = cpu_to_fdt32(m->offset);
10259bb9c6a1SRob Herring append_to_property(wn, prop->name, &value_32, sizeof(value_32), TYPE_UINT32);
10266f05afcbSRob Herring }
10276f05afcbSRob Herring
generate_local_fixups_tree_internal(struct dt_info * dti,struct node * lfn,struct node * node)10286f05afcbSRob Herring static void generate_local_fixups_tree_internal(struct dt_info *dti,
10296f05afcbSRob Herring struct node *lfn,
10306f05afcbSRob Herring struct node *node)
10316f05afcbSRob Herring {
10326f05afcbSRob Herring struct node *dt = dti->dt;
10336f05afcbSRob Herring struct node *c;
10346f05afcbSRob Herring struct property *prop;
10356f05afcbSRob Herring struct marker *m;
10366f05afcbSRob Herring struct node *refnode;
10376f05afcbSRob Herring
10386f05afcbSRob Herring for_each_property(node, prop) {
10396f05afcbSRob Herring m = prop->val.markers;
10406f05afcbSRob Herring for_each_marker_of_type(m, REF_PHANDLE) {
10416f05afcbSRob Herring refnode = get_node_by_ref(dt, m->ref);
10426f05afcbSRob Herring if (refnode)
10436f05afcbSRob Herring add_local_fixup_entry(dti, lfn, node, prop, m, refnode);
10446f05afcbSRob Herring }
10456f05afcbSRob Herring }
10466f05afcbSRob Herring
10476f05afcbSRob Herring for_each_child(node, c)
10486f05afcbSRob Herring generate_local_fixups_tree_internal(dti, lfn, c);
10496f05afcbSRob Herring }
10506f05afcbSRob Herring
generate_label_tree(struct dt_info * dti,const char * name,bool allocph)1051*12d638f4SRob Herring (Arm) void generate_label_tree(struct dt_info *dti, const char *name, bool allocph)
10526f05afcbSRob Herring {
10536f05afcbSRob Herring if (!any_label_tree(dti, dti->dt))
10546f05afcbSRob Herring return;
10556f05afcbSRob Herring generate_label_tree_internal(dti, build_root_node(dti->dt, name),
10566f05afcbSRob Herring dti->dt, allocph);
10576f05afcbSRob Herring }
10586f05afcbSRob Herring
generate_fixups_tree(struct dt_info * dti,const char * name)1059*12d638f4SRob Herring (Arm) void generate_fixups_tree(struct dt_info *dti, const char *name)
10606f05afcbSRob Herring {
10616f05afcbSRob Herring if (!any_fixup_tree(dti, dti->dt))
10626f05afcbSRob Herring return;
10636f05afcbSRob Herring generate_fixups_tree_internal(dti, build_root_node(dti->dt, name),
10646f05afcbSRob Herring dti->dt);
10656f05afcbSRob Herring }
10666f05afcbSRob Herring
generate_local_fixups_tree(struct dt_info * dti,const char * name)1067*12d638f4SRob Herring (Arm) void generate_local_fixups_tree(struct dt_info *dti, const char *name)
10686f05afcbSRob Herring {
10696f05afcbSRob Herring if (!any_local_fixup_tree(dti, dti->dt))
10706f05afcbSRob Herring return;
10716f05afcbSRob Herring generate_local_fixups_tree_internal(dti, build_root_node(dti->dt, name),
10726f05afcbSRob Herring dti->dt);
1073658f29a5SJohn Bonesio }
1074