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