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 28 void 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 46 void delete_labels(struct label **labels) 47 { 48 struct label *label; 49 50 for_each_label(*labels, label) 51 label->deleted = 1; 52 } 53 54 struct 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 68 struct 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 80 struct 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 88 struct 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 103 struct 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 122 struct 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 134 struct 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 143 struct node *omit_node_if_unused(struct node *node) 144 { 145 node->omit_if_unused = 1; 146 147 return node; 148 } 149 150 struct node *reference_node(struct node *node) 151 { 152 node->is_referenced = 1; 153 154 return node; 155 } 156 157 struct 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 243 struct 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 272 struct 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 280 void 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 293 void 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 306 void delete_property(struct property *prop) 307 { 308 prop->deleted = 1; 309 delete_labels(&prop->labels); 310 } 311 312 void 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 326 void 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 339 void 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 352 void 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 369 struct 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 381 struct 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 390 struct 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 408 struct 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 427 const 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 435 struct 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 446 cell_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 452 cell_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 458 struct 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 484 struct 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 512 struct 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 523 struct 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 550 struct 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 570 struct 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 594 struct 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 604 cell_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 635 uint32_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 658 static 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 677 static 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 707 static 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 717 static 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 743 static 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 753 static 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 779 static 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 789 void 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 */ 796 static 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 807 static 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 821 static 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 835 static 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 876 static 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 898 static 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 918 static 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 941 static 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 963 static 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 999 static 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 1022 void 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 1030 void 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 1038 void 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