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