blob: 41f2e09b9c276f617274d66dca4ae3d7b74a2bc1 [file] [log] [blame]
Tom Rini10e47792018-05-06 17:58:06 -04001// SPDX-License-Identifier: GPL-2.0+
Simon Glass1ccaa052017-05-18 20:08:54 -06002/*
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.
Simon Glass1ccaa052017-05-18 20:08:54 -060020 */
21
Simon Glass0f2af882020-05-10 11:40:05 -060022#include <log.h>
Simon Glass9bc15642020-02-03 07:36:16 -070023#include <malloc.h>
Simon Glass3ba929a2020-10-30 21:38:53 -060024#include <asm/global_data.h>
Simon Glassc06c1be2020-05-10 11:40:08 -060025#include <linux/bug.h>
Masahiro Yamada75f82d02018-03-05 01:20:11 +090026#include <linux/libfdt.h>
Simon Glass1ccaa052017-05-18 20:08:54 -060027#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 */
Bin Meng40e0b8a2023-04-05 22:37:55 +080035static LIST_HEAD(aliases_lookup);
Simon Glass1ccaa052017-05-18 20:08:54 -060036
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
Simon Glass4191dc12017-06-12 06:21:31 -0600101int 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
Simon Glass1ccaa052017-05-18 20:08:54 -0600125struct 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
Patrick Delaunaycaee1552020-01-13 11:34:56 +0100176const 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
Simon Glass1ccaa052017-05-18 20:08:54 -0600208static 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;
Simon Glass3694ac52017-06-07 10:28:45 -0600305 /*
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 */
Simon Glass1ccaa052017-05-18 20:08:54 -0600311 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
Simon Glassef75c592022-07-30 15:52:08 -0600345struct device_node *of_find_node_opts_by_path(struct device_node *root,
346 const char *path,
Simon Glass1ccaa052017-05-18 20:08:54 -0600347 const char **opts)
348{
349 struct device_node *np = NULL;
350 struct property *pp;
351 const char *separator = strchr(path, ':');
352
Simon Glassef75c592022-07-30 15:52:08 -0600353 if (!root)
354 root = gd->of_root;
Simon Glass1ccaa052017-05-18 20:08:54 -0600355 if (opts)
356 *opts = separator ? separator + 1 : NULL;
357
358 if (strcmp(path, "/") == 0)
Simon Glassef75c592022-07-30 15:52:08 -0600359 return of_node_get(root);
Simon Glass1ccaa052017-05-18 20:08:54 -0600360
361 /* The path could begin with an alias */
362 if (*path != '/') {
363 int len;
364 const char *p = separator;
365
Simon Glassef75c592022-07-30 15:52:08 -0600366 /* Only allow alias processing on the control FDT */
367 if (root != gd->of_root)
368 return NULL;
Simon Glass1ccaa052017-05-18 20:08:54 -0600369 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)
Simon Glassef75c592022-07-30 15:52:08 -0600391 np = of_node_get(root);
Simon Glass1ccaa052017-05-18 20:08:54 -0600392 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
Jens Wiklander7b68dad2018-08-20 11:09:58 +0200420static 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
Simon Glass176dd432022-09-06 20:26:57 -0600447struct device_node *of_find_node_by_phandle(struct device_node *root,
448 phandle handle)
Simon Glass1ccaa052017-05-18 20:08:54 -0600449{
450 struct device_node *np;
451
452 if (!handle)
453 return NULL;
454
Simon Glass176dd432022-09-06 20:26:57 -0600455 for_each_of_allnodes_from(root, np)
Simon Glass1ccaa052017-05-18 20:08:54 -0600456 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 *
Heinrich Schuchardt47b4c022022-01-19 18:05:50 +0100472 * Return: the property value on success, -EINVAL if the property does not
Simon Glasse3be5fc2022-09-06 20:27:18 -0600473 * exist and -EOVERFLOW if the property data isn't large enough.
Simon Glass1ccaa052017-05-18 20:08:54 -0600474 */
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);
Simon Glass1ccaa052017-05-18 20:08:54 -0600482 if (len > prop->length)
483 return ERR_PTR(-EOVERFLOW);
484
485 return prop->value;
486}
487
Stefan Herbrechtsmeier1b090e62022-06-14 15:21:30 +0200488int 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
Simon Glass1ccaa052017-05-18 20:08:54 -0600526int of_read_u32(const struct device_node *np, const char *propname, u32 *outp)
527{
Dario Binacchib3f1cdd2020-03-29 18:04:42 +0200528 return of_read_u32_index(np, propname, 0, outp);
Simon Glass1ccaa052017-05-18 20:08:54 -0600529}
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
Dario Binacchi81d80b52020-03-29 18:04:41 +0200550int 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
Michal Simek08a194e2023-08-25 11:37:46 +0200572int of_read_u64_index(const struct device_node *np, const char *propname,
573 int index, u64 *outp)
Simon Glass9d54a7a2018-06-11 13:07:10 -0600574{
575 const __be64 *val;
576
577 debug("%s: %s: ", __func__, propname);
578 if (!np)
579 return -EINVAL;
Michal Simek08a194e2023-08-25 11:37:46 +0200580
581 val = of_find_property_value_of_size(np, propname,
582 sizeof(*outp) * (index + 1));
Simon Glass9d54a7a2018-06-11 13:07:10 -0600583 if (IS_ERR(val)) {
584 debug("(not found)\n");
585 return PTR_ERR(val);
586 }
587
Michal Simek08a194e2023-08-25 11:37:46 +0200588 *outp = be64_to_cpup(val + index);
Simon Glass9d54a7a2018-06-11 13:07:10 -0600589 debug("%#llx (%lld)\n", (unsigned long long)*outp,
Michal Simek08a194e2023-08-25 11:37:46 +0200590 (unsigned long long)*outp);
Simon Glass9d54a7a2018-06-11 13:07:10 -0600591
592 return 0;
593}
594
Michal Simek08a194e2023-08-25 11:37:46 +0200595int 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
Simon Glass1ccaa052017-05-18 20:08:54 -0600600int of_property_match_string(const struct device_node *np, const char *propname,
601 const char *string)
602{
Eugen Hristev5d773d52023-05-04 15:22:21 +0300603 int len = 0;
604 const struct property *prop = of_find_property(np, propname, &len);
Simon Glass1ccaa052017-05-18 20:08:54 -0600605 size_t l;
606 int i;
607 const char *p, *end;
608
Eugen Hristev5d773d52023-05-04 15:22:21 +0300609 if (!prop && len == -FDT_ERR_NOTFOUND)
610 return -ENOENT;
Simon Glass1ccaa052017-05-18 20:08:54 -0600611 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.
Simon Glass7a3a1672021-10-23 17:26:06 -0600636 * @skip: Number of strings to skip over at beginning of list (cannot be
637 * negative)
Simon Glass1ccaa052017-05-18 20:08:54 -0600638 *
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;
Heinrich Schuchardtc13346e2020-02-15 21:46:04 +0100676 uint32_t count;
Simon Glass1ccaa052017-05-18 20:08:54 -0600677 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) {
Simon Glass176dd432022-09-06 20:26:57 -0600708 node = of_find_node_by_phandle(NULL, phandle);
Simon Glass1ccaa052017-05-18 20:08:54 -0600709 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,
Patrick Delaunay21e3b042020-09-10 18:26:17 +0200802 int cell_count, int index,
803 struct of_phandle_args *out_args)
Simon Glass1ccaa052017-05-18 20:08:54 -0600804{
805 if (index < 0)
806 return -EINVAL;
807
Patrick Delaunay21e3b042020-09-10 18:26:17 +0200808 return __of_parse_phandle_with_args(np, list_name, cells_name,
809 cell_count, index, out_args);
Simon Glass1ccaa052017-05-18 20:08:54 -0600810}
811
Patrice Chotardbe7dd602017-07-18 11:57:08 +0200812int of_count_phandle_with_args(const struct device_node *np,
Patrick Delaunayd776a842020-09-25 09:41:14 +0200813 const char *list_name, const char *cells_name,
814 int cell_count)
Patrice Chotardbe7dd602017-07-18 11:57:08 +0200815{
Patrick Delaunayd776a842020-09-25 09:41:14 +0200816 return __of_parse_phandle_with_args(np, list_name, cells_name,
817 cell_count, -1, NULL);
Patrice Chotardbe7dd602017-07-18 11:57:08 +0200818}
819
Simon Glass1ccaa052017-05-18 20:08:54 -0600820static 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)
Simon Glassef75c592022-07-30 15:52:08 -0600846 of_stdout = of_find_node_opts_by_path(NULL, name,
Simon Glass1ccaa052017-05-18 20:08:54 -0600847 &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
Michal Simekc6203cb2019-01-31 16:30:57 +0100914int 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
Simon Glass1ccaa052017-05-18 20:08:54 -0600932struct device_node *of_get_stdout(void)
933{
934 return of_stdout;
935}
Simon Glass3ee3d152022-07-30 15:52:13 -0600936
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
Simon Glass3ee3d152022-07-30 15:52:13 -0600957 /* 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
Simon Glass238afb52022-09-06 20:27:03 -0600972 if (pp_last)
973 pp_last->next = new;
974 else
975 np->properties = new;
Simon Glass3ee3d152022-07-30 15:52:13 -0600976
977 return 0;
978}
Simon Glass56bc3322022-09-06 20:27:02 -0600979
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}
Simon Glass45448772023-09-26 08:14:42 -06001042
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}