blob: 21c274125c2c8ed3ef3dea7b84043ec899fefd44 [file] [log] [blame]
David Gibsona4da2e32007-12-18 15:06:42 +11001/*
2 * (C) Copyright David Gibson <dwg@au1.ibm.com>, IBM Corporation. 2005.
3 *
4 *
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License as
7 * published by the Free Software Foundation; either version 2 of the
8 * License, or (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
18 * USA
19 */
20
21#include "dtc.h"
Rob Herringc2e70752018-11-28 18:37:35 -060022#include "srcpos.h"
David Gibsona4da2e32007-12-18 15:06:42 +110023
24/*
25 * Tree building functions
26 */
27
John Bonesio658f29a2010-11-17 15:28:20 -080028void add_label(struct label **labels, char *label)
29{
30 struct label *new;
31
32 /* Make sure the label isn't already there */
Stephen Warrencd296722012-09-28 21:25:59 +000033 for_each_label_withdel(*labels, new)
34 if (streq(new->label, label)) {
35 new->deleted = 0;
John Bonesio658f29a2010-11-17 15:28:20 -080036 return;
Stephen Warrencd296722012-09-28 21:25:59 +000037 }
John Bonesio658f29a2010-11-17 15:28:20 -080038
39 new = xmalloc(sizeof(*new));
Stephen Warrencd296722012-09-28 21:25:59 +000040 memset(new, 0, sizeof(*new));
John Bonesio658f29a2010-11-17 15:28:20 -080041 new->label = label;
42 new->next = *labels;
43 *labels = new;
44}
45
Stephen Warrencd296722012-09-28 21:25:59 +000046void delete_labels(struct label **labels)
47{
48 struct label *label;
49
50 for_each_label(*labels, label)
51 label->deleted = 1;
52}
53
Rob Herringc2e70752018-11-28 18:37:35 -060054struct property *build_property(char *name, struct data val,
55 struct srcpos *srcpos)
David Gibsona4da2e32007-12-18 15:06:42 +110056{
57 struct property *new = xmalloc(sizeof(*new));
58
John Bonesio658f29a2010-11-17 15:28:20 -080059 memset(new, 0, sizeof(*new));
60
David Gibsona4da2e32007-12-18 15:06:42 +110061 new->name = name;
62 new->val = val;
Rob Herringc2e70752018-11-28 18:37:35 -060063 new->srcpos = srcpos_copy(srcpos);
David Gibsona4da2e32007-12-18 15:06:42 +110064
David Gibsona4da2e32007-12-18 15:06:42 +110065 return new;
66}
67
Stephen Warrencd296722012-09-28 21:25:59 +000068struct property *build_property_delete(char *name)
69{
70 struct property *new = xmalloc(sizeof(*new));
71
72 memset(new, 0, sizeof(*new));
73
74 new->name = name;
75 new->deleted = 1;
76
77 return new;
78}
79
David Gibsona4da2e32007-12-18 15:06:42 +110080struct property *chain_property(struct property *first, struct property *list)
81{
82 assert(first->next == NULL);
83
84 first->next = list;
85 return first;
86}
87
88struct property *reverse_properties(struct property *first)
89{
90 struct property *p = first;
91 struct property *head = NULL;
92 struct property *next;
93
94 while (p) {
95 next = p->next;
96 p->next = head;
97 head = p;
98 p = next;
99 }
100 return head;
101}
102
Rob Herringc2e70752018-11-28 18:37:35 -0600103struct node *build_node(struct property *proplist, struct node *children,
104 struct srcpos *srcpos)
David Gibsona4da2e32007-12-18 15:06:42 +1100105{
106 struct node *new = xmalloc(sizeof(*new));
107 struct node *child;
108
109 memset(new, 0, sizeof(*new));
110
111 new->proplist = reverse_properties(proplist);
112 new->children = children;
Rob Herringc2e70752018-11-28 18:37:35 -0600113 new->srcpos = srcpos_copy(srcpos);
David Gibsona4da2e32007-12-18 15:06:42 +1100114
115 for_each_child(new, child) {
116 child->parent = new;
117 }
118
119 return new;
120}
121
Rob Herringc2e70752018-11-28 18:37:35 -0600122struct node *build_node_delete(struct srcpos *srcpos)
Stephen Warrencd296722012-09-28 21:25:59 +0000123{
124 struct node *new = xmalloc(sizeof(*new));
125
126 memset(new, 0, sizeof(*new));
127
128 new->deleted = 1;
Rob Herringc2e70752018-11-28 18:37:35 -0600129 new->srcpos = srcpos_copy(srcpos);
Stephen Warrencd296722012-09-28 21:25:59 +0000130
131 return new;
132}
133
John Bonesio658f29a2010-11-17 15:28:20 -0800134struct node *name_node(struct node *node, char *name)
David Gibsona4da2e32007-12-18 15:06:42 +1100135{
136 assert(node->name == NULL);
137
138 node->name = name;
139
David Gibsona4da2e32007-12-18 15:06:42 +1100140 return node;
141}
142
Rob Herring50aafd62018-05-08 13:07:49 -0500143struct node *omit_node_if_unused(struct node *node)
144{
145 node->omit_if_unused = 1;
146
147 return node;
148}
149
150struct node *reference_node(struct node *node)
151{
152 node->is_referenced = 1;
153
154 return node;
155}
156
John Bonesio658f29a2010-11-17 15:28:20 -0800157struct node *merge_nodes(struct node *old_node, struct node *new_node)
158{
159 struct property *new_prop, *old_prop;
160 struct node *new_child, *old_child;
161 struct label *l;
162
Stephen Warrencd296722012-09-28 21:25:59 +0000163 old_node->deleted = 0;
164
John Bonesio658f29a2010-11-17 15:28:20 -0800165 /* Add new node labels to old node */
Stephen Warrencd296722012-09-28 21:25:59 +0000166 for_each_label_withdel(new_node->labels, l)
John Bonesio658f29a2010-11-17 15:28:20 -0800167 add_label(&old_node->labels, l->label);
168
169 /* Move properties from the new node to the old node. If there
170 * is a collision, replace the old value with the new */
171 while (new_node->proplist) {
172 /* Pop the property off the list */
173 new_prop = new_node->proplist;
174 new_node->proplist = new_prop->next;
175 new_prop->next = NULL;
176
Stephen Warrencd296722012-09-28 21:25:59 +0000177 if (new_prop->deleted) {
178 delete_property_by_name(old_node, new_prop->name);
179 free(new_prop);
180 continue;
181 }
182
John Bonesio658f29a2010-11-17 15:28:20 -0800183 /* Look for a collision, set new value if there is */
Stephen Warrencd296722012-09-28 21:25:59 +0000184 for_each_property_withdel(old_node, old_prop) {
John Bonesio658f29a2010-11-17 15:28:20 -0800185 if (streq(old_prop->name, new_prop->name)) {
186 /* Add new labels to old property */
Stephen Warrencd296722012-09-28 21:25:59 +0000187 for_each_label_withdel(new_prop->labels, l)
John Bonesio658f29a2010-11-17 15:28:20 -0800188 add_label(&old_prop->labels, l->label);
189
190 old_prop->val = new_prop->val;
Stephen Warrencd296722012-09-28 21:25:59 +0000191 old_prop->deleted = 0;
Rob Herringc2e70752018-11-28 18:37:35 -0600192 free(old_prop->srcpos);
193 old_prop->srcpos = new_prop->srcpos;
John Bonesio658f29a2010-11-17 15:28:20 -0800194 free(new_prop);
195 new_prop = NULL;
196 break;
197 }
198 }
199
200 /* if no collision occurred, add property to the old node. */
201 if (new_prop)
202 add_property(old_node, new_prop);
203 }
204
205 /* Move the override child nodes into the primary node. If
206 * there is a collision, then merge the nodes. */
207 while (new_node->children) {
208 /* Pop the child node off the list */
209 new_child = new_node->children;
210 new_node->children = new_child->next_sibling;
211 new_child->parent = NULL;
212 new_child->next_sibling = NULL;
213
Stephen Warrencd296722012-09-28 21:25:59 +0000214 if (new_child->deleted) {
215 delete_node_by_name(old_node, new_child->name);
216 free(new_child);
217 continue;
218 }
219
John Bonesio658f29a2010-11-17 15:28:20 -0800220 /* Search for a collision. Merge if there is */
Stephen Warrencd296722012-09-28 21:25:59 +0000221 for_each_child_withdel(old_node, old_child) {
John Bonesio658f29a2010-11-17 15:28:20 -0800222 if (streq(old_child->name, new_child->name)) {
223 merge_nodes(old_child, new_child);
224 new_child = NULL;
225 break;
226 }
227 }
228
Rob Herring6f05afc2017-01-04 10:45:20 -0600229 /* if no collision occurred, add child to the old node. */
John Bonesio658f29a2010-11-17 15:28:20 -0800230 if (new_child)
231 add_child(old_node, new_child);
232 }
233
Rob Herringc2e70752018-11-28 18:37:35 -0600234 old_node->srcpos = srcpos_extend(old_node->srcpos, new_node->srcpos);
235
John Bonesio658f29a2010-11-17 15:28:20 -0800236 /* The new node contents are now merged into the old node. Free
237 * the new node. */
238 free(new_node);
239
240 return old_node;
241}
242
Rob Herring9130ba82018-02-27 17:40:38 -0600243struct node * add_orphan_node(struct node *dt, struct node *new_node, char *ref)
Rob Herring4201d052017-10-03 11:37:04 -0500244{
245 static unsigned int next_orphan_fragment = 0;
246 struct node *node;
247 struct property *p;
248 struct data d = empty_data;
249 char *name;
250
Rob Herring50aafd62018-05-08 13:07:49 -0500251 if (ref[0] == '/') {
Rob Herring9bb9c6a2019-06-12 07:05:52 -0600252 d = data_add_marker(d, TYPE_STRING, ref);
Rob Herring50aafd62018-05-08 13:07:49 -0500253 d = data_append_data(d, ref, strlen(ref) + 1);
Rob Herring4201d052017-10-03 11:37:04 -0500254
Rob Herringc2e70752018-11-28 18:37:35 -0600255 p = build_property("target-path", d, NULL);
Rob Herring50aafd62018-05-08 13:07:49 -0500256 } else {
257 d = data_add_marker(d, REF_PHANDLE, ref);
258 d = data_append_integer(d, 0xffffffff, 32);
259
Rob Herringc2e70752018-11-28 18:37:35 -0600260 p = build_property("target", d, NULL);
Rob Herring50aafd62018-05-08 13:07:49 -0500261 }
Rob Herring4201d052017-10-03 11:37:04 -0500262
263 xasprintf(&name, "fragment@%u",
264 next_orphan_fragment++);
265 name_node(new_node, "__overlay__");
Rob Herringc2e70752018-11-28 18:37:35 -0600266 node = build_node(p, new_node, NULL);
Rob Herring4201d052017-10-03 11:37:04 -0500267 name_node(node, name);
268
269 add_child(dt, node);
Rob Herring9130ba82018-02-27 17:40:38 -0600270 return dt;
Rob Herring4201d052017-10-03 11:37:04 -0500271}
272
David Gibsona4da2e32007-12-18 15:06:42 +1100273struct node *chain_node(struct node *first, struct node *list)
274{
275 assert(first->next_sibling == NULL);
276
277 first->next_sibling = list;
278 return first;
279}
280
281void add_property(struct node *node, struct property *prop)
282{
283 struct property **p;
284
285 prop->next = NULL;
286
287 p = &node->proplist;
288 while (*p)
289 p = &((*p)->next);
290
291 *p = prop;
292}
293
Stephen Warrencd296722012-09-28 21:25:59 +0000294void delete_property_by_name(struct node *node, char *name)
295{
296 struct property *prop = node->proplist;
297
298 while (prop) {
Rob Herring89d12312017-03-21 09:01:08 -0500299 if (streq(prop->name, name)) {
Stephen Warrencd296722012-09-28 21:25:59 +0000300 delete_property(prop);
301 return;
302 }
303 prop = prop->next;
304 }
305}
306
307void delete_property(struct property *prop)
308{
309 prop->deleted = 1;
310 delete_labels(&prop->labels);
311}
312
David Gibsona4da2e32007-12-18 15:06:42 +1100313void add_child(struct node *parent, struct node *child)
314{
315 struct node **p;
316
317 child->next_sibling = NULL;
David Gibsoned95d742008-08-07 12:24:17 +1000318 child->parent = parent;
David Gibsona4da2e32007-12-18 15:06:42 +1100319
320 p = &parent->children;
321 while (*p)
322 p = &((*p)->next_sibling);
323
324 *p = child;
325}
326
Stephen Warrencd296722012-09-28 21:25:59 +0000327void delete_node_by_name(struct node *parent, char *name)
328{
329 struct node *node = parent->children;
330
331 while (node) {
Rob Herring89d12312017-03-21 09:01:08 -0500332 if (streq(node->name, name)) {
Stephen Warrencd296722012-09-28 21:25:59 +0000333 delete_node(node);
334 return;
335 }
336 node = node->next_sibling;
337 }
338}
339
340void delete_node(struct node *node)
341{
342 struct property *prop;
343 struct node *child;
344
345 node->deleted = 1;
346 for_each_child(node, child)
347 delete_node(child);
348 for_each_property(node, prop)
349 delete_property(prop);
350 delete_labels(&node->labels);
351}
352
Rob Herring6f05afc2017-01-04 10:45:20 -0600353void append_to_property(struct node *node,
Rob Herring9bb9c6a2019-06-12 07:05:52 -0600354 char *name, const void *data, int len,
355 enum markertype type)
Rob Herring6f05afc2017-01-04 10:45:20 -0600356{
357 struct data d;
358 struct property *p;
359
360 p = get_property(node, name);
361 if (p) {
Rob Herring9bb9c6a2019-06-12 07:05:52 -0600362 d = data_add_marker(p->val, type, name);
363 d = data_append_data(d, data, len);
Rob Herring6f05afc2017-01-04 10:45:20 -0600364 p->val = d;
365 } else {
Rob Herring9bb9c6a2019-06-12 07:05:52 -0600366 d = data_add_marker(empty_data, type, name);
367 d = data_append_data(d, data, len);
Rob Herringc2e70752018-11-28 18:37:35 -0600368 p = build_property(name, d, NULL);
Rob Herring6f05afc2017-01-04 10:45:20 -0600369 add_property(node, p);
370 }
371}
372
John Bonesio658f29a2010-11-17 15:28:20 -0800373struct reserve_info *build_reserve_entry(uint64_t address, uint64_t size)
David Gibsona4da2e32007-12-18 15:06:42 +1100374{
375 struct reserve_info *new = xmalloc(sizeof(*new));
376
John Bonesio658f29a2010-11-17 15:28:20 -0800377 memset(new, 0, sizeof(*new));
378
Rob Herring89d12312017-03-21 09:01:08 -0500379 new->address = address;
380 new->size = size;
David Gibsona4da2e32007-12-18 15:06:42 +1100381
David Gibsona4da2e32007-12-18 15:06:42 +1100382 return new;
383}
384
385struct reserve_info *chain_reserve_entry(struct reserve_info *first,
386 struct reserve_info *list)
387{
388 assert(first->next == NULL);
389
390 first->next = list;
391 return first;
392}
393
394struct reserve_info *add_reserve_entry(struct reserve_info *list,
395 struct reserve_info *new)
396{
397 struct reserve_info *last;
398
399 new->next = NULL;
400
401 if (! list)
402 return new;
403
404 for (last = list; last->next; last = last->next)
405 ;
406
407 last->next = new;
408
409 return list;
410}
411
Rob Herring6f05afc2017-01-04 10:45:20 -0600412struct dt_info *build_dt_info(unsigned int dtsflags,
413 struct reserve_info *reservelist,
414 struct node *tree, uint32_t boot_cpuid_phys)
David Gibsona4da2e32007-12-18 15:06:42 +1100415{
Rob Herring6f05afc2017-01-04 10:45:20 -0600416 struct dt_info *dti;
David Gibsona4da2e32007-12-18 15:06:42 +1100417
Rob Herring6f05afc2017-01-04 10:45:20 -0600418 dti = xmalloc(sizeof(*dti));
419 dti->dtsflags = dtsflags;
420 dti->reservelist = reservelist;
421 dti->dt = tree;
422 dti->boot_cpuid_phys = boot_cpuid_phys;
David Gibsona4da2e32007-12-18 15:06:42 +1100423
Rob Herring6f05afc2017-01-04 10:45:20 -0600424 return dti;
David Gibsona4da2e32007-12-18 15:06:42 +1100425}
426
427/*
428 * Tree accessor functions
429 */
430
431const char *get_unitname(struct node *node)
432{
433 if (node->name[node->basenamelen] == '\0')
434 return "";
435 else
436 return node->name + node->basenamelen + 1;
437}
438
439struct property *get_property(struct node *node, const char *propname)
440{
441 struct property *prop;
442
443 for_each_property(node, prop)
444 if (streq(prop->name, propname))
445 return prop;
446
447 return NULL;
448}
449
450cell_t propval_cell(struct property *prop)
451{
452 assert(prop->val.len == sizeof(cell_t));
Rob Herring89d12312017-03-21 09:01:08 -0500453 return fdt32_to_cpu(*((fdt32_t *)prop->val.val));
David Gibsona4da2e32007-12-18 15:06:42 +1100454}
455
Rob Herring4201d052017-10-03 11:37:04 -0500456cell_t propval_cell_n(struct property *prop, int n)
457{
458 assert(prop->val.len / sizeof(cell_t) >= n);
459 return fdt32_to_cpu(*((fdt32_t *)prop->val.val + n));
460}
461
John Bonesio658f29a2010-11-17 15:28:20 -0800462struct property *get_property_by_label(struct node *tree, const char *label,
463 struct node **node)
464{
465 struct property *prop;
466 struct node *c;
467
468 *node = tree;
469
470 for_each_property(tree, prop) {
471 struct label *l;
472
473 for_each_label(prop->labels, l)
474 if (streq(l->label, label))
475 return prop;
476 }
477
478 for_each_child(tree, c) {
479 prop = get_property_by_label(c, label, node);
480 if (prop)
481 return prop;
482 }
483
484 *node = NULL;
485 return NULL;
486}
487
488struct marker *get_marker_label(struct node *tree, const char *label,
489 struct node **node, struct property **prop)
490{
491 struct marker *m;
492 struct property *p;
493 struct node *c;
494
495 *node = tree;
496
497 for_each_property(tree, p) {
498 *prop = p;
499 m = p->val.markers;
500 for_each_marker_of_type(m, LABEL)
501 if (streq(m->ref, label))
502 return m;
503 }
504
505 for_each_child(tree, c) {
506 m = get_marker_label(c, label, node, prop);
507 if (m)
508 return m;
509 }
510
511 *prop = NULL;
512 *node = NULL;
513 return NULL;
514}
515
David Gibsona4da2e32007-12-18 15:06:42 +1100516struct node *get_subnode(struct node *node, const char *nodename)
517{
518 struct node *child;
519
520 for_each_child(node, child)
521 if (streq(child->name, nodename))
522 return child;
523
524 return NULL;
525}
526
527struct node *get_node_by_path(struct node *tree, const char *path)
528{
529 const char *p;
530 struct node *child;
531
Stephen Warrencd296722012-09-28 21:25:59 +0000532 if (!path || ! (*path)) {
533 if (tree->deleted)
534 return NULL;
David Gibsona4da2e32007-12-18 15:06:42 +1100535 return tree;
Stephen Warrencd296722012-09-28 21:25:59 +0000536 }
David Gibsona4da2e32007-12-18 15:06:42 +1100537
538 while (path[0] == '/')
539 path++;
540
541 p = strchr(path, '/');
542
543 for_each_child(tree, child) {
Rob Herring4201d052017-10-03 11:37:04 -0500544 if (p && (strlen(child->name) == p-path) &&
Rob Herring9130ba82018-02-27 17:40:38 -0600545 strprefixeq(path, p - path, child->name))
David Gibsona4da2e32007-12-18 15:06:42 +1100546 return get_node_by_path(child, p+1);
547 else if (!p && streq(path, child->name))
548 return child;
549 }
550
551 return NULL;
552}
553
554struct node *get_node_by_label(struct node *tree, const char *label)
555{
556 struct node *child, *node;
John Bonesio658f29a2010-11-17 15:28:20 -0800557 struct label *l;
David Gibsona4da2e32007-12-18 15:06:42 +1100558
559 assert(label && (strlen(label) > 0));
560
John Bonesio658f29a2010-11-17 15:28:20 -0800561 for_each_label(tree->labels, l)
562 if (streq(l->label, label))
563 return tree;
David Gibsona4da2e32007-12-18 15:06:42 +1100564
565 for_each_child(tree, child) {
566 node = get_node_by_label(child, label);
567 if (node)
568 return node;
569 }
570
571 return NULL;
572}
573
574struct node *get_node_by_phandle(struct node *tree, cell_t phandle)
575{
576 struct node *child, *node;
577
Rob Herring9130ba82018-02-27 17:40:38 -0600578 if ((phandle == 0) || (phandle == -1)) {
579 assert(generate_fixups);
580 return NULL;
581 }
David Gibsona4da2e32007-12-18 15:06:42 +1100582
Stephen Warrencd296722012-09-28 21:25:59 +0000583 if (tree->phandle == phandle) {
584 if (tree->deleted)
585 return NULL;
David Gibsona4da2e32007-12-18 15:06:42 +1100586 return tree;
Stephen Warrencd296722012-09-28 21:25:59 +0000587 }
David Gibsona4da2e32007-12-18 15:06:42 +1100588
589 for_each_child(tree, child) {
590 node = get_node_by_phandle(child, phandle);
591 if (node)
592 return node;
593 }
594
595 return NULL;
596}
597
598struct node *get_node_by_ref(struct node *tree, const char *ref)
599{
Rob Herring47605972015-04-29 16:00:05 -0500600 if (streq(ref, "/"))
601 return tree;
602 else if (ref[0] == '/')
David Gibsona4da2e32007-12-18 15:06:42 +1100603 return get_node_by_path(tree, ref);
604 else
605 return get_node_by_label(tree, ref);
606}
607
608cell_t get_node_phandle(struct node *root, struct node *node)
609{
610 static cell_t phandle = 1; /* FIXME: ick, static local */
Rob Herringf8589272018-09-13 08:59:25 -0500611 struct data d = empty_data;
David Gibsona4da2e32007-12-18 15:06:42 +1100612
613 if ((node->phandle != 0) && (node->phandle != -1))
614 return node->phandle;
615
David Gibsona4da2e32007-12-18 15:06:42 +1100616 while (get_node_by_phandle(root, phandle))
617 phandle++;
618
619 node->phandle = phandle;
John Bonesio658f29a2010-11-17 15:28:20 -0800620
Rob Herringf8589272018-09-13 08:59:25 -0500621 d = data_add_marker(d, TYPE_UINT32, NULL);
622 d = data_append_cell(d, phandle);
623
John Bonesio658f29a2010-11-17 15:28:20 -0800624 if (!get_property(node, "linux,phandle")
625 && (phandle_format & PHANDLE_LEGACY))
Rob Herringc2e70752018-11-28 18:37:35 -0600626 add_property(node, build_property("linux,phandle", d, NULL));
John Bonesio658f29a2010-11-17 15:28:20 -0800627
628 if (!get_property(node, "phandle")
629 && (phandle_format & PHANDLE_EPAPR))
Rob Herringc2e70752018-11-28 18:37:35 -0600630 add_property(node, build_property("phandle", d, NULL));
John Bonesio658f29a2010-11-17 15:28:20 -0800631
632 /* If the node *does* have a phandle property, we must
633 * be dealing with a self-referencing phandle, which will be
634 * fixed up momentarily in the caller */
David Gibsona4da2e32007-12-18 15:06:42 +1100635
636 return node->phandle;
637}
John Bonesio658f29a2010-11-17 15:28:20 -0800638
639uint32_t guess_boot_cpuid(struct node *tree)
640{
641 struct node *cpus, *bootcpu;
642 struct property *reg;
643
644 cpus = get_node_by_path(tree, "/cpus");
645 if (!cpus)
646 return 0;
647
648
649 bootcpu = cpus->children;
650 if (!bootcpu)
651 return 0;
652
653 reg = get_property(bootcpu, "reg");
654 if (!reg || (reg->val.len != sizeof(uint32_t)))
655 return 0;
656
657 /* FIXME: Sanity check node? */
658
659 return propval_cell(reg);
660}
661
662static int cmp_reserve_info(const void *ax, const void *bx)
663{
664 const struct reserve_info *a, *b;
665
666 a = *((const struct reserve_info * const *)ax);
667 b = *((const struct reserve_info * const *)bx);
668
Rob Herring89d12312017-03-21 09:01:08 -0500669 if (a->address < b->address)
John Bonesio658f29a2010-11-17 15:28:20 -0800670 return -1;
Rob Herring89d12312017-03-21 09:01:08 -0500671 else if (a->address > b->address)
John Bonesio658f29a2010-11-17 15:28:20 -0800672 return 1;
Rob Herring89d12312017-03-21 09:01:08 -0500673 else if (a->size < b->size)
John Bonesio658f29a2010-11-17 15:28:20 -0800674 return -1;
Rob Herring89d12312017-03-21 09:01:08 -0500675 else if (a->size > b->size)
John Bonesio658f29a2010-11-17 15:28:20 -0800676 return 1;
677 else
678 return 0;
679}
680
Rob Herring6f05afc2017-01-04 10:45:20 -0600681static void sort_reserve_entries(struct dt_info *dti)
John Bonesio658f29a2010-11-17 15:28:20 -0800682{
683 struct reserve_info *ri, **tbl;
684 int n = 0, i = 0;
685
Rob Herring6f05afc2017-01-04 10:45:20 -0600686 for (ri = dti->reservelist;
John Bonesio658f29a2010-11-17 15:28:20 -0800687 ri;
688 ri = ri->next)
689 n++;
690
691 if (n == 0)
692 return;
693
694 tbl = xmalloc(n * sizeof(*tbl));
695
Rob Herring6f05afc2017-01-04 10:45:20 -0600696 for (ri = dti->reservelist;
John Bonesio658f29a2010-11-17 15:28:20 -0800697 ri;
698 ri = ri->next)
699 tbl[i++] = ri;
700
701 qsort(tbl, n, sizeof(*tbl), cmp_reserve_info);
702
Rob Herring6f05afc2017-01-04 10:45:20 -0600703 dti->reservelist = tbl[0];
John Bonesio658f29a2010-11-17 15:28:20 -0800704 for (i = 0; i < (n-1); i++)
705 tbl[i]->next = tbl[i+1];
706 tbl[n-1]->next = NULL;
707
708 free(tbl);
709}
710
711static int cmp_prop(const void *ax, const void *bx)
712{
713 const struct property *a, *b;
714
715 a = *((const struct property * const *)ax);
716 b = *((const struct property * const *)bx);
717
718 return strcmp(a->name, b->name);
719}
720
721static void sort_properties(struct node *node)
722{
723 int n = 0, i = 0;
724 struct property *prop, **tbl;
725
Stephen Warrencd296722012-09-28 21:25:59 +0000726 for_each_property_withdel(node, prop)
John Bonesio658f29a2010-11-17 15:28:20 -0800727 n++;
728
729 if (n == 0)
730 return;
731
732 tbl = xmalloc(n * sizeof(*tbl));
733
Stephen Warrencd296722012-09-28 21:25:59 +0000734 for_each_property_withdel(node, prop)
John Bonesio658f29a2010-11-17 15:28:20 -0800735 tbl[i++] = prop;
736
737 qsort(tbl, n, sizeof(*tbl), cmp_prop);
738
739 node->proplist = tbl[0];
740 for (i = 0; i < (n-1); i++)
741 tbl[i]->next = tbl[i+1];
742 tbl[n-1]->next = NULL;
743
744 free(tbl);
745}
746
747static int cmp_subnode(const void *ax, const void *bx)
748{
749 const struct node *a, *b;
750
751 a = *((const struct node * const *)ax);
752 b = *((const struct node * const *)bx);
753
754 return strcmp(a->name, b->name);
755}
756
757static void sort_subnodes(struct node *node)
758{
759 int n = 0, i = 0;
760 struct node *subnode, **tbl;
761
Stephen Warrencd296722012-09-28 21:25:59 +0000762 for_each_child_withdel(node, subnode)
John Bonesio658f29a2010-11-17 15:28:20 -0800763 n++;
764
765 if (n == 0)
766 return;
767
768 tbl = xmalloc(n * sizeof(*tbl));
769
Stephen Warrencd296722012-09-28 21:25:59 +0000770 for_each_child_withdel(node, subnode)
John Bonesio658f29a2010-11-17 15:28:20 -0800771 tbl[i++] = subnode;
772
773 qsort(tbl, n, sizeof(*tbl), cmp_subnode);
774
775 node->children = tbl[0];
776 for (i = 0; i < (n-1); i++)
777 tbl[i]->next_sibling = tbl[i+1];
778 tbl[n-1]->next_sibling = NULL;
779
780 free(tbl);
781}
782
783static void sort_node(struct node *node)
784{
785 struct node *c;
786
787 sort_properties(node);
788 sort_subnodes(node);
Stephen Warrencd296722012-09-28 21:25:59 +0000789 for_each_child_withdel(node, c)
John Bonesio658f29a2010-11-17 15:28:20 -0800790 sort_node(c);
791}
792
Rob Herring6f05afc2017-01-04 10:45:20 -0600793void sort_tree(struct dt_info *dti)
John Bonesio658f29a2010-11-17 15:28:20 -0800794{
Rob Herring6f05afc2017-01-04 10:45:20 -0600795 sort_reserve_entries(dti);
796 sort_node(dti->dt);
797}
798
799/* utility helper to avoid code duplication */
800static struct node *build_and_name_child_node(struct node *parent, char *name)
801{
802 struct node *node;
803
Rob Herringc2e70752018-11-28 18:37:35 -0600804 node = build_node(NULL, NULL, NULL);
Rob Herring6f05afc2017-01-04 10:45:20 -0600805 name_node(node, xstrdup(name));
806 add_child(parent, node);
807
808 return node;
809}
810
811static struct node *build_root_node(struct node *dt, char *name)
812{
813 struct node *an;
814
815 an = get_subnode(dt, name);
816 if (!an)
817 an = build_and_name_child_node(dt, name);
818
819 if (!an)
820 die("Could not build root node /%s\n", name);
821
822 return an;
823}
824
825static bool any_label_tree(struct dt_info *dti, struct node *node)
826{
827 struct node *c;
828
829 if (node->labels)
830 return true;
831
832 for_each_child(node, c)
833 if (any_label_tree(dti, c))
834 return true;
835
836 return false;
837}
838
839static void generate_label_tree_internal(struct dt_info *dti,
840 struct node *an, struct node *node,
841 bool allocph)
842{
843 struct node *dt = dti->dt;
844 struct node *c;
845 struct property *p;
846 struct label *l;
847
848 /* if there are labels */
849 if (node->labels) {
850
851 /* now add the label in the node */
852 for_each_label(node->labels, l) {
853
854 /* check whether the label already exists */
855 p = get_property(an, l->label);
856 if (p) {
857 fprintf(stderr, "WARNING: label %s already"
858 " exists in /%s", l->label,
859 an->name);
860 continue;
861 }
862
863 /* insert it */
864 p = build_property(l->label,
Rob Herring9bb9c6a2019-06-12 07:05:52 -0600865 data_copy_escape_string(node->fullpath,
866 strlen(node->fullpath)),
Rob Herringc2e70752018-11-28 18:37:35 -0600867 NULL);
Rob Herring6f05afc2017-01-04 10:45:20 -0600868 add_property(an, p);
869 }
870
871 /* force allocation of a phandle for this node */
872 if (allocph)
873 (void)get_node_phandle(dt, node);
874 }
875
876 for_each_child(node, c)
877 generate_label_tree_internal(dti, an, c, allocph);
878}
879
880static bool any_fixup_tree(struct dt_info *dti, struct node *node)
881{
882 struct node *c;
883 struct property *prop;
884 struct marker *m;
885
886 for_each_property(node, prop) {
887 m = prop->val.markers;
888 for_each_marker_of_type(m, REF_PHANDLE) {
889 if (!get_node_by_ref(dti->dt, m->ref))
890 return true;
891 }
892 }
893
894 for_each_child(node, c) {
895 if (any_fixup_tree(dti, c))
896 return true;
897 }
898
899 return false;
900}
901
902static void add_fixup_entry(struct dt_info *dti, struct node *fn,
903 struct node *node, struct property *prop,
904 struct marker *m)
905{
906 char *entry;
907
908 /* m->ref can only be a REF_PHANDLE, but check anyway */
909 assert(m->type == REF_PHANDLE);
910
911 /* there shouldn't be any ':' in the arguments */
912 if (strchr(node->fullpath, ':') || strchr(prop->name, ':'))
913 die("arguments should not contain ':'\n");
914
915 xasprintf(&entry, "%s:%s:%u",
916 node->fullpath, prop->name, m->offset);
Rob Herring9bb9c6a2019-06-12 07:05:52 -0600917 append_to_property(fn, m->ref, entry, strlen(entry) + 1, TYPE_STRING);
Rob Herring89d12312017-03-21 09:01:08 -0500918
919 free(entry);
Rob Herring6f05afc2017-01-04 10:45:20 -0600920}
921
922static void generate_fixups_tree_internal(struct dt_info *dti,
923 struct node *fn,
924 struct node *node)
925{
926 struct node *dt = dti->dt;
927 struct node *c;
928 struct property *prop;
929 struct marker *m;
930 struct node *refnode;
931
932 for_each_property(node, prop) {
933 m = prop->val.markers;
934 for_each_marker_of_type(m, REF_PHANDLE) {
935 refnode = get_node_by_ref(dt, m->ref);
936 if (!refnode)
937 add_fixup_entry(dti, fn, node, prop, m);
938 }
939 }
940
941 for_each_child(node, c)
942 generate_fixups_tree_internal(dti, fn, c);
943}
944
945static bool any_local_fixup_tree(struct dt_info *dti, struct node *node)
946{
947 struct node *c;
948 struct property *prop;
949 struct marker *m;
950
951 for_each_property(node, prop) {
952 m = prop->val.markers;
953 for_each_marker_of_type(m, REF_PHANDLE) {
954 if (get_node_by_ref(dti->dt, m->ref))
955 return true;
956 }
957 }
958
959 for_each_child(node, c) {
960 if (any_local_fixup_tree(dti, c))
961 return true;
962 }
963
964 return false;
965}
966
967static void add_local_fixup_entry(struct dt_info *dti,
968 struct node *lfn, struct node *node,
969 struct property *prop, struct marker *m,
970 struct node *refnode)
971{
972 struct node *wn, *nwn; /* local fixup node, walk node, new */
Rob Herring89d12312017-03-21 09:01:08 -0500973 fdt32_t value_32;
Rob Herring6f05afc2017-01-04 10:45:20 -0600974 char **compp;
975 int i, depth;
976
Rob Herring9bb9c6a2019-06-12 07:05:52 -0600977 /* walk back retrieving depth */
Rob Herring6f05afc2017-01-04 10:45:20 -0600978 depth = 0;
979 for (wn = node; wn; wn = wn->parent)
980 depth++;
981
982 /* allocate name array */
983 compp = xmalloc(sizeof(*compp) * depth);
984
985 /* store names in the array */
986 for (wn = node, i = depth - 1; wn; wn = wn->parent, i--)
987 compp[i] = wn->name;
988
989 /* walk the path components creating nodes if they don't exist */
990 for (wn = lfn, i = 1; i < depth; i++, wn = nwn) {
991 /* if no node exists, create it */
992 nwn = get_subnode(wn, compp[i]);
993 if (!nwn)
994 nwn = build_and_name_child_node(wn, compp[i]);
995 }
996
997 free(compp);
998
999 value_32 = cpu_to_fdt32(m->offset);
Rob Herring9bb9c6a2019-06-12 07:05:52 -06001000 append_to_property(wn, prop->name, &value_32, sizeof(value_32), TYPE_UINT32);
Rob Herring6f05afc2017-01-04 10:45:20 -06001001}
1002
1003static void generate_local_fixups_tree_internal(struct dt_info *dti,
1004 struct node *lfn,
1005 struct node *node)
1006{
1007 struct node *dt = dti->dt;
1008 struct node *c;
1009 struct property *prop;
1010 struct marker *m;
1011 struct node *refnode;
1012
1013 for_each_property(node, prop) {
1014 m = prop->val.markers;
1015 for_each_marker_of_type(m, REF_PHANDLE) {
1016 refnode = get_node_by_ref(dt, m->ref);
1017 if (refnode)
1018 add_local_fixup_entry(dti, lfn, node, prop, m, refnode);
1019 }
1020 }
1021
1022 for_each_child(node, c)
1023 generate_local_fixups_tree_internal(dti, lfn, c);
1024}
1025
1026void generate_label_tree(struct dt_info *dti, char *name, bool allocph)
1027{
1028 if (!any_label_tree(dti, dti->dt))
1029 return;
1030 generate_label_tree_internal(dti, build_root_node(dti->dt, name),
1031 dti->dt, allocph);
1032}
1033
1034void generate_fixups_tree(struct dt_info *dti, char *name)
1035{
1036 if (!any_fixup_tree(dti, dti->dt))
1037 return;
1038 generate_fixups_tree_internal(dti, build_root_node(dti->dt, name),
1039 dti->dt);
1040}
1041
1042void generate_local_fixups_tree(struct dt_info *dti, char *name)
1043{
1044 if (!any_local_fixup_tree(dti, dti->dt))
1045 return;
1046 generate_local_fixups_tree_internal(dti, build_root_node(dti->dt, name),
1047 dti->dt);
John Bonesio658f29a2010-11-17 15:28:20 -08001048}