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 23 /* 24 * Tree building functions 25 */ 26 27 void add_label(struct label **labels, char *label) 28 { 29 struct label *new; 30 31 /* Make sure the label isn't already there */ 32 for_each_label_withdel(*labels, new) 33 if (streq(new->label, label)) { 34 new->deleted = 0; 35 return; 36 } 37 38 new = xmalloc(sizeof(*new)); 39 memset(new, 0, sizeof(*new)); 40 new->label = label; 41 new->next = *labels; 42 *labels = new; 43 } 44 45 void delete_labels(struct label **labels) 46 { 47 struct label *label; 48 49 for_each_label(*labels, label) 50 label->deleted = 1; 51 } 52 53 struct property *build_property(char *name, struct data val) 54 { 55 struct property *new = xmalloc(sizeof(*new)); 56 57 memset(new, 0, sizeof(*new)); 58 59 new->name = name; 60 new->val = val; 61 62 return new; 63 } 64 65 struct property *build_property_delete(char *name) 66 { 67 struct property *new = xmalloc(sizeof(*new)); 68 69 memset(new, 0, sizeof(*new)); 70 71 new->name = name; 72 new->deleted = 1; 73 74 return new; 75 } 76 77 struct property *chain_property(struct property *first, struct property *list) 78 { 79 assert(first->next == NULL); 80 81 first->next = list; 82 return first; 83 } 84 85 struct property *reverse_properties(struct property *first) 86 { 87 struct property *p = first; 88 struct property *head = NULL; 89 struct property *next; 90 91 while (p) { 92 next = p->next; 93 p->next = head; 94 head = p; 95 p = next; 96 } 97 return head; 98 } 99 100 struct node *build_node(struct property *proplist, struct node *children) 101 { 102 struct node *new = xmalloc(sizeof(*new)); 103 struct node *child; 104 105 memset(new, 0, sizeof(*new)); 106 107 new->proplist = reverse_properties(proplist); 108 new->children = children; 109 110 for_each_child(new, child) { 111 child->parent = new; 112 } 113 114 return new; 115 } 116 117 struct node *build_node_delete(void) 118 { 119 struct node *new = xmalloc(sizeof(*new)); 120 121 memset(new, 0, sizeof(*new)); 122 123 new->deleted = 1; 124 125 return new; 126 } 127 128 struct node *name_node(struct node *node, char *name) 129 { 130 assert(node->name == NULL); 131 132 node->name = name; 133 134 return node; 135 } 136 137 struct node *omit_node_if_unused(struct node *node) 138 { 139 node->omit_if_unused = 1; 140 141 return node; 142 } 143 144 struct node *reference_node(struct node *node) 145 { 146 node->is_referenced = 1; 147 148 return node; 149 } 150 151 struct node *merge_nodes(struct node *old_node, struct node *new_node) 152 { 153 struct property *new_prop, *old_prop; 154 struct node *new_child, *old_child; 155 struct label *l; 156 157 old_node->deleted = 0; 158 159 /* Add new node labels to old node */ 160 for_each_label_withdel(new_node->labels, l) 161 add_label(&old_node->labels, l->label); 162 163 /* Move properties from the new node to the old node. If there 164 * is a collision, replace the old value with the new */ 165 while (new_node->proplist) { 166 /* Pop the property off the list */ 167 new_prop = new_node->proplist; 168 new_node->proplist = new_prop->next; 169 new_prop->next = NULL; 170 171 if (new_prop->deleted) { 172 delete_property_by_name(old_node, new_prop->name); 173 free(new_prop); 174 continue; 175 } 176 177 /* Look for a collision, set new value if there is */ 178 for_each_property_withdel(old_node, old_prop) { 179 if (streq(old_prop->name, new_prop->name)) { 180 /* Add new labels to old property */ 181 for_each_label_withdel(new_prop->labels, l) 182 add_label(&old_prop->labels, l->label); 183 184 old_prop->val = new_prop->val; 185 old_prop->deleted = 0; 186 free(new_prop); 187 new_prop = NULL; 188 break; 189 } 190 } 191 192 /* if no collision occurred, add property to the old node. */ 193 if (new_prop) 194 add_property(old_node, new_prop); 195 } 196 197 /* Move the override child nodes into the primary node. If 198 * there is a collision, then merge the nodes. */ 199 while (new_node->children) { 200 /* Pop the child node off the list */ 201 new_child = new_node->children; 202 new_node->children = new_child->next_sibling; 203 new_child->parent = NULL; 204 new_child->next_sibling = NULL; 205 206 if (new_child->deleted) { 207 delete_node_by_name(old_node, new_child->name); 208 free(new_child); 209 continue; 210 } 211 212 /* Search for a collision. Merge if there is */ 213 for_each_child_withdel(old_node, old_child) { 214 if (streq(old_child->name, new_child->name)) { 215 merge_nodes(old_child, new_child); 216 new_child = NULL; 217 break; 218 } 219 } 220 221 /* if no collision occurred, add child to the old node. */ 222 if (new_child) 223 add_child(old_node, new_child); 224 } 225 226 /* The new node contents are now merged into the old node. Free 227 * the new node. */ 228 free(new_node); 229 230 return old_node; 231 } 232 233 struct node * add_orphan_node(struct node *dt, struct node *new_node, char *ref) 234 { 235 static unsigned int next_orphan_fragment = 0; 236 struct node *node; 237 struct property *p; 238 struct data d = empty_data; 239 char *name; 240 241 if (ref[0] == '/') { 242 d = data_append_data(d, ref, strlen(ref) + 1); 243 244 p = build_property("target-path", d); 245 } else { 246 d = data_add_marker(d, REF_PHANDLE, ref); 247 d = data_append_integer(d, 0xffffffff, 32); 248 249 p = build_property("target", d); 250 } 251 252 xasprintf(&name, "fragment@%u", 253 next_orphan_fragment++); 254 name_node(new_node, "__overlay__"); 255 node = build_node(p, new_node); 256 name_node(node, name); 257 258 add_child(dt, node); 259 return dt; 260 } 261 262 struct node *chain_node(struct node *first, struct node *list) 263 { 264 assert(first->next_sibling == NULL); 265 266 first->next_sibling = list; 267 return first; 268 } 269 270 void add_property(struct node *node, struct property *prop) 271 { 272 struct property **p; 273 274 prop->next = NULL; 275 276 p = &node->proplist; 277 while (*p) 278 p = &((*p)->next); 279 280 *p = prop; 281 } 282 283 void delete_property_by_name(struct node *node, char *name) 284 { 285 struct property *prop = node->proplist; 286 287 while (prop) { 288 if (streq(prop->name, name)) { 289 delete_property(prop); 290 return; 291 } 292 prop = prop->next; 293 } 294 } 295 296 void delete_property(struct property *prop) 297 { 298 prop->deleted = 1; 299 delete_labels(&prop->labels); 300 } 301 302 void add_child(struct node *parent, struct node *child) 303 { 304 struct node **p; 305 306 child->next_sibling = NULL; 307 child->parent = parent; 308 309 p = &parent->children; 310 while (*p) 311 p = &((*p)->next_sibling); 312 313 *p = child; 314 } 315 316 void delete_node_by_name(struct node *parent, char *name) 317 { 318 struct node *node = parent->children; 319 320 while (node) { 321 if (streq(node->name, name)) { 322 delete_node(node); 323 return; 324 } 325 node = node->next_sibling; 326 } 327 } 328 329 void delete_node(struct node *node) 330 { 331 struct property *prop; 332 struct node *child; 333 334 node->deleted = 1; 335 for_each_child(node, child) 336 delete_node(child); 337 for_each_property(node, prop) 338 delete_property(prop); 339 delete_labels(&node->labels); 340 } 341 342 void append_to_property(struct node *node, 343 char *name, const void *data, int len) 344 { 345 struct data d; 346 struct property *p; 347 348 p = get_property(node, name); 349 if (p) { 350 d = data_append_data(p->val, data, len); 351 p->val = d; 352 } else { 353 d = data_append_data(empty_data, data, len); 354 p = build_property(name, d); 355 add_property(node, p); 356 } 357 } 358 359 struct reserve_info *build_reserve_entry(uint64_t address, uint64_t size) 360 { 361 struct reserve_info *new = xmalloc(sizeof(*new)); 362 363 memset(new, 0, sizeof(*new)); 364 365 new->address = address; 366 new->size = size; 367 368 return new; 369 } 370 371 struct reserve_info *chain_reserve_entry(struct reserve_info *first, 372 struct reserve_info *list) 373 { 374 assert(first->next == NULL); 375 376 first->next = list; 377 return first; 378 } 379 380 struct reserve_info *add_reserve_entry(struct reserve_info *list, 381 struct reserve_info *new) 382 { 383 struct reserve_info *last; 384 385 new->next = NULL; 386 387 if (! list) 388 return new; 389 390 for (last = list; last->next; last = last->next) 391 ; 392 393 last->next = new; 394 395 return list; 396 } 397 398 struct dt_info *build_dt_info(unsigned int dtsflags, 399 struct reserve_info *reservelist, 400 struct node *tree, uint32_t boot_cpuid_phys) 401 { 402 struct dt_info *dti; 403 404 dti = xmalloc(sizeof(*dti)); 405 dti->dtsflags = dtsflags; 406 dti->reservelist = reservelist; 407 dti->dt = tree; 408 dti->boot_cpuid_phys = boot_cpuid_phys; 409 410 return dti; 411 } 412 413 /* 414 * Tree accessor functions 415 */ 416 417 const char *get_unitname(struct node *node) 418 { 419 if (node->name[node->basenamelen] == '\0') 420 return ""; 421 else 422 return node->name + node->basenamelen + 1; 423 } 424 425 struct property *get_property(struct node *node, const char *propname) 426 { 427 struct property *prop; 428 429 for_each_property(node, prop) 430 if (streq(prop->name, propname)) 431 return prop; 432 433 return NULL; 434 } 435 436 cell_t propval_cell(struct property *prop) 437 { 438 assert(prop->val.len == sizeof(cell_t)); 439 return fdt32_to_cpu(*((fdt32_t *)prop->val.val)); 440 } 441 442 cell_t propval_cell_n(struct property *prop, int n) 443 { 444 assert(prop->val.len / sizeof(cell_t) >= n); 445 return fdt32_to_cpu(*((fdt32_t *)prop->val.val + n)); 446 } 447 448 struct property *get_property_by_label(struct node *tree, const char *label, 449 struct node **node) 450 { 451 struct property *prop; 452 struct node *c; 453 454 *node = tree; 455 456 for_each_property(tree, prop) { 457 struct label *l; 458 459 for_each_label(prop->labels, l) 460 if (streq(l->label, label)) 461 return prop; 462 } 463 464 for_each_child(tree, c) { 465 prop = get_property_by_label(c, label, node); 466 if (prop) 467 return prop; 468 } 469 470 *node = NULL; 471 return NULL; 472 } 473 474 struct marker *get_marker_label(struct node *tree, const char *label, 475 struct node **node, struct property **prop) 476 { 477 struct marker *m; 478 struct property *p; 479 struct node *c; 480 481 *node = tree; 482 483 for_each_property(tree, p) { 484 *prop = p; 485 m = p->val.markers; 486 for_each_marker_of_type(m, LABEL) 487 if (streq(m->ref, label)) 488 return m; 489 } 490 491 for_each_child(tree, c) { 492 m = get_marker_label(c, label, node, prop); 493 if (m) 494 return m; 495 } 496 497 *prop = NULL; 498 *node = NULL; 499 return NULL; 500 } 501 502 struct node *get_subnode(struct node *node, const char *nodename) 503 { 504 struct node *child; 505 506 for_each_child(node, child) 507 if (streq(child->name, nodename)) 508 return child; 509 510 return NULL; 511 } 512 513 struct node *get_node_by_path(struct node *tree, const char *path) 514 { 515 const char *p; 516 struct node *child; 517 518 if (!path || ! (*path)) { 519 if (tree->deleted) 520 return NULL; 521 return tree; 522 } 523 524 while (path[0] == '/') 525 path++; 526 527 p = strchr(path, '/'); 528 529 for_each_child(tree, child) { 530 if (p && (strlen(child->name) == p-path) && 531 strprefixeq(path, p - path, child->name)) 532 return get_node_by_path(child, p+1); 533 else if (!p && streq(path, child->name)) 534 return child; 535 } 536 537 return NULL; 538 } 539 540 struct node *get_node_by_label(struct node *tree, const char *label) 541 { 542 struct node *child, *node; 543 struct label *l; 544 545 assert(label && (strlen(label) > 0)); 546 547 for_each_label(tree->labels, l) 548 if (streq(l->label, label)) 549 return tree; 550 551 for_each_child(tree, child) { 552 node = get_node_by_label(child, label); 553 if (node) 554 return node; 555 } 556 557 return NULL; 558 } 559 560 struct node *get_node_by_phandle(struct node *tree, cell_t phandle) 561 { 562 struct node *child, *node; 563 564 if ((phandle == 0) || (phandle == -1)) { 565 assert(generate_fixups); 566 return NULL; 567 } 568 569 if (tree->phandle == phandle) { 570 if (tree->deleted) 571 return NULL; 572 return tree; 573 } 574 575 for_each_child(tree, child) { 576 node = get_node_by_phandle(child, phandle); 577 if (node) 578 return node; 579 } 580 581 return NULL; 582 } 583 584 struct node *get_node_by_ref(struct node *tree, const char *ref) 585 { 586 if (streq(ref, "/")) 587 return tree; 588 else if (ref[0] == '/') 589 return get_node_by_path(tree, ref); 590 else 591 return get_node_by_label(tree, ref); 592 } 593 594 cell_t get_node_phandle(struct node *root, struct node *node) 595 { 596 static cell_t phandle = 1; /* FIXME: ick, static local */ 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 if (!get_property(node, "linux,phandle") 607 && (phandle_format & PHANDLE_LEGACY)) 608 add_property(node, 609 build_property("linux,phandle", 610 data_append_cell(empty_data, phandle))); 611 612 if (!get_property(node, "phandle") 613 && (phandle_format & PHANDLE_EPAPR)) 614 add_property(node, 615 build_property("phandle", 616 data_append_cell(empty_data, phandle))); 617 618 /* If the node *does* have a phandle property, we must 619 * be dealing with a self-referencing phandle, which will be 620 * fixed up momentarily in the caller */ 621 622 return node->phandle; 623 } 624 625 uint32_t guess_boot_cpuid(struct node *tree) 626 { 627 struct node *cpus, *bootcpu; 628 struct property *reg; 629 630 cpus = get_node_by_path(tree, "/cpus"); 631 if (!cpus) 632 return 0; 633 634 635 bootcpu = cpus->children; 636 if (!bootcpu) 637 return 0; 638 639 reg = get_property(bootcpu, "reg"); 640 if (!reg || (reg->val.len != sizeof(uint32_t))) 641 return 0; 642 643 /* FIXME: Sanity check node? */ 644 645 return propval_cell(reg); 646 } 647 648 static int cmp_reserve_info(const void *ax, const void *bx) 649 { 650 const struct reserve_info *a, *b; 651 652 a = *((const struct reserve_info * const *)ax); 653 b = *((const struct reserve_info * const *)bx); 654 655 if (a->address < b->address) 656 return -1; 657 else if (a->address > b->address) 658 return 1; 659 else if (a->size < b->size) 660 return -1; 661 else if (a->size > b->size) 662 return 1; 663 else 664 return 0; 665 } 666 667 static void sort_reserve_entries(struct dt_info *dti) 668 { 669 struct reserve_info *ri, **tbl; 670 int n = 0, i = 0; 671 672 for (ri = dti->reservelist; 673 ri; 674 ri = ri->next) 675 n++; 676 677 if (n == 0) 678 return; 679 680 tbl = xmalloc(n * sizeof(*tbl)); 681 682 for (ri = dti->reservelist; 683 ri; 684 ri = ri->next) 685 tbl[i++] = ri; 686 687 qsort(tbl, n, sizeof(*tbl), cmp_reserve_info); 688 689 dti->reservelist = tbl[0]; 690 for (i = 0; i < (n-1); i++) 691 tbl[i]->next = tbl[i+1]; 692 tbl[n-1]->next = NULL; 693 694 free(tbl); 695 } 696 697 static int cmp_prop(const void *ax, const void *bx) 698 { 699 const struct property *a, *b; 700 701 a = *((const struct property * const *)ax); 702 b = *((const struct property * const *)bx); 703 704 return strcmp(a->name, b->name); 705 } 706 707 static void sort_properties(struct node *node) 708 { 709 int n = 0, i = 0; 710 struct property *prop, **tbl; 711 712 for_each_property_withdel(node, prop) 713 n++; 714 715 if (n == 0) 716 return; 717 718 tbl = xmalloc(n * sizeof(*tbl)); 719 720 for_each_property_withdel(node, prop) 721 tbl[i++] = prop; 722 723 qsort(tbl, n, sizeof(*tbl), cmp_prop); 724 725 node->proplist = tbl[0]; 726 for (i = 0; i < (n-1); i++) 727 tbl[i]->next = tbl[i+1]; 728 tbl[n-1]->next = NULL; 729 730 free(tbl); 731 } 732 733 static int cmp_subnode(const void *ax, const void *bx) 734 { 735 const struct node *a, *b; 736 737 a = *((const struct node * const *)ax); 738 b = *((const struct node * const *)bx); 739 740 return strcmp(a->name, b->name); 741 } 742 743 static void sort_subnodes(struct node *node) 744 { 745 int n = 0, i = 0; 746 struct node *subnode, **tbl; 747 748 for_each_child_withdel(node, subnode) 749 n++; 750 751 if (n == 0) 752 return; 753 754 tbl = xmalloc(n * sizeof(*tbl)); 755 756 for_each_child_withdel(node, subnode) 757 tbl[i++] = subnode; 758 759 qsort(tbl, n, sizeof(*tbl), cmp_subnode); 760 761 node->children = tbl[0]; 762 for (i = 0; i < (n-1); i++) 763 tbl[i]->next_sibling = tbl[i+1]; 764 tbl[n-1]->next_sibling = NULL; 765 766 free(tbl); 767 } 768 769 static void sort_node(struct node *node) 770 { 771 struct node *c; 772 773 sort_properties(node); 774 sort_subnodes(node); 775 for_each_child_withdel(node, c) 776 sort_node(c); 777 } 778 779 void sort_tree(struct dt_info *dti) 780 { 781 sort_reserve_entries(dti); 782 sort_node(dti->dt); 783 } 784 785 /* utility helper to avoid code duplication */ 786 static struct node *build_and_name_child_node(struct node *parent, char *name) 787 { 788 struct node *node; 789 790 node = build_node(NULL, NULL); 791 name_node(node, xstrdup(name)); 792 add_child(parent, node); 793 794 return node; 795 } 796 797 static struct node *build_root_node(struct node *dt, char *name) 798 { 799 struct node *an; 800 801 an = get_subnode(dt, name); 802 if (!an) 803 an = build_and_name_child_node(dt, name); 804 805 if (!an) 806 die("Could not build root node /%s\n", name); 807 808 return an; 809 } 810 811 static bool any_label_tree(struct dt_info *dti, struct node *node) 812 { 813 struct node *c; 814 815 if (node->labels) 816 return true; 817 818 for_each_child(node, c) 819 if (any_label_tree(dti, c)) 820 return true; 821 822 return false; 823 } 824 825 static void generate_label_tree_internal(struct dt_info *dti, 826 struct node *an, struct node *node, 827 bool allocph) 828 { 829 struct node *dt = dti->dt; 830 struct node *c; 831 struct property *p; 832 struct label *l; 833 834 /* if there are labels */ 835 if (node->labels) { 836 837 /* now add the label in the node */ 838 for_each_label(node->labels, l) { 839 840 /* check whether the label already exists */ 841 p = get_property(an, l->label); 842 if (p) { 843 fprintf(stderr, "WARNING: label %s already" 844 " exists in /%s", l->label, 845 an->name); 846 continue; 847 } 848 849 /* insert it */ 850 p = build_property(l->label, 851 data_copy_mem(node->fullpath, 852 strlen(node->fullpath) + 1)); 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); 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 retreiving 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)); 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 } 1034