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