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