1 #include "libfdt_env.h" 2 3 #include <fdt.h> 4 #include <libfdt.h> 5 6 #include "libfdt_internal.h" 7 8 /** 9 * overlay_get_target_phandle - retrieves the target phandle of a fragment 10 * @fdto: pointer to the device tree overlay blob 11 * @fragment: node offset of the fragment in the overlay 12 * 13 * overlay_get_target_phandle() retrieves the target phandle of an 14 * overlay fragment when that fragment uses a phandle (target 15 * property) instead of a path (target-path property). 16 * 17 * returns: 18 * the phandle pointed by the target property 19 * 0, if the phandle was not found 20 * -1, if the phandle was malformed 21 */ 22 static uint32_t overlay_get_target_phandle(const void *fdto, int fragment) 23 { 24 const fdt32_t *val; 25 int len; 26 27 val = fdt_getprop(fdto, fragment, "target", &len); 28 if (!val) 29 return 0; 30 31 if ((len != sizeof(*val)) || (fdt32_to_cpu(*val) == (uint32_t)-1)) 32 return (uint32_t)-1; 33 34 return fdt32_to_cpu(*val); 35 } 36 37 /** 38 * overlay_get_target - retrieves the offset of a fragment's target 39 * @fdt: Base device tree blob 40 * @fdto: Device tree overlay blob 41 * @fragment: node offset of the fragment in the overlay 42 * @pathp: pointer which receives the path of the target (or NULL) 43 * 44 * overlay_get_target() retrieves the target offset in the base 45 * device tree of a fragment, no matter how the actual targetting is 46 * done (through a phandle or a path) 47 * 48 * returns: 49 * the targetted node offset in the base device tree 50 * Negative error code on error 51 */ 52 static int overlay_get_target(const void *fdt, const void *fdto, 53 int fragment, char const **pathp) 54 { 55 uint32_t phandle; 56 const char *path = NULL; 57 int path_len = 0, ret; 58 59 /* Try first to do a phandle based lookup */ 60 phandle = overlay_get_target_phandle(fdto, fragment); 61 if (phandle == (uint32_t)-1) 62 return -FDT_ERR_BADPHANDLE; 63 64 /* no phandle, try path */ 65 if (!phandle) { 66 /* And then a path based lookup */ 67 path = fdt_getprop(fdto, fragment, "target-path", &path_len); 68 if (path) 69 ret = fdt_path_offset(fdt, path); 70 else 71 ret = path_len; 72 } else 73 ret = fdt_node_offset_by_phandle(fdt, phandle); 74 75 /* 76 * If we haven't found either a target or a 77 * target-path property in a node that contains a 78 * __overlay__ subnode (we wouldn't be called 79 * otherwise), consider it a improperly written 80 * overlay 81 */ 82 if (ret < 0 && path_len == -FDT_ERR_NOTFOUND) 83 ret = -FDT_ERR_BADOVERLAY; 84 85 /* return on error */ 86 if (ret < 0) 87 return ret; 88 89 /* return pointer to path (if available) */ 90 if (pathp) 91 *pathp = path ? path : NULL; 92 93 return ret; 94 } 95 96 /** 97 * overlay_phandle_add_offset - Increases a phandle by an offset 98 * @fdt: Base device tree blob 99 * @node: Device tree overlay blob 100 * @name: Name of the property to modify (phandle or linux,phandle) 101 * @delta: offset to apply 102 * 103 * overlay_phandle_add_offset() increments a node phandle by a given 104 * offset. 105 * 106 * returns: 107 * 0 on success. 108 * Negative error code on error 109 */ 110 static int overlay_phandle_add_offset(void *fdt, int node, 111 const char *name, uint32_t delta) 112 { 113 const fdt32_t *val; 114 uint32_t adj_val; 115 int len; 116 117 val = fdt_getprop(fdt, node, name, &len); 118 if (!val) 119 return len; 120 121 if (len != sizeof(*val)) 122 return -FDT_ERR_BADPHANDLE; 123 124 adj_val = fdt32_to_cpu(*val); 125 if ((adj_val + delta) < adj_val) 126 return -FDT_ERR_NOPHANDLES; 127 128 adj_val += delta; 129 if (adj_val == (uint32_t)-1) 130 return -FDT_ERR_NOPHANDLES; 131 132 return fdt_setprop_inplace_u32(fdt, node, name, adj_val); 133 } 134 135 /** 136 * overlay_adjust_node_phandles - Offsets the phandles of a node 137 * @fdto: Device tree overlay blob 138 * @node: Offset of the node we want to adjust 139 * @delta: Offset to shift the phandles of 140 * 141 * overlay_adjust_node_phandles() adds a constant to all the phandles 142 * of a given node. This is mainly use as part of the overlay 143 * application process, when we want to update all the overlay 144 * phandles to not conflict with the overlays of the base device tree. 145 * 146 * returns: 147 * 0 on success 148 * Negative error code on failure 149 */ 150 static int overlay_adjust_node_phandles(void *fdto, int node, 151 uint32_t delta) 152 { 153 int child; 154 int ret; 155 156 ret = overlay_phandle_add_offset(fdto, node, "phandle", delta); 157 if (ret && ret != -FDT_ERR_NOTFOUND) 158 return ret; 159 160 ret = overlay_phandle_add_offset(fdto, node, "linux,phandle", delta); 161 if (ret && ret != -FDT_ERR_NOTFOUND) 162 return ret; 163 164 fdt_for_each_subnode(child, fdto, node) { 165 ret = overlay_adjust_node_phandles(fdto, child, delta); 166 if (ret) 167 return ret; 168 } 169 170 return 0; 171 } 172 173 /** 174 * overlay_adjust_local_phandles - Adjust the phandles of a whole overlay 175 * @fdto: Device tree overlay blob 176 * @delta: Offset to shift the phandles of 177 * 178 * overlay_adjust_local_phandles() adds a constant to all the 179 * phandles of an overlay. This is mainly use as part of the overlay 180 * application process, when we want to update all the overlay 181 * phandles to not conflict with the overlays of the base device tree. 182 * 183 * returns: 184 * 0 on success 185 * Negative error code on failure 186 */ 187 static int overlay_adjust_local_phandles(void *fdto, uint32_t delta) 188 { 189 /* 190 * Start adjusting the phandles from the overlay root 191 */ 192 return overlay_adjust_node_phandles(fdto, 0, delta); 193 } 194 195 /** 196 * overlay_update_local_node_references - Adjust the overlay references 197 * @fdto: Device tree overlay blob 198 * @tree_node: Node offset of the node to operate on 199 * @fixup_node: Node offset of the matching local fixups node 200 * @delta: Offset to shift the phandles of 201 * 202 * overlay_update_local_nodes_references() update the phandles 203 * pointing to a node within the device tree overlay by adding a 204 * constant delta. 205 * 206 * This is mainly used as part of a device tree application process, 207 * where you want the device tree overlays phandles to not conflict 208 * with the ones from the base device tree before merging them. 209 * 210 * returns: 211 * 0 on success 212 * Negative error code on failure 213 */ 214 static int overlay_update_local_node_references(void *fdto, 215 int tree_node, 216 int fixup_node, 217 uint32_t delta) 218 { 219 int fixup_prop; 220 int fixup_child; 221 int ret; 222 223 fdt_for_each_property_offset(fixup_prop, fdto, fixup_node) { 224 const fdt32_t *fixup_val; 225 const char *tree_val; 226 const char *name; 227 int fixup_len; 228 int tree_len; 229 int i; 230 231 fixup_val = fdt_getprop_by_offset(fdto, fixup_prop, 232 &name, &fixup_len); 233 if (!fixup_val) 234 return fixup_len; 235 236 if (fixup_len % sizeof(uint32_t)) 237 return -FDT_ERR_BADOVERLAY; 238 239 tree_val = fdt_getprop(fdto, tree_node, name, &tree_len); 240 if (!tree_val) { 241 if (tree_len == -FDT_ERR_NOTFOUND) 242 return -FDT_ERR_BADOVERLAY; 243 244 return tree_len; 245 } 246 247 for (i = 0; i < (fixup_len / sizeof(uint32_t)); i++) { 248 fdt32_t adj_val; 249 uint32_t poffset; 250 251 poffset = fdt32_to_cpu(fixup_val[i]); 252 253 /* 254 * phandles to fixup can be unaligned. 255 * 256 * Use a memcpy for the architectures that do 257 * not support unaligned accesses. 258 */ 259 memcpy(&adj_val, tree_val + poffset, sizeof(adj_val)); 260 261 adj_val = cpu_to_fdt32(fdt32_to_cpu(adj_val) + delta); 262 263 ret = fdt_setprop_inplace_namelen_partial(fdto, 264 tree_node, 265 name, 266 strlen(name), 267 poffset, 268 &adj_val, 269 sizeof(adj_val)); 270 if (ret == -FDT_ERR_NOSPACE) 271 return -FDT_ERR_BADOVERLAY; 272 273 if (ret) 274 return ret; 275 } 276 } 277 278 fdt_for_each_subnode(fixup_child, fdto, fixup_node) { 279 const char *fixup_child_name = fdt_get_name(fdto, fixup_child, 280 NULL); 281 int tree_child; 282 283 tree_child = fdt_subnode_offset(fdto, tree_node, 284 fixup_child_name); 285 if (tree_child == -FDT_ERR_NOTFOUND) 286 return -FDT_ERR_BADOVERLAY; 287 if (tree_child < 0) 288 return tree_child; 289 290 ret = overlay_update_local_node_references(fdto, 291 tree_child, 292 fixup_child, 293 delta); 294 if (ret) 295 return ret; 296 } 297 298 return 0; 299 } 300 301 /** 302 * overlay_update_local_references - Adjust the overlay references 303 * @fdto: Device tree overlay blob 304 * @delta: Offset to shift the phandles of 305 * 306 * overlay_update_local_references() update all the phandles pointing 307 * to a node within the device tree overlay by adding a constant 308 * delta to not conflict with the base overlay. 309 * 310 * This is mainly used as part of a device tree application process, 311 * where you want the device tree overlays phandles to not conflict 312 * with the ones from the base device tree before merging them. 313 * 314 * returns: 315 * 0 on success 316 * Negative error code on failure 317 */ 318 static int overlay_update_local_references(void *fdto, uint32_t delta) 319 { 320 int fixups; 321 322 fixups = fdt_path_offset(fdto, "/__local_fixups__"); 323 if (fixups < 0) { 324 /* There's no local phandles to adjust, bail out */ 325 if (fixups == -FDT_ERR_NOTFOUND) 326 return 0; 327 328 return fixups; 329 } 330 331 /* 332 * Update our local references from the root of the tree 333 */ 334 return overlay_update_local_node_references(fdto, 0, fixups, 335 delta); 336 } 337 338 /** 339 * overlay_fixup_one_phandle - Set an overlay phandle to the base one 340 * @fdt: Base Device Tree blob 341 * @fdto: Device tree overlay blob 342 * @symbols_off: Node offset of the symbols node in the base device tree 343 * @path: Path to a node holding a phandle in the overlay 344 * @path_len: number of path characters to consider 345 * @name: Name of the property holding the phandle reference in the overlay 346 * @name_len: number of name characters to consider 347 * @poffset: Offset within the overlay property where the phandle is stored 348 * @label: Label of the node referenced by the phandle 349 * 350 * overlay_fixup_one_phandle() resolves an overlay phandle pointing to 351 * a node in the base device tree. 352 * 353 * This is part of the device tree overlay application process, when 354 * you want all the phandles in the overlay to point to the actual 355 * base dt nodes. 356 * 357 * returns: 358 * 0 on success 359 * Negative error code on failure 360 */ 361 static int overlay_fixup_one_phandle(void *fdt, void *fdto, 362 int symbols_off, 363 const char *path, uint32_t path_len, 364 const char *name, uint32_t name_len, 365 int poffset, const char *label) 366 { 367 const char *symbol_path; 368 uint32_t phandle; 369 fdt32_t phandle_prop; 370 int symbol_off, fixup_off; 371 int prop_len; 372 373 if (symbols_off < 0) 374 return symbols_off; 375 376 symbol_path = fdt_getprop(fdt, symbols_off, label, 377 &prop_len); 378 if (!symbol_path) 379 return prop_len; 380 381 symbol_off = fdt_path_offset(fdt, symbol_path); 382 if (symbol_off < 0) 383 return symbol_off; 384 385 phandle = fdt_get_phandle(fdt, symbol_off); 386 if (!phandle) 387 return -FDT_ERR_NOTFOUND; 388 389 fixup_off = fdt_path_offset_namelen(fdto, path, path_len); 390 if (fixup_off == -FDT_ERR_NOTFOUND) 391 return -FDT_ERR_BADOVERLAY; 392 if (fixup_off < 0) 393 return fixup_off; 394 395 phandle_prop = cpu_to_fdt32(phandle); 396 return fdt_setprop_inplace_namelen_partial(fdto, fixup_off, 397 name, name_len, poffset, 398 &phandle_prop, 399 sizeof(phandle_prop)); 400 }; 401 402 /** 403 * overlay_fixup_phandle - Set an overlay phandle to the base one 404 * @fdt: Base Device Tree blob 405 * @fdto: Device tree overlay blob 406 * @symbols_off: Node offset of the symbols node in the base device tree 407 * @property: Property offset in the overlay holding the list of fixups 408 * 409 * overlay_fixup_phandle() resolves all the overlay phandles pointed 410 * to in a __fixups__ property, and updates them to match the phandles 411 * in use in the base device tree. 412 * 413 * This is part of the device tree overlay application process, when 414 * you want all the phandles in the overlay to point to the actual 415 * base dt nodes. 416 * 417 * returns: 418 * 0 on success 419 * Negative error code on failure 420 */ 421 static int overlay_fixup_phandle(void *fdt, void *fdto, int symbols_off, 422 int property) 423 { 424 const char *value; 425 const char *label; 426 int len; 427 428 value = fdt_getprop_by_offset(fdto, property, 429 &label, &len); 430 if (!value) { 431 if (len == -FDT_ERR_NOTFOUND) 432 return -FDT_ERR_INTERNAL; 433 434 return len; 435 } 436 437 do { 438 const char *path, *name, *fixup_end; 439 const char *fixup_str = value; 440 uint32_t path_len, name_len; 441 uint32_t fixup_len; 442 char *sep, *endptr; 443 int poffset, ret; 444 445 fixup_end = memchr(value, '\0', len); 446 if (!fixup_end) 447 return -FDT_ERR_BADOVERLAY; 448 fixup_len = fixup_end - fixup_str; 449 450 len -= fixup_len + 1; 451 value += fixup_len + 1; 452 453 path = fixup_str; 454 sep = memchr(fixup_str, ':', fixup_len); 455 if (!sep || *sep != ':') 456 return -FDT_ERR_BADOVERLAY; 457 458 path_len = sep - path; 459 if (path_len == (fixup_len - 1)) 460 return -FDT_ERR_BADOVERLAY; 461 462 fixup_len -= path_len + 1; 463 name = sep + 1; 464 sep = memchr(name, ':', fixup_len); 465 if (!sep || *sep != ':') 466 return -FDT_ERR_BADOVERLAY; 467 468 name_len = sep - name; 469 if (!name_len) 470 return -FDT_ERR_BADOVERLAY; 471 472 poffset = strtoul(sep + 1, &endptr, 10); 473 if ((*endptr != '\0') || (endptr <= (sep + 1))) 474 return -FDT_ERR_BADOVERLAY; 475 476 ret = overlay_fixup_one_phandle(fdt, fdto, symbols_off, 477 path, path_len, name, name_len, 478 poffset, label); 479 if (ret) 480 return ret; 481 } while (len > 0); 482 483 return 0; 484 } 485 486 /** 487 * overlay_fixup_phandles - Resolve the overlay phandles to the base 488 * device tree 489 * @fdt: Base Device Tree blob 490 * @fdto: Device tree overlay blob 491 * 492 * overlay_fixup_phandles() resolves all the overlay phandles pointing 493 * to nodes in the base device tree. 494 * 495 * This is one of the steps of the device tree overlay application 496 * process, when you want all the phandles in the overlay to point to 497 * the actual base dt nodes. 498 * 499 * returns: 500 * 0 on success 501 * Negative error code on failure 502 */ 503 static int overlay_fixup_phandles(void *fdt, void *fdto) 504 { 505 int fixups_off, symbols_off; 506 int property; 507 508 /* We can have overlays without any fixups */ 509 fixups_off = fdt_path_offset(fdto, "/__fixups__"); 510 if (fixups_off == -FDT_ERR_NOTFOUND) 511 return 0; /* nothing to do */ 512 if (fixups_off < 0) 513 return fixups_off; 514 515 /* And base DTs without symbols */ 516 symbols_off = fdt_path_offset(fdt, "/__symbols__"); 517 if ((symbols_off < 0 && (symbols_off != -FDT_ERR_NOTFOUND))) 518 return symbols_off; 519 520 fdt_for_each_property_offset(property, fdto, fixups_off) { 521 int ret; 522 523 ret = overlay_fixup_phandle(fdt, fdto, symbols_off, property); 524 if (ret) 525 return ret; 526 } 527 528 return 0; 529 } 530 531 /** 532 * overlay_apply_node - Merges a node into the base device tree 533 * @fdt: Base Device Tree blob 534 * @target: Node offset in the base device tree to apply the fragment to 535 * @fdto: Device tree overlay blob 536 * @node: Node offset in the overlay holding the changes to merge 537 * 538 * overlay_apply_node() merges a node into a target base device tree 539 * node pointed. 540 * 541 * This is part of the final step in the device tree overlay 542 * application process, when all the phandles have been adjusted and 543 * resolved and you just have to merge overlay into the base device 544 * tree. 545 * 546 * returns: 547 * 0 on success 548 * Negative error code on failure 549 */ 550 static int overlay_apply_node(void *fdt, int target, 551 void *fdto, int node) 552 { 553 int property; 554 int subnode; 555 556 fdt_for_each_property_offset(property, fdto, node) { 557 const char *name; 558 const void *prop; 559 int prop_len; 560 int ret; 561 562 prop = fdt_getprop_by_offset(fdto, property, &name, 563 &prop_len); 564 if (prop_len == -FDT_ERR_NOTFOUND) 565 return -FDT_ERR_INTERNAL; 566 if (prop_len < 0) 567 return prop_len; 568 569 ret = fdt_setprop(fdt, target, name, prop, prop_len); 570 if (ret) 571 return ret; 572 } 573 574 fdt_for_each_subnode(subnode, fdto, node) { 575 const char *name = fdt_get_name(fdto, subnode, NULL); 576 int nnode; 577 int ret; 578 579 nnode = fdt_add_subnode(fdt, target, name); 580 if (nnode == -FDT_ERR_EXISTS) { 581 nnode = fdt_subnode_offset(fdt, target, name); 582 if (nnode == -FDT_ERR_NOTFOUND) 583 return -FDT_ERR_INTERNAL; 584 } 585 586 if (nnode < 0) 587 return nnode; 588 589 ret = overlay_apply_node(fdt, nnode, fdto, subnode); 590 if (ret) 591 return ret; 592 } 593 594 return 0; 595 } 596 597 /** 598 * overlay_merge - Merge an overlay into its base device tree 599 * @fdt: Base Device Tree blob 600 * @fdto: Device tree overlay blob 601 * 602 * overlay_merge() merges an overlay into its base device tree. 603 * 604 * This is the next to last step in the device tree overlay application 605 * process, when all the phandles have been adjusted and resolved and 606 * you just have to merge overlay into the base device tree. 607 * 608 * returns: 609 * 0 on success 610 * Negative error code on failure 611 */ 612 static int overlay_merge(void *fdt, void *fdto) 613 { 614 int fragment; 615 616 fdt_for_each_subnode(fragment, fdto, 0) { 617 int overlay; 618 int target; 619 int ret; 620 621 /* 622 * Each fragments will have an __overlay__ node. If 623 * they don't, it's not supposed to be merged 624 */ 625 overlay = fdt_subnode_offset(fdto, fragment, "__overlay__"); 626 if (overlay == -FDT_ERR_NOTFOUND) 627 continue; 628 629 if (overlay < 0) 630 return overlay; 631 632 target = overlay_get_target(fdt, fdto, fragment, NULL); 633 if (target < 0) 634 return target; 635 636 ret = overlay_apply_node(fdt, target, fdto, overlay); 637 if (ret) 638 return ret; 639 } 640 641 return 0; 642 } 643 644 static int get_path_len(const void *fdt, int nodeoffset) 645 { 646 int len = 0, namelen; 647 const char *name; 648 649 FDT_CHECK_HEADER(fdt); 650 651 for (;;) { 652 name = fdt_get_name(fdt, nodeoffset, &namelen); 653 if (!name) 654 return namelen; 655 656 /* root? we're done */ 657 if (namelen == 0) 658 break; 659 660 nodeoffset = fdt_parent_offset(fdt, nodeoffset); 661 if (nodeoffset < 0) 662 return nodeoffset; 663 len += namelen + 1; 664 } 665 666 /* in case of root pretend it's "/" */ 667 if (len == 0) 668 len++; 669 return len; 670 } 671 672 /** 673 * overlay_symbol_update - Update the symbols of base tree after a merge 674 * @fdt: Base Device Tree blob 675 * @fdto: Device tree overlay blob 676 * 677 * overlay_symbol_update() updates the symbols of the base tree with the 678 * symbols of the applied overlay 679 * 680 * This is the last step in the device tree overlay application 681 * process, allowing the reference of overlay symbols by subsequent 682 * overlay operations. 683 * 684 * returns: 685 * 0 on success 686 * Negative error code on failure 687 */ 688 static int overlay_symbol_update(void *fdt, void *fdto) 689 { 690 int root_sym, ov_sym, prop, path_len, fragment, target; 691 int len, frag_name_len, ret, rel_path_len; 692 const char *s, *e; 693 const char *path; 694 const char *name; 695 const char *frag_name; 696 const char *rel_path; 697 const char *target_path; 698 char *buf; 699 void *p; 700 701 ov_sym = fdt_subnode_offset(fdto, 0, "__symbols__"); 702 703 /* if no overlay symbols exist no problem */ 704 if (ov_sym < 0) 705 return 0; 706 707 root_sym = fdt_subnode_offset(fdt, 0, "__symbols__"); 708 709 /* it no root symbols exist we should create them */ 710 if (root_sym == -FDT_ERR_NOTFOUND) 711 root_sym = fdt_add_subnode(fdt, 0, "__symbols__"); 712 713 /* any error is fatal now */ 714 if (root_sym < 0) 715 return root_sym; 716 717 /* iterate over each overlay symbol */ 718 fdt_for_each_property_offset(prop, fdto, ov_sym) { 719 path = fdt_getprop_by_offset(fdto, prop, &name, &path_len); 720 if (!path) 721 return path_len; 722 723 /* verify it's a string property (terminated by a single \0) */ 724 if (path_len < 1 || memchr(path, '\0', path_len) != &path[path_len - 1]) 725 return -FDT_ERR_BADVALUE; 726 727 /* keep end marker to avoid strlen() */ 728 e = path + path_len; 729 730 /* format: /<fragment-name>/__overlay__/<relative-subnode-path> */ 731 732 if (*path != '/') 733 return -FDT_ERR_BADVALUE; 734 735 /* get fragment name first */ 736 s = strchr(path + 1, '/'); 737 if (!s) 738 return -FDT_ERR_BADOVERLAY; 739 740 frag_name = path + 1; 741 frag_name_len = s - path - 1; 742 743 /* verify format; safe since "s" lies in \0 terminated prop */ 744 len = sizeof("/__overlay__/") - 1; 745 if ((e - s) < len || memcmp(s, "/__overlay__/", len)) 746 return -FDT_ERR_BADOVERLAY; 747 748 rel_path = s + len; 749 rel_path_len = e - rel_path; 750 751 /* find the fragment index in which the symbol lies */ 752 ret = fdt_subnode_offset_namelen(fdto, 0, frag_name, 753 frag_name_len); 754 /* not found? */ 755 if (ret < 0) 756 return -FDT_ERR_BADOVERLAY; 757 fragment = ret; 758 759 /* an __overlay__ subnode must exist */ 760 ret = fdt_subnode_offset(fdto, fragment, "__overlay__"); 761 if (ret < 0) 762 return -FDT_ERR_BADOVERLAY; 763 764 /* get the target of the fragment */ 765 ret = overlay_get_target(fdt, fdto, fragment, &target_path); 766 if (ret < 0) 767 return ret; 768 target = ret; 769 770 /* if we have a target path use */ 771 if (!target_path) { 772 ret = get_path_len(fdt, target); 773 if (ret < 0) 774 return ret; 775 len = ret; 776 } else { 777 len = strlen(target_path); 778 } 779 780 ret = fdt_setprop_placeholder(fdt, root_sym, name, 781 len + (len > 1) + rel_path_len + 1, &p); 782 if (ret < 0) 783 return ret; 784 785 if (!target_path) { 786 /* again in case setprop_placeholder changed it */ 787 ret = overlay_get_target(fdt, fdto, fragment, &target_path); 788 if (ret < 0) 789 return ret; 790 target = ret; 791 } 792 793 buf = p; 794 if (len > 1) { /* target is not root */ 795 if (!target_path) { 796 ret = fdt_get_path(fdt, target, buf, len + 1); 797 if (ret < 0) 798 return ret; 799 } else 800 memcpy(buf, target_path, len + 1); 801 802 } else 803 len--; 804 805 buf[len] = '/'; 806 memcpy(buf + len + 1, rel_path, rel_path_len); 807 buf[len + 1 + rel_path_len] = '\0'; 808 } 809 810 return 0; 811 } 812 813 int fdt_overlay_apply(void *fdt, void *fdto) 814 { 815 uint32_t delta = fdt_get_max_phandle(fdt); 816 int ret; 817 818 FDT_CHECK_HEADER(fdt); 819 FDT_CHECK_HEADER(fdto); 820 821 ret = overlay_adjust_local_phandles(fdto, delta); 822 if (ret) 823 goto err; 824 825 ret = overlay_update_local_references(fdto, delta); 826 if (ret) 827 goto err; 828 829 ret = overlay_fixup_phandles(fdt, fdto); 830 if (ret) 831 goto err; 832 833 ret = overlay_merge(fdt, fdto); 834 if (ret) 835 goto err; 836 837 ret = overlay_symbol_update(fdt, fdto); 838 if (ret) 839 goto err; 840 841 /* 842 * The overlay has been damaged, erase its magic. 843 */ 844 fdt_set_magic(fdto, ~0); 845 846 return 0; 847 848 err: 849 /* 850 * The overlay might have been damaged, erase its magic. 851 */ 852 fdt_set_magic(fdto, ~0); 853 854 /* 855 * The base device tree might have been damaged, erase its 856 * magic. 857 */ 858 fdt_set_magic(fdt, ~0); 859 860 return ret; 861 } 862