xref: /linux/scripts/dtc/livetree.c (revision a1ff5a7d78a036d6c2178ee5acd6ba4946243800)
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