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