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