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