1// SPDX-License-Identifier: GPL-2.0+ 2/* 3 * Originally from Linux v4.9 4 * Paul Mackerras August 1996. 5 * Copyright (C) 1996-2005 Paul Mackerras. 6 * 7 * Adapted for 64bit PowerPC by Dave Engebretsen and Peter Bergner. 8 * {engebret|bergner}@us.ibm.com 9 * 10 * Adapted for sparc and sparc64 by David S. Miller davem@davemloft.net 11 * 12 * Reconsolidated from arch/x/kernel/prom.c by Stephen Rothwell and 13 * Grant Likely. 14 * 15 * Modified for U-Boot 16 * Copyright (c) 2017 Google, Inc 17 * 18 * This file follows drivers/of/base.c with functions in the same order as the 19 * Linux version. 20 */ 21 22#include <log.h> 23#include <malloc.h> 24#include <asm/global_data.h> 25#include <linux/bug.h> 26#include <linux/libfdt.h> 27#include <dm/of_access.h> 28#include <linux/ctype.h> 29#include <linux/err.h> 30#include <linux/ioport.h> 31 32DECLARE_GLOBAL_DATA_PTR; 33 34/* list of struct alias_prop aliases */ 35static LIST_HEAD(aliases_lookup); 36 37/* "/aliaes" node */ 38static struct device_node *of_aliases; 39 40/* "/chosen" node */ 41static struct device_node *of_chosen; 42 43/* node pointed to by the stdout-path alias */ 44static struct device_node *of_stdout; 45 46/* pointer to options given after the alias (separated by :) or NULL if none */ 47static const char *of_stdout_options; 48 49/** 50 * struct alias_prop - Alias property in 'aliases' node 51 * 52 * The structure represents one alias property of 'aliases' node as 53 * an entry in aliases_lookup list. 54 * 55 * @link: List node to link the structure in aliases_lookup list 56 * @alias: Alias property name 57 * @np: Pointer to device_node that the alias stands for 58 * @id: Index value from end of alias name 59 * @stem: Alias string without the index 60 */ 61struct alias_prop { 62 struct list_head link; 63 const char *alias; 64 struct device_node *np; 65 int id; 66 char stem[0]; 67}; 68 69int of_n_addr_cells(const struct device_node *np) 70{ 71 const __be32 *ip; 72 73 do { 74 if (np->parent) 75 np = np->parent; 76 ip = of_get_property(np, "#address-cells", NULL); 77 if (ip) 78 return be32_to_cpup(ip); 79 } while (np->parent); 80 81 /* No #address-cells property for the root node */ 82 return OF_ROOT_NODE_ADDR_CELLS_DEFAULT; 83} 84 85int of_n_size_cells(const struct device_node *np) 86{ 87 const __be32 *ip; 88 89 do { 90 if (np->parent) 91 np = np->parent; 92 ip = of_get_property(np, "#size-cells", NULL); 93 if (ip) 94 return be32_to_cpup(ip); 95 } while (np->parent); 96 97 /* No #size-cells property for the root node */ 98 return OF_ROOT_NODE_SIZE_CELLS_DEFAULT; 99} 100 101int of_simple_addr_cells(const struct device_node *np) 102{ 103 const __be32 *ip; 104 105 ip = of_get_property(np, "#address-cells", NULL); 106 if (ip) 107 return be32_to_cpup(ip); 108 109 /* Return a default of 2 to match fdt_address_cells()*/ 110 return 2; 111} 112 113int of_simple_size_cells(const struct device_node *np) 114{ 115 const __be32 *ip; 116 117 ip = of_get_property(np, "#size-cells", NULL); 118 if (ip) 119 return be32_to_cpup(ip); 120 121 /* Return a default of 2 to match fdt_size_cells()*/ 122 return 2; 123} 124 125struct property *of_find_property(const struct device_node *np, 126 const char *name, int *lenp) 127{ 128 struct property *pp; 129 130 if (!np) 131 return NULL; 132 133 for (pp = np->properties; pp; pp = pp->next) { 134 if (strcmp(pp->name, name) == 0) { 135 if (lenp) 136 *lenp = pp->length; 137 break; 138 } 139 } 140 if (!pp && lenp) 141 *lenp = -FDT_ERR_NOTFOUND; 142 143 return pp; 144} 145 146struct device_node *of_find_all_nodes(struct device_node *prev) 147{ 148 struct device_node *np; 149 150 if (!prev) { 151 np = gd->of_root; 152 } else if (prev->child) { 153 np = prev->child; 154 } else { 155 /* 156 * Walk back up looking for a sibling, or the end of the 157 * structure 158 */ 159 np = prev; 160 while (np->parent && !np->sibling) 161 np = np->parent; 162 np = np->sibling; /* Might be null at the end of the tree */ 163 } 164 165 return np; 166} 167 168const void *of_get_property(const struct device_node *np, const char *name, 169 int *lenp) 170{ 171 struct property *pp = of_find_property(np, name, lenp); 172 173 return pp ? pp->value : NULL; 174} 175 176const struct property *of_get_first_property(const struct device_node *np) 177{ 178 if (!np) 179 return NULL; 180 181 return np->properties; 182} 183 184const struct property *of_get_next_property(const struct device_node *np, 185 const struct property *property) 186{ 187 if (!np) 188 return NULL; 189 190 return property->next; 191} 192 193const void *of_get_property_by_prop(const struct device_node *np, 194 const struct property *property, 195 const char **name, 196 int *lenp) 197{ 198 if (!np || !property) 199 return NULL; 200 if (name) 201 *name = property->name; 202 if (lenp) 203 *lenp = property->length; 204 205 return property->value; 206} 207 208static const char *of_prop_next_string(struct property *prop, const char *cur) 209{ 210 const void *curv = cur; 211 212 if (!prop) 213 return NULL; 214 215 if (!cur) 216 return prop->value; 217 218 curv += strlen(cur) + 1; 219 if (curv >= prop->value + prop->length) 220 return NULL; 221 222 return curv; 223} 224 225int of_device_is_compatible(const struct device_node *device, 226 const char *compat, const char *type, 227 const char *name) 228{ 229 struct property *prop; 230 const char *cp; 231 int index = 0, score = 0; 232 233 /* Compatible match has highest priority */ 234 if (compat && compat[0]) { 235 prop = of_find_property(device, "compatible", NULL); 236 for (cp = of_prop_next_string(prop, NULL); cp; 237 cp = of_prop_next_string(prop, cp), index++) { 238 if (of_compat_cmp(cp, compat, strlen(compat)) == 0) { 239 score = INT_MAX/2 - (index << 2); 240 break; 241 } 242 } 243 if (!score) 244 return 0; 245 } 246 247 /* Matching type is better than matching name */ 248 if (type && type[0]) { 249 if (!device->type || of_node_cmp(type, device->type)) 250 return 0; 251 score += 2; 252 } 253 254 /* Matching name is a bit better than not */ 255 if (name && name[0]) { 256 if (!device->name || of_node_cmp(name, device->name)) 257 return 0; 258 score++; 259 } 260 261 return score; 262} 263 264bool of_device_is_available(const struct device_node *device) 265{ 266 const char *status; 267 int statlen; 268 269 if (!device) 270 return false; 271 272 status = of_get_property(device, "status", &statlen); 273 if (status == NULL) 274 return true; 275 276 if (statlen > 0) { 277 if (!strcmp(status, "okay")) 278 return true; 279 } 280 281 return false; 282} 283 284struct device_node *of_get_parent(const struct device_node *node) 285{ 286 const struct device_node *np; 287 288 if (!node) 289 return NULL; 290 291 np = of_node_get(node->parent); 292 293 return (struct device_node *)np; 294} 295 296static struct device_node *__of_get_next_child(const struct device_node *node, 297 struct device_node *prev) 298{ 299 struct device_node *next; 300 301 if (!node) 302 return NULL; 303 304 next = prev ? prev->sibling : node->child; 305 /* 306 * coverity[dead_error_line : FALSE] 307 * Dead code here since our current implementation of of_node_get() 308 * always returns NULL (Coverity CID 163245). But we leave it as is 309 * since we may want to implement get/put later. 310 */ 311 for (; next; next = next->sibling) 312 if (of_node_get(next)) 313 break; 314 of_node_put(prev); 315 return next; 316} 317 318#define __for_each_child_of_node(parent, child) \ 319 for (child = __of_get_next_child(parent, NULL); child != NULL; \ 320 child = __of_get_next_child(parent, child)) 321 322static struct device_node *__of_find_node_by_path(struct device_node *parent, 323 const char *path) 324{ 325 struct device_node *child; 326 int len; 327 328 len = strcspn(path, "/:"); 329 if (!len) 330 return NULL; 331 332 __for_each_child_of_node(parent, child) { 333 const char *name = strrchr(child->full_name, '/'); 334 335 name++; 336 if (strncmp(path, name, len) == 0 && (strlen(name) == len)) 337 return child; 338 } 339 return NULL; 340} 341 342#define for_each_property_of_node(dn, pp) \ 343 for (pp = dn->properties; pp != NULL; pp = pp->next) 344 345struct device_node *of_find_node_opts_by_path(struct device_node *root, 346 const char *path, 347 const char **opts) 348{ 349 struct device_node *np = NULL; 350 struct property *pp; 351 const char *separator = strchr(path, ':'); 352 353 if (!root) 354 root = gd->of_root; 355 if (opts) 356 *opts = separator ? separator + 1 : NULL; 357 358 if (strcmp(path, "/") == 0) 359 return of_node_get(root); 360 361 /* The path could begin with an alias */ 362 if (*path != '/') { 363 int len; 364 const char *p = separator; 365 366 /* Only allow alias processing on the control FDT */ 367 if (root != gd->of_root) 368 return NULL; 369 if (!p) 370 p = strchrnul(path, '/'); 371 len = p - path; 372 373 /* of_aliases must not be NULL */ 374 if (!of_aliases) 375 return NULL; 376 377 for_each_property_of_node(of_aliases, pp) { 378 if (strlen(pp->name) == len && !strncmp(pp->name, path, 379 len)) { 380 np = of_find_node_by_path(pp->value); 381 break; 382 } 383 } 384 if (!np) 385 return NULL; 386 path = p; 387 } 388 389 /* Step down the tree matching path components */ 390 if (!np) 391 np = of_node_get(root); 392 while (np && *path == '/') { 393 struct device_node *tmp = np; 394 395 path++; /* Increment past '/' delimiter */ 396 np = __of_find_node_by_path(np, path); 397 of_node_put(tmp); 398 path = strchrnul(path, '/'); 399 if (separator && separator < path) 400 break; 401 } 402 403 return np; 404} 405 406struct device_node *of_find_compatible_node(struct device_node *from, 407 const char *type, const char *compatible) 408{ 409 struct device_node *np; 410 411 for_each_of_allnodes_from(from, np) 412 if (of_device_is_compatible(np, compatible, type, NULL) && 413 of_node_get(np)) 414 break; 415 of_node_put(from); 416 417 return np; 418} 419 420static int of_device_has_prop_value(const struct device_node *device, 421 const char *propname, const void *propval, 422 int proplen) 423{ 424 struct property *prop = of_find_property(device, propname, NULL); 425 426 if (!prop || !prop->value || prop->length != proplen) 427 return 0; 428 return !memcmp(prop->value, propval, proplen); 429} 430 431struct device_node *of_find_node_by_prop_value(struct device_node *from, 432 const char *propname, 433 const void *propval, int proplen) 434{ 435 struct device_node *np; 436 437 for_each_of_allnodes_from(from, np) { 438 if (of_device_has_prop_value(np, propname, propval, proplen) && 439 of_node_get(np)) 440 break; 441 } 442 of_node_put(from); 443 444 return np; 445} 446 447struct device_node *of_find_node_by_phandle(struct device_node *root, 448 phandle handle) 449{ 450 struct device_node *np; 451 452 if (!handle) 453 return NULL; 454 455 for_each_of_allnodes_from(root, np) 456 if (np->phandle == handle) 457 break; 458 (void)of_node_get(np); 459 460 return np; 461} 462 463/** 464 * of_find_property_value_of_size() - find property of given size 465 * 466 * Search for a property in a device node and validate the requested size. 467 * 468 * @np: device node from which the property value is to be read. 469 * @propname: name of the property to be searched. 470 * @len: requested length of property value 471 * 472 * Return: the property value on success, -EINVAL if the property does not 473 * exist and -EOVERFLOW if the property data isn't large enough. 474 */ 475static void *of_find_property_value_of_size(const struct device_node *np, 476 const char *propname, u32 len) 477{ 478 struct property *prop = of_find_property(np, propname, NULL); 479 480 if (!prop) 481 return ERR_PTR(-EINVAL); 482 if (len > prop->length) 483 return ERR_PTR(-EOVERFLOW); 484 485 return prop->value; 486} 487 488int of_read_u8(const struct device_node *np, const char *propname, u8 *outp) 489{ 490 const u8 *val; 491 492 debug("%s: %s: ", __func__, propname); 493 if (!np) 494 return -EINVAL; 495 val = of_find_property_value_of_size(np, propname, sizeof(*outp)); 496 if (IS_ERR(val)) { 497 debug("(not found)\n"); 498 return PTR_ERR(val); 499 } 500 501 *outp = *val; 502 debug("%#x (%d)\n", *outp, *outp); 503 504 return 0; 505} 506 507int of_read_u16(const struct device_node *np, const char *propname, u16 *outp) 508{ 509 const __be16 *val; 510 511 debug("%s: %s: ", __func__, propname); 512 if (!np) 513 return -EINVAL; 514 val = of_find_property_value_of_size(np, propname, sizeof(*outp)); 515 if (IS_ERR(val)) { 516 debug("(not found)\n"); 517 return PTR_ERR(val); 518 } 519 520 *outp = be16_to_cpup(val); 521 debug("%#x (%d)\n", *outp, *outp); 522 523 return 0; 524} 525 526int of_read_u32(const struct device_node *np, const char *propname, u32 *outp) 527{ 528 return of_read_u32_index(np, propname, 0, outp); 529} 530 531int of_read_u32_array(const struct device_node *np, const char *propname, 532 u32 *out_values, size_t sz) 533{ 534 const __be32 *val; 535 536 debug("%s: %s: ", __func__, propname); 537 val = of_find_property_value_of_size(np, propname, 538 sz * sizeof(*out_values)); 539 540 if (IS_ERR(val)) 541 return PTR_ERR(val); 542 543 debug("size %zd\n", sz); 544 while (sz--) 545 *out_values++ = be32_to_cpup(val++); 546 547 return 0; 548} 549 550int of_read_u32_index(const struct device_node *np, const char *propname, 551 int index, u32 *outp) 552{ 553 const __be32 *val; 554 555 debug("%s: %s: ", __func__, propname); 556 if (!np) 557 return -EINVAL; 558 559 val = of_find_property_value_of_size(np, propname, 560 sizeof(*outp) * (index + 1)); 561 if (IS_ERR(val)) { 562 debug("(not found)\n"); 563 return PTR_ERR(val); 564 } 565 566 *outp = be32_to_cpup(val + index); 567 debug("%#x (%d)\n", *outp, *outp); 568 569 return 0; 570} 571 572int of_read_u64_index(const struct device_node *np, const char *propname, 573 int index, u64 *outp) 574{ 575 const __be64 *val; 576 577 debug("%s: %s: ", __func__, propname); 578 if (!np) 579 return -EINVAL; 580 581 val = of_find_property_value_of_size(np, propname, 582 sizeof(*outp) * (index + 1)); 583 if (IS_ERR(val)) { 584 debug("(not found)\n"); 585 return PTR_ERR(val); 586 } 587 588 *outp = be64_to_cpup(val + index); 589 debug("%#llx (%lld)\n", (unsigned long long)*outp, 590 (unsigned long long)*outp); 591 592 return 0; 593} 594 595int of_read_u64(const struct device_node *np, const char *propname, u64 *outp) 596{ 597 return of_read_u64_index(np, propname, 0, outp); 598} 599 600int of_property_match_string(const struct device_node *np, const char *propname, 601 const char *string) 602{ 603 int len = 0; 604 const struct property *prop = of_find_property(np, propname, &len); 605 size_t l; 606 int i; 607 const char *p, *end; 608 609 if (!prop && len == -FDT_ERR_NOTFOUND) 610 return -ENOENT; 611 if (!prop) 612 return -EINVAL; 613 if (!prop->value) 614 return -ENODATA; 615 616 p = prop->value; 617 end = p + prop->length; 618 619 for (i = 0; p < end; i++, p += l) { 620 l = strnlen(p, end - p) + 1; 621 if (p + l > end) 622 return -EILSEQ; 623 debug("comparing %s with %s\n", string, p); 624 if (strcmp(string, p) == 0) 625 return i; /* Found it; return index */ 626 } 627 return -ENODATA; 628} 629 630/** 631 * of_property_read_string_helper() - Utility helper for parsing string properties 632 * @np: device node from which the property value is to be read. 633 * @propname: name of the property to be searched. 634 * @out_strs: output array of string pointers. 635 * @sz: number of array elements to read. 636 * @skip: Number of strings to skip over at beginning of list (cannot be 637 * negative) 638 * 639 * Don't call this function directly. It is a utility helper for the 640 * of_property_read_string*() family of functions. 641 */ 642int of_property_read_string_helper(const struct device_node *np, 643 const char *propname, const char **out_strs, 644 size_t sz, int skip) 645{ 646 const struct property *prop = of_find_property(np, propname, NULL); 647 int l = 0, i = 0; 648 const char *p, *end; 649 650 if (!prop) 651 return -EINVAL; 652 if (!prop->value) 653 return -ENODATA; 654 p = prop->value; 655 end = p + prop->length; 656 657 for (i = 0; p < end && (!out_strs || i < skip + sz); i++, p += l) { 658 l = strnlen(p, end - p) + 1; 659 if (p + l > end) 660 return -EILSEQ; 661 if (out_strs && i >= skip) 662 *out_strs++ = p; 663 } 664 i -= skip; 665 return i <= 0 ? -ENODATA : i; 666} 667 668static int __of_parse_phandle_with_args(const struct device_node *np, 669 const char *list_name, 670 const char *cells_name, 671 int cell_count, int index, 672 struct of_phandle_args *out_args) 673{ 674 const __be32 *list, *list_end; 675 int rc = 0, cur_index = 0; 676 uint32_t count; 677 struct device_node *node = NULL; 678 phandle phandle; 679 int size; 680 681 /* Retrieve the phandle list property */ 682 list = of_get_property(np, list_name, &size); 683 if (!list) 684 return -ENOENT; 685 list_end = list + size / sizeof(*list); 686 687 /* Loop over the phandles until all the requested entry is found */ 688 while (list < list_end) { 689 rc = -EINVAL; 690 count = 0; 691 692 /* 693 * If phandle is 0, then it is an empty entry with no 694 * arguments. Skip forward to the next entry. 695 */ 696 phandle = be32_to_cpup(list++); 697 if (phandle) { 698 /* 699 * Find the provider node and parse the #*-cells 700 * property to determine the argument length. 701 * 702 * This is not needed if the cell count is hard-coded 703 * (i.e. cells_name not set, but cell_count is set), 704 * except when we're going to return the found node 705 * below. 706 */ 707 if (cells_name || cur_index == index) { 708 node = of_find_node_by_phandle(NULL, phandle); 709 if (!node) { 710 debug("%s: could not find phandle\n", 711 np->full_name); 712 goto err; 713 } 714 } 715 716 if (cells_name) { 717 if (of_read_u32(node, cells_name, &count)) { 718 debug("%s: could not get %s for %s\n", 719 np->full_name, cells_name, 720 node->full_name); 721 goto err; 722 } 723 } else { 724 count = cell_count; 725 } 726 727 /* 728 * Make sure that the arguments actually fit in the 729 * remaining property data length 730 */ 731 if (list + count > list_end) { 732 debug("%s: arguments longer than property\n", 733 np->full_name); 734 goto err; 735 } 736 } 737 738 /* 739 * All of the error cases above bail out of the loop, so at 740 * this point, the parsing is successful. If the requested 741 * index matches, then fill the out_args structure and return, 742 * or return -ENOENT for an empty entry. 743 */ 744 rc = -ENOENT; 745 if (cur_index == index) { 746 if (!phandle) 747 goto err; 748 749 if (out_args) { 750 int i; 751 if (WARN_ON(count > OF_MAX_PHANDLE_ARGS)) 752 count = OF_MAX_PHANDLE_ARGS; 753 out_args->np = node; 754 out_args->args_count = count; 755 for (i = 0; i < count; i++) 756 out_args->args[i] = 757 be32_to_cpup(list++); 758 } else { 759 of_node_put(node); 760 } 761 762 /* Found it! return success */ 763 return 0; 764 } 765 766 of_node_put(node); 767 node = NULL; 768 list += count; 769 cur_index++; 770 } 771 772 /* 773 * Unlock node before returning result; will be one of: 774 * -ENOENT : index is for empty phandle 775 * -EINVAL : parsing error on data 776 * [1..n] : Number of phandle (count mode; when index = -1) 777 */ 778 rc = index < 0 ? cur_index : -ENOENT; 779 err: 780 if (node) 781 of_node_put(node); 782 return rc; 783} 784 785struct device_node *of_parse_phandle(const struct device_node *np, 786 const char *phandle_name, int index) 787{ 788 struct of_phandle_args args; 789 790 if (index < 0) 791 return NULL; 792 793 if (__of_parse_phandle_with_args(np, phandle_name, NULL, 0, index, 794 &args)) 795 return NULL; 796 797 return args.np; 798} 799 800int of_parse_phandle_with_args(const struct device_node *np, 801 const char *list_name, const char *cells_name, 802 int cell_count, int index, 803 struct of_phandle_args *out_args) 804{ 805 if (index < 0) 806 return -EINVAL; 807 808 return __of_parse_phandle_with_args(np, list_name, cells_name, 809 cell_count, index, out_args); 810} 811 812int of_count_phandle_with_args(const struct device_node *np, 813 const char *list_name, const char *cells_name, 814 int cell_count) 815{ 816 return __of_parse_phandle_with_args(np, list_name, cells_name, 817 cell_count, -1, NULL); 818} 819 820static void of_alias_add(struct alias_prop *ap, struct device_node *np, 821 int id, const char *stem, int stem_len) 822{ 823 ap->np = np; 824 ap->id = id; 825 strncpy(ap->stem, stem, stem_len); 826 ap->stem[stem_len] = 0; 827 list_add_tail(&ap->link, &aliases_lookup); 828 debug("adding DT alias:%s: stem=%s id=%i node=%s\n", 829 ap->alias, ap->stem, ap->id, of_node_full_name(np)); 830} 831 832int of_alias_scan(void) 833{ 834 struct property *pp; 835 836 of_aliases = of_find_node_by_path("/aliases"); 837 of_chosen = of_find_node_by_path("/chosen"); 838 if (of_chosen == NULL) 839 of_chosen = of_find_node_by_path("/chosen@0"); 840 841 if (of_chosen) { 842 const char *name; 843 844 name = of_get_property(of_chosen, "stdout-path", NULL); 845 if (name) 846 of_stdout = of_find_node_opts_by_path(NULL, name, 847 &of_stdout_options); 848 } 849 850 if (!of_aliases) 851 return 0; 852 853 for_each_property_of_node(of_aliases, pp) { 854 const char *start = pp->name; 855 const char *end = start + strlen(start); 856 struct device_node *np; 857 struct alias_prop *ap; 858 ulong id; 859 int len; 860 861 /* Skip those we do not want to proceed */ 862 if (!strcmp(pp->name, "name") || 863 !strcmp(pp->name, "phandle") || 864 !strcmp(pp->name, "linux,phandle")) 865 continue; 866 867 np = of_find_node_by_path(pp->value); 868 if (!np) 869 continue; 870 871 /* 872 * walk the alias backwards to extract the id and work out 873 * the 'stem' string 874 */ 875 while (isdigit(*(end-1)) && end > start) 876 end--; 877 len = end - start; 878 879 if (strict_strtoul(end, 10, &id) < 0) 880 continue; 881 882 /* Allocate an alias_prop with enough space for the stem */ 883 ap = malloc(sizeof(*ap) + len + 1); 884 if (!ap) 885 return -ENOMEM; 886 memset(ap, 0, sizeof(*ap) + len + 1); 887 ap->alias = start; 888 of_alias_add(ap, np, id, start, len); 889 } 890 891 return 0; 892} 893 894int of_alias_get_id(const struct device_node *np, const char *stem) 895{ 896 struct alias_prop *app; 897 int id = -ENODEV; 898 899 mutex_lock(&of_mutex); 900 list_for_each_entry(app, &aliases_lookup, link) { 901 if (strcmp(app->stem, stem) != 0) 902 continue; 903 904 if (np == app->np) { 905 id = app->id; 906 break; 907 } 908 } 909 mutex_unlock(&of_mutex); 910 911 return id; 912} 913 914int of_alias_get_highest_id(const char *stem) 915{ 916 struct alias_prop *app; 917 int id = -1; 918 919 mutex_lock(&of_mutex); 920 list_for_each_entry(app, &aliases_lookup, link) { 921 if (strcmp(app->stem, stem) != 0) 922 continue; 923 924 if (app->id > id) 925 id = app->id; 926 } 927 mutex_unlock(&of_mutex); 928 929 return id; 930} 931 932struct device_node *of_get_stdout(void) 933{ 934 return of_stdout; 935} 936 937int of_write_prop(struct device_node *np, const char *propname, int len, 938 const void *value) 939{ 940 struct property *pp; 941 struct property *pp_last = NULL; 942 struct property *new; 943 944 if (!np) 945 return -EINVAL; 946 947 for (pp = np->properties; pp; pp = pp->next) { 948 if (strcmp(pp->name, propname) == 0) { 949 /* Property exists -> change value */ 950 pp->value = (void *)value; 951 pp->length = len; 952 return 0; 953 } 954 pp_last = pp; 955 } 956 957 /* Property does not exist -> append new property */ 958 new = malloc(sizeof(struct property)); 959 if (!new) 960 return -ENOMEM; 961 962 new->name = strdup(propname); 963 if (!new->name) { 964 free(new); 965 return -ENOMEM; 966 } 967 968 new->value = (void *)value; 969 new->length = len; 970 new->next = NULL; 971 972 if (pp_last) 973 pp_last->next = new; 974 else 975 np->properties = new; 976 977 return 0; 978} 979 980int of_add_subnode(struct device_node *parent, const char *name, int len, 981 struct device_node **childp) 982{ 983 struct device_node *child, *new, *last_sibling = NULL; 984 char *new_name, *full_name; 985 int parent_fnl; 986 987 if (len == -1) 988 len = strlen(name); 989 __for_each_child_of_node(parent, child) { 990 /* 991 * make sure we don't use a child called "trevor" when we are 992 * searching for "trev". 993 */ 994 if (!strncmp(child->name, name, len) && strlen(name) == len) { 995 *childp = child; 996 return -EEXIST; 997 } 998 last_sibling = child; 999 } 1000 1001 /* Subnode does not exist -> append new subnode */ 1002 new = calloc(1, sizeof(struct device_node)); 1003 if (!new) 1004 return -ENOMEM; 1005 1006 new_name = memdup(name, len + 1); 1007 if (!new_name) { 1008 free(new); 1009 return -ENOMEM; 1010 } 1011 new_name[len] = '\0'; 1012 1013 /* 1014 * if the parent is the root node (named "") we don't need to prepend 1015 * its full path 1016 */ 1017 parent_fnl = *parent->name ? strlen(parent->full_name) : 0; 1018 full_name = calloc(1, parent_fnl + 1 + len + 1); 1019 if (!full_name) { 1020 free(new_name); 1021 free(new); 1022 return -ENOMEM; 1023 } 1024 new->name = new_name; /* assign to constant pointer */ 1025 1026 strcpy(full_name, parent->full_name); /* "" for root node */ 1027 full_name[parent_fnl] = '/'; 1028 strlcpy(&full_name[parent_fnl + 1], name, len + 1); 1029 new->full_name = full_name; 1030 1031 /* Add as last sibling of the parent */ 1032 if (last_sibling) 1033 last_sibling->sibling = new; 1034 if (!parent->child) 1035 parent->child = new; 1036 new->parent = parent; 1037 1038 *childp = new; 1039 1040 return 0; 1041} 1042 1043int __of_remove_property(struct device_node *np, struct property *prop) 1044{ 1045 struct property **next; 1046 1047 for (next = &np->properties; *next; next = &(*next)->next) { 1048 if (*next == prop) 1049 break; 1050 } 1051 if (!*next) 1052 return -ENODEV; 1053 1054 /* found the node */ 1055 *next = prop->next; 1056 1057 return 0; 1058} 1059 1060int of_remove_property(struct device_node *np, struct property *prop) 1061{ 1062 int rc; 1063 1064 mutex_lock(&of_mutex); 1065 1066 rc = __of_remove_property(np, prop); 1067 1068 mutex_unlock(&of_mutex); 1069 1070 return rc; 1071} 1072 1073int of_remove_node(struct device_node *to_remove) 1074{ 1075 struct device_node *parent = to_remove->parent; 1076 struct device_node *np, *prev; 1077 1078 if (!parent) 1079 return -EPERM; 1080 prev = NULL; 1081 __for_each_child_of_node(parent, np) { 1082 if (np == to_remove) 1083 break; 1084 prev = np; 1085 } 1086 if (!np) 1087 return -EFAULT; 1088 1089 /* if there is a previous node, link it to this one's sibling */ 1090 if (prev) 1091 prev->sibling = np->sibling; 1092 else 1093 parent->child = np->sibling; 1094 1095 /* 1096 * don't free it, since if this is an unflattened tree, all the memory 1097 * was alloced in one block; this pointer will be somewhere in the 1098 * middle of that 1099 * 1100 * TODO(sjg@chromium.org): Consider marking nodes as 'allocated'? 1101 * 1102 * free(np); 1103 */ 1104 1105 return 0; 1106} 1107