xref: /OK3568_Linux_fs/kernel/scripts/dtc/livetree.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0-or-later
2*4882a593Smuzhiyun /*
3*4882a593Smuzhiyun  * (C) Copyright David Gibson <dwg@au1.ibm.com>, IBM Corporation.  2005.
4*4882a593Smuzhiyun  */
5*4882a593Smuzhiyun 
6*4882a593Smuzhiyun #include "dtc.h"
7*4882a593Smuzhiyun #include "srcpos.h"
8*4882a593Smuzhiyun 
9*4882a593Smuzhiyun /*
10*4882a593Smuzhiyun  * Tree building functions
11*4882a593Smuzhiyun  */
12*4882a593Smuzhiyun 
add_label(struct label ** labels,char * label)13*4882a593Smuzhiyun void add_label(struct label **labels, char *label)
14*4882a593Smuzhiyun {
15*4882a593Smuzhiyun 	struct label *new;
16*4882a593Smuzhiyun 
17*4882a593Smuzhiyun 	/* Make sure the label isn't already there */
18*4882a593Smuzhiyun 	for_each_label_withdel(*labels, new)
19*4882a593Smuzhiyun 		if (streq(new->label, label)) {
20*4882a593Smuzhiyun 			new->deleted = 0;
21*4882a593Smuzhiyun 			return;
22*4882a593Smuzhiyun 		}
23*4882a593Smuzhiyun 
24*4882a593Smuzhiyun 	new = xmalloc(sizeof(*new));
25*4882a593Smuzhiyun 	memset(new, 0, sizeof(*new));
26*4882a593Smuzhiyun 	new->label = label;
27*4882a593Smuzhiyun 	new->next = *labels;
28*4882a593Smuzhiyun 	*labels = new;
29*4882a593Smuzhiyun }
30*4882a593Smuzhiyun 
delete_labels(struct label ** labels)31*4882a593Smuzhiyun void delete_labels(struct label **labels)
32*4882a593Smuzhiyun {
33*4882a593Smuzhiyun 	struct label *label;
34*4882a593Smuzhiyun 
35*4882a593Smuzhiyun 	for_each_label(*labels, label)
36*4882a593Smuzhiyun 		label->deleted = 1;
37*4882a593Smuzhiyun }
38*4882a593Smuzhiyun 
build_property(char * name,struct data val,struct srcpos * srcpos)39*4882a593Smuzhiyun struct property *build_property(char *name, struct data val,
40*4882a593Smuzhiyun 				struct srcpos *srcpos)
41*4882a593Smuzhiyun {
42*4882a593Smuzhiyun 	struct property *new = xmalloc(sizeof(*new));
43*4882a593Smuzhiyun 
44*4882a593Smuzhiyun 	memset(new, 0, sizeof(*new));
45*4882a593Smuzhiyun 
46*4882a593Smuzhiyun 	new->name = name;
47*4882a593Smuzhiyun 	new->val = val;
48*4882a593Smuzhiyun 	new->srcpos = srcpos_copy(srcpos);
49*4882a593Smuzhiyun 
50*4882a593Smuzhiyun 	return new;
51*4882a593Smuzhiyun }
52*4882a593Smuzhiyun 
build_property_delete(char * name)53*4882a593Smuzhiyun struct property *build_property_delete(char *name)
54*4882a593Smuzhiyun {
55*4882a593Smuzhiyun 	struct property *new = xmalloc(sizeof(*new));
56*4882a593Smuzhiyun 
57*4882a593Smuzhiyun 	memset(new, 0, sizeof(*new));
58*4882a593Smuzhiyun 
59*4882a593Smuzhiyun 	new->name = name;
60*4882a593Smuzhiyun 	new->deleted = 1;
61*4882a593Smuzhiyun 
62*4882a593Smuzhiyun 	return new;
63*4882a593Smuzhiyun }
64*4882a593Smuzhiyun 
chain_property(struct property * first,struct property * list)65*4882a593Smuzhiyun struct property *chain_property(struct property *first, struct property *list)
66*4882a593Smuzhiyun {
67*4882a593Smuzhiyun 	assert(first->next == NULL);
68*4882a593Smuzhiyun 
69*4882a593Smuzhiyun 	first->next = list;
70*4882a593Smuzhiyun 	return first;
71*4882a593Smuzhiyun }
72*4882a593Smuzhiyun 
reverse_properties(struct property * first)73*4882a593Smuzhiyun struct property *reverse_properties(struct property *first)
74*4882a593Smuzhiyun {
75*4882a593Smuzhiyun 	struct property *p = first;
76*4882a593Smuzhiyun 	struct property *head = NULL;
77*4882a593Smuzhiyun 	struct property *next;
78*4882a593Smuzhiyun 
79*4882a593Smuzhiyun 	while (p) {
80*4882a593Smuzhiyun 		next = p->next;
81*4882a593Smuzhiyun 		p->next = head;
82*4882a593Smuzhiyun 		head = p;
83*4882a593Smuzhiyun 		p = next;
84*4882a593Smuzhiyun 	}
85*4882a593Smuzhiyun 	return head;
86*4882a593Smuzhiyun }
87*4882a593Smuzhiyun 
build_node(struct property * proplist,struct node * children,struct srcpos * srcpos)88*4882a593Smuzhiyun struct node *build_node(struct property *proplist, struct node *children,
89*4882a593Smuzhiyun 			struct srcpos *srcpos)
90*4882a593Smuzhiyun {
91*4882a593Smuzhiyun 	struct node *new = xmalloc(sizeof(*new));
92*4882a593Smuzhiyun 	struct node *child;
93*4882a593Smuzhiyun 
94*4882a593Smuzhiyun 	memset(new, 0, sizeof(*new));
95*4882a593Smuzhiyun 
96*4882a593Smuzhiyun 	new->proplist = reverse_properties(proplist);
97*4882a593Smuzhiyun 	new->children = children;
98*4882a593Smuzhiyun 	new->srcpos = srcpos_copy(srcpos);
99*4882a593Smuzhiyun 
100*4882a593Smuzhiyun 	for_each_child(new, child) {
101*4882a593Smuzhiyun 		child->parent = new;
102*4882a593Smuzhiyun 	}
103*4882a593Smuzhiyun 
104*4882a593Smuzhiyun 	return new;
105*4882a593Smuzhiyun }
106*4882a593Smuzhiyun 
build_node_delete(struct srcpos * srcpos)107*4882a593Smuzhiyun struct node *build_node_delete(struct srcpos *srcpos)
108*4882a593Smuzhiyun {
109*4882a593Smuzhiyun 	struct node *new = xmalloc(sizeof(*new));
110*4882a593Smuzhiyun 
111*4882a593Smuzhiyun 	memset(new, 0, sizeof(*new));
112*4882a593Smuzhiyun 
113*4882a593Smuzhiyun 	new->deleted = 1;
114*4882a593Smuzhiyun 	new->srcpos = srcpos_copy(srcpos);
115*4882a593Smuzhiyun 
116*4882a593Smuzhiyun 	return new;
117*4882a593Smuzhiyun }
118*4882a593Smuzhiyun 
name_node(struct node * node,char * name)119*4882a593Smuzhiyun struct node *name_node(struct node *node, char *name)
120*4882a593Smuzhiyun {
121*4882a593Smuzhiyun 	assert(node->name == NULL);
122*4882a593Smuzhiyun 
123*4882a593Smuzhiyun 	node->name = name;
124*4882a593Smuzhiyun 
125*4882a593Smuzhiyun 	return node;
126*4882a593Smuzhiyun }
127*4882a593Smuzhiyun 
omit_node_if_unused(struct node * node)128*4882a593Smuzhiyun struct node *omit_node_if_unused(struct node *node)
129*4882a593Smuzhiyun {
130*4882a593Smuzhiyun 	node->omit_if_unused = 1;
131*4882a593Smuzhiyun 
132*4882a593Smuzhiyun 	return node;
133*4882a593Smuzhiyun }
134*4882a593Smuzhiyun 
reference_node(struct node * node)135*4882a593Smuzhiyun struct node *reference_node(struct node *node)
136*4882a593Smuzhiyun {
137*4882a593Smuzhiyun 	node->is_referenced = 1;
138*4882a593Smuzhiyun 
139*4882a593Smuzhiyun 	return node;
140*4882a593Smuzhiyun }
141*4882a593Smuzhiyun 
merge_nodes(struct node * old_node,struct node * new_node)142*4882a593Smuzhiyun struct node *merge_nodes(struct node *old_node, struct node *new_node)
143*4882a593Smuzhiyun {
144*4882a593Smuzhiyun 	struct property *new_prop, *old_prop;
145*4882a593Smuzhiyun 	struct node *new_child, *old_child;
146*4882a593Smuzhiyun 	struct label *l;
147*4882a593Smuzhiyun 
148*4882a593Smuzhiyun 	old_node->deleted = 0;
149*4882a593Smuzhiyun 
150*4882a593Smuzhiyun 	/* Add new node labels to old node */
151*4882a593Smuzhiyun 	for_each_label_withdel(new_node->labels, l)
152*4882a593Smuzhiyun 		add_label(&old_node->labels, l->label);
153*4882a593Smuzhiyun 
154*4882a593Smuzhiyun 	/* Move properties from the new node to the old node.  If there
155*4882a593Smuzhiyun 	 * is a collision, replace the old value with the new */
156*4882a593Smuzhiyun 	while (new_node->proplist) {
157*4882a593Smuzhiyun 		/* Pop the property off the list */
158*4882a593Smuzhiyun 		new_prop = new_node->proplist;
159*4882a593Smuzhiyun 		new_node->proplist = new_prop->next;
160*4882a593Smuzhiyun 		new_prop->next = NULL;
161*4882a593Smuzhiyun 
162*4882a593Smuzhiyun 		if (new_prop->deleted) {
163*4882a593Smuzhiyun 			delete_property_by_name(old_node, new_prop->name);
164*4882a593Smuzhiyun 			free(new_prop);
165*4882a593Smuzhiyun 			continue;
166*4882a593Smuzhiyun 		}
167*4882a593Smuzhiyun 
168*4882a593Smuzhiyun 		/* Look for a collision, set new value if there is */
169*4882a593Smuzhiyun 		for_each_property_withdel(old_node, old_prop) {
170*4882a593Smuzhiyun 			if (streq(old_prop->name, new_prop->name)) {
171*4882a593Smuzhiyun 				/* Add new labels to old property */
172*4882a593Smuzhiyun 				for_each_label_withdel(new_prop->labels, l)
173*4882a593Smuzhiyun 					add_label(&old_prop->labels, l->label);
174*4882a593Smuzhiyun 
175*4882a593Smuzhiyun 				old_prop->val = new_prop->val;
176*4882a593Smuzhiyun 				old_prop->deleted = 0;
177*4882a593Smuzhiyun 				free(old_prop->srcpos);
178*4882a593Smuzhiyun 				old_prop->srcpos = new_prop->srcpos;
179*4882a593Smuzhiyun 				free(new_prop);
180*4882a593Smuzhiyun 				new_prop = NULL;
181*4882a593Smuzhiyun 				break;
182*4882a593Smuzhiyun 			}
183*4882a593Smuzhiyun 		}
184*4882a593Smuzhiyun 
185*4882a593Smuzhiyun 		/* if no collision occurred, add property to the old node. */
186*4882a593Smuzhiyun 		if (new_prop)
187*4882a593Smuzhiyun 			add_property(old_node, new_prop);
188*4882a593Smuzhiyun 	}
189*4882a593Smuzhiyun 
190*4882a593Smuzhiyun 	/* Move the override child nodes into the primary node.  If
191*4882a593Smuzhiyun 	 * there is a collision, then merge the nodes. */
192*4882a593Smuzhiyun 	while (new_node->children) {
193*4882a593Smuzhiyun 		/* Pop the child node off the list */
194*4882a593Smuzhiyun 		new_child = new_node->children;
195*4882a593Smuzhiyun 		new_node->children = new_child->next_sibling;
196*4882a593Smuzhiyun 		new_child->parent = NULL;
197*4882a593Smuzhiyun 		new_child->next_sibling = NULL;
198*4882a593Smuzhiyun 
199*4882a593Smuzhiyun 		if (new_child->deleted) {
200*4882a593Smuzhiyun 			delete_node_by_name(old_node, new_child->name);
201*4882a593Smuzhiyun 			free(new_child);
202*4882a593Smuzhiyun 			continue;
203*4882a593Smuzhiyun 		}
204*4882a593Smuzhiyun 
205*4882a593Smuzhiyun 		/* Search for a collision.  Merge if there is */
206*4882a593Smuzhiyun 		for_each_child_withdel(old_node, old_child) {
207*4882a593Smuzhiyun 			if (streq(old_child->name, new_child->name)) {
208*4882a593Smuzhiyun 				merge_nodes(old_child, new_child);
209*4882a593Smuzhiyun 				new_child = NULL;
210*4882a593Smuzhiyun 				break;
211*4882a593Smuzhiyun 			}
212*4882a593Smuzhiyun 		}
213*4882a593Smuzhiyun 
214*4882a593Smuzhiyun 		/* if no collision occurred, add child to the old node. */
215*4882a593Smuzhiyun 		if (new_child)
216*4882a593Smuzhiyun 			add_child(old_node, new_child);
217*4882a593Smuzhiyun 	}
218*4882a593Smuzhiyun 
219*4882a593Smuzhiyun 	old_node->srcpos = srcpos_extend(old_node->srcpos, new_node->srcpos);
220*4882a593Smuzhiyun 
221*4882a593Smuzhiyun 	/* The new node contents are now merged into the old node.  Free
222*4882a593Smuzhiyun 	 * the new node. */
223*4882a593Smuzhiyun 	free(new_node);
224*4882a593Smuzhiyun 
225*4882a593Smuzhiyun 	return old_node;
226*4882a593Smuzhiyun }
227*4882a593Smuzhiyun 
add_orphan_node(struct node * dt,struct node * new_node,char * ref)228*4882a593Smuzhiyun struct node * add_orphan_node(struct node *dt, struct node *new_node, char *ref)
229*4882a593Smuzhiyun {
230*4882a593Smuzhiyun 	static unsigned int next_orphan_fragment = 0;
231*4882a593Smuzhiyun 	struct node *node;
232*4882a593Smuzhiyun 	struct property *p;
233*4882a593Smuzhiyun 	struct data d = empty_data;
234*4882a593Smuzhiyun 	char *name;
235*4882a593Smuzhiyun 
236*4882a593Smuzhiyun 	if (ref[0] == '/') {
237*4882a593Smuzhiyun 		d = data_add_marker(d, TYPE_STRING, ref);
238*4882a593Smuzhiyun 		d = data_append_data(d, ref, strlen(ref) + 1);
239*4882a593Smuzhiyun 
240*4882a593Smuzhiyun 		p = build_property("target-path", d, NULL);
241*4882a593Smuzhiyun 	} else {
242*4882a593Smuzhiyun 		d = data_add_marker(d, REF_PHANDLE, ref);
243*4882a593Smuzhiyun 		d = data_append_integer(d, 0xffffffff, 32);
244*4882a593Smuzhiyun 
245*4882a593Smuzhiyun 		p = build_property("target", d, NULL);
246*4882a593Smuzhiyun 	}
247*4882a593Smuzhiyun 
248*4882a593Smuzhiyun 	xasprintf(&name, "fragment@%u",
249*4882a593Smuzhiyun 			next_orphan_fragment++);
250*4882a593Smuzhiyun 	name_node(new_node, "__overlay__");
251*4882a593Smuzhiyun 	node = build_node(p, new_node, NULL);
252*4882a593Smuzhiyun 	name_node(node, name);
253*4882a593Smuzhiyun 
254*4882a593Smuzhiyun 	add_child(dt, node);
255*4882a593Smuzhiyun 	return dt;
256*4882a593Smuzhiyun }
257*4882a593Smuzhiyun 
chain_node(struct node * first,struct node * list)258*4882a593Smuzhiyun struct node *chain_node(struct node *first, struct node *list)
259*4882a593Smuzhiyun {
260*4882a593Smuzhiyun 	assert(first->next_sibling == NULL);
261*4882a593Smuzhiyun 
262*4882a593Smuzhiyun 	first->next_sibling = list;
263*4882a593Smuzhiyun 	return first;
264*4882a593Smuzhiyun }
265*4882a593Smuzhiyun 
add_property(struct node * node,struct property * prop)266*4882a593Smuzhiyun void add_property(struct node *node, struct property *prop)
267*4882a593Smuzhiyun {
268*4882a593Smuzhiyun 	struct property **p;
269*4882a593Smuzhiyun 
270*4882a593Smuzhiyun 	prop->next = NULL;
271*4882a593Smuzhiyun 
272*4882a593Smuzhiyun 	p = &node->proplist;
273*4882a593Smuzhiyun 	while (*p)
274*4882a593Smuzhiyun 		p = &((*p)->next);
275*4882a593Smuzhiyun 
276*4882a593Smuzhiyun 	*p = prop;
277*4882a593Smuzhiyun }
278*4882a593Smuzhiyun 
delete_property_by_name(struct node * node,char * name)279*4882a593Smuzhiyun void delete_property_by_name(struct node *node, char *name)
280*4882a593Smuzhiyun {
281*4882a593Smuzhiyun 	struct property *prop = node->proplist;
282*4882a593Smuzhiyun 
283*4882a593Smuzhiyun 	while (prop) {
284*4882a593Smuzhiyun 		if (streq(prop->name, name)) {
285*4882a593Smuzhiyun 			delete_property(prop);
286*4882a593Smuzhiyun 			return;
287*4882a593Smuzhiyun 		}
288*4882a593Smuzhiyun 		prop = prop->next;
289*4882a593Smuzhiyun 	}
290*4882a593Smuzhiyun }
291*4882a593Smuzhiyun 
delete_property(struct property * prop)292*4882a593Smuzhiyun void delete_property(struct property *prop)
293*4882a593Smuzhiyun {
294*4882a593Smuzhiyun 	prop->deleted = 1;
295*4882a593Smuzhiyun 	delete_labels(&prop->labels);
296*4882a593Smuzhiyun }
297*4882a593Smuzhiyun 
add_child(struct node * parent,struct node * child)298*4882a593Smuzhiyun void add_child(struct node *parent, struct node *child)
299*4882a593Smuzhiyun {
300*4882a593Smuzhiyun 	struct node **p;
301*4882a593Smuzhiyun 
302*4882a593Smuzhiyun 	child->next_sibling = NULL;
303*4882a593Smuzhiyun 	child->parent = parent;
304*4882a593Smuzhiyun 
305*4882a593Smuzhiyun 	p = &parent->children;
306*4882a593Smuzhiyun 	while (*p)
307*4882a593Smuzhiyun 		p = &((*p)->next_sibling);
308*4882a593Smuzhiyun 
309*4882a593Smuzhiyun 	*p = child;
310*4882a593Smuzhiyun }
311*4882a593Smuzhiyun 
delete_node_by_name(struct node * parent,char * name)312*4882a593Smuzhiyun void delete_node_by_name(struct node *parent, char *name)
313*4882a593Smuzhiyun {
314*4882a593Smuzhiyun 	struct node *node = parent->children;
315*4882a593Smuzhiyun 
316*4882a593Smuzhiyun 	while (node) {
317*4882a593Smuzhiyun 		if (streq(node->name, name)) {
318*4882a593Smuzhiyun 			delete_node(node);
319*4882a593Smuzhiyun 			return;
320*4882a593Smuzhiyun 		}
321*4882a593Smuzhiyun 		node = node->next_sibling;
322*4882a593Smuzhiyun 	}
323*4882a593Smuzhiyun }
324*4882a593Smuzhiyun 
delete_node(struct node * node)325*4882a593Smuzhiyun void delete_node(struct node *node)
326*4882a593Smuzhiyun {
327*4882a593Smuzhiyun 	struct property *prop;
328*4882a593Smuzhiyun 	struct node *child;
329*4882a593Smuzhiyun 
330*4882a593Smuzhiyun 	node->deleted = 1;
331*4882a593Smuzhiyun 	for_each_child(node, child)
332*4882a593Smuzhiyun 		delete_node(child);
333*4882a593Smuzhiyun 	for_each_property(node, prop)
334*4882a593Smuzhiyun 		delete_property(prop);
335*4882a593Smuzhiyun 	delete_labels(&node->labels);
336*4882a593Smuzhiyun }
337*4882a593Smuzhiyun 
append_to_property(struct node * node,char * name,const void * data,int len,enum markertype type)338*4882a593Smuzhiyun void append_to_property(struct node *node,
339*4882a593Smuzhiyun 			char *name, const void *data, int len,
340*4882a593Smuzhiyun 			enum markertype type)
341*4882a593Smuzhiyun {
342*4882a593Smuzhiyun 	struct data d;
343*4882a593Smuzhiyun 	struct property *p;
344*4882a593Smuzhiyun 
345*4882a593Smuzhiyun 	p = get_property(node, name);
346*4882a593Smuzhiyun 	if (p) {
347*4882a593Smuzhiyun 		d = data_add_marker(p->val, type, name);
348*4882a593Smuzhiyun 		d = data_append_data(d, data, len);
349*4882a593Smuzhiyun 		p->val = d;
350*4882a593Smuzhiyun 	} else {
351*4882a593Smuzhiyun 		d = data_add_marker(empty_data, type, name);
352*4882a593Smuzhiyun 		d = data_append_data(d, data, len);
353*4882a593Smuzhiyun 		p = build_property(name, d, NULL);
354*4882a593Smuzhiyun 		add_property(node, p);
355*4882a593Smuzhiyun 	}
356*4882a593Smuzhiyun }
357*4882a593Smuzhiyun 
build_reserve_entry(uint64_t address,uint64_t size)358*4882a593Smuzhiyun struct reserve_info *build_reserve_entry(uint64_t address, uint64_t size)
359*4882a593Smuzhiyun {
360*4882a593Smuzhiyun 	struct reserve_info *new = xmalloc(sizeof(*new));
361*4882a593Smuzhiyun 
362*4882a593Smuzhiyun 	memset(new, 0, sizeof(*new));
363*4882a593Smuzhiyun 
364*4882a593Smuzhiyun 	new->address = address;
365*4882a593Smuzhiyun 	new->size = size;
366*4882a593Smuzhiyun 
367*4882a593Smuzhiyun 	return new;
368*4882a593Smuzhiyun }
369*4882a593Smuzhiyun 
chain_reserve_entry(struct reserve_info * first,struct reserve_info * list)370*4882a593Smuzhiyun struct reserve_info *chain_reserve_entry(struct reserve_info *first,
371*4882a593Smuzhiyun 					struct reserve_info *list)
372*4882a593Smuzhiyun {
373*4882a593Smuzhiyun 	assert(first->next == NULL);
374*4882a593Smuzhiyun 
375*4882a593Smuzhiyun 	first->next = list;
376*4882a593Smuzhiyun 	return first;
377*4882a593Smuzhiyun }
378*4882a593Smuzhiyun 
add_reserve_entry(struct reserve_info * list,struct reserve_info * new)379*4882a593Smuzhiyun struct reserve_info *add_reserve_entry(struct reserve_info *list,
380*4882a593Smuzhiyun 				      struct reserve_info *new)
381*4882a593Smuzhiyun {
382*4882a593Smuzhiyun 	struct reserve_info *last;
383*4882a593Smuzhiyun 
384*4882a593Smuzhiyun 	new->next = NULL;
385*4882a593Smuzhiyun 
386*4882a593Smuzhiyun 	if (! list)
387*4882a593Smuzhiyun 		return new;
388*4882a593Smuzhiyun 
389*4882a593Smuzhiyun 	for (last = list; last->next; last = last->next)
390*4882a593Smuzhiyun 		;
391*4882a593Smuzhiyun 
392*4882a593Smuzhiyun 	last->next = new;
393*4882a593Smuzhiyun 
394*4882a593Smuzhiyun 	return list;
395*4882a593Smuzhiyun }
396*4882a593Smuzhiyun 
build_dt_info(unsigned int dtsflags,struct reserve_info * reservelist,struct node * tree,uint32_t boot_cpuid_phys)397*4882a593Smuzhiyun struct dt_info *build_dt_info(unsigned int dtsflags,
398*4882a593Smuzhiyun 			      struct reserve_info *reservelist,
399*4882a593Smuzhiyun 			      struct node *tree, uint32_t boot_cpuid_phys)
400*4882a593Smuzhiyun {
401*4882a593Smuzhiyun 	struct dt_info *dti;
402*4882a593Smuzhiyun 
403*4882a593Smuzhiyun 	dti = xmalloc(sizeof(*dti));
404*4882a593Smuzhiyun 	dti->dtsflags = dtsflags;
405*4882a593Smuzhiyun 	dti->reservelist = reservelist;
406*4882a593Smuzhiyun 	dti->dt = tree;
407*4882a593Smuzhiyun 	dti->boot_cpuid_phys = boot_cpuid_phys;
408*4882a593Smuzhiyun 
409*4882a593Smuzhiyun 	return dti;
410*4882a593Smuzhiyun }
411*4882a593Smuzhiyun 
412*4882a593Smuzhiyun /*
413*4882a593Smuzhiyun  * Tree accessor functions
414*4882a593Smuzhiyun  */
415*4882a593Smuzhiyun 
get_unitname(struct node * node)416*4882a593Smuzhiyun const char *get_unitname(struct node *node)
417*4882a593Smuzhiyun {
418*4882a593Smuzhiyun 	if (node->name[node->basenamelen] == '\0')
419*4882a593Smuzhiyun 		return "";
420*4882a593Smuzhiyun 	else
421*4882a593Smuzhiyun 		return node->name + node->basenamelen + 1;
422*4882a593Smuzhiyun }
423*4882a593Smuzhiyun 
get_property(struct node * node,const char * propname)424*4882a593Smuzhiyun struct property *get_property(struct node *node, const char *propname)
425*4882a593Smuzhiyun {
426*4882a593Smuzhiyun 	struct property *prop;
427*4882a593Smuzhiyun 
428*4882a593Smuzhiyun 	for_each_property(node, prop)
429*4882a593Smuzhiyun 		if (streq(prop->name, propname))
430*4882a593Smuzhiyun 			return prop;
431*4882a593Smuzhiyun 
432*4882a593Smuzhiyun 	return NULL;
433*4882a593Smuzhiyun }
434*4882a593Smuzhiyun 
propval_cell(struct property * prop)435*4882a593Smuzhiyun cell_t propval_cell(struct property *prop)
436*4882a593Smuzhiyun {
437*4882a593Smuzhiyun 	assert(prop->val.len == sizeof(cell_t));
438*4882a593Smuzhiyun 	return fdt32_to_cpu(*((fdt32_t *)prop->val.val));
439*4882a593Smuzhiyun }
440*4882a593Smuzhiyun 
propval_cell_n(struct property * prop,int n)441*4882a593Smuzhiyun cell_t propval_cell_n(struct property *prop, int n)
442*4882a593Smuzhiyun {
443*4882a593Smuzhiyun 	assert(prop->val.len / sizeof(cell_t) >= n);
444*4882a593Smuzhiyun 	return fdt32_to_cpu(*((fdt32_t *)prop->val.val + n));
445*4882a593Smuzhiyun }
446*4882a593Smuzhiyun 
get_property_by_label(struct node * tree,const char * label,struct node ** node)447*4882a593Smuzhiyun struct property *get_property_by_label(struct node *tree, const char *label,
448*4882a593Smuzhiyun 				       struct node **node)
449*4882a593Smuzhiyun {
450*4882a593Smuzhiyun 	struct property *prop;
451*4882a593Smuzhiyun 	struct node *c;
452*4882a593Smuzhiyun 
453*4882a593Smuzhiyun 	*node = tree;
454*4882a593Smuzhiyun 
455*4882a593Smuzhiyun 	for_each_property(tree, prop) {
456*4882a593Smuzhiyun 		struct label *l;
457*4882a593Smuzhiyun 
458*4882a593Smuzhiyun 		for_each_label(prop->labels, l)
459*4882a593Smuzhiyun 			if (streq(l->label, label))
460*4882a593Smuzhiyun 				return prop;
461*4882a593Smuzhiyun 	}
462*4882a593Smuzhiyun 
463*4882a593Smuzhiyun 	for_each_child(tree, c) {
464*4882a593Smuzhiyun 		prop = get_property_by_label(c, label, node);
465*4882a593Smuzhiyun 		if (prop)
466*4882a593Smuzhiyun 			return prop;
467*4882a593Smuzhiyun 	}
468*4882a593Smuzhiyun 
469*4882a593Smuzhiyun 	*node = NULL;
470*4882a593Smuzhiyun 	return NULL;
471*4882a593Smuzhiyun }
472*4882a593Smuzhiyun 
get_marker_label(struct node * tree,const char * label,struct node ** node,struct property ** prop)473*4882a593Smuzhiyun struct marker *get_marker_label(struct node *tree, const char *label,
474*4882a593Smuzhiyun 				struct node **node, struct property **prop)
475*4882a593Smuzhiyun {
476*4882a593Smuzhiyun 	struct marker *m;
477*4882a593Smuzhiyun 	struct property *p;
478*4882a593Smuzhiyun 	struct node *c;
479*4882a593Smuzhiyun 
480*4882a593Smuzhiyun 	*node = tree;
481*4882a593Smuzhiyun 
482*4882a593Smuzhiyun 	for_each_property(tree, p) {
483*4882a593Smuzhiyun 		*prop = p;
484*4882a593Smuzhiyun 		m = p->val.markers;
485*4882a593Smuzhiyun 		for_each_marker_of_type(m, LABEL)
486*4882a593Smuzhiyun 			if (streq(m->ref, label))
487*4882a593Smuzhiyun 				return m;
488*4882a593Smuzhiyun 	}
489*4882a593Smuzhiyun 
490*4882a593Smuzhiyun 	for_each_child(tree, c) {
491*4882a593Smuzhiyun 		m = get_marker_label(c, label, node, prop);
492*4882a593Smuzhiyun 		if (m)
493*4882a593Smuzhiyun 			return m;
494*4882a593Smuzhiyun 	}
495*4882a593Smuzhiyun 
496*4882a593Smuzhiyun 	*prop = NULL;
497*4882a593Smuzhiyun 	*node = NULL;
498*4882a593Smuzhiyun 	return NULL;
499*4882a593Smuzhiyun }
500*4882a593Smuzhiyun 
get_subnode(struct node * node,const char * nodename)501*4882a593Smuzhiyun struct node *get_subnode(struct node *node, const char *nodename)
502*4882a593Smuzhiyun {
503*4882a593Smuzhiyun 	struct node *child;
504*4882a593Smuzhiyun 
505*4882a593Smuzhiyun 	for_each_child(node, child)
506*4882a593Smuzhiyun 		if (streq(child->name, nodename))
507*4882a593Smuzhiyun 			return child;
508*4882a593Smuzhiyun 
509*4882a593Smuzhiyun 	return NULL;
510*4882a593Smuzhiyun }
511*4882a593Smuzhiyun 
get_node_by_path(struct node * tree,const char * path)512*4882a593Smuzhiyun struct node *get_node_by_path(struct node *tree, const char *path)
513*4882a593Smuzhiyun {
514*4882a593Smuzhiyun 	const char *p;
515*4882a593Smuzhiyun 	struct node *child;
516*4882a593Smuzhiyun 
517*4882a593Smuzhiyun 	if (!path || ! (*path)) {
518*4882a593Smuzhiyun 		if (tree->deleted)
519*4882a593Smuzhiyun 			return NULL;
520*4882a593Smuzhiyun 		return tree;
521*4882a593Smuzhiyun 	}
522*4882a593Smuzhiyun 
523*4882a593Smuzhiyun 	while (path[0] == '/')
524*4882a593Smuzhiyun 		path++;
525*4882a593Smuzhiyun 
526*4882a593Smuzhiyun 	p = strchr(path, '/');
527*4882a593Smuzhiyun 
528*4882a593Smuzhiyun 	for_each_child(tree, child) {
529*4882a593Smuzhiyun 		if (p && strprefixeq(path, p - path, child->name))
530*4882a593Smuzhiyun 			return get_node_by_path(child, p+1);
531*4882a593Smuzhiyun 		else if (!p && streq(path, child->name))
532*4882a593Smuzhiyun 			return child;
533*4882a593Smuzhiyun 	}
534*4882a593Smuzhiyun 
535*4882a593Smuzhiyun 	return NULL;
536*4882a593Smuzhiyun }
537*4882a593Smuzhiyun 
get_node_by_label(struct node * tree,const char * label)538*4882a593Smuzhiyun struct node *get_node_by_label(struct node *tree, const char *label)
539*4882a593Smuzhiyun {
540*4882a593Smuzhiyun 	struct node *child, *node;
541*4882a593Smuzhiyun 	struct label *l;
542*4882a593Smuzhiyun 
543*4882a593Smuzhiyun 	assert(label && (strlen(label) > 0));
544*4882a593Smuzhiyun 
545*4882a593Smuzhiyun 	for_each_label(tree->labels, l)
546*4882a593Smuzhiyun 		if (streq(l->label, label))
547*4882a593Smuzhiyun 			return tree;
548*4882a593Smuzhiyun 
549*4882a593Smuzhiyun 	for_each_child(tree, child) {
550*4882a593Smuzhiyun 		node = get_node_by_label(child, label);
551*4882a593Smuzhiyun 		if (node)
552*4882a593Smuzhiyun 			return node;
553*4882a593Smuzhiyun 	}
554*4882a593Smuzhiyun 
555*4882a593Smuzhiyun 	return NULL;
556*4882a593Smuzhiyun }
557*4882a593Smuzhiyun 
get_node_by_phandle(struct node * tree,cell_t phandle)558*4882a593Smuzhiyun struct node *get_node_by_phandle(struct node *tree, cell_t phandle)
559*4882a593Smuzhiyun {
560*4882a593Smuzhiyun 	struct node *child, *node;
561*4882a593Smuzhiyun 
562*4882a593Smuzhiyun 	if ((phandle == 0) || (phandle == -1)) {
563*4882a593Smuzhiyun 		assert(generate_fixups);
564*4882a593Smuzhiyun 		return NULL;
565*4882a593Smuzhiyun 	}
566*4882a593Smuzhiyun 
567*4882a593Smuzhiyun 	if (tree->phandle == phandle) {
568*4882a593Smuzhiyun 		if (tree->deleted)
569*4882a593Smuzhiyun 			return NULL;
570*4882a593Smuzhiyun 		return tree;
571*4882a593Smuzhiyun 	}
572*4882a593Smuzhiyun 
573*4882a593Smuzhiyun 	for_each_child(tree, child) {
574*4882a593Smuzhiyun 		node = get_node_by_phandle(child, phandle);
575*4882a593Smuzhiyun 		if (node)
576*4882a593Smuzhiyun 			return node;
577*4882a593Smuzhiyun 	}
578*4882a593Smuzhiyun 
579*4882a593Smuzhiyun 	return NULL;
580*4882a593Smuzhiyun }
581*4882a593Smuzhiyun 
get_node_by_ref(struct node * tree,const char * ref)582*4882a593Smuzhiyun struct node *get_node_by_ref(struct node *tree, const char *ref)
583*4882a593Smuzhiyun {
584*4882a593Smuzhiyun 	if (streq(ref, "/"))
585*4882a593Smuzhiyun 		return tree;
586*4882a593Smuzhiyun 	else if (ref[0] == '/')
587*4882a593Smuzhiyun 		return get_node_by_path(tree, ref);
588*4882a593Smuzhiyun 	else
589*4882a593Smuzhiyun 		return get_node_by_label(tree, ref);
590*4882a593Smuzhiyun }
591*4882a593Smuzhiyun 
get_node_phandle(struct node * root,struct node * node)592*4882a593Smuzhiyun cell_t get_node_phandle(struct node *root, struct node *node)
593*4882a593Smuzhiyun {
594*4882a593Smuzhiyun 	static cell_t phandle = 1; /* FIXME: ick, static local */
595*4882a593Smuzhiyun 	struct data d = empty_data;
596*4882a593Smuzhiyun 
597*4882a593Smuzhiyun 	if ((node->phandle != 0) && (node->phandle != -1))
598*4882a593Smuzhiyun 		return node->phandle;
599*4882a593Smuzhiyun 
600*4882a593Smuzhiyun 	while (get_node_by_phandle(root, phandle))
601*4882a593Smuzhiyun 		phandle++;
602*4882a593Smuzhiyun 
603*4882a593Smuzhiyun 	node->phandle = phandle;
604*4882a593Smuzhiyun 
605*4882a593Smuzhiyun 	d = data_add_marker(d, TYPE_UINT32, NULL);
606*4882a593Smuzhiyun 	d = data_append_cell(d, phandle);
607*4882a593Smuzhiyun 
608*4882a593Smuzhiyun 	if (!get_property(node, "linux,phandle")
609*4882a593Smuzhiyun 	    && (phandle_format & PHANDLE_LEGACY))
610*4882a593Smuzhiyun 		add_property(node, build_property("linux,phandle", d, NULL));
611*4882a593Smuzhiyun 
612*4882a593Smuzhiyun 	if (!get_property(node, "phandle")
613*4882a593Smuzhiyun 	    && (phandle_format & PHANDLE_EPAPR))
614*4882a593Smuzhiyun 		add_property(node, build_property("phandle", d, NULL));
615*4882a593Smuzhiyun 
616*4882a593Smuzhiyun 	/* If the node *does* have a phandle property, we must
617*4882a593Smuzhiyun 	 * be dealing with a self-referencing phandle, which will be
618*4882a593Smuzhiyun 	 * fixed up momentarily in the caller */
619*4882a593Smuzhiyun 
620*4882a593Smuzhiyun 	return node->phandle;
621*4882a593Smuzhiyun }
622*4882a593Smuzhiyun 
guess_boot_cpuid(struct node * tree)623*4882a593Smuzhiyun uint32_t guess_boot_cpuid(struct node *tree)
624*4882a593Smuzhiyun {
625*4882a593Smuzhiyun 	struct node *cpus, *bootcpu;
626*4882a593Smuzhiyun 	struct property *reg;
627*4882a593Smuzhiyun 
628*4882a593Smuzhiyun 	cpus = get_node_by_path(tree, "/cpus");
629*4882a593Smuzhiyun 	if (!cpus)
630*4882a593Smuzhiyun 		return 0;
631*4882a593Smuzhiyun 
632*4882a593Smuzhiyun 
633*4882a593Smuzhiyun 	bootcpu = cpus->children;
634*4882a593Smuzhiyun 	if (!bootcpu)
635*4882a593Smuzhiyun 		return 0;
636*4882a593Smuzhiyun 
637*4882a593Smuzhiyun 	reg = get_property(bootcpu, "reg");
638*4882a593Smuzhiyun 	if (!reg || (reg->val.len != sizeof(uint32_t)))
639*4882a593Smuzhiyun 		return 0;
640*4882a593Smuzhiyun 
641*4882a593Smuzhiyun 	/* FIXME: Sanity check node? */
642*4882a593Smuzhiyun 
643*4882a593Smuzhiyun 	return propval_cell(reg);
644*4882a593Smuzhiyun }
645*4882a593Smuzhiyun 
cmp_reserve_info(const void * ax,const void * bx)646*4882a593Smuzhiyun static int cmp_reserve_info(const void *ax, const void *bx)
647*4882a593Smuzhiyun {
648*4882a593Smuzhiyun 	const struct reserve_info *a, *b;
649*4882a593Smuzhiyun 
650*4882a593Smuzhiyun 	a = *((const struct reserve_info * const *)ax);
651*4882a593Smuzhiyun 	b = *((const struct reserve_info * const *)bx);
652*4882a593Smuzhiyun 
653*4882a593Smuzhiyun 	if (a->address < b->address)
654*4882a593Smuzhiyun 		return -1;
655*4882a593Smuzhiyun 	else if (a->address > b->address)
656*4882a593Smuzhiyun 		return 1;
657*4882a593Smuzhiyun 	else if (a->size < b->size)
658*4882a593Smuzhiyun 		return -1;
659*4882a593Smuzhiyun 	else if (a->size > b->size)
660*4882a593Smuzhiyun 		return 1;
661*4882a593Smuzhiyun 	else
662*4882a593Smuzhiyun 		return 0;
663*4882a593Smuzhiyun }
664*4882a593Smuzhiyun 
sort_reserve_entries(struct dt_info * dti)665*4882a593Smuzhiyun static void sort_reserve_entries(struct dt_info *dti)
666*4882a593Smuzhiyun {
667*4882a593Smuzhiyun 	struct reserve_info *ri, **tbl;
668*4882a593Smuzhiyun 	int n = 0, i = 0;
669*4882a593Smuzhiyun 
670*4882a593Smuzhiyun 	for (ri = dti->reservelist;
671*4882a593Smuzhiyun 	     ri;
672*4882a593Smuzhiyun 	     ri = ri->next)
673*4882a593Smuzhiyun 		n++;
674*4882a593Smuzhiyun 
675*4882a593Smuzhiyun 	if (n == 0)
676*4882a593Smuzhiyun 		return;
677*4882a593Smuzhiyun 
678*4882a593Smuzhiyun 	tbl = xmalloc(n * sizeof(*tbl));
679*4882a593Smuzhiyun 
680*4882a593Smuzhiyun 	for (ri = dti->reservelist;
681*4882a593Smuzhiyun 	     ri;
682*4882a593Smuzhiyun 	     ri = ri->next)
683*4882a593Smuzhiyun 		tbl[i++] = ri;
684*4882a593Smuzhiyun 
685*4882a593Smuzhiyun 	qsort(tbl, n, sizeof(*tbl), cmp_reserve_info);
686*4882a593Smuzhiyun 
687*4882a593Smuzhiyun 	dti->reservelist = tbl[0];
688*4882a593Smuzhiyun 	for (i = 0; i < (n-1); i++)
689*4882a593Smuzhiyun 		tbl[i]->next = tbl[i+1];
690*4882a593Smuzhiyun 	tbl[n-1]->next = NULL;
691*4882a593Smuzhiyun 
692*4882a593Smuzhiyun 	free(tbl);
693*4882a593Smuzhiyun }
694*4882a593Smuzhiyun 
cmp_prop(const void * ax,const void * bx)695*4882a593Smuzhiyun static int cmp_prop(const void *ax, const void *bx)
696*4882a593Smuzhiyun {
697*4882a593Smuzhiyun 	const struct property *a, *b;
698*4882a593Smuzhiyun 
699*4882a593Smuzhiyun 	a = *((const struct property * const *)ax);
700*4882a593Smuzhiyun 	b = *((const struct property * const *)bx);
701*4882a593Smuzhiyun 
702*4882a593Smuzhiyun 	return strcmp(a->name, b->name);
703*4882a593Smuzhiyun }
704*4882a593Smuzhiyun 
sort_properties(struct node * node)705*4882a593Smuzhiyun static void sort_properties(struct node *node)
706*4882a593Smuzhiyun {
707*4882a593Smuzhiyun 	int n = 0, i = 0;
708*4882a593Smuzhiyun 	struct property *prop, **tbl;
709*4882a593Smuzhiyun 
710*4882a593Smuzhiyun 	for_each_property_withdel(node, prop)
711*4882a593Smuzhiyun 		n++;
712*4882a593Smuzhiyun 
713*4882a593Smuzhiyun 	if (n == 0)
714*4882a593Smuzhiyun 		return;
715*4882a593Smuzhiyun 
716*4882a593Smuzhiyun 	tbl = xmalloc(n * sizeof(*tbl));
717*4882a593Smuzhiyun 
718*4882a593Smuzhiyun 	for_each_property_withdel(node, prop)
719*4882a593Smuzhiyun 		tbl[i++] = prop;
720*4882a593Smuzhiyun 
721*4882a593Smuzhiyun 	qsort(tbl, n, sizeof(*tbl), cmp_prop);
722*4882a593Smuzhiyun 
723*4882a593Smuzhiyun 	node->proplist = tbl[0];
724*4882a593Smuzhiyun 	for (i = 0; i < (n-1); i++)
725*4882a593Smuzhiyun 		tbl[i]->next = tbl[i+1];
726*4882a593Smuzhiyun 	tbl[n-1]->next = NULL;
727*4882a593Smuzhiyun 
728*4882a593Smuzhiyun 	free(tbl);
729*4882a593Smuzhiyun }
730*4882a593Smuzhiyun 
cmp_subnode(const void * ax,const void * bx)731*4882a593Smuzhiyun static int cmp_subnode(const void *ax, const void *bx)
732*4882a593Smuzhiyun {
733*4882a593Smuzhiyun 	const struct node *a, *b;
734*4882a593Smuzhiyun 
735*4882a593Smuzhiyun 	a = *((const struct node * const *)ax);
736*4882a593Smuzhiyun 	b = *((const struct node * const *)bx);
737*4882a593Smuzhiyun 
738*4882a593Smuzhiyun 	return strcmp(a->name, b->name);
739*4882a593Smuzhiyun }
740*4882a593Smuzhiyun 
sort_subnodes(struct node * node)741*4882a593Smuzhiyun static void sort_subnodes(struct node *node)
742*4882a593Smuzhiyun {
743*4882a593Smuzhiyun 	int n = 0, i = 0;
744*4882a593Smuzhiyun 	struct node *subnode, **tbl;
745*4882a593Smuzhiyun 
746*4882a593Smuzhiyun 	for_each_child_withdel(node, subnode)
747*4882a593Smuzhiyun 		n++;
748*4882a593Smuzhiyun 
749*4882a593Smuzhiyun 	if (n == 0)
750*4882a593Smuzhiyun 		return;
751*4882a593Smuzhiyun 
752*4882a593Smuzhiyun 	tbl = xmalloc(n * sizeof(*tbl));
753*4882a593Smuzhiyun 
754*4882a593Smuzhiyun 	for_each_child_withdel(node, subnode)
755*4882a593Smuzhiyun 		tbl[i++] = subnode;
756*4882a593Smuzhiyun 
757*4882a593Smuzhiyun 	qsort(tbl, n, sizeof(*tbl), cmp_subnode);
758*4882a593Smuzhiyun 
759*4882a593Smuzhiyun 	node->children = tbl[0];
760*4882a593Smuzhiyun 	for (i = 0; i < (n-1); i++)
761*4882a593Smuzhiyun 		tbl[i]->next_sibling = tbl[i+1];
762*4882a593Smuzhiyun 	tbl[n-1]->next_sibling = NULL;
763*4882a593Smuzhiyun 
764*4882a593Smuzhiyun 	free(tbl);
765*4882a593Smuzhiyun }
766*4882a593Smuzhiyun 
sort_node(struct node * node)767*4882a593Smuzhiyun static void sort_node(struct node *node)
768*4882a593Smuzhiyun {
769*4882a593Smuzhiyun 	struct node *c;
770*4882a593Smuzhiyun 
771*4882a593Smuzhiyun 	sort_properties(node);
772*4882a593Smuzhiyun 	sort_subnodes(node);
773*4882a593Smuzhiyun 	for_each_child_withdel(node, c)
774*4882a593Smuzhiyun 		sort_node(c);
775*4882a593Smuzhiyun }
776*4882a593Smuzhiyun 
sort_tree(struct dt_info * dti)777*4882a593Smuzhiyun void sort_tree(struct dt_info *dti)
778*4882a593Smuzhiyun {
779*4882a593Smuzhiyun 	sort_reserve_entries(dti);
780*4882a593Smuzhiyun 	sort_node(dti->dt);
781*4882a593Smuzhiyun }
782*4882a593Smuzhiyun 
783*4882a593Smuzhiyun /* utility helper to avoid code duplication */
build_and_name_child_node(struct node * parent,char * name)784*4882a593Smuzhiyun static struct node *build_and_name_child_node(struct node *parent, char *name)
785*4882a593Smuzhiyun {
786*4882a593Smuzhiyun 	struct node *node;
787*4882a593Smuzhiyun 
788*4882a593Smuzhiyun 	node = build_node(NULL, NULL, NULL);
789*4882a593Smuzhiyun 	name_node(node, xstrdup(name));
790*4882a593Smuzhiyun 	add_child(parent, node);
791*4882a593Smuzhiyun 
792*4882a593Smuzhiyun 	return node;
793*4882a593Smuzhiyun }
794*4882a593Smuzhiyun 
build_root_node(struct node * dt,char * name)795*4882a593Smuzhiyun static struct node *build_root_node(struct node *dt, char *name)
796*4882a593Smuzhiyun {
797*4882a593Smuzhiyun 	struct node *an;
798*4882a593Smuzhiyun 
799*4882a593Smuzhiyun 	an = get_subnode(dt, name);
800*4882a593Smuzhiyun 	if (!an)
801*4882a593Smuzhiyun 		an = build_and_name_child_node(dt, name);
802*4882a593Smuzhiyun 
803*4882a593Smuzhiyun 	if (!an)
804*4882a593Smuzhiyun 		die("Could not build root node /%s\n", name);
805*4882a593Smuzhiyun 
806*4882a593Smuzhiyun 	return an;
807*4882a593Smuzhiyun }
808*4882a593Smuzhiyun 
any_label_tree(struct dt_info * dti,struct node * node)809*4882a593Smuzhiyun static bool any_label_tree(struct dt_info *dti, struct node *node)
810*4882a593Smuzhiyun {
811*4882a593Smuzhiyun 	struct node *c;
812*4882a593Smuzhiyun 
813*4882a593Smuzhiyun 	if (node->labels)
814*4882a593Smuzhiyun 		return true;
815*4882a593Smuzhiyun 
816*4882a593Smuzhiyun 	for_each_child(node, c)
817*4882a593Smuzhiyun 		if (any_label_tree(dti, c))
818*4882a593Smuzhiyun 			return true;
819*4882a593Smuzhiyun 
820*4882a593Smuzhiyun 	return false;
821*4882a593Smuzhiyun }
822*4882a593Smuzhiyun 
generate_label_tree_internal(struct dt_info * dti,struct node * an,struct node * node,bool allocph)823*4882a593Smuzhiyun static void generate_label_tree_internal(struct dt_info *dti,
824*4882a593Smuzhiyun 					 struct node *an, struct node *node,
825*4882a593Smuzhiyun 					 bool allocph)
826*4882a593Smuzhiyun {
827*4882a593Smuzhiyun 	struct node *dt = dti->dt;
828*4882a593Smuzhiyun 	struct node *c;
829*4882a593Smuzhiyun 	struct property *p;
830*4882a593Smuzhiyun 	struct label *l;
831*4882a593Smuzhiyun 
832*4882a593Smuzhiyun 	/* if there are labels */
833*4882a593Smuzhiyun 	if (node->labels) {
834*4882a593Smuzhiyun 
835*4882a593Smuzhiyun 		/* now add the label in the node */
836*4882a593Smuzhiyun 		for_each_label(node->labels, l) {
837*4882a593Smuzhiyun 
838*4882a593Smuzhiyun 			/* check whether the label already exists */
839*4882a593Smuzhiyun 			p = get_property(an, l->label);
840*4882a593Smuzhiyun 			if (p) {
841*4882a593Smuzhiyun 				fprintf(stderr, "WARNING: label %s already"
842*4882a593Smuzhiyun 					" exists in /%s", l->label,
843*4882a593Smuzhiyun 					an->name);
844*4882a593Smuzhiyun 				continue;
845*4882a593Smuzhiyun 			}
846*4882a593Smuzhiyun 
847*4882a593Smuzhiyun 			/* insert it */
848*4882a593Smuzhiyun 			p = build_property(l->label,
849*4882a593Smuzhiyun 				data_copy_escape_string(node->fullpath,
850*4882a593Smuzhiyun 						strlen(node->fullpath)),
851*4882a593Smuzhiyun 				NULL);
852*4882a593Smuzhiyun 			add_property(an, p);
853*4882a593Smuzhiyun 		}
854*4882a593Smuzhiyun 
855*4882a593Smuzhiyun 		/* force allocation of a phandle for this node */
856*4882a593Smuzhiyun 		if (allocph)
857*4882a593Smuzhiyun 			(void)get_node_phandle(dt, node);
858*4882a593Smuzhiyun 	}
859*4882a593Smuzhiyun 
860*4882a593Smuzhiyun 	for_each_child(node, c)
861*4882a593Smuzhiyun 		generate_label_tree_internal(dti, an, c, allocph);
862*4882a593Smuzhiyun }
863*4882a593Smuzhiyun 
any_fixup_tree(struct dt_info * dti,struct node * node)864*4882a593Smuzhiyun static bool any_fixup_tree(struct dt_info *dti, struct node *node)
865*4882a593Smuzhiyun {
866*4882a593Smuzhiyun 	struct node *c;
867*4882a593Smuzhiyun 	struct property *prop;
868*4882a593Smuzhiyun 	struct marker *m;
869*4882a593Smuzhiyun 
870*4882a593Smuzhiyun 	for_each_property(node, prop) {
871*4882a593Smuzhiyun 		m = prop->val.markers;
872*4882a593Smuzhiyun 		for_each_marker_of_type(m, REF_PHANDLE) {
873*4882a593Smuzhiyun 			if (!get_node_by_ref(dti->dt, m->ref))
874*4882a593Smuzhiyun 				return true;
875*4882a593Smuzhiyun 		}
876*4882a593Smuzhiyun 	}
877*4882a593Smuzhiyun 
878*4882a593Smuzhiyun 	for_each_child(node, c) {
879*4882a593Smuzhiyun 		if (any_fixup_tree(dti, c))
880*4882a593Smuzhiyun 			return true;
881*4882a593Smuzhiyun 	}
882*4882a593Smuzhiyun 
883*4882a593Smuzhiyun 	return false;
884*4882a593Smuzhiyun }
885*4882a593Smuzhiyun 
add_fixup_entry(struct dt_info * dti,struct node * fn,struct node * node,struct property * prop,struct marker * m)886*4882a593Smuzhiyun static void add_fixup_entry(struct dt_info *dti, struct node *fn,
887*4882a593Smuzhiyun 			    struct node *node, struct property *prop,
888*4882a593Smuzhiyun 			    struct marker *m)
889*4882a593Smuzhiyun {
890*4882a593Smuzhiyun 	char *entry;
891*4882a593Smuzhiyun 
892*4882a593Smuzhiyun 	/* m->ref can only be a REF_PHANDLE, but check anyway */
893*4882a593Smuzhiyun 	assert(m->type == REF_PHANDLE);
894*4882a593Smuzhiyun 
895*4882a593Smuzhiyun 	/* there shouldn't be any ':' in the arguments */
896*4882a593Smuzhiyun 	if (strchr(node->fullpath, ':') || strchr(prop->name, ':'))
897*4882a593Smuzhiyun 		die("arguments should not contain ':'\n");
898*4882a593Smuzhiyun 
899*4882a593Smuzhiyun 	xasprintf(&entry, "%s:%s:%u",
900*4882a593Smuzhiyun 			node->fullpath, prop->name, m->offset);
901*4882a593Smuzhiyun 	append_to_property(fn, m->ref, entry, strlen(entry) + 1, TYPE_STRING);
902*4882a593Smuzhiyun 
903*4882a593Smuzhiyun 	free(entry);
904*4882a593Smuzhiyun }
905*4882a593Smuzhiyun 
generate_fixups_tree_internal(struct dt_info * dti,struct node * fn,struct node * node)906*4882a593Smuzhiyun static void generate_fixups_tree_internal(struct dt_info *dti,
907*4882a593Smuzhiyun 					  struct node *fn,
908*4882a593Smuzhiyun 					  struct node *node)
909*4882a593Smuzhiyun {
910*4882a593Smuzhiyun 	struct node *dt = dti->dt;
911*4882a593Smuzhiyun 	struct node *c;
912*4882a593Smuzhiyun 	struct property *prop;
913*4882a593Smuzhiyun 	struct marker *m;
914*4882a593Smuzhiyun 	struct node *refnode;
915*4882a593Smuzhiyun 
916*4882a593Smuzhiyun 	for_each_property(node, prop) {
917*4882a593Smuzhiyun 		m = prop->val.markers;
918*4882a593Smuzhiyun 		for_each_marker_of_type(m, REF_PHANDLE) {
919*4882a593Smuzhiyun 			refnode = get_node_by_ref(dt, m->ref);
920*4882a593Smuzhiyun 			if (!refnode)
921*4882a593Smuzhiyun 				add_fixup_entry(dti, fn, node, prop, m);
922*4882a593Smuzhiyun 		}
923*4882a593Smuzhiyun 	}
924*4882a593Smuzhiyun 
925*4882a593Smuzhiyun 	for_each_child(node, c)
926*4882a593Smuzhiyun 		generate_fixups_tree_internal(dti, fn, c);
927*4882a593Smuzhiyun }
928*4882a593Smuzhiyun 
any_local_fixup_tree(struct dt_info * dti,struct node * node)929*4882a593Smuzhiyun static bool any_local_fixup_tree(struct dt_info *dti, struct node *node)
930*4882a593Smuzhiyun {
931*4882a593Smuzhiyun 	struct node *c;
932*4882a593Smuzhiyun 	struct property *prop;
933*4882a593Smuzhiyun 	struct marker *m;
934*4882a593Smuzhiyun 
935*4882a593Smuzhiyun 	for_each_property(node, prop) {
936*4882a593Smuzhiyun 		m = prop->val.markers;
937*4882a593Smuzhiyun 		for_each_marker_of_type(m, REF_PHANDLE) {
938*4882a593Smuzhiyun 			if (get_node_by_ref(dti->dt, m->ref))
939*4882a593Smuzhiyun 				return true;
940*4882a593Smuzhiyun 		}
941*4882a593Smuzhiyun 	}
942*4882a593Smuzhiyun 
943*4882a593Smuzhiyun 	for_each_child(node, c) {
944*4882a593Smuzhiyun 		if (any_local_fixup_tree(dti, c))
945*4882a593Smuzhiyun 			return true;
946*4882a593Smuzhiyun 	}
947*4882a593Smuzhiyun 
948*4882a593Smuzhiyun 	return false;
949*4882a593Smuzhiyun }
950*4882a593Smuzhiyun 
add_local_fixup_entry(struct dt_info * dti,struct node * lfn,struct node * node,struct property * prop,struct marker * m,struct node * refnode)951*4882a593Smuzhiyun static void add_local_fixup_entry(struct dt_info *dti,
952*4882a593Smuzhiyun 		struct node *lfn, struct node *node,
953*4882a593Smuzhiyun 		struct property *prop, struct marker *m,
954*4882a593Smuzhiyun 		struct node *refnode)
955*4882a593Smuzhiyun {
956*4882a593Smuzhiyun 	struct node *wn, *nwn;	/* local fixup node, walk node, new */
957*4882a593Smuzhiyun 	fdt32_t value_32;
958*4882a593Smuzhiyun 	char **compp;
959*4882a593Smuzhiyun 	int i, depth;
960*4882a593Smuzhiyun 
961*4882a593Smuzhiyun 	/* walk back retrieving depth */
962*4882a593Smuzhiyun 	depth = 0;
963*4882a593Smuzhiyun 	for (wn = node; wn; wn = wn->parent)
964*4882a593Smuzhiyun 		depth++;
965*4882a593Smuzhiyun 
966*4882a593Smuzhiyun 	/* allocate name array */
967*4882a593Smuzhiyun 	compp = xmalloc(sizeof(*compp) * depth);
968*4882a593Smuzhiyun 
969*4882a593Smuzhiyun 	/* store names in the array */
970*4882a593Smuzhiyun 	for (wn = node, i = depth - 1; wn; wn = wn->parent, i--)
971*4882a593Smuzhiyun 		compp[i] = wn->name;
972*4882a593Smuzhiyun 
973*4882a593Smuzhiyun 	/* walk the path components creating nodes if they don't exist */
974*4882a593Smuzhiyun 	for (wn = lfn, i = 1; i < depth; i++, wn = nwn) {
975*4882a593Smuzhiyun 		/* if no node exists, create it */
976*4882a593Smuzhiyun 		nwn = get_subnode(wn, compp[i]);
977*4882a593Smuzhiyun 		if (!nwn)
978*4882a593Smuzhiyun 			nwn = build_and_name_child_node(wn, compp[i]);
979*4882a593Smuzhiyun 	}
980*4882a593Smuzhiyun 
981*4882a593Smuzhiyun 	free(compp);
982*4882a593Smuzhiyun 
983*4882a593Smuzhiyun 	value_32 = cpu_to_fdt32(m->offset);
984*4882a593Smuzhiyun 	append_to_property(wn, prop->name, &value_32, sizeof(value_32), TYPE_UINT32);
985*4882a593Smuzhiyun }
986*4882a593Smuzhiyun 
generate_local_fixups_tree_internal(struct dt_info * dti,struct node * lfn,struct node * node)987*4882a593Smuzhiyun static void generate_local_fixups_tree_internal(struct dt_info *dti,
988*4882a593Smuzhiyun 						struct node *lfn,
989*4882a593Smuzhiyun 						struct node *node)
990*4882a593Smuzhiyun {
991*4882a593Smuzhiyun 	struct node *dt = dti->dt;
992*4882a593Smuzhiyun 	struct node *c;
993*4882a593Smuzhiyun 	struct property *prop;
994*4882a593Smuzhiyun 	struct marker *m;
995*4882a593Smuzhiyun 	struct node *refnode;
996*4882a593Smuzhiyun 
997*4882a593Smuzhiyun 	for_each_property(node, prop) {
998*4882a593Smuzhiyun 		m = prop->val.markers;
999*4882a593Smuzhiyun 		for_each_marker_of_type(m, REF_PHANDLE) {
1000*4882a593Smuzhiyun 			refnode = get_node_by_ref(dt, m->ref);
1001*4882a593Smuzhiyun 			if (refnode)
1002*4882a593Smuzhiyun 				add_local_fixup_entry(dti, lfn, node, prop, m, refnode);
1003*4882a593Smuzhiyun 		}
1004*4882a593Smuzhiyun 	}
1005*4882a593Smuzhiyun 
1006*4882a593Smuzhiyun 	for_each_child(node, c)
1007*4882a593Smuzhiyun 		generate_local_fixups_tree_internal(dti, lfn, c);
1008*4882a593Smuzhiyun }
1009*4882a593Smuzhiyun 
generate_label_tree(struct dt_info * dti,char * name,bool allocph)1010*4882a593Smuzhiyun void generate_label_tree(struct dt_info *dti, char *name, bool allocph)
1011*4882a593Smuzhiyun {
1012*4882a593Smuzhiyun 	if (!any_label_tree(dti, dti->dt))
1013*4882a593Smuzhiyun 		return;
1014*4882a593Smuzhiyun 	generate_label_tree_internal(dti, build_root_node(dti->dt, name),
1015*4882a593Smuzhiyun 				     dti->dt, allocph);
1016*4882a593Smuzhiyun }
1017*4882a593Smuzhiyun 
generate_fixups_tree(struct dt_info * dti,char * name)1018*4882a593Smuzhiyun void generate_fixups_tree(struct dt_info *dti, char *name)
1019*4882a593Smuzhiyun {
1020*4882a593Smuzhiyun 	if (!any_fixup_tree(dti, dti->dt))
1021*4882a593Smuzhiyun 		return;
1022*4882a593Smuzhiyun 	generate_fixups_tree_internal(dti, build_root_node(dti->dt, name),
1023*4882a593Smuzhiyun 				      dti->dt);
1024*4882a593Smuzhiyun }
1025*4882a593Smuzhiyun 
generate_local_fixups_tree(struct dt_info * dti,char * name)1026*4882a593Smuzhiyun void generate_local_fixups_tree(struct dt_info *dti, char *name)
1027*4882a593Smuzhiyun {
1028*4882a593Smuzhiyun 	if (!any_local_fixup_tree(dti, dti->dt))
1029*4882a593Smuzhiyun 		return;
1030*4882a593Smuzhiyun 	generate_local_fixups_tree_internal(dti, build_root_node(dti->dt, name),
1031*4882a593Smuzhiyun 					    dti->dt);
1032*4882a593Smuzhiyun }
1033