xref: /rk3399_rockchip-uboot/scripts/dtc/livetree.c (revision bd3ad955a3cc8367062de9abdc193070874f403e)
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 
add_label(struct label ** labels,char * label)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 
delete_labels(struct label ** labels)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 
build_property(char * name,struct data val)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 
build_property_delete(char * name)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 
chain_property(struct property * first,struct property * list)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 
reverse_properties(struct property * first)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 
build_node(struct property * proplist,struct node * children)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 
build_node_delete(void)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 
name_node(struct node * node,char * name)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 
merge_nodes(struct node * old_node,struct node * new_node)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 
add_orphan_node(struct node * dt,struct node * new_node,char * ref)21914df9b24SMasahiro Yamada void add_orphan_node(struct node *dt, struct node *new_node, char *ref)
22014df9b24SMasahiro Yamada {
22114df9b24SMasahiro Yamada 	static unsigned int next_orphan_fragment = 0;
22214df9b24SMasahiro Yamada 	struct node *node;
22314df9b24SMasahiro Yamada 	struct property *p;
22414df9b24SMasahiro Yamada 	struct data d = empty_data;
22514df9b24SMasahiro Yamada 	char *name;
22614df9b24SMasahiro Yamada 
22714df9b24SMasahiro Yamada 	d = data_add_marker(d, REF_PHANDLE, ref);
22814df9b24SMasahiro Yamada 	d = data_append_integer(d, 0xffffffff, 32);
22914df9b24SMasahiro Yamada 
23014df9b24SMasahiro Yamada 	p = build_property("target", d);
23114df9b24SMasahiro Yamada 
23214df9b24SMasahiro Yamada 	xasprintf(&name, "fragment@%u",
23314df9b24SMasahiro Yamada 			next_orphan_fragment++);
23414df9b24SMasahiro Yamada 	name_node(new_node, "__overlay__");
23514df9b24SMasahiro Yamada 	node = build_node(p, new_node);
23614df9b24SMasahiro Yamada 	name_node(node, name);
23714df9b24SMasahiro Yamada 
23814df9b24SMasahiro Yamada 	add_child(dt, node);
23914df9b24SMasahiro Yamada }
24014df9b24SMasahiro Yamada 
chain_node(struct node * first,struct node * list)241d18719a4STom Rini struct node *chain_node(struct node *first, struct node *list)
242d18719a4STom Rini {
243d18719a4STom Rini 	assert(first->next_sibling == NULL);
244d18719a4STom Rini 
245d18719a4STom Rini 	first->next_sibling = list;
246d18719a4STom Rini 	return first;
247d18719a4STom Rini }
248d18719a4STom Rini 
add_property(struct node * node,struct property * prop)249d18719a4STom Rini void add_property(struct node *node, struct property *prop)
250d18719a4STom Rini {
251d18719a4STom Rini 	struct property **p;
252d18719a4STom Rini 
253d18719a4STom Rini 	prop->next = NULL;
254d18719a4STom Rini 
255d18719a4STom Rini 	p = &node->proplist;
256d18719a4STom Rini 	while (*p)
257d18719a4STom Rini 		p = &((*p)->next);
258d18719a4STom Rini 
259d18719a4STom Rini 	*p = prop;
260d18719a4STom Rini }
261d18719a4STom Rini 
delete_property_by_name(struct node * node,char * name)262d18719a4STom Rini void delete_property_by_name(struct node *node, char *name)
263d18719a4STom Rini {
264d18719a4STom Rini 	struct property *prop = node->proplist;
265d18719a4STom Rini 
266d18719a4STom Rini 	while (prop) {
267d18719a4STom Rini 		if (streq(prop->name, name)) {
268d18719a4STom Rini 			delete_property(prop);
269d18719a4STom Rini 			return;
270d18719a4STom Rini 		}
271d18719a4STom Rini 		prop = prop->next;
272d18719a4STom Rini 	}
273d18719a4STom Rini }
274d18719a4STom Rini 
delete_property(struct property * prop)275d18719a4STom Rini void delete_property(struct property *prop)
276d18719a4STom Rini {
277d18719a4STom Rini 	prop->deleted = 1;
278d18719a4STom Rini 	delete_labels(&prop->labels);
279d18719a4STom Rini }
280d18719a4STom Rini 
add_child(struct node * parent,struct node * child)281d18719a4STom Rini void add_child(struct node *parent, struct node *child)
282d18719a4STom Rini {
283d18719a4STom Rini 	struct node **p;
284d18719a4STom Rini 
285d18719a4STom Rini 	child->next_sibling = NULL;
286d18719a4STom Rini 	child->parent = parent;
287d18719a4STom Rini 
288d18719a4STom Rini 	p = &parent->children;
289d18719a4STom Rini 	while (*p)
290d18719a4STom Rini 		p = &((*p)->next_sibling);
291d18719a4STom Rini 
292d18719a4STom Rini 	*p = child;
293d18719a4STom Rini }
294d18719a4STom Rini 
delete_node_by_name(struct node * parent,char * name)295d18719a4STom Rini void delete_node_by_name(struct node *parent, char *name)
296d18719a4STom Rini {
297d18719a4STom Rini 	struct node *node = parent->children;
298d18719a4STom Rini 
299d18719a4STom Rini 	while (node) {
300d18719a4STom Rini 		if (streq(node->name, name)) {
301d18719a4STom Rini 			delete_node(node);
302d18719a4STom Rini 			return;
303d18719a4STom Rini 		}
304d18719a4STom Rini 		node = node->next_sibling;
305d18719a4STom Rini 	}
306d18719a4STom Rini }
307d18719a4STom Rini 
delete_node(struct node * node)308d18719a4STom Rini void delete_node(struct node *node)
309d18719a4STom Rini {
310d18719a4STom Rini 	struct property *prop;
311d18719a4STom Rini 	struct node *child;
312d18719a4STom Rini 
313d18719a4STom Rini 	node->deleted = 1;
314d18719a4STom Rini 	for_each_child(node, child)
315d18719a4STom Rini 		delete_node(child);
316d18719a4STom Rini 	for_each_property(node, prop)
317d18719a4STom Rini 		delete_property(prop);
318d18719a4STom Rini 	delete_labels(&node->labels);
319d18719a4STom Rini }
320d18719a4STom Rini 
append_to_property(struct node * node,char * name,const void * data,int len)321d18719a4STom Rini void append_to_property(struct node *node,
322d18719a4STom Rini 				    char *name, const void *data, int len)
323d18719a4STom Rini {
324d18719a4STom Rini 	struct data d;
325d18719a4STom Rini 	struct property *p;
326d18719a4STom Rini 
327d18719a4STom Rini 	p = get_property(node, name);
328d18719a4STom Rini 	if (p) {
329d18719a4STom Rini 		d = data_append_data(p->val, data, len);
330d18719a4STom Rini 		p->val = d;
331d18719a4STom Rini 	} else {
332d18719a4STom Rini 		d = data_append_data(empty_data, data, len);
333d18719a4STom Rini 		p = build_property(name, d);
334d18719a4STom Rini 		add_property(node, p);
335d18719a4STom Rini 	}
336d18719a4STom Rini }
337d18719a4STom Rini 
build_reserve_entry(uint64_t address,uint64_t size)338d18719a4STom Rini struct reserve_info *build_reserve_entry(uint64_t address, uint64_t size)
339d18719a4STom Rini {
340d18719a4STom Rini 	struct reserve_info *new = xmalloc(sizeof(*new));
341d18719a4STom Rini 
342d18719a4STom Rini 	memset(new, 0, sizeof(*new));
343d18719a4STom Rini 
344e23ffda2STom Rini 	new->address = address;
345e23ffda2STom Rini 	new->size = size;
346d18719a4STom Rini 
347d18719a4STom Rini 	return new;
348d18719a4STom Rini }
349d18719a4STom Rini 
chain_reserve_entry(struct reserve_info * first,struct reserve_info * list)350d18719a4STom Rini struct reserve_info *chain_reserve_entry(struct reserve_info *first,
351d18719a4STom Rini 					struct reserve_info *list)
352d18719a4STom Rini {
353d18719a4STom Rini 	assert(first->next == NULL);
354d18719a4STom Rini 
355d18719a4STom Rini 	first->next = list;
356d18719a4STom Rini 	return first;
357d18719a4STom Rini }
358d18719a4STom Rini 
add_reserve_entry(struct reserve_info * list,struct reserve_info * new)359d18719a4STom Rini struct reserve_info *add_reserve_entry(struct reserve_info *list,
360d18719a4STom Rini 				      struct reserve_info *new)
361d18719a4STom Rini {
362d18719a4STom Rini 	struct reserve_info *last;
363d18719a4STom Rini 
364d18719a4STom Rini 	new->next = NULL;
365d18719a4STom Rini 
366d18719a4STom Rini 	if (! list)
367d18719a4STom Rini 		return new;
368d18719a4STom Rini 
369d18719a4STom Rini 	for (last = list; last->next; last = last->next)
370d18719a4STom Rini 		;
371d18719a4STom Rini 
372d18719a4STom Rini 	last->next = new;
373d18719a4STom Rini 
374d18719a4STom Rini 	return list;
375d18719a4STom Rini }
376d18719a4STom Rini 
build_dt_info(unsigned int dtsflags,struct reserve_info * reservelist,struct node * tree,uint32_t boot_cpuid_phys)377d18719a4STom Rini struct dt_info *build_dt_info(unsigned int dtsflags,
378d18719a4STom Rini 			      struct reserve_info *reservelist,
379d18719a4STom Rini 			      struct node *tree, uint32_t boot_cpuid_phys)
380d18719a4STom Rini {
381d18719a4STom Rini 	struct dt_info *dti;
382d18719a4STom Rini 
383d18719a4STom Rini 	dti = xmalloc(sizeof(*dti));
384d18719a4STom Rini 	dti->dtsflags = dtsflags;
385d18719a4STom Rini 	dti->reservelist = reservelist;
386d18719a4STom Rini 	dti->dt = tree;
387d18719a4STom Rini 	dti->boot_cpuid_phys = boot_cpuid_phys;
388d18719a4STom Rini 
389d18719a4STom Rini 	return dti;
390d18719a4STom Rini }
391d18719a4STom Rini 
392d18719a4STom Rini /*
393d18719a4STom Rini  * Tree accessor functions
394d18719a4STom Rini  */
395d18719a4STom Rini 
get_unitname(struct node * node)396d18719a4STom Rini const char *get_unitname(struct node *node)
397d18719a4STom Rini {
398d18719a4STom Rini 	if (node->name[node->basenamelen] == '\0')
399d18719a4STom Rini 		return "";
400d18719a4STom Rini 	else
401d18719a4STom Rini 		return node->name + node->basenamelen + 1;
402d18719a4STom Rini }
403d18719a4STom Rini 
get_property(struct node * node,const char * propname)404d18719a4STom Rini struct property *get_property(struct node *node, const char *propname)
405d18719a4STom Rini {
406d18719a4STom Rini 	struct property *prop;
407d18719a4STom Rini 
408d18719a4STom Rini 	for_each_property(node, prop)
409d18719a4STom Rini 		if (streq(prop->name, propname))
410d18719a4STom Rini 			return prop;
411d18719a4STom Rini 
412d18719a4STom Rini 	return NULL;
413d18719a4STom Rini }
414d18719a4STom Rini 
propval_cell(struct property * prop)415d18719a4STom Rini cell_t propval_cell(struct property *prop)
416d18719a4STom Rini {
417d18719a4STom Rini 	assert(prop->val.len == sizeof(cell_t));
418e23ffda2STom Rini 	return fdt32_to_cpu(*((fdt32_t *)prop->val.val));
419d18719a4STom Rini }
420d18719a4STom Rini 
propval_cell_n(struct property * prop,int n)42114df9b24SMasahiro Yamada cell_t propval_cell_n(struct property *prop, int n)
42214df9b24SMasahiro Yamada {
42314df9b24SMasahiro Yamada 	assert(prop->val.len / sizeof(cell_t) >= n);
42414df9b24SMasahiro Yamada 	return fdt32_to_cpu(*((fdt32_t *)prop->val.val + n));
42514df9b24SMasahiro Yamada }
42614df9b24SMasahiro Yamada 
get_property_by_label(struct node * tree,const char * label,struct node ** node)427d18719a4STom Rini struct property *get_property_by_label(struct node *tree, const char *label,
428d18719a4STom Rini 				       struct node **node)
429d18719a4STom Rini {
430d18719a4STom Rini 	struct property *prop;
431d18719a4STom Rini 	struct node *c;
432d18719a4STom Rini 
433d18719a4STom Rini 	*node = tree;
434d18719a4STom Rini 
435d18719a4STom Rini 	for_each_property(tree, prop) {
436d18719a4STom Rini 		struct label *l;
437d18719a4STom Rini 
438d18719a4STom Rini 		for_each_label(prop->labels, l)
439d18719a4STom Rini 			if (streq(l->label, label))
440d18719a4STom Rini 				return prop;
441d18719a4STom Rini 	}
442d18719a4STom Rini 
443d18719a4STom Rini 	for_each_child(tree, c) {
444d18719a4STom Rini 		prop = get_property_by_label(c, label, node);
445d18719a4STom Rini 		if (prop)
446d18719a4STom Rini 			return prop;
447d18719a4STom Rini 	}
448d18719a4STom Rini 
449d18719a4STom Rini 	*node = NULL;
450d18719a4STom Rini 	return NULL;
451d18719a4STom Rini }
452d18719a4STom Rini 
get_marker_label(struct node * tree,const char * label,struct node ** node,struct property ** prop)453d18719a4STom Rini struct marker *get_marker_label(struct node *tree, const char *label,
454d18719a4STom Rini 				struct node **node, struct property **prop)
455d18719a4STom Rini {
456d18719a4STom Rini 	struct marker *m;
457d18719a4STom Rini 	struct property *p;
458d18719a4STom Rini 	struct node *c;
459d18719a4STom Rini 
460d18719a4STom Rini 	*node = tree;
461d18719a4STom Rini 
462d18719a4STom Rini 	for_each_property(tree, p) {
463d18719a4STom Rini 		*prop = p;
464d18719a4STom Rini 		m = p->val.markers;
465d18719a4STom Rini 		for_each_marker_of_type(m, LABEL)
466d18719a4STom Rini 			if (streq(m->ref, label))
467d18719a4STom Rini 				return m;
468d18719a4STom Rini 	}
469d18719a4STom Rini 
470d18719a4STom Rini 	for_each_child(tree, c) {
471d18719a4STom Rini 		m = get_marker_label(c, label, node, prop);
472d18719a4STom Rini 		if (m)
473d18719a4STom Rini 			return m;
474d18719a4STom Rini 	}
475d18719a4STom Rini 
476d18719a4STom Rini 	*prop = NULL;
477d18719a4STom Rini 	*node = NULL;
478d18719a4STom Rini 	return NULL;
479d18719a4STom Rini }
480d18719a4STom Rini 
get_subnode(struct node * node,const char * nodename)481d18719a4STom Rini struct node *get_subnode(struct node *node, const char *nodename)
482d18719a4STom Rini {
483d18719a4STom Rini 	struct node *child;
484d18719a4STom Rini 
485d18719a4STom Rini 	for_each_child(node, child)
486d18719a4STom Rini 		if (streq(child->name, nodename))
487d18719a4STom Rini 			return child;
488d18719a4STom Rini 
489d18719a4STom Rini 	return NULL;
490d18719a4STom Rini }
491d18719a4STom Rini 
get_node_by_path(struct node * tree,const char * path)492d18719a4STom Rini struct node *get_node_by_path(struct node *tree, const char *path)
493d18719a4STom Rini {
494d18719a4STom Rini 	const char *p;
495d18719a4STom Rini 	struct node *child;
496d18719a4STom Rini 
497d18719a4STom Rini 	if (!path || ! (*path)) {
498d18719a4STom Rini 		if (tree->deleted)
499d18719a4STom Rini 			return NULL;
500d18719a4STom Rini 		return tree;
501d18719a4STom Rini 	}
502d18719a4STom Rini 
503d18719a4STom Rini 	while (path[0] == '/')
504d18719a4STom Rini 		path++;
505d18719a4STom Rini 
506d18719a4STom Rini 	p = strchr(path, '/');
507d18719a4STom Rini 
508d18719a4STom Rini 	for_each_child(tree, child) {
509d7857e40STom Rini 		if (p && (strlen(child->name) == p-path) &&
510d7857e40STom Rini 				strneq(path, child->name, p-path))
511d18719a4STom Rini 			return get_node_by_path(child, p+1);
512d18719a4STom Rini 		else if (!p && streq(path, child->name))
513d18719a4STom Rini 			return child;
514d18719a4STom Rini 	}
515d18719a4STom Rini 
516d18719a4STom Rini 	return NULL;
517d18719a4STom Rini }
518d18719a4STom Rini 
get_node_by_label(struct node * tree,const char * label)519d18719a4STom Rini struct node *get_node_by_label(struct node *tree, const char *label)
520d18719a4STom Rini {
521d18719a4STom Rini 	struct node *child, *node;
522d18719a4STom Rini 	struct label *l;
523d18719a4STom Rini 
524d18719a4STom Rini 	assert(label && (strlen(label) > 0));
525d18719a4STom Rini 
526d18719a4STom Rini 	for_each_label(tree->labels, l)
527d18719a4STom Rini 		if (streq(l->label, label))
528d18719a4STom Rini 			return tree;
529d18719a4STom Rini 
530d18719a4STom Rini 	for_each_child(tree, child) {
531d18719a4STom Rini 		node = get_node_by_label(child, label);
532d18719a4STom Rini 		if (node)
533d18719a4STom Rini 			return node;
534d18719a4STom Rini 	}
535d18719a4STom Rini 
536d18719a4STom Rini 	return NULL;
537d18719a4STom Rini }
538d18719a4STom Rini 
get_node_by_phandle(struct node * tree,cell_t phandle)539d18719a4STom Rini struct node *get_node_by_phandle(struct node *tree, cell_t phandle)
540d18719a4STom Rini {
541d18719a4STom Rini 	struct node *child, *node;
542d18719a4STom Rini 
543d18719a4STom Rini 	assert((phandle != 0) && (phandle != -1));
544d18719a4STom Rini 
545d18719a4STom Rini 	if (tree->phandle == phandle) {
546d18719a4STom Rini 		if (tree->deleted)
547d18719a4STom Rini 			return NULL;
548d18719a4STom Rini 		return tree;
549d18719a4STom Rini 	}
550d18719a4STom Rini 
551d18719a4STom Rini 	for_each_child(tree, child) {
552d18719a4STom Rini 		node = get_node_by_phandle(child, phandle);
553d18719a4STom Rini 		if (node)
554d18719a4STom Rini 			return node;
555d18719a4STom Rini 	}
556d18719a4STom Rini 
557d18719a4STom Rini 	return NULL;
558d18719a4STom Rini }
559d18719a4STom Rini 
get_node_by_ref(struct node * tree,const char * ref)560d18719a4STom Rini struct node *get_node_by_ref(struct node *tree, const char *ref)
561d18719a4STom Rini {
562d18719a4STom Rini 	if (streq(ref, "/"))
563d18719a4STom Rini 		return tree;
564d18719a4STom Rini 	else if (ref[0] == '/')
565d18719a4STom Rini 		return get_node_by_path(tree, ref);
566d18719a4STom Rini 	else
567d18719a4STom Rini 		return get_node_by_label(tree, ref);
568d18719a4STom Rini }
569d18719a4STom Rini 
get_node_phandle(struct node * root,struct node * node)570d18719a4STom Rini cell_t get_node_phandle(struct node *root, struct node *node)
571d18719a4STom Rini {
572*bd3ad955SJianqun Xu 	static cell_t phandle = 0x10000000; /* FIXME: ick, static local */
573d18719a4STom Rini 
574d18719a4STom Rini 	if ((node->phandle != 0) && (node->phandle != -1))
575d18719a4STom Rini 		return node->phandle;
576d18719a4STom Rini 
577d18719a4STom Rini 	while (get_node_by_phandle(root, phandle))
578d18719a4STom Rini 		phandle++;
579d18719a4STom Rini 
580d18719a4STom Rini 	node->phandle = phandle;
581d18719a4STom Rini 
582d18719a4STom Rini 	if (!get_property(node, "linux,phandle")
583d18719a4STom Rini 	    && (phandle_format & PHANDLE_LEGACY))
584d18719a4STom Rini 		add_property(node,
585d18719a4STom Rini 			     build_property("linux,phandle",
586d18719a4STom Rini 					    data_append_cell(empty_data, phandle)));
587d18719a4STom Rini 
588d18719a4STom Rini 	if (!get_property(node, "phandle")
589d18719a4STom Rini 	    && (phandle_format & PHANDLE_EPAPR))
590d18719a4STom Rini 		add_property(node,
591d18719a4STom Rini 			     build_property("phandle",
592d18719a4STom Rini 					    data_append_cell(empty_data, phandle)));
593d18719a4STom Rini 
594d18719a4STom Rini 	/* If the node *does* have a phandle property, we must
595d18719a4STom Rini 	 * be dealing with a self-referencing phandle, which will be
596d18719a4STom Rini 	 * fixed up momentarily in the caller */
597d18719a4STom Rini 
598d18719a4STom Rini 	return node->phandle;
599d18719a4STom Rini }
600d18719a4STom Rini 
guess_boot_cpuid(struct node * tree)601d18719a4STom Rini uint32_t guess_boot_cpuid(struct node *tree)
602d18719a4STom Rini {
603d18719a4STom Rini 	struct node *cpus, *bootcpu;
604d18719a4STom Rini 	struct property *reg;
605d18719a4STom Rini 
606d18719a4STom Rini 	cpus = get_node_by_path(tree, "/cpus");
607d18719a4STom Rini 	if (!cpus)
608d18719a4STom Rini 		return 0;
609d18719a4STom Rini 
610d18719a4STom Rini 
611d18719a4STom Rini 	bootcpu = cpus->children;
612d18719a4STom Rini 	if (!bootcpu)
613d18719a4STom Rini 		return 0;
614d18719a4STom Rini 
615d18719a4STom Rini 	reg = get_property(bootcpu, "reg");
616d18719a4STom Rini 	if (!reg || (reg->val.len != sizeof(uint32_t)))
617d18719a4STom Rini 		return 0;
618d18719a4STom Rini 
619d18719a4STom Rini 	/* FIXME: Sanity check node? */
620d18719a4STom Rini 
621d18719a4STom Rini 	return propval_cell(reg);
622d18719a4STom Rini }
623d18719a4STom Rini 
cmp_reserve_info(const void * ax,const void * bx)624d18719a4STom Rini static int cmp_reserve_info(const void *ax, const void *bx)
625d18719a4STom Rini {
626d18719a4STom Rini 	const struct reserve_info *a, *b;
627d18719a4STom Rini 
628d18719a4STom Rini 	a = *((const struct reserve_info * const *)ax);
629d18719a4STom Rini 	b = *((const struct reserve_info * const *)bx);
630d18719a4STom Rini 
631e23ffda2STom Rini 	if (a->address < b->address)
632d18719a4STom Rini 		return -1;
633e23ffda2STom Rini 	else if (a->address > b->address)
634d18719a4STom Rini 		return 1;
635e23ffda2STom Rini 	else if (a->size < b->size)
636d18719a4STom Rini 		return -1;
637e23ffda2STom Rini 	else if (a->size > b->size)
638d18719a4STom Rini 		return 1;
639d18719a4STom Rini 	else
640d18719a4STom Rini 		return 0;
641d18719a4STom Rini }
642d18719a4STom Rini 
sort_reserve_entries(struct dt_info * dti)643d18719a4STom Rini static void sort_reserve_entries(struct dt_info *dti)
644d18719a4STom Rini {
645d18719a4STom Rini 	struct reserve_info *ri, **tbl;
646d18719a4STom Rini 	int n = 0, i = 0;
647d18719a4STom Rini 
648d18719a4STom Rini 	for (ri = dti->reservelist;
649d18719a4STom Rini 	     ri;
650d18719a4STom Rini 	     ri = ri->next)
651d18719a4STom Rini 		n++;
652d18719a4STom Rini 
653d18719a4STom Rini 	if (n == 0)
654d18719a4STom Rini 		return;
655d18719a4STom Rini 
656d18719a4STom Rini 	tbl = xmalloc(n * sizeof(*tbl));
657d18719a4STom Rini 
658d18719a4STom Rini 	for (ri = dti->reservelist;
659d18719a4STom Rini 	     ri;
660d18719a4STom Rini 	     ri = ri->next)
661d18719a4STom Rini 		tbl[i++] = ri;
662d18719a4STom Rini 
663d18719a4STom Rini 	qsort(tbl, n, sizeof(*tbl), cmp_reserve_info);
664d18719a4STom Rini 
665d18719a4STom Rini 	dti->reservelist = tbl[0];
666d18719a4STom Rini 	for (i = 0; i < (n-1); i++)
667d18719a4STom Rini 		tbl[i]->next = tbl[i+1];
668d18719a4STom Rini 	tbl[n-1]->next = NULL;
669d18719a4STom Rini 
670d18719a4STom Rini 	free(tbl);
671d18719a4STom Rini }
672d18719a4STom Rini 
cmp_prop(const void * ax,const void * bx)673d18719a4STom Rini static int cmp_prop(const void *ax, const void *bx)
674d18719a4STom Rini {
675d18719a4STom Rini 	const struct property *a, *b;
676d18719a4STom Rini 
677d18719a4STom Rini 	a = *((const struct property * const *)ax);
678d18719a4STom Rini 	b = *((const struct property * const *)bx);
679d18719a4STom Rini 
680d18719a4STom Rini 	return strcmp(a->name, b->name);
681d18719a4STom Rini }
682d18719a4STom Rini 
sort_properties(struct node * node)683d18719a4STom Rini static void sort_properties(struct node *node)
684d18719a4STom Rini {
685d18719a4STom Rini 	int n = 0, i = 0;
686d18719a4STom Rini 	struct property *prop, **tbl;
687d18719a4STom Rini 
688d18719a4STom Rini 	for_each_property_withdel(node, prop)
689d18719a4STom Rini 		n++;
690d18719a4STom Rini 
691d18719a4STom Rini 	if (n == 0)
692d18719a4STom Rini 		return;
693d18719a4STom Rini 
694d18719a4STom Rini 	tbl = xmalloc(n * sizeof(*tbl));
695d18719a4STom Rini 
696d18719a4STom Rini 	for_each_property_withdel(node, prop)
697d18719a4STom Rini 		tbl[i++] = prop;
698d18719a4STom Rini 
699d18719a4STom Rini 	qsort(tbl, n, sizeof(*tbl), cmp_prop);
700d18719a4STom Rini 
701d18719a4STom Rini 	node->proplist = tbl[0];
702d18719a4STom Rini 	for (i = 0; i < (n-1); i++)
703d18719a4STom Rini 		tbl[i]->next = tbl[i+1];
704d18719a4STom Rini 	tbl[n-1]->next = NULL;
705d18719a4STom Rini 
706d18719a4STom Rini 	free(tbl);
707d18719a4STom Rini }
708d18719a4STom Rini 
cmp_subnode(const void * ax,const void * bx)709d18719a4STom Rini static int cmp_subnode(const void *ax, const void *bx)
710d18719a4STom Rini {
711d18719a4STom Rini 	const struct node *a, *b;
712d18719a4STom Rini 
713d18719a4STom Rini 	a = *((const struct node * const *)ax);
714d18719a4STom Rini 	b = *((const struct node * const *)bx);
715d18719a4STom Rini 
716d18719a4STom Rini 	return strcmp(a->name, b->name);
717d18719a4STom Rini }
718d18719a4STom Rini 
sort_subnodes(struct node * node)719d18719a4STom Rini static void sort_subnodes(struct node *node)
720d18719a4STom Rini {
721d18719a4STom Rini 	int n = 0, i = 0;
722d18719a4STom Rini 	struct node *subnode, **tbl;
723d18719a4STom Rini 
724d18719a4STom Rini 	for_each_child_withdel(node, subnode)
725d18719a4STom Rini 		n++;
726d18719a4STom Rini 
727d18719a4STom Rini 	if (n == 0)
728d18719a4STom Rini 		return;
729d18719a4STom Rini 
730d18719a4STom Rini 	tbl = xmalloc(n * sizeof(*tbl));
731d18719a4STom Rini 
732d18719a4STom Rini 	for_each_child_withdel(node, subnode)
733d18719a4STom Rini 		tbl[i++] = subnode;
734d18719a4STom Rini 
735d18719a4STom Rini 	qsort(tbl, n, sizeof(*tbl), cmp_subnode);
736d18719a4STom Rini 
737d18719a4STom Rini 	node->children = tbl[0];
738d18719a4STom Rini 	for (i = 0; i < (n-1); i++)
739d18719a4STom Rini 		tbl[i]->next_sibling = tbl[i+1];
740d18719a4STom Rini 	tbl[n-1]->next_sibling = NULL;
741d18719a4STom Rini 
742d18719a4STom Rini 	free(tbl);
743d18719a4STom Rini }
744d18719a4STom Rini 
sort_node(struct node * node)745d18719a4STom Rini static void sort_node(struct node *node)
746d18719a4STom Rini {
747d18719a4STom Rini 	struct node *c;
748d18719a4STom Rini 
749d18719a4STom Rini 	sort_properties(node);
750d18719a4STom Rini 	sort_subnodes(node);
751d18719a4STom Rini 	for_each_child_withdel(node, c)
752d18719a4STom Rini 		sort_node(c);
753d18719a4STom Rini }
754d18719a4STom Rini 
sort_tree(struct dt_info * dti)755d18719a4STom Rini void sort_tree(struct dt_info *dti)
756d18719a4STom Rini {
757d18719a4STom Rini 	sort_reserve_entries(dti);
758d18719a4STom Rini 	sort_node(dti->dt);
759d18719a4STom Rini }
760d18719a4STom Rini 
761d18719a4STom Rini /* utility helper to avoid code duplication */
build_and_name_child_node(struct node * parent,char * name)762d18719a4STom Rini static struct node *build_and_name_child_node(struct node *parent, char *name)
763d18719a4STom Rini {
764d18719a4STom Rini 	struct node *node;
765d18719a4STom Rini 
766d18719a4STom Rini 	node = build_node(NULL, NULL);
767d18719a4STom Rini 	name_node(node, xstrdup(name));
768d18719a4STom Rini 	add_child(parent, node);
769d18719a4STom Rini 
770d18719a4STom Rini 	return node;
771d18719a4STom Rini }
772d18719a4STom Rini 
build_root_node(struct node * dt,char * name)773d18719a4STom Rini static struct node *build_root_node(struct node *dt, char *name)
774d18719a4STom Rini {
775d18719a4STom Rini 	struct node *an;
776d18719a4STom Rini 
777d18719a4STom Rini 	an = get_subnode(dt, name);
778d18719a4STom Rini 	if (!an)
779d18719a4STom Rini 		an = build_and_name_child_node(dt, name);
780d18719a4STom Rini 
781d18719a4STom Rini 	if (!an)
782d18719a4STom Rini 		die("Could not build root node /%s\n", name);
783d18719a4STom Rini 
784d18719a4STom Rini 	return an;
785d18719a4STom Rini }
786d18719a4STom Rini 
any_label_tree(struct dt_info * dti,struct node * node)787d18719a4STom Rini static bool any_label_tree(struct dt_info *dti, struct node *node)
788d18719a4STom Rini {
789d18719a4STom Rini 	struct node *c;
790d18719a4STom Rini 
791d18719a4STom Rini 	if (node->labels)
792d18719a4STom Rini 		return true;
793d18719a4STom Rini 
794d18719a4STom Rini 	for_each_child(node, c)
795d18719a4STom Rini 		if (any_label_tree(dti, c))
796d18719a4STom Rini 			return true;
797d18719a4STom Rini 
798d18719a4STom Rini 	return false;
799d18719a4STom Rini }
800d18719a4STom Rini 
generate_label_tree_internal(struct dt_info * dti,struct node * an,struct node * node,bool allocph)801d18719a4STom Rini static void generate_label_tree_internal(struct dt_info *dti,
802d18719a4STom Rini 					 struct node *an, struct node *node,
803d18719a4STom Rini 					 bool allocph)
804d18719a4STom Rini {
805d18719a4STom Rini 	struct node *dt = dti->dt;
806d18719a4STom Rini 	struct node *c;
807d18719a4STom Rini 	struct property *p;
808d18719a4STom Rini 	struct label *l;
809d18719a4STom Rini 
810d18719a4STom Rini 	/* if there are labels */
811d18719a4STom Rini 	if (node->labels) {
812d18719a4STom Rini 
813d18719a4STom Rini 		/* now add the label in the node */
814d18719a4STom Rini 		for_each_label(node->labels, l) {
815d18719a4STom Rini 
816d18719a4STom Rini 			/* check whether the label already exists */
817d18719a4STom Rini 			p = get_property(an, l->label);
818d18719a4STom Rini 			if (p) {
819d18719a4STom Rini 				fprintf(stderr, "WARNING: label %s already"
820d18719a4STom Rini 					" exists in /%s", l->label,
821d18719a4STom Rini 					an->name);
822d18719a4STom Rini 				continue;
823d18719a4STom Rini 			}
824d18719a4STom Rini 
825d18719a4STom Rini 			/* insert it */
826d18719a4STom Rini 			p = build_property(l->label,
827d18719a4STom Rini 				data_copy_mem(node->fullpath,
828d18719a4STom Rini 						strlen(node->fullpath) + 1));
829d18719a4STom Rini 			add_property(an, p);
830d18719a4STom Rini 		}
831d18719a4STom Rini 
832d18719a4STom Rini 		/* force allocation of a phandle for this node */
833d18719a4STom Rini 		if (allocph)
834d18719a4STom Rini 			(void)get_node_phandle(dt, node);
835d18719a4STom Rini 	}
836d18719a4STom Rini 
837d18719a4STom Rini 	for_each_child(node, c)
838d18719a4STom Rini 		generate_label_tree_internal(dti, an, c, allocph);
839d18719a4STom Rini }
840d18719a4STom Rini 
any_fixup_tree(struct dt_info * dti,struct node * node)841d18719a4STom Rini static bool any_fixup_tree(struct dt_info *dti, struct node *node)
842d18719a4STom Rini {
843d18719a4STom Rini 	struct node *c;
844d18719a4STom Rini 	struct property *prop;
845d18719a4STom Rini 	struct marker *m;
846d18719a4STom Rini 
847d18719a4STom Rini 	for_each_property(node, prop) {
848d18719a4STom Rini 		m = prop->val.markers;
849d18719a4STom Rini 		for_each_marker_of_type(m, REF_PHANDLE) {
850d18719a4STom Rini 			if (!get_node_by_ref(dti->dt, m->ref))
851d18719a4STom Rini 				return true;
852d18719a4STom Rini 		}
853d18719a4STom Rini 	}
854d18719a4STom Rini 
855d18719a4STom Rini 	for_each_child(node, c) {
856d18719a4STom Rini 		if (any_fixup_tree(dti, c))
857d18719a4STom Rini 			return true;
858d18719a4STom Rini 	}
859d18719a4STom Rini 
860d18719a4STom Rini 	return false;
861d18719a4STom Rini }
862d18719a4STom Rini 
add_fixup_entry(struct dt_info * dti,struct node * fn,struct node * node,struct property * prop,struct marker * m)863d18719a4STom Rini static void add_fixup_entry(struct dt_info *dti, struct node *fn,
864d18719a4STom Rini 			    struct node *node, struct property *prop,
865d18719a4STom Rini 			    struct marker *m)
866d18719a4STom Rini {
867d18719a4STom Rini 	char *entry;
868d18719a4STom Rini 
869d18719a4STom Rini 	/* m->ref can only be a REF_PHANDLE, but check anyway */
870d18719a4STom Rini 	assert(m->type == REF_PHANDLE);
871d18719a4STom Rini 
872d18719a4STom Rini 	/* there shouldn't be any ':' in the arguments */
873d18719a4STom Rini 	if (strchr(node->fullpath, ':') || strchr(prop->name, ':'))
874d18719a4STom Rini 		die("arguments should not contain ':'\n");
875d18719a4STom Rini 
876d18719a4STom Rini 	xasprintf(&entry, "%s:%s:%u",
877d18719a4STom Rini 			node->fullpath, prop->name, m->offset);
878d18719a4STom Rini 	append_to_property(fn, m->ref, entry, strlen(entry) + 1);
879d18719a4STom Rini 
880d18719a4STom Rini 	free(entry);
881d18719a4STom Rini }
882d18719a4STom Rini 
generate_fixups_tree_internal(struct dt_info * dti,struct node * fn,struct node * node)883d18719a4STom Rini static void generate_fixups_tree_internal(struct dt_info *dti,
884d18719a4STom Rini 					  struct node *fn,
885d18719a4STom Rini 					  struct node *node)
886d18719a4STom Rini {
887d18719a4STom Rini 	struct node *dt = dti->dt;
888d18719a4STom Rini 	struct node *c;
889d18719a4STom Rini 	struct property *prop;
890d18719a4STom Rini 	struct marker *m;
891d18719a4STom Rini 	struct node *refnode;
892d18719a4STom Rini 
893d18719a4STom Rini 	for_each_property(node, prop) {
894d18719a4STom Rini 		m = prop->val.markers;
895d18719a4STom Rini 		for_each_marker_of_type(m, REF_PHANDLE) {
896d18719a4STom Rini 			refnode = get_node_by_ref(dt, m->ref);
897d18719a4STom Rini 			if (!refnode)
898d18719a4STom Rini 				add_fixup_entry(dti, fn, node, prop, m);
899d18719a4STom Rini 		}
900d18719a4STom Rini 	}
901d18719a4STom Rini 
902d18719a4STom Rini 	for_each_child(node, c)
903d18719a4STom Rini 		generate_fixups_tree_internal(dti, fn, c);
904d18719a4STom Rini }
905d18719a4STom Rini 
any_local_fixup_tree(struct dt_info * dti,struct node * node)906d18719a4STom Rini static bool any_local_fixup_tree(struct dt_info *dti, struct node *node)
907d18719a4STom Rini {
908d18719a4STom Rini 	struct node *c;
909d18719a4STom Rini 	struct property *prop;
910d18719a4STom Rini 	struct marker *m;
911d18719a4STom Rini 
912d18719a4STom Rini 	for_each_property(node, prop) {
913d18719a4STom Rini 		m = prop->val.markers;
914d18719a4STom Rini 		for_each_marker_of_type(m, REF_PHANDLE) {
915d18719a4STom Rini 			if (get_node_by_ref(dti->dt, m->ref))
916d18719a4STom Rini 				return true;
917d18719a4STom Rini 		}
918d18719a4STom Rini 	}
919d18719a4STom Rini 
920d18719a4STom Rini 	for_each_child(node, c) {
921d18719a4STom Rini 		if (any_local_fixup_tree(dti, c))
922d18719a4STom Rini 			return true;
923d18719a4STom Rini 	}
924d18719a4STom Rini 
925d18719a4STom Rini 	return false;
926d18719a4STom Rini }
927d18719a4STom Rini 
add_local_fixup_entry(struct dt_info * dti,struct node * lfn,struct node * node,struct property * prop,struct marker * m,struct node * refnode)928d18719a4STom Rini static void add_local_fixup_entry(struct dt_info *dti,
929d18719a4STom Rini 		struct node *lfn, struct node *node,
930d18719a4STom Rini 		struct property *prop, struct marker *m,
931d18719a4STom Rini 		struct node *refnode)
932d18719a4STom Rini {
933d18719a4STom Rini 	struct node *wn, *nwn;	/* local fixup node, walk node, new */
934e23ffda2STom Rini 	fdt32_t value_32;
935d18719a4STom Rini 	char **compp;
936d18719a4STom Rini 	int i, depth;
937d18719a4STom Rini 
938d18719a4STom Rini 	/* walk back retreiving depth */
939d18719a4STom Rini 	depth = 0;
940d18719a4STom Rini 	for (wn = node; wn; wn = wn->parent)
941d18719a4STom Rini 		depth++;
942d18719a4STom Rini 
943d18719a4STom Rini 	/* allocate name array */
944d18719a4STom Rini 	compp = xmalloc(sizeof(*compp) * depth);
945d18719a4STom Rini 
946d18719a4STom Rini 	/* store names in the array */
947d18719a4STom Rini 	for (wn = node, i = depth - 1; wn; wn = wn->parent, i--)
948d18719a4STom Rini 		compp[i] = wn->name;
949d18719a4STom Rini 
950d18719a4STom Rini 	/* walk the path components creating nodes if they don't exist */
951d18719a4STom Rini 	for (wn = lfn, i = 1; i < depth; i++, wn = nwn) {
952d18719a4STom Rini 		/* if no node exists, create it */
953d18719a4STom Rini 		nwn = get_subnode(wn, compp[i]);
954d18719a4STom Rini 		if (!nwn)
955d18719a4STom Rini 			nwn = build_and_name_child_node(wn, compp[i]);
956d18719a4STom Rini 	}
957d18719a4STom Rini 
958d18719a4STom Rini 	free(compp);
959d18719a4STom Rini 
960d18719a4STom Rini 	value_32 = cpu_to_fdt32(m->offset);
961d18719a4STom Rini 	append_to_property(wn, prop->name, &value_32, sizeof(value_32));
962d18719a4STom Rini }
963d18719a4STom Rini 
generate_local_fixups_tree_internal(struct dt_info * dti,struct node * lfn,struct node * node)964d18719a4STom Rini static void generate_local_fixups_tree_internal(struct dt_info *dti,
965d18719a4STom Rini 						struct node *lfn,
966d18719a4STom Rini 						struct node *node)
967d18719a4STom Rini {
968d18719a4STom Rini 	struct node *dt = dti->dt;
969d18719a4STom Rini 	struct node *c;
970d18719a4STom Rini 	struct property *prop;
971d18719a4STom Rini 	struct marker *m;
972d18719a4STom Rini 	struct node *refnode;
973d18719a4STom Rini 
974d18719a4STom Rini 	for_each_property(node, prop) {
975d18719a4STom Rini 		m = prop->val.markers;
976d18719a4STom Rini 		for_each_marker_of_type(m, REF_PHANDLE) {
977d18719a4STom Rini 			refnode = get_node_by_ref(dt, m->ref);
978d18719a4STom Rini 			if (refnode)
979d18719a4STom Rini 				add_local_fixup_entry(dti, lfn, node, prop, m, refnode);
980d18719a4STom Rini 		}
981d18719a4STom Rini 	}
982d18719a4STom Rini 
983d18719a4STom Rini 	for_each_child(node, c)
984d18719a4STom Rini 		generate_local_fixups_tree_internal(dti, lfn, c);
985d18719a4STom Rini }
986d18719a4STom Rini 
generate_label_tree(struct dt_info * dti,char * name,bool allocph)987d18719a4STom Rini void generate_label_tree(struct dt_info *dti, char *name, bool allocph)
988d18719a4STom Rini {
989d18719a4STom Rini 	if (!any_label_tree(dti, dti->dt))
990d18719a4STom Rini 		return;
991d18719a4STom Rini 	generate_label_tree_internal(dti, build_root_node(dti->dt, name),
992d18719a4STom Rini 				     dti->dt, allocph);
993d18719a4STom Rini }
994d18719a4STom Rini 
generate_fixups_tree(struct dt_info * dti,char * name)995d18719a4STom Rini void generate_fixups_tree(struct dt_info *dti, char *name)
996d18719a4STom Rini {
997d18719a4STom Rini 	if (!any_fixup_tree(dti, dti->dt))
998d18719a4STom Rini 		return;
999d18719a4STom Rini 	generate_fixups_tree_internal(dti, build_root_node(dti->dt, name),
1000d18719a4STom Rini 				      dti->dt);
1001d18719a4STom Rini }
1002d18719a4STom Rini 
generate_local_fixups_tree(struct dt_info * dti,char * name)1003d18719a4STom Rini void generate_local_fixups_tree(struct dt_info *dti, char *name)
1004d18719a4STom Rini {
1005d18719a4STom Rini 	if (!any_local_fixup_tree(dti, dti->dt))
1006d18719a4STom Rini 		return;
1007d18719a4STom Rini 	generate_local_fixups_tree_internal(dti, build_root_node(dti->dt, name),
1008d18719a4STom Rini 					    dti->dt);
1009d18719a4STom Rini }
1010