]> git.kernelconcepts.de Git - karo-tx-uboot.git/blob - lib/libfdt/fdt_wip.c
Merge branch 'u-boot-imx/master' into 'u-boot-arm/master'
[karo-tx-uboot.git] / lib / libfdt / fdt_wip.c
1 /*
2  * libfdt - Flat Device Tree manipulation
3  * Copyright (C) 2006 David Gibson, IBM Corporation.
4  * SPDX-License-Identifier:     GPL-2.0+ BSD-2-Clause
5  */
6 #include "libfdt_env.h"
7
8 #ifndef USE_HOSTCC
9 #include <fdt.h>
10 #include <libfdt.h>
11 #else
12 #include "fdt_host.h"
13 #endif
14
15 #include "libfdt_internal.h"
16
17 int fdt_setprop_inplace(void *fdt, int nodeoffset, const char *name,
18                         const void *val, int len)
19 {
20         void *propval;
21         int proplen;
22
23         propval = fdt_getprop_w(fdt, nodeoffset, name, &proplen);
24         if (! propval)
25                 return proplen;
26
27         if (proplen != len)
28                 return -FDT_ERR_NOSPACE;
29
30         memcpy(propval, val, len);
31         return 0;
32 }
33
34 static void _fdt_nop_region(void *start, int len)
35 {
36         fdt32_t *p;
37
38         for (p = start; (char *)p < ((char *)start + len); p++)
39                 *p = cpu_to_fdt32(FDT_NOP);
40 }
41
42 int fdt_nop_property(void *fdt, int nodeoffset, const char *name)
43 {
44         struct fdt_property *prop;
45         int len;
46
47         prop = fdt_get_property_w(fdt, nodeoffset, name, &len);
48         if (! prop)
49                 return len;
50
51         _fdt_nop_region(prop, len + sizeof(*prop));
52
53         return 0;
54 }
55
56 int _fdt_node_end_offset(void *fdt, int offset)
57 {
58         int depth = 0;
59
60         while ((offset >= 0) && (depth >= 0))
61                 offset = fdt_next_node(fdt, offset, &depth);
62
63         return offset;
64 }
65
66 int fdt_nop_node(void *fdt, int nodeoffset)
67 {
68         int endoffset;
69
70         endoffset = _fdt_node_end_offset(fdt, nodeoffset);
71         if (endoffset < 0)
72                 return endoffset;
73
74         _fdt_nop_region(fdt_offset_ptr_w(fdt, nodeoffset, 0),
75                         endoffset - nodeoffset);
76         return 0;
77 }
78
79 #define FDT_MAX_DEPTH   32
80
81 static int str_in_list(const char *str, char * const list[], int count)
82 {
83         int i;
84
85         for (i = 0; i < count; i++)
86                 if (!strcmp(list[i], str))
87                         return 1;
88
89         return 0;
90 }
91
92 int fdt_find_regions(const void *fdt, char * const inc[], int inc_count,
93                      char * const exc_prop[], int exc_prop_count,
94                      struct fdt_region region[], int max_regions,
95                      char *path, int path_len, int add_string_tab)
96 {
97         int stack[FDT_MAX_DEPTH];
98         char *end;
99         int nextoffset = 0;
100         uint32_t tag;
101         int count = 0;
102         int start = -1;
103         int depth = -1;
104         int want = 0;
105         int base = fdt_off_dt_struct(fdt);
106
107         end = path;
108         *end = '\0';
109         do {
110                 const struct fdt_property *prop;
111                 const char *name;
112                 const char *str;
113                 int include = 0;
114                 int stop_at = 0;
115                 int offset;
116                 int len;
117
118                 offset = nextoffset;
119                 tag = fdt_next_tag(fdt, offset, &nextoffset);
120                 stop_at = nextoffset;
121
122                 switch (tag) {
123                 case FDT_PROP:
124                         include = want >= 2;
125                         stop_at = offset;
126                         prop = fdt_get_property_by_offset(fdt, offset, NULL);
127                         str = fdt_string(fdt, fdt32_to_cpu(prop->nameoff));
128                         if (str_in_list(str, exc_prop, exc_prop_count))
129                                 include = 0;
130                         break;
131
132                 case FDT_NOP:
133                         include = want >= 2;
134                         stop_at = offset;
135                         break;
136
137                 case FDT_BEGIN_NODE:
138                         depth++;
139                         if (depth == FDT_MAX_DEPTH)
140                                 return -FDT_ERR_BADSTRUCTURE;
141                         name = fdt_get_name(fdt, offset, &len);
142                         if (end - path + 2 + len >= path_len)
143                                 return -FDT_ERR_NOSPACE;
144                         if (end != path + 1)
145                                 *end++ = '/';
146                         strcpy(end, name);
147                         end += len;
148                         stack[depth] = want;
149                         if (want == 1)
150                                 stop_at = offset;
151                         if (str_in_list(path, inc, inc_count))
152                                 want = 2;
153                         else if (want)
154                                 want--;
155                         else
156                                 stop_at = offset;
157                         include = want;
158                         break;
159
160                 case FDT_END_NODE:
161                         include = want;
162                         want = stack[depth--];
163                         while (end > path && *--end != '/')
164                                 ;
165                         *end = '\0';
166                         break;
167
168                 case FDT_END:
169                         include = 1;
170                         break;
171                 }
172
173                 if (include && start == -1) {
174                         /* Should we merge with previous? */
175                         if (count && count <= max_regions &&
176                             offset == region[count - 1].offset +
177                                         region[count - 1].size - base)
178                                 start = region[--count].offset - base;
179                         else
180                                 start = offset;
181                 }
182
183                 if (!include && start != -1) {
184                         if (count < max_regions) {
185                                 region[count].offset = base + start;
186                                 region[count].size = stop_at - start;
187                         }
188                         count++;
189                         start = -1;
190                 }
191         } while (tag != FDT_END);
192
193         if (nextoffset != fdt_size_dt_struct(fdt))
194                 return -FDT_ERR_BADLAYOUT;
195
196         /* Add a region for the END tag and the string table */
197         if (count < max_regions) {
198                 region[count].offset = base + start;
199                 region[count].size = nextoffset - start;
200                 if (add_string_tab)
201                         region[count].size += fdt_size_dt_strings(fdt);
202         }
203         count++;
204
205         return count;
206 }