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