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