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