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