aboutsummaryrefslogtreecommitdiffstats
path: root/scripts/dtc/libfdt/fdt_ro.c
diff options
context:
space:
mode:
Diffstat (limited to 'scripts/dtc/libfdt/fdt_ro.c')
-rw-r--r--scripts/dtc/libfdt/fdt_ro.c275
1 files changed, 85 insertions, 190 deletions
diff --git a/scripts/dtc/libfdt/fdt_ro.c b/scripts/dtc/libfdt/fdt_ro.c
index 02b6d687537..22e692919ff 100644
--- a/scripts/dtc/libfdt/fdt_ro.c
+++ b/scripts/dtc/libfdt/fdt_ro.c
@@ -80,14 +80,6 @@ const char *fdt_string(const void *fdt, int stroffset)
80 return (const char *)fdt + fdt_off_dt_strings(fdt) + stroffset; 80 return (const char *)fdt + fdt_off_dt_strings(fdt) + stroffset;
81} 81}
82 82
83static int _fdt_string_eq(const void *fdt, int stroffset,
84 const char *s, int len)
85{
86 const char *p = fdt_string(fdt, stroffset);
87
88 return (strlen(p) == len) && (memcmp(p, s, len) == 0);
89}
90
91int fdt_get_mem_rsv(const void *fdt, int n, uint64_t *address, uint64_t *size) 83int fdt_get_mem_rsv(const void *fdt, int n, uint64_t *address, uint64_t *size)
92{ 84{
93 FDT_CHECK_HEADER(fdt); 85 FDT_CHECK_HEADER(fdt);
@@ -105,30 +97,6 @@ int fdt_num_mem_rsv(const void *fdt)
105 return i; 97 return i;
106} 98}
107 99
108static int _nextprop(const void *fdt, int offset)
109{
110 uint32_t tag;
111 int nextoffset;
112
113 do {
114 tag = fdt_next_tag(fdt, offset, &nextoffset);
115
116 switch (tag) {
117 case FDT_END:
118 if (nextoffset >= 0)
119 return -FDT_ERR_BADSTRUCTURE;
120 else
121 return nextoffset;
122
123 case FDT_PROP:
124 return offset;
125 }
126 offset = nextoffset;
127 } while (tag == FDT_NOP);
128
129 return -FDT_ERR_NOTFOUND;
130}
131
132int fdt_subnode_offset_namelen(const void *fdt, int offset, 100int fdt_subnode_offset_namelen(const void *fdt, int offset,
133 const char *name, int namelen) 101 const char *name, int namelen)
134{ 102{
@@ -136,16 +104,20 @@ int fdt_subnode_offset_namelen(const void *fdt, int offset,
136 104
137 FDT_CHECK_HEADER(fdt); 105 FDT_CHECK_HEADER(fdt);
138 106
139 for (depth = 0; 107 for (depth = 0, offset = fdt_next_node(fdt, offset, &depth);
140 (offset >= 0) && (depth >= 0); 108 (offset >= 0) && (depth > 0);
141 offset = fdt_next_node(fdt, offset, &depth)) 109 offset = fdt_next_node(fdt, offset, &depth)) {
142 if ((depth == 1) 110 if (depth < 0)
143 && _fdt_nodename_eq(fdt, offset, name, namelen)) 111 return -FDT_ERR_NOTFOUND;
112 else if ((depth == 1)
113 && _fdt_nodename_eq(fdt, offset, name, namelen))
144 return offset; 114 return offset;
115 }
145 116
146 if (depth < 0) 117 if (offset < 0)
118 return offset; /* error */
119 else
147 return -FDT_ERR_NOTFOUND; 120 return -FDT_ERR_NOTFOUND;
148 return offset; /* error */
149} 121}
150 122
151int fdt_subnode_offset(const void *fdt, int parentoffset, 123int fdt_subnode_offset(const void *fdt, int parentoffset,
@@ -162,20 +134,8 @@ int fdt_path_offset(const void *fdt, const char *path)
162 134
163 FDT_CHECK_HEADER(fdt); 135 FDT_CHECK_HEADER(fdt);
164 136
165 /* see if we have an alias */ 137 if (*path != '/')
166 if (*path != '/') { 138 return -FDT_ERR_BADPATH;
167 const char *q = strchr(path, '/');
168
169 if (!q)
170 q = end;
171
172 p = fdt_get_alias_namelen(fdt, p, q - p);
173 if (!p)
174 return -FDT_ERR_BADPATH;
175 offset = fdt_path_offset(fdt, p);
176
177 p = q;
178 }
179 139
180 while (*p) { 140 while (*p) {
181 const char *q; 141 const char *q;
@@ -218,142 +178,93 @@ const char *fdt_get_name(const void *fdt, int nodeoffset, int *len)
218 return NULL; 178 return NULL;
219} 179}
220 180
221int fdt_first_property_offset(const void *fdt, int nodeoffset) 181const struct fdt_property *fdt_get_property(const void *fdt,
222{ 182 int nodeoffset,
223 int offset; 183 const char *name, int *lenp)
224
225 if ((offset = _fdt_check_node_offset(fdt, nodeoffset)) < 0)
226 return offset;
227
228 return _nextprop(fdt, offset);
229}
230
231int fdt_next_property_offset(const void *fdt, int offset)
232{
233 if ((offset = _fdt_check_prop_offset(fdt, offset)) < 0)
234 return offset;
235
236 return _nextprop(fdt, offset);
237}
238
239const struct fdt_property *fdt_get_property_by_offset(const void *fdt,
240 int offset,
241 int *lenp)
242{ 184{
243 int err; 185 uint32_t tag;
244 const struct fdt_property *prop; 186 const struct fdt_property *prop;
187 int namestroff;
188 int offset, nextoffset;
189 int err;
245 190
246 if ((err = _fdt_check_prop_offset(fdt, offset)) < 0) { 191 if (((err = fdt_check_header(fdt)) != 0)
247 if (lenp) 192 || ((err = _fdt_check_node_offset(fdt, nodeoffset)) < 0))
248 *lenp = err; 193 goto fail;
249 return NULL;
250 }
251
252 prop = _fdt_offset_ptr(fdt, offset);
253 194
254 if (lenp) 195 nextoffset = err;
255 *lenp = fdt32_to_cpu(prop->len); 196 do {
197 offset = nextoffset;
256 198
257 return prop; 199 tag = fdt_next_tag(fdt, offset, &nextoffset);
258} 200 switch (tag) {
201 case FDT_END:
202 err = -FDT_ERR_TRUNCATED;
203 goto fail;
259 204
260const struct fdt_property *fdt_get_property_namelen(const void *fdt, 205 case FDT_BEGIN_NODE:
261 int offset, 206 case FDT_END_NODE:
262 const char *name, 207 case FDT_NOP:
263 int namelen, int *lenp) 208 break;
264{
265 for (offset = fdt_first_property_offset(fdt, offset);
266 (offset >= 0);
267 (offset = fdt_next_property_offset(fdt, offset))) {
268 const struct fdt_property *prop;
269 209
270 if (!(prop = fdt_get_property_by_offset(fdt, offset, lenp))) { 210 case FDT_PROP:
271 offset = -FDT_ERR_INTERNAL; 211 err = -FDT_ERR_BADSTRUCTURE;
212 prop = fdt_offset_ptr(fdt, offset, sizeof(*prop));
213 if (! prop)
214 goto fail;
215 namestroff = fdt32_to_cpu(prop->nameoff);
216 if (strcmp(fdt_string(fdt, namestroff), name) == 0) {
217 /* Found it! */
218 int len = fdt32_to_cpu(prop->len);
219 prop = fdt_offset_ptr(fdt, offset,
220 sizeof(*prop)+len);
221 if (! prop)
222 goto fail;
223
224 if (lenp)
225 *lenp = len;
226
227 return prop;
228 }
272 break; 229 break;
230
231 default:
232 err = -FDT_ERR_BADSTRUCTURE;
233 goto fail;
273 } 234 }
274 if (_fdt_string_eq(fdt, fdt32_to_cpu(prop->nameoff), 235 } while ((tag != FDT_BEGIN_NODE) && (tag != FDT_END_NODE));
275 name, namelen))
276 return prop;
277 }
278 236
237 err = -FDT_ERR_NOTFOUND;
238 fail:
279 if (lenp) 239 if (lenp)
280 *lenp = offset; 240 *lenp = err;
281 return NULL; 241 return NULL;
282} 242}
283 243
284const struct fdt_property *fdt_get_property(const void *fdt, 244const void *fdt_getprop(const void *fdt, int nodeoffset,
285 int nodeoffset, 245 const char *name, int *lenp)
286 const char *name, int *lenp)
287{
288 return fdt_get_property_namelen(fdt, nodeoffset, name,
289 strlen(name), lenp);
290}
291
292const void *fdt_getprop_namelen(const void *fdt, int nodeoffset,
293 const char *name, int namelen, int *lenp)
294{ 246{
295 const struct fdt_property *prop; 247 const struct fdt_property *prop;
296 248
297 prop = fdt_get_property_namelen(fdt, nodeoffset, name, namelen, lenp); 249 prop = fdt_get_property(fdt, nodeoffset, name, lenp);
298 if (! prop) 250 if (! prop)
299 return NULL; 251 return NULL;
300 252
301 return prop->data; 253 return prop->data;
302} 254}
303 255
304const void *fdt_getprop_by_offset(const void *fdt, int offset,
305 const char **namep, int *lenp)
306{
307 const struct fdt_property *prop;
308
309 prop = fdt_get_property_by_offset(fdt, offset, lenp);
310 if (!prop)
311 return NULL;
312 if (namep)
313 *namep = fdt_string(fdt, fdt32_to_cpu(prop->nameoff));
314 return prop->data;
315}
316
317const void *fdt_getprop(const void *fdt, int nodeoffset,
318 const char *name, int *lenp)
319{
320 return fdt_getprop_namelen(fdt, nodeoffset, name, strlen(name), lenp);
321}
322
323uint32_t fdt_get_phandle(const void *fdt, int nodeoffset) 256uint32_t fdt_get_phandle(const void *fdt, int nodeoffset)
324{ 257{
325 const uint32_t *php; 258 const uint32_t *php;
326 int len; 259 int len;
327 260
328 /* FIXME: This is a bit sub-optimal, since we potentially scan 261 php = fdt_getprop(fdt, nodeoffset, "linux,phandle", &len);
329 * over all the properties twice. */ 262 if (!php || (len != sizeof(*php)))
330 php = fdt_getprop(fdt, nodeoffset, "phandle", &len); 263 return 0;
331 if (!php || (len != sizeof(*php))) {
332 php = fdt_getprop(fdt, nodeoffset, "linux,phandle", &len);
333 if (!php || (len != sizeof(*php)))
334 return 0;
335 }
336 264
337 return fdt32_to_cpu(*php); 265 return fdt32_to_cpu(*php);
338} 266}
339 267
340const char *fdt_get_alias_namelen(const void *fdt,
341 const char *name, int namelen)
342{
343 int aliasoffset;
344
345 aliasoffset = fdt_path_offset(fdt, "/aliases");
346 if (aliasoffset < 0)
347 return NULL;
348
349 return fdt_getprop_namelen(fdt, aliasoffset, name, namelen, NULL);
350}
351
352const char *fdt_get_alias(const void *fdt, const char *name)
353{
354 return fdt_get_alias_namelen(fdt, name, strlen(name));
355}
356
357int fdt_get_path(const void *fdt, int nodeoffset, char *buf, int buflen) 268int fdt_get_path(const void *fdt, int nodeoffset, char *buf, int buflen)
358{ 269{
359 int pdepth = 0, p = 0; 270 int pdepth = 0, p = 0;
@@ -368,6 +279,9 @@ int fdt_get_path(const void *fdt, int nodeoffset, char *buf, int buflen)
368 for (offset = 0, depth = 0; 279 for (offset = 0, depth = 0;
369 (offset >= 0) && (offset <= nodeoffset); 280 (offset >= 0) && (offset <= nodeoffset);
370 offset = fdt_next_node(fdt, offset, &depth)) { 281 offset = fdt_next_node(fdt, offset, &depth)) {
282 if (pdepth < depth)
283 continue; /* overflowed buffer */
284
371 while (pdepth > depth) { 285 while (pdepth > depth) {
372 do { 286 do {
373 p--; 287 p--;
@@ -375,16 +289,14 @@ int fdt_get_path(const void *fdt, int nodeoffset, char *buf, int buflen)
375 pdepth--; 289 pdepth--;
376 } 290 }
377 291
378 if (pdepth >= depth) { 292 name = fdt_get_name(fdt, offset, &namelen);
379 name = fdt_get_name(fdt, offset, &namelen); 293 if (!name)
380 if (!name) 294 return namelen;
381 return namelen; 295 if ((p + namelen + 1) <= buflen) {
382 if ((p + namelen + 1) <= buflen) { 296 memcpy(buf + p, name, namelen);
383 memcpy(buf + p, name, namelen); 297 p += namelen;
384 p += namelen; 298 buf[p++] = '/';
385 buf[p++] = '/'; 299 pdepth++;
386 pdepth++;
387 }
388 } 300 }
389 301
390 if (offset == nodeoffset) { 302 if (offset == nodeoffset) {
@@ -394,7 +306,7 @@ int fdt_get_path(const void *fdt, int nodeoffset, char *buf, int buflen)
394 if (p > 1) /* special case so that root path is "/", not "" */ 306 if (p > 1) /* special case so that root path is "/", not "" */
395 p--; 307 p--;
396 buf[p] = '\0'; 308 buf[p] = '\0';
397 return 0; 309 return p;
398 } 310 }
399 } 311 }
400 312
@@ -492,31 +404,14 @@ int fdt_node_offset_by_prop_value(const void *fdt, int startoffset,
492 404
493int fdt_node_offset_by_phandle(const void *fdt, uint32_t phandle) 405int fdt_node_offset_by_phandle(const void *fdt, uint32_t phandle)
494{ 406{
495 int offset;
496
497 if ((phandle == 0) || (phandle == -1)) 407 if ((phandle == 0) || (phandle == -1))
498 return -FDT_ERR_BADPHANDLE; 408 return -FDT_ERR_BADPHANDLE;
499 409 phandle = cpu_to_fdt32(phandle);
500 FDT_CHECK_HEADER(fdt); 410 return fdt_node_offset_by_prop_value(fdt, -1, "linux,phandle",
501 411 &phandle, sizeof(phandle));
502 /* FIXME: The algorithm here is pretty horrible: we
503 * potentially scan each property of a node in
504 * fdt_get_phandle(), then if that didn't find what
505 * we want, we scan over them again making our way to the next
506 * node. Still it's the easiest to implement approach;
507 * performance can come later. */
508 for (offset = fdt_next_node(fdt, -1, NULL);
509 offset >= 0;
510 offset = fdt_next_node(fdt, offset, NULL)) {
511 if (fdt_get_phandle(fdt, offset) == phandle)
512 return offset;
513 }
514
515 return offset; /* error from fdt_next_node() */
516} 412}
517 413
518static int _fdt_stringlist_contains(const char *strlist, int listlen, 414static int _stringlist_contains(const char *strlist, int listlen, const char *str)
519 const char *str)
520{ 415{
521 int len = strlen(str); 416 int len = strlen(str);
522 const char *p; 417 const char *p;
@@ -542,7 +437,7 @@ int fdt_node_check_compatible(const void *fdt, int nodeoffset,
542 prop = fdt_getprop(fdt, nodeoffset, "compatible", &len); 437 prop = fdt_getprop(fdt, nodeoffset, "compatible", &len);
543 if (!prop) 438 if (!prop)
544 return len; 439 return len;
545 if (_fdt_stringlist_contains(prop, len, compatible)) 440 if (_stringlist_contains(prop, len, compatible))
546 return 0; 441 return 0;
547 else 442 else
548 return 1; 443 return 1;