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