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(char * name,struct data val,struct srcpos * srcpos)39c2e7075cSRob Herring struct property *build_property(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
469fffb55fSDavid Gibson new->name = 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(char * name)53cd296721SStephen Warren struct property *build_property_delete(char *name)
54cd296721SStephen Warren {
55cd296721SStephen Warren struct property *new = xmalloc(sizeof(*new));
56cd296721SStephen Warren
57cd296721SStephen Warren memset(new, 0, sizeof(*new));
58cd296721SStephen Warren
59cd296721SStephen Warren new->name = 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,char * name)119658f29a5SJohn Bonesio struct node *name_node(struct node *node, char *name)
1209fffb55fSDavid Gibson {
1219fffb55fSDavid Gibson assert(node->name == NULL);
1229fffb55fSDavid Gibson
1239fffb55fSDavid Gibson node->name = 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);
2534201d057SRob Herring
2544201d057SRob Herring add_child(dt, node);
2559130ba88SRob Herring return dt;
2564201d057SRob Herring }
2574201d057SRob Herring
chain_node(struct node * first,struct node * list)2589fffb55fSDavid Gibson struct node *chain_node(struct node *first, struct node *list)
2599fffb55fSDavid Gibson {
2609fffb55fSDavid Gibson assert(first->next_sibling == NULL);
2619fffb55fSDavid Gibson
2629fffb55fSDavid Gibson first->next_sibling = list;
2639fffb55fSDavid Gibson return first;
2649fffb55fSDavid Gibson }
2659fffb55fSDavid Gibson
add_property(struct node * node,struct property * prop)2669fffb55fSDavid Gibson void add_property(struct node *node, struct property *prop)
2679fffb55fSDavid Gibson {
2689fffb55fSDavid Gibson struct property **p;
2699fffb55fSDavid Gibson
2709fffb55fSDavid Gibson prop->next = NULL;
2719fffb55fSDavid Gibson
2729fffb55fSDavid Gibson p = &node->proplist;
2739fffb55fSDavid Gibson while (*p)
2749fffb55fSDavid Gibson p = &((*p)->next);
2759fffb55fSDavid Gibson
2769fffb55fSDavid Gibson *p = prop;
2779fffb55fSDavid Gibson }
2789fffb55fSDavid Gibson
delete_property_by_name(struct node * node,char * name)279cd296721SStephen Warren void delete_property_by_name(struct node *node, char *name)
280cd296721SStephen Warren {
281cd296721SStephen Warren struct property *prop = node->proplist;
282cd296721SStephen Warren
283cd296721SStephen Warren while (prop) {
28489d12310SRob Herring if (streq(prop->name, name)) {
285cd296721SStephen Warren delete_property(prop);
286cd296721SStephen Warren return;
287cd296721SStephen Warren }
288cd296721SStephen Warren prop = prop->next;
289cd296721SStephen Warren }
290cd296721SStephen Warren }
291cd296721SStephen Warren
delete_property(struct property * prop)292cd296721SStephen Warren void delete_property(struct property *prop)
293cd296721SStephen Warren {
294cd296721SStephen Warren prop->deleted = 1;
295cd296721SStephen Warren delete_labels(&prop->labels);
296cd296721SStephen Warren }
297cd296721SStephen Warren
add_child(struct node * parent,struct node * child)2989fffb55fSDavid Gibson void add_child(struct node *parent, struct node *child)
2999fffb55fSDavid Gibson {
3009fffb55fSDavid Gibson struct node **p;
3019fffb55fSDavid Gibson
3029fffb55fSDavid Gibson child->next_sibling = NULL;
3039fffb55fSDavid Gibson child->parent = parent;
3049fffb55fSDavid Gibson
3059fffb55fSDavid Gibson p = &parent->children;
3069fffb55fSDavid Gibson while (*p)
3079fffb55fSDavid Gibson p = &((*p)->next_sibling);
3089fffb55fSDavid Gibson
3099fffb55fSDavid Gibson *p = child;
3109fffb55fSDavid Gibson }
3119fffb55fSDavid Gibson
delete_node_by_name(struct node * parent,char * name)312cd296721SStephen Warren void delete_node_by_name(struct node *parent, char *name)
313cd296721SStephen Warren {
314cd296721SStephen Warren struct node *node = parent->children;
315cd296721SStephen Warren
316cd296721SStephen Warren while (node) {
31789d12310SRob Herring if (streq(node->name, name)) {
318cd296721SStephen Warren delete_node(node);
319cd296721SStephen Warren return;
320cd296721SStephen Warren }
321cd296721SStephen Warren node = node->next_sibling;
322cd296721SStephen Warren }
323cd296721SStephen Warren }
324cd296721SStephen Warren
delete_node(struct node * node)325cd296721SStephen Warren void delete_node(struct node *node)
326cd296721SStephen Warren {
327cd296721SStephen Warren struct property *prop;
328cd296721SStephen Warren struct node *child;
329cd296721SStephen Warren
330cd296721SStephen Warren node->deleted = 1;
331cd296721SStephen Warren for_each_child(node, child)
332cd296721SStephen Warren delete_node(child);
333cd296721SStephen Warren for_each_property(node, prop)
334cd296721SStephen Warren delete_property(prop);
335cd296721SStephen Warren delete_labels(&node->labels);
336cd296721SStephen Warren }
337cd296721SStephen Warren
append_to_property(struct node * node,char * name,const void * data,int len,enum markertype type)3386f05afcbSRob Herring void append_to_property(struct node *node,
3399bb9c6a1SRob Herring char *name, const void *data, int len,
3409bb9c6a1SRob Herring enum markertype type)
3416f05afcbSRob Herring {
3426f05afcbSRob Herring struct data d;
3436f05afcbSRob Herring struct property *p;
3446f05afcbSRob Herring
3456f05afcbSRob Herring p = get_property(node, name);
3466f05afcbSRob Herring if (p) {
3479bb9c6a1SRob Herring d = data_add_marker(p->val, type, name);
3489bb9c6a1SRob Herring d = data_append_data(d, data, len);
3496f05afcbSRob Herring p->val = d;
3506f05afcbSRob Herring } else {
3519bb9c6a1SRob Herring d = data_add_marker(empty_data, type, name);
3529bb9c6a1SRob Herring d = data_append_data(d, data, len);
353c2e7075cSRob Herring p = build_property(name, d, NULL);
3546f05afcbSRob Herring add_property(node, p);
3556f05afcbSRob Herring }
3566f05afcbSRob Herring }
3576f05afcbSRob Herring
build_reserve_entry(uint64_t address,uint64_t size)358658f29a5SJohn Bonesio struct reserve_info *build_reserve_entry(uint64_t address, uint64_t size)
3599fffb55fSDavid Gibson {
3609fffb55fSDavid Gibson struct reserve_info *new = xmalloc(sizeof(*new));
3619fffb55fSDavid Gibson
362658f29a5SJohn Bonesio memset(new, 0, sizeof(*new));
363658f29a5SJohn Bonesio
36489d12310SRob Herring new->address = address;
36589d12310SRob Herring new->size = size;
3669fffb55fSDavid Gibson
3679fffb55fSDavid Gibson return new;
3689fffb55fSDavid Gibson }
3699fffb55fSDavid Gibson
chain_reserve_entry(struct reserve_info * first,struct reserve_info * list)3709fffb55fSDavid Gibson struct reserve_info *chain_reserve_entry(struct reserve_info *first,
3719fffb55fSDavid Gibson struct reserve_info *list)
3729fffb55fSDavid Gibson {
3739fffb55fSDavid Gibson assert(first->next == NULL);
3749fffb55fSDavid Gibson
3759fffb55fSDavid Gibson first->next = list;
3769fffb55fSDavid Gibson return first;
3779fffb55fSDavid Gibson }
3789fffb55fSDavid Gibson
add_reserve_entry(struct reserve_info * list,struct reserve_info * new)3799fffb55fSDavid Gibson struct reserve_info *add_reserve_entry(struct reserve_info *list,
3809fffb55fSDavid Gibson struct reserve_info *new)
3819fffb55fSDavid Gibson {
3829fffb55fSDavid Gibson struct reserve_info *last;
3839fffb55fSDavid Gibson
3849fffb55fSDavid Gibson new->next = NULL;
3859fffb55fSDavid Gibson
3869fffb55fSDavid Gibson if (! list)
3879fffb55fSDavid Gibson return new;
3889fffb55fSDavid Gibson
3899fffb55fSDavid Gibson for (last = list; last->next; last = last->next)
3909fffb55fSDavid Gibson ;
3919fffb55fSDavid Gibson
3929fffb55fSDavid Gibson last->next = new;
3939fffb55fSDavid Gibson
3949fffb55fSDavid Gibson return list;
3959fffb55fSDavid Gibson }
3969fffb55fSDavid Gibson
build_dt_info(unsigned int dtsflags,struct reserve_info * reservelist,struct node * tree,uint32_t boot_cpuid_phys)3976f05afcbSRob Herring struct dt_info *build_dt_info(unsigned int dtsflags,
3986f05afcbSRob Herring struct reserve_info *reservelist,
3999fffb55fSDavid Gibson struct node *tree, uint32_t boot_cpuid_phys)
4009fffb55fSDavid Gibson {
4016f05afcbSRob Herring struct dt_info *dti;
4029fffb55fSDavid Gibson
4036f05afcbSRob Herring dti = xmalloc(sizeof(*dti));
4046f05afcbSRob Herring dti->dtsflags = dtsflags;
4056f05afcbSRob Herring dti->reservelist = reservelist;
4066f05afcbSRob Herring dti->dt = tree;
4076f05afcbSRob Herring dti->boot_cpuid_phys = boot_cpuid_phys;
4089fffb55fSDavid Gibson
4096f05afcbSRob Herring return dti;
4109fffb55fSDavid Gibson }
4119fffb55fSDavid Gibson
4129fffb55fSDavid Gibson /*
4139fffb55fSDavid Gibson * Tree accessor functions
4149fffb55fSDavid Gibson */
4159fffb55fSDavid Gibson
get_unitname(struct node * node)4169fffb55fSDavid Gibson const char *get_unitname(struct node *node)
4179fffb55fSDavid Gibson {
4189fffb55fSDavid Gibson if (node->name[node->basenamelen] == '\0')
4199fffb55fSDavid Gibson return "";
4209fffb55fSDavid Gibson else
4219fffb55fSDavid Gibson return node->name + node->basenamelen + 1;
4229fffb55fSDavid Gibson }
4239fffb55fSDavid Gibson
get_property(struct node * node,const char * propname)4249fffb55fSDavid Gibson struct property *get_property(struct node *node, const char *propname)
4259fffb55fSDavid Gibson {
4269fffb55fSDavid Gibson struct property *prop;
4279fffb55fSDavid Gibson
4289fffb55fSDavid Gibson for_each_property(node, prop)
4299fffb55fSDavid Gibson if (streq(prop->name, propname))
4309fffb55fSDavid Gibson return prop;
4319fffb55fSDavid Gibson
4329fffb55fSDavid Gibson return NULL;
4339fffb55fSDavid Gibson }
4349fffb55fSDavid Gibson
propval_cell(struct property * prop)4359fffb55fSDavid Gibson cell_t propval_cell(struct property *prop)
4369fffb55fSDavid Gibson {
4379fffb55fSDavid Gibson assert(prop->val.len == sizeof(cell_t));
43889d12310SRob Herring return fdt32_to_cpu(*((fdt32_t *)prop->val.val));
4399fffb55fSDavid Gibson }
4409fffb55fSDavid Gibson
propval_cell_n(struct property * prop,unsigned int n)44179edff12SRob Herring cell_t propval_cell_n(struct property *prop, unsigned int n)
4424201d057SRob Herring {
4434201d057SRob Herring assert(prop->val.len / sizeof(cell_t) >= n);
4444201d057SRob Herring return fdt32_to_cpu(*((fdt32_t *)prop->val.val + n));
4454201d057SRob Herring }
4464201d057SRob Herring
get_property_by_label(struct node * tree,const char * label,struct node ** node)447658f29a5SJohn Bonesio struct property *get_property_by_label(struct node *tree, const char *label,
448658f29a5SJohn Bonesio struct node **node)
449658f29a5SJohn Bonesio {
450658f29a5SJohn Bonesio struct property *prop;
451658f29a5SJohn Bonesio struct node *c;
452658f29a5SJohn Bonesio
453658f29a5SJohn Bonesio *node = tree;
454658f29a5SJohn Bonesio
455658f29a5SJohn Bonesio for_each_property(tree, prop) {
456658f29a5SJohn Bonesio struct label *l;
457658f29a5SJohn Bonesio
458658f29a5SJohn Bonesio for_each_label(prop->labels, l)
459658f29a5SJohn Bonesio if (streq(l->label, label))
460658f29a5SJohn Bonesio return prop;
461658f29a5SJohn Bonesio }
462658f29a5SJohn Bonesio
463658f29a5SJohn Bonesio for_each_child(tree, c) {
464658f29a5SJohn Bonesio prop = get_property_by_label(c, label, node);
465658f29a5SJohn Bonesio if (prop)
466658f29a5SJohn Bonesio return prop;
467658f29a5SJohn Bonesio }
468658f29a5SJohn Bonesio
469658f29a5SJohn Bonesio *node = NULL;
470658f29a5SJohn Bonesio return NULL;
471658f29a5SJohn Bonesio }
472658f29a5SJohn Bonesio
get_marker_label(struct node * tree,const char * label,struct node ** node,struct property ** prop)473658f29a5SJohn Bonesio struct marker *get_marker_label(struct node *tree, const char *label,
474658f29a5SJohn Bonesio struct node **node, struct property **prop)
475658f29a5SJohn Bonesio {
476658f29a5SJohn Bonesio struct marker *m;
477658f29a5SJohn Bonesio struct property *p;
478658f29a5SJohn Bonesio struct node *c;
479658f29a5SJohn Bonesio
480658f29a5SJohn Bonesio *node = tree;
481658f29a5SJohn Bonesio
482658f29a5SJohn Bonesio for_each_property(tree, p) {
483658f29a5SJohn Bonesio *prop = p;
484658f29a5SJohn Bonesio m = p->val.markers;
485658f29a5SJohn Bonesio for_each_marker_of_type(m, LABEL)
486658f29a5SJohn Bonesio if (streq(m->ref, label))
487658f29a5SJohn Bonesio return m;
488658f29a5SJohn Bonesio }
489658f29a5SJohn Bonesio
490658f29a5SJohn Bonesio for_each_child(tree, c) {
491658f29a5SJohn Bonesio m = get_marker_label(c, label, node, prop);
492658f29a5SJohn Bonesio if (m)
493658f29a5SJohn Bonesio return m;
494658f29a5SJohn Bonesio }
495658f29a5SJohn Bonesio
496658f29a5SJohn Bonesio *prop = NULL;
497658f29a5SJohn Bonesio *node = NULL;
498658f29a5SJohn Bonesio return NULL;
499658f29a5SJohn Bonesio }
500658f29a5SJohn Bonesio
get_subnode(struct node * node,const char * nodename)5019fffb55fSDavid Gibson struct node *get_subnode(struct node *node, const char *nodename)
5029fffb55fSDavid Gibson {
5039fffb55fSDavid Gibson struct node *child;
5049fffb55fSDavid Gibson
5059fffb55fSDavid Gibson for_each_child(node, child)
5069fffb55fSDavid Gibson if (streq(child->name, nodename))
5079fffb55fSDavid Gibson return child;
5089fffb55fSDavid Gibson
5099fffb55fSDavid Gibson return NULL;
5109fffb55fSDavid Gibson }
5119fffb55fSDavid Gibson
get_node_by_path(struct node * tree,const char * path)5129fffb55fSDavid Gibson struct node *get_node_by_path(struct node *tree, const char *path)
5139fffb55fSDavid Gibson {
5149fffb55fSDavid Gibson const char *p;
5159fffb55fSDavid Gibson struct node *child;
5169fffb55fSDavid Gibson
517cd296721SStephen Warren if (!path || ! (*path)) {
518cd296721SStephen Warren if (tree->deleted)
519cd296721SStephen Warren return NULL;
5209fffb55fSDavid Gibson return tree;
521cd296721SStephen Warren }
5229fffb55fSDavid Gibson
5239fffb55fSDavid Gibson while (path[0] == '/')
5249fffb55fSDavid Gibson path++;
5259fffb55fSDavid Gibson
5269fffb55fSDavid Gibson p = strchr(path, '/');
5279fffb55fSDavid Gibson
5289fffb55fSDavid Gibson for_each_child(tree, child) {
529a77725a9SRob Herring if (p && strprefixeq(path, (size_t)(p - path), child->name))
5309fffb55fSDavid Gibson return get_node_by_path(child, p+1);
5319fffb55fSDavid Gibson else if (!p && streq(path, child->name))
5329fffb55fSDavid Gibson return child;
5339fffb55fSDavid Gibson }
5349fffb55fSDavid Gibson
5359fffb55fSDavid Gibson return NULL;
5369fffb55fSDavid Gibson }
5379fffb55fSDavid Gibson
get_node_by_label(struct node * tree,const char * label)5389fffb55fSDavid Gibson struct node *get_node_by_label(struct node *tree, const char *label)
5399fffb55fSDavid Gibson {
5409fffb55fSDavid Gibson struct node *child, *node;
541658f29a5SJohn Bonesio struct label *l;
5429fffb55fSDavid Gibson
5439fffb55fSDavid Gibson assert(label && (strlen(label) > 0));
5449fffb55fSDavid Gibson
545658f29a5SJohn Bonesio for_each_label(tree->labels, l)
546658f29a5SJohn Bonesio if (streq(l->label, label))
5479fffb55fSDavid Gibson return tree;
5489fffb55fSDavid Gibson
5499fffb55fSDavid Gibson for_each_child(tree, child) {
5509fffb55fSDavid Gibson node = get_node_by_label(child, label);
5519fffb55fSDavid Gibson if (node)
5529fffb55fSDavid Gibson return node;
5539fffb55fSDavid Gibson }
5549fffb55fSDavid Gibson
5559fffb55fSDavid Gibson return NULL;
5569fffb55fSDavid Gibson }
5579fffb55fSDavid Gibson
get_node_by_phandle(struct node * tree,cell_t phandle)5589fffb55fSDavid Gibson struct node *get_node_by_phandle(struct node *tree, cell_t phandle)
5599fffb55fSDavid Gibson {
5609fffb55fSDavid Gibson struct node *child, *node;
5619fffb55fSDavid Gibson
562a77725a9SRob Herring if (!phandle_is_valid(phandle)) {
5639130ba88SRob Herring assert(generate_fixups);
5649130ba88SRob Herring return NULL;
5659130ba88SRob Herring }
5669fffb55fSDavid Gibson
567cd296721SStephen Warren if (tree->phandle == phandle) {
568cd296721SStephen Warren if (tree->deleted)
569cd296721SStephen Warren return NULL;
5709fffb55fSDavid Gibson return tree;
571cd296721SStephen Warren }
5729fffb55fSDavid Gibson
5739fffb55fSDavid Gibson for_each_child(tree, child) {
5749fffb55fSDavid Gibson node = get_node_by_phandle(child, phandle);
5759fffb55fSDavid Gibson if (node)
5769fffb55fSDavid Gibson return node;
5779fffb55fSDavid Gibson }
5789fffb55fSDavid Gibson
5799fffb55fSDavid Gibson return NULL;
5809fffb55fSDavid Gibson }
5819fffb55fSDavid Gibson
get_node_by_ref(struct node * tree,const char * ref)5829fffb55fSDavid Gibson struct node *get_node_by_ref(struct node *tree, const char *ref)
5839fffb55fSDavid Gibson {
584*ea3723a5SRob Herring struct node *target = tree;
585*ea3723a5SRob Herring const char *label = NULL, *path = NULL;
586*ea3723a5SRob Herring
58747605971SRob Herring if (streq(ref, "/"))
58847605971SRob Herring return tree;
589*ea3723a5SRob Herring
590*ea3723a5SRob Herring if (ref[0] == '/')
591*ea3723a5SRob Herring path = ref;
5929fffb55fSDavid Gibson else
593*ea3723a5SRob Herring label = ref;
594*ea3723a5SRob Herring
595*ea3723a5SRob Herring if (label) {
596*ea3723a5SRob Herring const char *slash = strchr(label, '/');
597*ea3723a5SRob Herring char *buf = NULL;
598*ea3723a5SRob Herring
599*ea3723a5SRob Herring if (slash) {
600*ea3723a5SRob Herring buf = xstrndup(label, slash - label);
601*ea3723a5SRob Herring label = buf;
602*ea3723a5SRob Herring path = slash + 1;
603*ea3723a5SRob Herring }
604*ea3723a5SRob Herring
605*ea3723a5SRob Herring target = get_node_by_label(tree, label);
606*ea3723a5SRob Herring
607*ea3723a5SRob Herring free(buf);
608*ea3723a5SRob Herring
609*ea3723a5SRob Herring if (!target)
610*ea3723a5SRob Herring return NULL;
611*ea3723a5SRob Herring }
612*ea3723a5SRob Herring
613*ea3723a5SRob Herring if (path)
614*ea3723a5SRob Herring target = get_node_by_path(target, path);
615*ea3723a5SRob Herring
616*ea3723a5SRob Herring return target;
6179fffb55fSDavid Gibson }
6189fffb55fSDavid Gibson
get_node_phandle(struct node * root,struct node * node)6199fffb55fSDavid Gibson cell_t get_node_phandle(struct node *root, struct node *node)
6209fffb55fSDavid Gibson {
6219fffb55fSDavid Gibson static cell_t phandle = 1; /* FIXME: ick, static local */
622f858927fSRob Herring struct data d = empty_data;
6239fffb55fSDavid Gibson
624a77725a9SRob Herring if (phandle_is_valid(node->phandle))
6259fffb55fSDavid Gibson return node->phandle;
6269fffb55fSDavid Gibson
6279fffb55fSDavid Gibson while (get_node_by_phandle(root, phandle))
6289fffb55fSDavid Gibson phandle++;
6299fffb55fSDavid Gibson
6309fffb55fSDavid Gibson node->phandle = phandle;
631658f29a5SJohn Bonesio
632f858927fSRob Herring d = data_add_marker(d, TYPE_UINT32, NULL);
633f858927fSRob Herring d = data_append_cell(d, phandle);
634f858927fSRob Herring
635658f29a5SJohn Bonesio if (!get_property(node, "linux,phandle")
636658f29a5SJohn Bonesio && (phandle_format & PHANDLE_LEGACY))
637c2e7075cSRob Herring add_property(node, build_property("linux,phandle", d, NULL));
638658f29a5SJohn Bonesio
639658f29a5SJohn Bonesio if (!get_property(node, "phandle")
640658f29a5SJohn Bonesio && (phandle_format & PHANDLE_EPAPR))
641c2e7075cSRob Herring add_property(node, build_property("phandle", d, NULL));
642658f29a5SJohn Bonesio
643658f29a5SJohn Bonesio /* If the node *does* have a phandle property, we must
644658f29a5SJohn Bonesio * be dealing with a self-referencing phandle, which will be
645658f29a5SJohn Bonesio * fixed up momentarily in the caller */
6469fffb55fSDavid Gibson
6479fffb55fSDavid Gibson return node->phandle;
6489fffb55fSDavid Gibson }
649658f29a5SJohn Bonesio
guess_boot_cpuid(struct node * tree)650658f29a5SJohn Bonesio uint32_t guess_boot_cpuid(struct node *tree)
651658f29a5SJohn Bonesio {
652658f29a5SJohn Bonesio struct node *cpus, *bootcpu;
653658f29a5SJohn Bonesio struct property *reg;
654658f29a5SJohn Bonesio
655658f29a5SJohn Bonesio cpus = get_node_by_path(tree, "/cpus");
656658f29a5SJohn Bonesio if (!cpus)
657658f29a5SJohn Bonesio return 0;
658658f29a5SJohn Bonesio
659658f29a5SJohn Bonesio
660658f29a5SJohn Bonesio bootcpu = cpus->children;
661658f29a5SJohn Bonesio if (!bootcpu)
662658f29a5SJohn Bonesio return 0;
663658f29a5SJohn Bonesio
664658f29a5SJohn Bonesio reg = get_property(bootcpu, "reg");
665658f29a5SJohn Bonesio if (!reg || (reg->val.len != sizeof(uint32_t)))
666658f29a5SJohn Bonesio return 0;
667658f29a5SJohn Bonesio
668658f29a5SJohn Bonesio /* FIXME: Sanity check node? */
669658f29a5SJohn Bonesio
670658f29a5SJohn Bonesio return propval_cell(reg);
671658f29a5SJohn Bonesio }
672658f29a5SJohn Bonesio
cmp_reserve_info(const void * ax,const void * bx)673658f29a5SJohn Bonesio static int cmp_reserve_info(const void *ax, const void *bx)
674658f29a5SJohn Bonesio {
675658f29a5SJohn Bonesio const struct reserve_info *a, *b;
676658f29a5SJohn Bonesio
677658f29a5SJohn Bonesio a = *((const struct reserve_info * const *)ax);
678658f29a5SJohn Bonesio b = *((const struct reserve_info * const *)bx);
679658f29a5SJohn Bonesio
68089d12310SRob Herring if (a->address < b->address)
681658f29a5SJohn Bonesio return -1;
68289d12310SRob Herring else if (a->address > b->address)
683658f29a5SJohn Bonesio return 1;
68489d12310SRob Herring else if (a->size < b->size)
685658f29a5SJohn Bonesio return -1;
68689d12310SRob Herring else if (a->size > b->size)
687658f29a5SJohn Bonesio return 1;
688658f29a5SJohn Bonesio else
689658f29a5SJohn Bonesio return 0;
690658f29a5SJohn Bonesio }
691658f29a5SJohn Bonesio
sort_reserve_entries(struct dt_info * dti)6926f05afcbSRob Herring static void sort_reserve_entries(struct dt_info *dti)
693658f29a5SJohn Bonesio {
694658f29a5SJohn Bonesio struct reserve_info *ri, **tbl;
695658f29a5SJohn Bonesio int n = 0, i = 0;
696658f29a5SJohn Bonesio
6976f05afcbSRob Herring for (ri = dti->reservelist;
698658f29a5SJohn Bonesio ri;
699658f29a5SJohn Bonesio ri = ri->next)
700658f29a5SJohn Bonesio n++;
701658f29a5SJohn Bonesio
702658f29a5SJohn Bonesio if (n == 0)
703658f29a5SJohn Bonesio return;
704658f29a5SJohn Bonesio
705658f29a5SJohn Bonesio tbl = xmalloc(n * sizeof(*tbl));
706658f29a5SJohn Bonesio
7076f05afcbSRob Herring for (ri = dti->reservelist;
708658f29a5SJohn Bonesio ri;
709658f29a5SJohn Bonesio ri = ri->next)
710658f29a5SJohn Bonesio tbl[i++] = ri;
711658f29a5SJohn Bonesio
712658f29a5SJohn Bonesio qsort(tbl, n, sizeof(*tbl), cmp_reserve_info);
713658f29a5SJohn Bonesio
7146f05afcbSRob Herring dti->reservelist = tbl[0];
715658f29a5SJohn Bonesio for (i = 0; i < (n-1); i++)
716658f29a5SJohn Bonesio tbl[i]->next = tbl[i+1];
717658f29a5SJohn Bonesio tbl[n-1]->next = NULL;
718658f29a5SJohn Bonesio
719658f29a5SJohn Bonesio free(tbl);
720658f29a5SJohn Bonesio }
721658f29a5SJohn Bonesio
cmp_prop(const void * ax,const void * bx)722658f29a5SJohn Bonesio static int cmp_prop(const void *ax, const void *bx)
723658f29a5SJohn Bonesio {
724658f29a5SJohn Bonesio const struct property *a, *b;
725658f29a5SJohn Bonesio
726658f29a5SJohn Bonesio a = *((const struct property * const *)ax);
727658f29a5SJohn Bonesio b = *((const struct property * const *)bx);
728658f29a5SJohn Bonesio
729658f29a5SJohn Bonesio return strcmp(a->name, b->name);
730658f29a5SJohn Bonesio }
731658f29a5SJohn Bonesio
sort_properties(struct node * node)732658f29a5SJohn Bonesio static void sort_properties(struct node *node)
733658f29a5SJohn Bonesio {
734658f29a5SJohn Bonesio int n = 0, i = 0;
735658f29a5SJohn Bonesio struct property *prop, **tbl;
736658f29a5SJohn Bonesio
737cd296721SStephen Warren for_each_property_withdel(node, prop)
738658f29a5SJohn Bonesio n++;
739658f29a5SJohn Bonesio
740658f29a5SJohn Bonesio if (n == 0)
741658f29a5SJohn Bonesio return;
742658f29a5SJohn Bonesio
743658f29a5SJohn Bonesio tbl = xmalloc(n * sizeof(*tbl));
744658f29a5SJohn Bonesio
745cd296721SStephen Warren for_each_property_withdel(node, prop)
746658f29a5SJohn Bonesio tbl[i++] = prop;
747658f29a5SJohn Bonesio
748658f29a5SJohn Bonesio qsort(tbl, n, sizeof(*tbl), cmp_prop);
749658f29a5SJohn Bonesio
750658f29a5SJohn Bonesio node->proplist = tbl[0];
751658f29a5SJohn Bonesio for (i = 0; i < (n-1); i++)
752658f29a5SJohn Bonesio tbl[i]->next = tbl[i+1];
753658f29a5SJohn Bonesio tbl[n-1]->next = NULL;
754658f29a5SJohn Bonesio
755658f29a5SJohn Bonesio free(tbl);
756658f29a5SJohn Bonesio }
757658f29a5SJohn Bonesio
cmp_subnode(const void * ax,const void * bx)758658f29a5SJohn Bonesio static int cmp_subnode(const void *ax, const void *bx)
759658f29a5SJohn Bonesio {
760658f29a5SJohn Bonesio const struct node *a, *b;
761658f29a5SJohn Bonesio
762658f29a5SJohn Bonesio a = *((const struct node * const *)ax);
763658f29a5SJohn Bonesio b = *((const struct node * const *)bx);
764658f29a5SJohn Bonesio
765658f29a5SJohn Bonesio return strcmp(a->name, b->name);
766658f29a5SJohn Bonesio }
767658f29a5SJohn Bonesio
sort_subnodes(struct node * node)768658f29a5SJohn Bonesio static void sort_subnodes(struct node *node)
769658f29a5SJohn Bonesio {
770658f29a5SJohn Bonesio int n = 0, i = 0;
771658f29a5SJohn Bonesio struct node *subnode, **tbl;
772658f29a5SJohn Bonesio
773cd296721SStephen Warren for_each_child_withdel(node, subnode)
774658f29a5SJohn Bonesio n++;
775658f29a5SJohn Bonesio
776658f29a5SJohn Bonesio if (n == 0)
777658f29a5SJohn Bonesio return;
778658f29a5SJohn Bonesio
779658f29a5SJohn Bonesio tbl = xmalloc(n * sizeof(*tbl));
780658f29a5SJohn Bonesio
781cd296721SStephen Warren for_each_child_withdel(node, subnode)
782658f29a5SJohn Bonesio tbl[i++] = subnode;
783658f29a5SJohn Bonesio
784658f29a5SJohn Bonesio qsort(tbl, n, sizeof(*tbl), cmp_subnode);
785658f29a5SJohn Bonesio
786658f29a5SJohn Bonesio node->children = tbl[0];
787658f29a5SJohn Bonesio for (i = 0; i < (n-1); i++)
788658f29a5SJohn Bonesio tbl[i]->next_sibling = tbl[i+1];
789658f29a5SJohn Bonesio tbl[n-1]->next_sibling = NULL;
790658f29a5SJohn Bonesio
791658f29a5SJohn Bonesio free(tbl);
792658f29a5SJohn Bonesio }
793658f29a5SJohn Bonesio
sort_node(struct node * node)794658f29a5SJohn Bonesio static void sort_node(struct node *node)
795658f29a5SJohn Bonesio {
796658f29a5SJohn Bonesio struct node *c;
797658f29a5SJohn Bonesio
798658f29a5SJohn Bonesio sort_properties(node);
799658f29a5SJohn Bonesio sort_subnodes(node);
800cd296721SStephen Warren for_each_child_withdel(node, c)
801658f29a5SJohn Bonesio sort_node(c);
802658f29a5SJohn Bonesio }
803658f29a5SJohn Bonesio
sort_tree(struct dt_info * dti)8046f05afcbSRob Herring void sort_tree(struct dt_info *dti)
805658f29a5SJohn Bonesio {
8066f05afcbSRob Herring sort_reserve_entries(dti);
8076f05afcbSRob Herring sort_node(dti->dt);
8086f05afcbSRob Herring }
8096f05afcbSRob Herring
8106f05afcbSRob Herring /* utility helper to avoid code duplication */
build_and_name_child_node(struct node * parent,char * name)8116f05afcbSRob Herring static struct node *build_and_name_child_node(struct node *parent, char *name)
8126f05afcbSRob Herring {
8136f05afcbSRob Herring struct node *node;
8146f05afcbSRob Herring
815c2e7075cSRob Herring node = build_node(NULL, NULL, NULL);
8166f05afcbSRob Herring name_node(node, xstrdup(name));
8176f05afcbSRob Herring add_child(parent, node);
8186f05afcbSRob Herring
8196f05afcbSRob Herring return node;
8206f05afcbSRob Herring }
8216f05afcbSRob Herring
build_root_node(struct node * dt,char * name)8226f05afcbSRob Herring static struct node *build_root_node(struct node *dt, char *name)
8236f05afcbSRob Herring {
8246f05afcbSRob Herring struct node *an;
8256f05afcbSRob Herring
8266f05afcbSRob Herring an = get_subnode(dt, name);
8276f05afcbSRob Herring if (!an)
8286f05afcbSRob Herring an = build_and_name_child_node(dt, name);
8296f05afcbSRob Herring
8306f05afcbSRob Herring if (!an)
8316f05afcbSRob Herring die("Could not build root node /%s\n", name);
8326f05afcbSRob Herring
8336f05afcbSRob Herring return an;
8346f05afcbSRob Herring }
8356f05afcbSRob Herring
any_label_tree(struct dt_info * dti,struct node * node)8366f05afcbSRob Herring static bool any_label_tree(struct dt_info *dti, struct node *node)
8376f05afcbSRob Herring {
8386f05afcbSRob Herring struct node *c;
8396f05afcbSRob Herring
8406f05afcbSRob Herring if (node->labels)
8416f05afcbSRob Herring return true;
8426f05afcbSRob Herring
8436f05afcbSRob Herring for_each_child(node, c)
8446f05afcbSRob Herring if (any_label_tree(dti, c))
8456f05afcbSRob Herring return true;
8466f05afcbSRob Herring
8476f05afcbSRob Herring return false;
8486f05afcbSRob Herring }
8496f05afcbSRob Herring
generate_label_tree_internal(struct dt_info * dti,struct node * an,struct node * node,bool allocph)8506f05afcbSRob Herring static void generate_label_tree_internal(struct dt_info *dti,
8516f05afcbSRob Herring struct node *an, struct node *node,
8526f05afcbSRob Herring bool allocph)
8536f05afcbSRob Herring {
8546f05afcbSRob Herring struct node *dt = dti->dt;
8556f05afcbSRob Herring struct node *c;
8566f05afcbSRob Herring struct property *p;
8576f05afcbSRob Herring struct label *l;
8586f05afcbSRob Herring
8596f05afcbSRob Herring /* if there are labels */
8606f05afcbSRob Herring if (node->labels) {
8616f05afcbSRob Herring
8626f05afcbSRob Herring /* now add the label in the node */
8636f05afcbSRob Herring for_each_label(node->labels, l) {
8646f05afcbSRob Herring
8656f05afcbSRob Herring /* check whether the label already exists */
8666f05afcbSRob Herring p = get_property(an, l->label);
8676f05afcbSRob Herring if (p) {
8686f05afcbSRob Herring fprintf(stderr, "WARNING: label %s already"
8696f05afcbSRob Herring " exists in /%s", l->label,
8706f05afcbSRob Herring an->name);
8716f05afcbSRob Herring continue;
8726f05afcbSRob Herring }
8736f05afcbSRob Herring
8746f05afcbSRob Herring /* insert it */
8756f05afcbSRob Herring p = build_property(l->label,
8769bb9c6a1SRob Herring data_copy_escape_string(node->fullpath,
8779bb9c6a1SRob Herring strlen(node->fullpath)),
878c2e7075cSRob Herring NULL);
8796f05afcbSRob Herring add_property(an, p);
8806f05afcbSRob Herring }
8816f05afcbSRob Herring
8826f05afcbSRob Herring /* force allocation of a phandle for this node */
8836f05afcbSRob Herring if (allocph)
8846f05afcbSRob Herring (void)get_node_phandle(dt, node);
8856f05afcbSRob Herring }
8866f05afcbSRob Herring
8876f05afcbSRob Herring for_each_child(node, c)
8886f05afcbSRob Herring generate_label_tree_internal(dti, an, c, allocph);
8896f05afcbSRob Herring }
8906f05afcbSRob Herring
any_fixup_tree(struct dt_info * dti,struct node * node)8916f05afcbSRob Herring static bool any_fixup_tree(struct dt_info *dti, struct node *node)
8926f05afcbSRob Herring {
8936f05afcbSRob Herring struct node *c;
8946f05afcbSRob Herring struct property *prop;
8956f05afcbSRob Herring struct marker *m;
8966f05afcbSRob Herring
8976f05afcbSRob Herring for_each_property(node, prop) {
8986f05afcbSRob Herring m = prop->val.markers;
8996f05afcbSRob Herring for_each_marker_of_type(m, REF_PHANDLE) {
9006f05afcbSRob Herring if (!get_node_by_ref(dti->dt, m->ref))
9016f05afcbSRob Herring return true;
9026f05afcbSRob Herring }
9036f05afcbSRob Herring }
9046f05afcbSRob Herring
9056f05afcbSRob Herring for_each_child(node, c) {
9066f05afcbSRob Herring if (any_fixup_tree(dti, c))
9076f05afcbSRob Herring return true;
9086f05afcbSRob Herring }
9096f05afcbSRob Herring
9106f05afcbSRob Herring return false;
9116f05afcbSRob Herring }
9126f05afcbSRob Herring
add_fixup_entry(struct dt_info * dti,struct node * fn,struct node * node,struct property * prop,struct marker * m)9136f05afcbSRob Herring static void add_fixup_entry(struct dt_info *dti, struct node *fn,
9146f05afcbSRob Herring struct node *node, struct property *prop,
9156f05afcbSRob Herring struct marker *m)
9166f05afcbSRob Herring {
9176f05afcbSRob Herring char *entry;
9186f05afcbSRob Herring
9196f05afcbSRob Herring /* m->ref can only be a REF_PHANDLE, but check anyway */
9206f05afcbSRob Herring assert(m->type == REF_PHANDLE);
9216f05afcbSRob Herring
922*ea3723a5SRob Herring /* The format only permits fixups for references to label, not
923*ea3723a5SRob Herring * references to path */
924*ea3723a5SRob Herring if (strchr(m->ref, '/'))
925*ea3723a5SRob Herring die("Can't generate fixup for reference to path &{%s}\n",
926*ea3723a5SRob Herring m->ref);
927*ea3723a5SRob Herring
9286f05afcbSRob Herring /* there shouldn't be any ':' in the arguments */
9296f05afcbSRob Herring if (strchr(node->fullpath, ':') || strchr(prop->name, ':'))
9306f05afcbSRob Herring die("arguments should not contain ':'\n");
9316f05afcbSRob Herring
9326f05afcbSRob Herring xasprintf(&entry, "%s:%s:%u",
9336f05afcbSRob Herring node->fullpath, prop->name, m->offset);
9349bb9c6a1SRob Herring append_to_property(fn, m->ref, entry, strlen(entry) + 1, TYPE_STRING);
93589d12310SRob Herring
93689d12310SRob Herring free(entry);
9376f05afcbSRob Herring }
9386f05afcbSRob Herring
generate_fixups_tree_internal(struct dt_info * dti,struct node * fn,struct node * node)9396f05afcbSRob Herring static void generate_fixups_tree_internal(struct dt_info *dti,
9406f05afcbSRob Herring struct node *fn,
9416f05afcbSRob Herring struct node *node)
9426f05afcbSRob Herring {
9436f05afcbSRob Herring struct node *dt = dti->dt;
9446f05afcbSRob Herring struct node *c;
9456f05afcbSRob Herring struct property *prop;
9466f05afcbSRob Herring struct marker *m;
9476f05afcbSRob Herring struct node *refnode;
9486f05afcbSRob Herring
9496f05afcbSRob Herring for_each_property(node, prop) {
9506f05afcbSRob Herring m = prop->val.markers;
9516f05afcbSRob Herring for_each_marker_of_type(m, REF_PHANDLE) {
9526f05afcbSRob Herring refnode = get_node_by_ref(dt, m->ref);
9536f05afcbSRob Herring if (!refnode)
9546f05afcbSRob Herring add_fixup_entry(dti, fn, node, prop, m);
9556f05afcbSRob Herring }
9566f05afcbSRob Herring }
9576f05afcbSRob Herring
9586f05afcbSRob Herring for_each_child(node, c)
9596f05afcbSRob Herring generate_fixups_tree_internal(dti, fn, c);
9606f05afcbSRob Herring }
9616f05afcbSRob Herring
any_local_fixup_tree(struct dt_info * dti,struct node * node)9626f05afcbSRob Herring static bool any_local_fixup_tree(struct dt_info *dti, struct node *node)
9636f05afcbSRob Herring {
9646f05afcbSRob Herring struct node *c;
9656f05afcbSRob Herring struct property *prop;
9666f05afcbSRob Herring struct marker *m;
9676f05afcbSRob Herring
9686f05afcbSRob Herring for_each_property(node, prop) {
9696f05afcbSRob Herring m = prop->val.markers;
9706f05afcbSRob Herring for_each_marker_of_type(m, REF_PHANDLE) {
9716f05afcbSRob Herring if (get_node_by_ref(dti->dt, m->ref))
9726f05afcbSRob Herring return true;
9736f05afcbSRob Herring }
9746f05afcbSRob Herring }
9756f05afcbSRob Herring
9766f05afcbSRob Herring for_each_child(node, c) {
9776f05afcbSRob Herring if (any_local_fixup_tree(dti, c))
9786f05afcbSRob Herring return true;
9796f05afcbSRob Herring }
9806f05afcbSRob Herring
9816f05afcbSRob Herring return false;
9826f05afcbSRob Herring }
9836f05afcbSRob Herring
add_local_fixup_entry(struct dt_info * dti,struct node * lfn,struct node * node,struct property * prop,struct marker * m,struct node * refnode)9846f05afcbSRob Herring static void add_local_fixup_entry(struct dt_info *dti,
9856f05afcbSRob Herring struct node *lfn, struct node *node,
9866f05afcbSRob Herring struct property *prop, struct marker *m,
9876f05afcbSRob Herring struct node *refnode)
9886f05afcbSRob Herring {
9896f05afcbSRob Herring struct node *wn, *nwn; /* local fixup node, walk node, new */
99089d12310SRob Herring fdt32_t value_32;
9916f05afcbSRob Herring char **compp;
9926f05afcbSRob Herring int i, depth;
9936f05afcbSRob Herring
9949bb9c6a1SRob Herring /* walk back retrieving depth */
9956f05afcbSRob Herring depth = 0;
9966f05afcbSRob Herring for (wn = node; wn; wn = wn->parent)
9976f05afcbSRob Herring depth++;
9986f05afcbSRob Herring
9996f05afcbSRob Herring /* allocate name array */
10006f05afcbSRob Herring compp = xmalloc(sizeof(*compp) * depth);
10016f05afcbSRob Herring
10026f05afcbSRob Herring /* store names in the array */
10036f05afcbSRob Herring for (wn = node, i = depth - 1; wn; wn = wn->parent, i--)
10046f05afcbSRob Herring compp[i] = wn->name;
10056f05afcbSRob Herring
10066f05afcbSRob Herring /* walk the path components creating nodes if they don't exist */
10076f05afcbSRob Herring for (wn = lfn, i = 1; i < depth; i++, wn = nwn) {
10086f05afcbSRob Herring /* if no node exists, create it */
10096f05afcbSRob Herring nwn = get_subnode(wn, compp[i]);
10106f05afcbSRob Herring if (!nwn)
10116f05afcbSRob Herring nwn = build_and_name_child_node(wn, compp[i]);
10126f05afcbSRob Herring }
10136f05afcbSRob Herring
10146f05afcbSRob Herring free(compp);
10156f05afcbSRob Herring
10166f05afcbSRob Herring value_32 = cpu_to_fdt32(m->offset);
10179bb9c6a1SRob Herring append_to_property(wn, prop->name, &value_32, sizeof(value_32), TYPE_UINT32);
10186f05afcbSRob Herring }
10196f05afcbSRob Herring
generate_local_fixups_tree_internal(struct dt_info * dti,struct node * lfn,struct node * node)10206f05afcbSRob Herring static void generate_local_fixups_tree_internal(struct dt_info *dti,
10216f05afcbSRob Herring struct node *lfn,
10226f05afcbSRob Herring struct node *node)
10236f05afcbSRob Herring {
10246f05afcbSRob Herring struct node *dt = dti->dt;
10256f05afcbSRob Herring struct node *c;
10266f05afcbSRob Herring struct property *prop;
10276f05afcbSRob Herring struct marker *m;
10286f05afcbSRob Herring struct node *refnode;
10296f05afcbSRob Herring
10306f05afcbSRob Herring for_each_property(node, prop) {
10316f05afcbSRob Herring m = prop->val.markers;
10326f05afcbSRob Herring for_each_marker_of_type(m, REF_PHANDLE) {
10336f05afcbSRob Herring refnode = get_node_by_ref(dt, m->ref);
10346f05afcbSRob Herring if (refnode)
10356f05afcbSRob Herring add_local_fixup_entry(dti, lfn, node, prop, m, refnode);
10366f05afcbSRob Herring }
10376f05afcbSRob Herring }
10386f05afcbSRob Herring
10396f05afcbSRob Herring for_each_child(node, c)
10406f05afcbSRob Herring generate_local_fixups_tree_internal(dti, lfn, c);
10416f05afcbSRob Herring }
10426f05afcbSRob Herring
generate_label_tree(struct dt_info * dti,char * name,bool allocph)10436f05afcbSRob Herring void generate_label_tree(struct dt_info *dti, char *name, bool allocph)
10446f05afcbSRob Herring {
10456f05afcbSRob Herring if (!any_label_tree(dti, dti->dt))
10466f05afcbSRob Herring return;
10476f05afcbSRob Herring generate_label_tree_internal(dti, build_root_node(dti->dt, name),
10486f05afcbSRob Herring dti->dt, allocph);
10496f05afcbSRob Herring }
10506f05afcbSRob Herring
generate_fixups_tree(struct dt_info * dti,char * name)10516f05afcbSRob Herring void generate_fixups_tree(struct dt_info *dti, char *name)
10526f05afcbSRob Herring {
10536f05afcbSRob Herring if (!any_fixup_tree(dti, dti->dt))
10546f05afcbSRob Herring return;
10556f05afcbSRob Herring generate_fixups_tree_internal(dti, build_root_node(dti->dt, name),
10566f05afcbSRob Herring dti->dt);
10576f05afcbSRob Herring }
10586f05afcbSRob Herring
generate_local_fixups_tree(struct dt_info * dti,char * name)10596f05afcbSRob Herring void generate_local_fixups_tree(struct dt_info *dti, char *name)
10606f05afcbSRob Herring {
10616f05afcbSRob Herring if (!any_local_fixup_tree(dti, dti->dt))
10626f05afcbSRob Herring return;
10636f05afcbSRob Herring generate_local_fixups_tree_internal(dti, build_root_node(dti->dt, name),
10646f05afcbSRob Herring dti->dt);
1065658f29a5SJohn Bonesio }
1066