of_access.c 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877
  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. #include <common.h>
  22. #include <malloc.h>
  23. #include <linux/libfdt.h>
  24. #include <dm/of_access.h>
  25. #include <linux/ctype.h>
  26. #include <linux/err.h>
  27. #include <linux/ioport.h>
  28. DECLARE_GLOBAL_DATA_PTR;
  29. /* list of struct alias_prop aliases */
  30. LIST_HEAD(aliases_lookup);
  31. /* "/aliaes" node */
  32. static struct device_node *of_aliases;
  33. /* "/chosen" node */
  34. static struct device_node *of_chosen;
  35. /* node pointed to by the stdout-path alias */
  36. static struct device_node *of_stdout;
  37. /* pointer to options given after the alias (separated by :) or NULL if none */
  38. static const char *of_stdout_options;
  39. /**
  40. * struct alias_prop - Alias property in 'aliases' node
  41. *
  42. * The structure represents one alias property of 'aliases' node as
  43. * an entry in aliases_lookup list.
  44. *
  45. * @link: List node to link the structure in aliases_lookup list
  46. * @alias: Alias property name
  47. * @np: Pointer to device_node that the alias stands for
  48. * @id: Index value from end of alias name
  49. * @stem: Alias string without the index
  50. */
  51. struct alias_prop {
  52. struct list_head link;
  53. const char *alias;
  54. struct device_node *np;
  55. int id;
  56. char stem[0];
  57. };
  58. int of_n_addr_cells(const struct device_node *np)
  59. {
  60. const __be32 *ip;
  61. do {
  62. if (np->parent)
  63. np = np->parent;
  64. ip = of_get_property(np, "#address-cells", NULL);
  65. if (ip)
  66. return be32_to_cpup(ip);
  67. } while (np->parent);
  68. /* No #address-cells property for the root node */
  69. return OF_ROOT_NODE_ADDR_CELLS_DEFAULT;
  70. }
  71. int of_n_size_cells(const struct device_node *np)
  72. {
  73. const __be32 *ip;
  74. do {
  75. if (np->parent)
  76. np = np->parent;
  77. ip = of_get_property(np, "#size-cells", NULL);
  78. if (ip)
  79. return be32_to_cpup(ip);
  80. } while (np->parent);
  81. /* No #size-cells property for the root node */
  82. return OF_ROOT_NODE_SIZE_CELLS_DEFAULT;
  83. }
  84. int of_simple_addr_cells(const struct device_node *np)
  85. {
  86. const __be32 *ip;
  87. ip = of_get_property(np, "#address-cells", NULL);
  88. if (ip)
  89. return be32_to_cpup(ip);
  90. /* Return a default of 2 to match fdt_address_cells()*/
  91. return 2;
  92. }
  93. int of_simple_size_cells(const struct device_node *np)
  94. {
  95. const __be32 *ip;
  96. ip = of_get_property(np, "#size-cells", NULL);
  97. if (ip)
  98. return be32_to_cpup(ip);
  99. /* Return a default of 2 to match fdt_size_cells()*/
  100. return 2;
  101. }
  102. struct property *of_find_property(const struct device_node *np,
  103. const char *name, int *lenp)
  104. {
  105. struct property *pp;
  106. if (!np)
  107. return NULL;
  108. for (pp = np->properties; pp; pp = pp->next) {
  109. if (strcmp(pp->name, name) == 0) {
  110. if (lenp)
  111. *lenp = pp->length;
  112. break;
  113. }
  114. }
  115. if (!pp && lenp)
  116. *lenp = -FDT_ERR_NOTFOUND;
  117. return pp;
  118. }
  119. struct device_node *of_find_all_nodes(struct device_node *prev)
  120. {
  121. struct device_node *np;
  122. if (!prev) {
  123. np = gd->of_root;
  124. } else if (prev->child) {
  125. np = prev->child;
  126. } else {
  127. /*
  128. * Walk back up looking for a sibling, or the end of the
  129. * structure
  130. */
  131. np = prev;
  132. while (np->parent && !np->sibling)
  133. np = np->parent;
  134. np = np->sibling; /* Might be null at the end of the tree */
  135. }
  136. return np;
  137. }
  138. const void *of_get_property(const struct device_node *np, const char *name,
  139. int *lenp)
  140. {
  141. struct property *pp = of_find_property(np, name, lenp);
  142. return pp ? pp->value : NULL;
  143. }
  144. const struct property *of_get_first_property(const struct device_node *np)
  145. {
  146. if (!np)
  147. return NULL;
  148. return np->properties;
  149. }
  150. const struct property *of_get_next_property(const struct device_node *np,
  151. const struct property *property)
  152. {
  153. if (!np)
  154. return NULL;
  155. return property->next;
  156. }
  157. const void *of_get_property_by_prop(const struct device_node *np,
  158. const struct property *property,
  159. const char **name,
  160. int *lenp)
  161. {
  162. if (!np || !property)
  163. return NULL;
  164. if (name)
  165. *name = property->name;
  166. if (lenp)
  167. *lenp = property->length;
  168. return property->value;
  169. }
  170. static const char *of_prop_next_string(struct property *prop, const char *cur)
  171. {
  172. const void *curv = cur;
  173. if (!prop)
  174. return NULL;
  175. if (!cur)
  176. return prop->value;
  177. curv += strlen(cur) + 1;
  178. if (curv >= prop->value + prop->length)
  179. return NULL;
  180. return curv;
  181. }
  182. int of_device_is_compatible(const struct device_node *device,
  183. const char *compat, const char *type,
  184. const char *name)
  185. {
  186. struct property *prop;
  187. const char *cp;
  188. int index = 0, score = 0;
  189. /* Compatible match has highest priority */
  190. if (compat && compat[0]) {
  191. prop = of_find_property(device, "compatible", NULL);
  192. for (cp = of_prop_next_string(prop, NULL); cp;
  193. cp = of_prop_next_string(prop, cp), index++) {
  194. if (of_compat_cmp(cp, compat, strlen(compat)) == 0) {
  195. score = INT_MAX/2 - (index << 2);
  196. break;
  197. }
  198. }
  199. if (!score)
  200. return 0;
  201. }
  202. /* Matching type is better than matching name */
  203. if (type && type[0]) {
  204. if (!device->type || of_node_cmp(type, device->type))
  205. return 0;
  206. score += 2;
  207. }
  208. /* Matching name is a bit better than not */
  209. if (name && name[0]) {
  210. if (!device->name || of_node_cmp(name, device->name))
  211. return 0;
  212. score++;
  213. }
  214. return score;
  215. }
  216. bool of_device_is_available(const struct device_node *device)
  217. {
  218. const char *status;
  219. int statlen;
  220. if (!device)
  221. return false;
  222. status = of_get_property(device, "status", &statlen);
  223. if (status == NULL)
  224. return true;
  225. if (statlen > 0) {
  226. if (!strcmp(status, "okay"))
  227. return true;
  228. }
  229. return false;
  230. }
  231. struct device_node *of_get_parent(const struct device_node *node)
  232. {
  233. const struct device_node *np;
  234. if (!node)
  235. return NULL;
  236. np = of_node_get(node->parent);
  237. return (struct device_node *)np;
  238. }
  239. static struct device_node *__of_get_next_child(const struct device_node *node,
  240. struct device_node *prev)
  241. {
  242. struct device_node *next;
  243. if (!node)
  244. return NULL;
  245. next = prev ? prev->sibling : node->child;
  246. /*
  247. * coverity[dead_error_line : FALSE]
  248. * Dead code here since our current implementation of of_node_get()
  249. * always returns NULL (Coverity CID 163245). But we leave it as is
  250. * since we may want to implement get/put later.
  251. */
  252. for (; next; next = next->sibling)
  253. if (of_node_get(next))
  254. break;
  255. of_node_put(prev);
  256. return next;
  257. }
  258. #define __for_each_child_of_node(parent, child) \
  259. for (child = __of_get_next_child(parent, NULL); child != NULL; \
  260. child = __of_get_next_child(parent, child))
  261. static struct device_node *__of_find_node_by_path(struct device_node *parent,
  262. const char *path)
  263. {
  264. struct device_node *child;
  265. int len;
  266. len = strcspn(path, "/:");
  267. if (!len)
  268. return NULL;
  269. __for_each_child_of_node(parent, child) {
  270. const char *name = strrchr(child->full_name, '/');
  271. name++;
  272. if (strncmp(path, name, len) == 0 && (strlen(name) == len))
  273. return child;
  274. }
  275. return NULL;
  276. }
  277. #define for_each_property_of_node(dn, pp) \
  278. for (pp = dn->properties; pp != NULL; pp = pp->next)
  279. struct device_node *of_find_node_opts_by_path(const char *path,
  280. const char **opts)
  281. {
  282. struct device_node *np = NULL;
  283. struct property *pp;
  284. const char *separator = strchr(path, ':');
  285. if (opts)
  286. *opts = separator ? separator + 1 : NULL;
  287. if (strcmp(path, "/") == 0)
  288. return of_node_get(gd->of_root);
  289. /* The path could begin with an alias */
  290. if (*path != '/') {
  291. int len;
  292. const char *p = separator;
  293. if (!p)
  294. p = strchrnul(path, '/');
  295. len = p - path;
  296. /* of_aliases must not be NULL */
  297. if (!of_aliases)
  298. return NULL;
  299. for_each_property_of_node(of_aliases, pp) {
  300. if (strlen(pp->name) == len && !strncmp(pp->name, path,
  301. len)) {
  302. np = of_find_node_by_path(pp->value);
  303. break;
  304. }
  305. }
  306. if (!np)
  307. return NULL;
  308. path = p;
  309. }
  310. /* Step down the tree matching path components */
  311. if (!np)
  312. np = of_node_get(gd->of_root);
  313. while (np && *path == '/') {
  314. struct device_node *tmp = np;
  315. path++; /* Increment past '/' delimiter */
  316. np = __of_find_node_by_path(np, path);
  317. of_node_put(tmp);
  318. path = strchrnul(path, '/');
  319. if (separator && separator < path)
  320. break;
  321. }
  322. return np;
  323. }
  324. struct device_node *of_find_compatible_node(struct device_node *from,
  325. const char *type, const char *compatible)
  326. {
  327. struct device_node *np;
  328. for_each_of_allnodes_from(from, np)
  329. if (of_device_is_compatible(np, compatible, type, NULL) &&
  330. of_node_get(np))
  331. break;
  332. of_node_put(from);
  333. return np;
  334. }
  335. static int of_device_has_prop_value(const struct device_node *device,
  336. const char *propname, const void *propval,
  337. int proplen)
  338. {
  339. struct property *prop = of_find_property(device, propname, NULL);
  340. if (!prop || !prop->value || prop->length != proplen)
  341. return 0;
  342. return !memcmp(prop->value, propval, proplen);
  343. }
  344. struct device_node *of_find_node_by_prop_value(struct device_node *from,
  345. const char *propname,
  346. const void *propval, int proplen)
  347. {
  348. struct device_node *np;
  349. for_each_of_allnodes_from(from, np) {
  350. if (of_device_has_prop_value(np, propname, propval, proplen) &&
  351. of_node_get(np))
  352. break;
  353. }
  354. of_node_put(from);
  355. return np;
  356. }
  357. struct device_node *of_find_node_by_phandle(phandle handle)
  358. {
  359. struct device_node *np;
  360. if (!handle)
  361. return NULL;
  362. for_each_of_allnodes(np)
  363. if (np->phandle == handle)
  364. break;
  365. (void)of_node_get(np);
  366. return np;
  367. }
  368. /**
  369. * of_find_property_value_of_size() - find property of given size
  370. *
  371. * Search for a property in a device node and validate the requested size.
  372. *
  373. * @np: device node from which the property value is to be read.
  374. * @propname: name of the property to be searched.
  375. * @len: requested length of property value
  376. *
  377. * @return the property value on success, -EINVAL if the property does not
  378. * exist, -ENODATA if property does not have a value, and -EOVERFLOW if the
  379. * property data isn't large enough.
  380. */
  381. static void *of_find_property_value_of_size(const struct device_node *np,
  382. const char *propname, u32 len)
  383. {
  384. struct property *prop = of_find_property(np, propname, NULL);
  385. if (!prop)
  386. return ERR_PTR(-EINVAL);
  387. if (!prop->value)
  388. return ERR_PTR(-ENODATA);
  389. if (len > prop->length)
  390. return ERR_PTR(-EOVERFLOW);
  391. return prop->value;
  392. }
  393. int of_read_u32(const struct device_node *np, const char *propname, u32 *outp)
  394. {
  395. return of_read_u32_index(np, propname, 0, outp);
  396. }
  397. int of_read_u32_array(const struct device_node *np, const char *propname,
  398. u32 *out_values, size_t sz)
  399. {
  400. const __be32 *val;
  401. debug("%s: %s: ", __func__, propname);
  402. val = of_find_property_value_of_size(np, propname,
  403. sz * sizeof(*out_values));
  404. if (IS_ERR(val))
  405. return PTR_ERR(val);
  406. debug("size %zd\n", sz);
  407. while (sz--)
  408. *out_values++ = be32_to_cpup(val++);
  409. return 0;
  410. }
  411. int of_read_u32_index(const struct device_node *np, const char *propname,
  412. int index, u32 *outp)
  413. {
  414. const __be32 *val;
  415. debug("%s: %s: ", __func__, propname);
  416. if (!np)
  417. return -EINVAL;
  418. val = of_find_property_value_of_size(np, propname,
  419. sizeof(*outp) * (index + 1));
  420. if (IS_ERR(val)) {
  421. debug("(not found)\n");
  422. return PTR_ERR(val);
  423. }
  424. *outp = be32_to_cpup(val + index);
  425. debug("%#x (%d)\n", *outp, *outp);
  426. return 0;
  427. }
  428. int of_read_u64(const struct device_node *np, const char *propname, u64 *outp)
  429. {
  430. const __be64 *val;
  431. debug("%s: %s: ", __func__, propname);
  432. if (!np)
  433. return -EINVAL;
  434. val = of_find_property_value_of_size(np, propname, sizeof(*outp));
  435. if (IS_ERR(val)) {
  436. debug("(not found)\n");
  437. return PTR_ERR(val);
  438. }
  439. *outp = be64_to_cpup(val);
  440. debug("%#llx (%lld)\n", (unsigned long long)*outp,
  441. (unsigned long long)*outp);
  442. return 0;
  443. }
  444. int of_property_match_string(const struct device_node *np, const char *propname,
  445. const char *string)
  446. {
  447. const struct property *prop = of_find_property(np, propname, NULL);
  448. size_t l;
  449. int i;
  450. const char *p, *end;
  451. if (!prop)
  452. return -EINVAL;
  453. if (!prop->value)
  454. return -ENODATA;
  455. p = prop->value;
  456. end = p + prop->length;
  457. for (i = 0; p < end; i++, p += l) {
  458. l = strnlen(p, end - p) + 1;
  459. if (p + l > end)
  460. return -EILSEQ;
  461. debug("comparing %s with %s\n", string, p);
  462. if (strcmp(string, p) == 0)
  463. return i; /* Found it; return index */
  464. }
  465. return -ENODATA;
  466. }
  467. /**
  468. * of_property_read_string_helper() - Utility helper for parsing string properties
  469. * @np: device node from which the property value is to be read.
  470. * @propname: name of the property to be searched.
  471. * @out_strs: output array of string pointers.
  472. * @sz: number of array elements to read.
  473. * @skip: Number of strings to skip over at beginning of list.
  474. *
  475. * Don't call this function directly. It is a utility helper for the
  476. * of_property_read_string*() family of functions.
  477. */
  478. int of_property_read_string_helper(const struct device_node *np,
  479. const char *propname, const char **out_strs,
  480. size_t sz, int skip)
  481. {
  482. const struct property *prop = of_find_property(np, propname, NULL);
  483. int l = 0, i = 0;
  484. const char *p, *end;
  485. if (!prop)
  486. return -EINVAL;
  487. if (!prop->value)
  488. return -ENODATA;
  489. p = prop->value;
  490. end = p + prop->length;
  491. for (i = 0; p < end && (!out_strs || i < skip + sz); i++, p += l) {
  492. l = strnlen(p, end - p) + 1;
  493. if (p + l > end)
  494. return -EILSEQ;
  495. if (out_strs && i >= skip)
  496. *out_strs++ = p;
  497. }
  498. i -= skip;
  499. return i <= 0 ? -ENODATA : i;
  500. }
  501. static int __of_parse_phandle_with_args(const struct device_node *np,
  502. const char *list_name,
  503. const char *cells_name,
  504. int cell_count, int index,
  505. struct of_phandle_args *out_args)
  506. {
  507. const __be32 *list, *list_end;
  508. int rc = 0, cur_index = 0;
  509. uint32_t count;
  510. struct device_node *node = NULL;
  511. phandle phandle;
  512. int size;
  513. /* Retrieve the phandle list property */
  514. list = of_get_property(np, list_name, &size);
  515. if (!list)
  516. return -ENOENT;
  517. list_end = list + size / sizeof(*list);
  518. /* Loop over the phandles until all the requested entry is found */
  519. while (list < list_end) {
  520. rc = -EINVAL;
  521. count = 0;
  522. /*
  523. * If phandle is 0, then it is an empty entry with no
  524. * arguments. Skip forward to the next entry.
  525. */
  526. phandle = be32_to_cpup(list++);
  527. if (phandle) {
  528. /*
  529. * Find the provider node and parse the #*-cells
  530. * property to determine the argument length.
  531. *
  532. * This is not needed if the cell count is hard-coded
  533. * (i.e. cells_name not set, but cell_count is set),
  534. * except when we're going to return the found node
  535. * below.
  536. */
  537. if (cells_name || cur_index == index) {
  538. node = of_find_node_by_phandle(phandle);
  539. if (!node) {
  540. debug("%s: could not find phandle\n",
  541. np->full_name);
  542. goto err;
  543. }
  544. }
  545. if (cells_name) {
  546. if (of_read_u32(node, cells_name, &count)) {
  547. debug("%s: could not get %s for %s\n",
  548. np->full_name, cells_name,
  549. node->full_name);
  550. goto err;
  551. }
  552. } else {
  553. count = cell_count;
  554. }
  555. /*
  556. * Make sure that the arguments actually fit in the
  557. * remaining property data length
  558. */
  559. if (list + count > list_end) {
  560. debug("%s: arguments longer than property\n",
  561. np->full_name);
  562. goto err;
  563. }
  564. }
  565. /*
  566. * All of the error cases above bail out of the loop, so at
  567. * this point, the parsing is successful. If the requested
  568. * index matches, then fill the out_args structure and return,
  569. * or return -ENOENT for an empty entry.
  570. */
  571. rc = -ENOENT;
  572. if (cur_index == index) {
  573. if (!phandle)
  574. goto err;
  575. if (out_args) {
  576. int i;
  577. if (WARN_ON(count > OF_MAX_PHANDLE_ARGS))
  578. count = OF_MAX_PHANDLE_ARGS;
  579. out_args->np = node;
  580. out_args->args_count = count;
  581. for (i = 0; i < count; i++)
  582. out_args->args[i] =
  583. be32_to_cpup(list++);
  584. } else {
  585. of_node_put(node);
  586. }
  587. /* Found it! return success */
  588. return 0;
  589. }
  590. of_node_put(node);
  591. node = NULL;
  592. list += count;
  593. cur_index++;
  594. }
  595. /*
  596. * Unlock node before returning result; will be one of:
  597. * -ENOENT : index is for empty phandle
  598. * -EINVAL : parsing error on data
  599. * [1..n] : Number of phandle (count mode; when index = -1)
  600. */
  601. rc = index < 0 ? cur_index : -ENOENT;
  602. err:
  603. if (node)
  604. of_node_put(node);
  605. return rc;
  606. }
  607. struct device_node *of_parse_phandle(const struct device_node *np,
  608. const char *phandle_name, int index)
  609. {
  610. struct of_phandle_args args;
  611. if (index < 0)
  612. return NULL;
  613. if (__of_parse_phandle_with_args(np, phandle_name, NULL, 0, index,
  614. &args))
  615. return NULL;
  616. return args.np;
  617. }
  618. int of_parse_phandle_with_args(const struct device_node *np,
  619. const char *list_name, const char *cells_name,
  620. int index, struct of_phandle_args *out_args)
  621. {
  622. if (index < 0)
  623. return -EINVAL;
  624. return __of_parse_phandle_with_args(np, list_name, cells_name, 0,
  625. index, out_args);
  626. }
  627. int of_count_phandle_with_args(const struct device_node *np,
  628. const char *list_name, const char *cells_name)
  629. {
  630. return __of_parse_phandle_with_args(np, list_name, cells_name, 0,
  631. -1, NULL);
  632. }
  633. static void of_alias_add(struct alias_prop *ap, struct device_node *np,
  634. int id, const char *stem, int stem_len)
  635. {
  636. ap->np = np;
  637. ap->id = id;
  638. strncpy(ap->stem, stem, stem_len);
  639. ap->stem[stem_len] = 0;
  640. list_add_tail(&ap->link, &aliases_lookup);
  641. debug("adding DT alias:%s: stem=%s id=%i node=%s\n",
  642. ap->alias, ap->stem, ap->id, of_node_full_name(np));
  643. }
  644. int of_alias_scan(void)
  645. {
  646. struct property *pp;
  647. of_aliases = of_find_node_by_path("/aliases");
  648. of_chosen = of_find_node_by_path("/chosen");
  649. if (of_chosen == NULL)
  650. of_chosen = of_find_node_by_path("/chosen@0");
  651. if (of_chosen) {
  652. const char *name;
  653. name = of_get_property(of_chosen, "stdout-path", NULL);
  654. if (name)
  655. of_stdout = of_find_node_opts_by_path(name,
  656. &of_stdout_options);
  657. }
  658. if (!of_aliases)
  659. return 0;
  660. for_each_property_of_node(of_aliases, pp) {
  661. const char *start = pp->name;
  662. const char *end = start + strlen(start);
  663. struct device_node *np;
  664. struct alias_prop *ap;
  665. ulong id;
  666. int len;
  667. /* Skip those we do not want to proceed */
  668. if (!strcmp(pp->name, "name") ||
  669. !strcmp(pp->name, "phandle") ||
  670. !strcmp(pp->name, "linux,phandle"))
  671. continue;
  672. np = of_find_node_by_path(pp->value);
  673. if (!np)
  674. continue;
  675. /*
  676. * walk the alias backwards to extract the id and work out
  677. * the 'stem' string
  678. */
  679. while (isdigit(*(end-1)) && end > start)
  680. end--;
  681. len = end - start;
  682. if (strict_strtoul(end, 10, &id) < 0)
  683. continue;
  684. /* Allocate an alias_prop with enough space for the stem */
  685. ap = malloc(sizeof(*ap) + len + 1);
  686. if (!ap)
  687. return -ENOMEM;
  688. memset(ap, 0, sizeof(*ap) + len + 1);
  689. ap->alias = start;
  690. of_alias_add(ap, np, id, start, len);
  691. }
  692. return 0;
  693. }
  694. int of_alias_get_id(const struct device_node *np, const char *stem)
  695. {
  696. struct alias_prop *app;
  697. int id = -ENODEV;
  698. mutex_lock(&of_mutex);
  699. list_for_each_entry(app, &aliases_lookup, link) {
  700. if (strcmp(app->stem, stem) != 0)
  701. continue;
  702. if (np == app->np) {
  703. id = app->id;
  704. break;
  705. }
  706. }
  707. mutex_unlock(&of_mutex);
  708. return id;
  709. }
  710. int of_alias_get_highest_id(const char *stem)
  711. {
  712. struct alias_prop *app;
  713. int id = -1;
  714. mutex_lock(&of_mutex);
  715. list_for_each_entry(app, &aliases_lookup, link) {
  716. if (strcmp(app->stem, stem) != 0)
  717. continue;
  718. if (app->id > id)
  719. id = app->id;
  720. }
  721. mutex_unlock(&of_mutex);
  722. return id;
  723. }
  724. struct device_node *of_get_stdout(void)
  725. {
  726. return of_stdout;
  727. }