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