aboutsummaryrefslogtreecommitdiffstats
path: root/scripts/dtc/libfdt/fdt_ro.c
diff options
context:
space:
mode:
authorStephen Warren <swarren@nvidia.com>2012-09-28 17:25:59 -0400
committerRob Herring <rob.herring@calxeda.com>2012-10-01 12:11:35 -0400
commitcd296721a9645f9f28800a072490fa15458d1fb7 (patch)
tree492b9a268a48af07844fbbd39519f95676ee73fe /scripts/dtc/libfdt/fdt_ro.c
parentacc2097934b5403b97f95763fe99fc115b818061 (diff)
dtc: import latest upstream dtc
This updates scripts/dtc to commit 317a5d9 "dtc: zero out new label objects" from git://git.jdl.com/software/dtc.git. This adds features such as: * /bits/ syntax for cell data. * Math expressions within cell data. * The ability to delete properties or nodes. * Support for #line directives in the input file, which allows the use of cpp on *.dts. * -i command-line option (/include/ path) * -W/-E command-line options for error/warning control. * Removal of spew to STDOUT containing the filename being compiled. * Many additions to the libfdt API. Signed-off-by: Stephen Warren <swarren@nvidia.com> Acked-by: Jon Loeliger <jdl@jdl.com> Signed-off-by: Rob Herring <rob.herring@calxeda.com>
Diffstat (limited to 'scripts/dtc/libfdt/fdt_ro.c')
-rw-r--r--scripts/dtc/libfdt/fdt_ro.c275
1 files changed, 190 insertions, 85 deletions
diff --git a/scripts/dtc/libfdt/fdt_ro.c b/scripts/dtc/libfdt/fdt_ro.c
index 22e692919ff9..02b6d687537f 100644
--- a/scripts/dtc/libfdt/fdt_ro.c
+++ b/scripts/dtc/libfdt/fdt_ro.c
@@ -80,6 +80,14 @@ 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
83int fdt_get_mem_rsv(const void *fdt, int n, uint64_t *address, uint64_t *size) 91int fdt_get_mem_rsv(const void *fdt, int n, uint64_t *address, uint64_t *size)
84{ 92{
85 FDT_CHECK_HEADER(fdt); 93 FDT_CHECK_HEADER(fdt);
@@ -97,6 +105,30 @@ int fdt_num_mem_rsv(const void *fdt)
97 return i; 105 return i;
98} 106}
99 107
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
100int fdt_subnode_offset_namelen(const void *fdt, int offset, 132int fdt_subnode_offset_namelen(const void *fdt, int offset,
101 const char *name, int namelen) 133 const char *name, int namelen)
102{ 134{
@@ -104,20 +136,16 @@ int fdt_subnode_offset_namelen(const void *fdt, int offset,
104 136
105 FDT_CHECK_HEADER(fdt); 137 FDT_CHECK_HEADER(fdt);
106 138
107 for (depth = 0, offset = fdt_next_node(fdt, offset, &depth); 139 for (depth = 0;
108 (offset >= 0) && (depth > 0); 140 (offset >= 0) && (depth >= 0);
109 offset = fdt_next_node(fdt, offset, &depth)) { 141 offset = fdt_next_node(fdt, offset, &depth))
110 if (depth < 0) 142 if ((depth == 1)
111 return -FDT_ERR_NOTFOUND; 143 && _fdt_nodename_eq(fdt, offset, name, namelen))
112 else if ((depth == 1)
113 && _fdt_nodename_eq(fdt, offset, name, namelen))
114 return offset; 144 return offset;
115 }
116 145
117 if (offset < 0) 146 if (depth < 0)
118 return offset; /* error */
119 else
120 return -FDT_ERR_NOTFOUND; 147 return -FDT_ERR_NOTFOUND;
148 return offset; /* error */
121} 149}
122 150
123int fdt_subnode_offset(const void *fdt, int parentoffset, 151int fdt_subnode_offset(const void *fdt, int parentoffset,
@@ -134,8 +162,20 @@ int fdt_path_offset(const void *fdt, const char *path)
134 162
135 FDT_CHECK_HEADER(fdt); 163 FDT_CHECK_HEADER(fdt);
136 164
137 if (*path != '/') 165 /* see if we have an alias */
138 return -FDT_ERR_BADPATH; 166 if (*path != '/') {
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 }
139 179
140 while (*p) { 180 while (*p) {
141 const char *q; 181 const char *q;
@@ -178,93 +218,142 @@ const char *fdt_get_name(const void *fdt, int nodeoffset, int *len)
178 return NULL; 218 return NULL;
179} 219}
180 220
181const struct fdt_property *fdt_get_property(const void *fdt, 221int fdt_first_property_offset(const void *fdt, int nodeoffset)
182 int nodeoffset, 222{
183 const char *name, int *lenp) 223 int offset;
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)
184{ 242{
185 uint32_t tag;
186 const struct fdt_property *prop;
187 int namestroff;
188 int offset, nextoffset;
189 int err; 243 int err;
244 const struct fdt_property *prop;
190 245
191 if (((err = fdt_check_header(fdt)) != 0) 246 if ((err = _fdt_check_prop_offset(fdt, offset)) < 0) {
192 || ((err = _fdt_check_node_offset(fdt, nodeoffset)) < 0)) 247 if (lenp)
193 goto fail; 248 *lenp = err;
249 return NULL;
250 }
194 251
195 nextoffset = err; 252 prop = _fdt_offset_ptr(fdt, offset);
196 do {
197 offset = nextoffset;
198 253
199 tag = fdt_next_tag(fdt, offset, &nextoffset); 254 if (lenp)
200 switch (tag) { 255 *lenp = fdt32_to_cpu(prop->len);
201 case FDT_END:
202 err = -FDT_ERR_TRUNCATED;
203 goto fail;
204 256
205 case FDT_BEGIN_NODE: 257 return prop;
206 case FDT_END_NODE: 258}
207 case FDT_NOP:
208 break;
209 259
210 case FDT_PROP: 260const struct fdt_property *fdt_get_property_namelen(const void *fdt,
211 err = -FDT_ERR_BADSTRUCTURE; 261 int offset,
212 prop = fdt_offset_ptr(fdt, offset, sizeof(*prop)); 262 const char *name,
213 if (! prop) 263 int namelen, int *lenp)
214 goto fail; 264{
215 namestroff = fdt32_to_cpu(prop->nameoff); 265 for (offset = fdt_first_property_offset(fdt, offset);
216 if (strcmp(fdt_string(fdt, namestroff), name) == 0) { 266 (offset >= 0);
217 /* Found it! */ 267 (offset = fdt_next_property_offset(fdt, offset))) {
218 int len = fdt32_to_cpu(prop->len); 268 const struct fdt_property *prop;
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 }
229 break;
230 269
231 default: 270 if (!(prop = fdt_get_property_by_offset(fdt, offset, lenp))) {
232 err = -FDT_ERR_BADSTRUCTURE; 271 offset = -FDT_ERR_INTERNAL;
233 goto fail; 272 break;
234 } 273 }
235 } while ((tag != FDT_BEGIN_NODE) && (tag != FDT_END_NODE)); 274 if (_fdt_string_eq(fdt, fdt32_to_cpu(prop->nameoff),
275 name, namelen))
276 return prop;
277 }
236 278
237 err = -FDT_ERR_NOTFOUND;
238 fail:
239 if (lenp) 279 if (lenp)
240 *lenp = err; 280 *lenp = offset;
241 return NULL; 281 return NULL;
242} 282}
243 283
244const void *fdt_getprop(const void *fdt, int nodeoffset, 284const struct fdt_property *fdt_get_property(const void *fdt,
245 const char *name, int *lenp) 285 int nodeoffset,
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)
246{ 294{
247 const struct fdt_property *prop; 295 const struct fdt_property *prop;
248 296
249 prop = fdt_get_property(fdt, nodeoffset, name, lenp); 297 prop = fdt_get_property_namelen(fdt, nodeoffset, name, namelen, lenp);
250 if (! prop) 298 if (! prop)
251 return NULL; 299 return NULL;
252 300
253 return prop->data; 301 return prop->data;
254} 302}
255 303
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
256uint32_t fdt_get_phandle(const void *fdt, int nodeoffset) 323uint32_t fdt_get_phandle(const void *fdt, int nodeoffset)
257{ 324{
258 const uint32_t *php; 325 const uint32_t *php;
259 int len; 326 int len;
260 327
261 php = fdt_getprop(fdt, nodeoffset, "linux,phandle", &len); 328 /* FIXME: This is a bit sub-optimal, since we potentially scan
262 if (!php || (len != sizeof(*php))) 329 * over all the properties twice. */
263 return 0; 330 php = fdt_getprop(fdt, nodeoffset, "phandle", &len);
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 }
264 336
265 return fdt32_to_cpu(*php); 337 return fdt32_to_cpu(*php);
266} 338}
267 339
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
268int fdt_get_path(const void *fdt, int nodeoffset, char *buf, int buflen) 357int fdt_get_path(const void *fdt, int nodeoffset, char *buf, int buflen)
269{ 358{
270 int pdepth = 0, p = 0; 359 int pdepth = 0, p = 0;
@@ -279,9 +368,6 @@ int fdt_get_path(const void *fdt, int nodeoffset, char *buf, int buflen)
279 for (offset = 0, depth = 0; 368 for (offset = 0, depth = 0;
280 (offset >= 0) && (offset <= nodeoffset); 369 (offset >= 0) && (offset <= nodeoffset);
281 offset = fdt_next_node(fdt, offset, &depth)) { 370 offset = fdt_next_node(fdt, offset, &depth)) {
282 if (pdepth < depth)
283 continue; /* overflowed buffer */
284
285 while (pdepth > depth) { 371 while (pdepth > depth) {
286 do { 372 do {
287 p--; 373 p--;
@@ -289,14 +375,16 @@ int fdt_get_path(const void *fdt, int nodeoffset, char *buf, int buflen)
289 pdepth--; 375 pdepth--;
290 } 376 }
291 377
292 name = fdt_get_name(fdt, offset, &namelen); 378 if (pdepth >= depth) {
293 if (!name) 379 name = fdt_get_name(fdt, offset, &namelen);
294 return namelen; 380 if (!name)
295 if ((p + namelen + 1) <= buflen) { 381 return namelen;
296 memcpy(buf + p, name, namelen); 382 if ((p + namelen + 1) <= buflen) {
297 p += namelen; 383 memcpy(buf + p, name, namelen);
298 buf[p++] = '/'; 384 p += namelen;
299 pdepth++; 385 buf[p++] = '/';
386 pdepth++;
387 }
300 } 388 }
301 389
302 if (offset == nodeoffset) { 390 if (offset == nodeoffset) {
@@ -306,7 +394,7 @@ int fdt_get_path(const void *fdt, int nodeoffset, char *buf, int buflen)
306 if (p > 1) /* special case so that root path is "/", not "" */ 394 if (p > 1) /* special case so that root path is "/", not "" */
307 p--; 395 p--;
308 buf[p] = '\0'; 396 buf[p] = '\0';
309 return p; 397 return 0;
310 } 398 }
311 } 399 }
312 400
@@ -404,14 +492,31 @@ int fdt_node_offset_by_prop_value(const void *fdt, int startoffset,
404 492
405int fdt_node_offset_by_phandle(const void *fdt, uint32_t phandle) 493int fdt_node_offset_by_phandle(const void *fdt, uint32_t phandle)
406{ 494{
495 int offset;
496
407 if ((phandle == 0) || (phandle == -1)) 497 if ((phandle == 0) || (phandle == -1))
408 return -FDT_ERR_BADPHANDLE; 498 return -FDT_ERR_BADPHANDLE;
409 phandle = cpu_to_fdt32(phandle); 499
410 return fdt_node_offset_by_prop_value(fdt, -1, "linux,phandle", 500 FDT_CHECK_HEADER(fdt);
411 &phandle, sizeof(phandle)); 501
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() */
412} 516}
413 517
414static int _stringlist_contains(const char *strlist, int listlen, const char *str) 518static int _fdt_stringlist_contains(const char *strlist, int listlen,
519 const char *str)
415{ 520{
416 int len = strlen(str); 521 int len = strlen(str);
417 const char *p; 522 const char *p;
@@ -437,7 +542,7 @@ int fdt_node_check_compatible(const void *fdt, int nodeoffset,
437 prop = fdt_getprop(fdt, nodeoffset, "compatible", &len); 542 prop = fdt_getprop(fdt, nodeoffset, "compatible", &len);
438 if (!prop) 543 if (!prop)
439 return len; 544 return len;
440 if (_stringlist_contains(prop, len, compatible)) 545 if (_fdt_stringlist_contains(prop, len, compatible))
441 return 0; 546 return 0;
442 else 547 else
443 return 1; 548 return 1;