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