root/scripts/dtc/livetree.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. add_label
  2. delete_labels
  3. build_property
  4. build_property_delete
  5. chain_property
  6. reverse_properties
  7. build_node
  8. build_node_delete
  9. name_node
  10. omit_node_if_unused
  11. reference_node
  12. merge_nodes
  13. add_orphan_node
  14. chain_node
  15. add_property
  16. delete_property_by_name
  17. delete_property
  18. add_child
  19. delete_node_by_name
  20. delete_node
  21. append_to_property
  22. build_reserve_entry
  23. chain_reserve_entry
  24. add_reserve_entry
  25. build_dt_info
  26. get_unitname
  27. get_property
  28. propval_cell
  29. propval_cell_n
  30. get_property_by_label
  31. get_marker_label
  32. get_subnode
  33. get_node_by_path
  34. get_node_by_label
  35. get_node_by_phandle
  36. get_node_by_ref
  37. get_node_phandle
  38. guess_boot_cpuid
  39. cmp_reserve_info
  40. sort_reserve_entries
  41. cmp_prop
  42. sort_properties
  43. cmp_subnode
  44. sort_subnodes
  45. sort_node
  46. sort_tree
  47. build_and_name_child_node
  48. build_root_node
  49. any_label_tree
  50. generate_label_tree_internal
  51. any_fixup_tree
  52. add_fixup_entry
  53. generate_fixups_tree_internal
  54. any_local_fixup_tree
  55. add_local_fixup_entry
  56. generate_local_fixups_tree_internal
  57. generate_label_tree
  58. generate_fixups_tree
  59. generate_local_fixups_tree

   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 
  13 void 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 
  31 void delete_labels(struct label **labels)
  32 {
  33         struct label *label;
  34 
  35         for_each_label(*labels, label)
  36                 label->deleted = 1;
  37 }
  38 
  39 struct 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 
  53 struct 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 
  65 struct 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 
  73 struct 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 
  88 struct 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 
 107 struct 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 
 119 struct 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 
 128 struct node *omit_node_if_unused(struct node *node)
 129 {
 130         node->omit_if_unused = 1;
 131 
 132         return node;
 133 }
 134 
 135 struct node *reference_node(struct node *node)
 136 {
 137         node->is_referenced = 1;
 138 
 139         return node;
 140 }
 141 
 142 struct 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 
 228 struct 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 
 258 struct 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 
 266 void 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 
 279 void 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 
 292 void delete_property(struct property *prop)
 293 {
 294         prop->deleted = 1;
 295         delete_labels(&prop->labels);
 296 }
 297 
 298 void 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 
 312 void 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 
 325 void 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 
 338 void 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 
 358 struct 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 
 370 struct 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 
 379 struct 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 
 397 struct 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 
 416 const 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 
 424 struct 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 
 435 cell_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 
 441 cell_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 
 447 struct 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 
 473 struct 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 
 501 struct 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 
 512 struct 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 
 539 struct 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 
 559 struct 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 
 583 struct 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 
 593 cell_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 
 624 uint32_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 
 647 static 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 
 666 static 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 
 696 static 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 
 706 static 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 
 732 static 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 
 742 static 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 
 768 static 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 
 778 void 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 */
 785 static 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 
 796 static 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 
 810 static 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 
 824 static 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 
 865 static 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 
 887 static 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 
 907 static 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 
 930 static 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 
 952 static 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 
 988 static 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 
1011 void 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 
1019 void 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 
1027 void 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 }

/* [<][>][^][v][top][bottom][index][help] */