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