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