fdt_ro.c (204431) | fdt_ro.c (204433) |
---|---|
1/* 2 * libfdt - Flat Device Tree manipulation 3 * Copyright (C) 2006 David Gibson, IBM Corporation. 4 * 5 * libfdt is dual licensed: you can use it either under the terms of 6 * the GPL, or the BSD license, at your option. 7 * 8 * a) This library is free software; you can redistribute it and/or --- 66 unchanged lines hidden (view full) --- 75 return 0; 76} 77 78const char *fdt_string(const void *fdt, int stroffset) 79{ 80 return (const char *)fdt + fdt_off_dt_strings(fdt) + stroffset; 81} 82 | 1/* 2 * libfdt - Flat Device Tree manipulation 3 * Copyright (C) 2006 David Gibson, IBM Corporation. 4 * 5 * libfdt is dual licensed: you can use it either under the terms of 6 * the GPL, or the BSD license, at your option. 7 * 8 * a) This library is free software; you can redistribute it and/or --- 66 unchanged lines hidden (view full) --- 75 return 0; 76} 77 78const char *fdt_string(const void *fdt, int stroffset) 79{ 80 return (const char *)fdt + fdt_off_dt_strings(fdt) + stroffset; 81} 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) 84{ 85 FDT_CHECK_HEADER(fdt); 86 *address = fdt64_to_cpu(_fdt_mem_rsv(fdt, n)->address); 87 *size = fdt64_to_cpu(_fdt_mem_rsv(fdt, n)->size); 88 return 0; 89} 90 --- 9 unchanged lines hidden (view full) --- 100int fdt_subnode_offset_namelen(const void *fdt, int offset, 101 const char *name, int namelen) 102{ 103 int depth; 104 105 FDT_CHECK_HEADER(fdt); 106 107 for (depth = 0; | 91int fdt_get_mem_rsv(const void *fdt, int n, uint64_t *address, uint64_t *size) 92{ 93 FDT_CHECK_HEADER(fdt); 94 *address = fdt64_to_cpu(_fdt_mem_rsv(fdt, n)->address); 95 *size = fdt64_to_cpu(_fdt_mem_rsv(fdt, n)->size); 96 return 0; 97} 98 --- 9 unchanged lines hidden (view full) --- 108int fdt_subnode_offset_namelen(const void *fdt, int offset, 109 const char *name, int namelen) 110{ 111 int depth; 112 113 FDT_CHECK_HEADER(fdt); 114 115 for (depth = 0; |
108 offset >= 0; 109 offset = fdt_next_node(fdt, offset, &depth)) { 110 if (depth < 0) 111 return -FDT_ERR_NOTFOUND; 112 else if ((depth == 1) 113 && _fdt_nodename_eq(fdt, offset, name, namelen)) | 116 (offset >= 0) && (depth >= 0); 117 offset = fdt_next_node(fdt, offset, &depth)) 118 if ((depth == 1) 119 && _fdt_nodename_eq(fdt, offset, name, namelen)) |
114 return offset; | 120 return offset; |
115 } | |
116 | 121 |
122 if (depth < 0) 123 return -FDT_ERR_NOTFOUND; |
|
117 return offset; /* error */ 118} 119 120int fdt_subnode_offset(const void *fdt, int parentoffset, 121 const char *name) 122{ 123 return fdt_subnode_offset_namelen(fdt, parentoffset, name, strlen(name)); 124} 125 126int fdt_path_offset(const void *fdt, const char *path) 127{ 128 const char *end = path + strlen(path); 129 const char *p = path; 130 int offset = 0; 131 132 FDT_CHECK_HEADER(fdt); 133 | 124 return offset; /* error */ 125} 126 127int fdt_subnode_offset(const void *fdt, int parentoffset, 128 const char *name) 129{ 130 return fdt_subnode_offset_namelen(fdt, parentoffset, name, strlen(name)); 131} 132 133int fdt_path_offset(const void *fdt, const char *path) 134{ 135 const char *end = path + strlen(path); 136 const char *p = path; 137 int offset = 0; 138 139 FDT_CHECK_HEADER(fdt); 140 |
134 if (*path != '/') 135 return -FDT_ERR_BADPATH; | 141 /* see if we have an alias */ 142 if (*path != '/') { 143 const char *q = strchr(path, '/'); |
136 | 144 |
145 if (!q) 146 q = end; 147 148 p = fdt_get_alias_namelen(fdt, p, q - p); 149 if (!p) 150 return -FDT_ERR_BADPATH; 151 offset = fdt_path_offset(fdt, p); 152 153 p = q; 154 } 155 |
|
137 while (*p) { 138 const char *q; 139 140 while (*p == '/') 141 p++; 142 if (! *p) 143 return offset; 144 q = strchr(p, '/'); --- 25 unchanged lines hidden (view full) --- 170 return nh->name; 171 172 fail: 173 if (len) 174 *len = err; 175 return NULL; 176} 177 | 156 while (*p) { 157 const char *q; 158 159 while (*p == '/') 160 p++; 161 if (! *p) 162 return offset; 163 q = strchr(p, '/'); --- 25 unchanged lines hidden (view full) --- 189 return nh->name; 190 191 fail: 192 if (len) 193 *len = err; 194 return NULL; 195} 196 |
178const struct fdt_property *fdt_get_property(const void *fdt, 179 int nodeoffset, 180 const char *name, int *lenp) | 197const struct fdt_property *fdt_get_property_namelen(const void *fdt, 198 int nodeoffset, 199 const char *name, 200 int namelen, int *lenp) |
181{ 182 uint32_t tag; 183 const struct fdt_property *prop; | 201{ 202 uint32_t tag; 203 const struct fdt_property *prop; |
184 int namestroff; | |
185 int offset, nextoffset; 186 int err; 187 188 if (((err = fdt_check_header(fdt)) != 0) 189 || ((err = _fdt_check_node_offset(fdt, nodeoffset)) < 0)) 190 goto fail; 191 192 nextoffset = err; 193 do { 194 offset = nextoffset; 195 196 tag = fdt_next_tag(fdt, offset, &nextoffset); 197 switch (tag) { 198 case FDT_END: | 204 int offset, nextoffset; 205 int err; 206 207 if (((err = fdt_check_header(fdt)) != 0) 208 || ((err = _fdt_check_node_offset(fdt, nodeoffset)) < 0)) 209 goto fail; 210 211 nextoffset = err; 212 do { 213 offset = nextoffset; 214 215 tag = fdt_next_tag(fdt, offset, &nextoffset); 216 switch (tag) { 217 case FDT_END: |
199 err = -FDT_ERR_TRUNCATED; | 218 if (nextoffset < 0) 219 err = nextoffset; 220 else 221 /* FDT_END tag with unclosed nodes */ 222 err = -FDT_ERR_BADSTRUCTURE; |
200 goto fail; 201 | 223 goto fail; 224 |
202 case FDT_BEGIN_NODE: 203 case FDT_END_NODE: 204 case FDT_NOP: 205 break; 206 | |
207 case FDT_PROP: | 225 case FDT_PROP: |
208 err = -FDT_ERR_BADSTRUCTURE; 209 prop = fdt_offset_ptr(fdt, offset, sizeof(*prop)); 210 if (! prop) 211 goto fail; 212 namestroff = fdt32_to_cpu(prop->nameoff); 213 if (strcmp(fdt_string(fdt, namestroff), name) == 0) { | 226 prop = _fdt_offset_ptr(fdt, offset); 227 if (_fdt_string_eq(fdt, fdt32_to_cpu(prop->nameoff), 228 name, namelen)) { |
214 /* Found it! */ | 229 /* Found it! */ |
215 int len = fdt32_to_cpu(prop->len); 216 prop = fdt_offset_ptr(fdt, offset, 217 sizeof(*prop)+len); 218 if (! prop) 219 goto fail; 220 | |
221 if (lenp) | 230 if (lenp) |
222 *lenp = len; | 231 *lenp = fdt32_to_cpu(prop->len); |
223 224 return prop; 225 } 226 break; | 232 233 return prop; 234 } 235 break; |
227 228 default: 229 err = -FDT_ERR_BADSTRUCTURE; 230 goto fail; | |
231 } 232 } while ((tag != FDT_BEGIN_NODE) && (tag != FDT_END_NODE)); 233 234 err = -FDT_ERR_NOTFOUND; 235 fail: 236 if (lenp) 237 *lenp = err; 238 return NULL; 239} 240 | 236 } 237 } while ((tag != FDT_BEGIN_NODE) && (tag != FDT_END_NODE)); 238 239 err = -FDT_ERR_NOTFOUND; 240 fail: 241 if (lenp) 242 *lenp = err; 243 return NULL; 244} 245 |
241const void *fdt_getprop(const void *fdt, int nodeoffset, 242 const char *name, int *lenp) | 246const struct fdt_property *fdt_get_property(const void *fdt, 247 int nodeoffset, 248 const char *name, int *lenp) |
243{ | 249{ |
250 return fdt_get_property_namelen(fdt, nodeoffset, name, 251 strlen(name), lenp); 252} 253 254const void *fdt_getprop_namelen(const void *fdt, int nodeoffset, 255 const char *name, int namelen, int *lenp) 256{ |
|
244 const struct fdt_property *prop; 245 | 257 const struct fdt_property *prop; 258 |
246 prop = fdt_get_property(fdt, nodeoffset, name, lenp); | 259 prop = fdt_get_property_namelen(fdt, nodeoffset, name, namelen, lenp); |
247 if (! prop) 248 return NULL; 249 250 return prop->data; 251} 252 | 260 if (! prop) 261 return NULL; 262 263 return prop->data; 264} 265 |
266const void *fdt_getprop(const void *fdt, int nodeoffset, 267 const char *name, int *lenp) 268{ 269 return fdt_getprop_namelen(fdt, nodeoffset, name, strlen(name), lenp); 270} 271 |
|
253uint32_t fdt_get_phandle(const void *fdt, int nodeoffset) 254{ 255 const uint32_t *php; 256 int len; 257 | 272uint32_t fdt_get_phandle(const void *fdt, int nodeoffset) 273{ 274 const uint32_t *php; 275 int len; 276 |
258 php = fdt_getprop(fdt, nodeoffset, "linux,phandle", &len); 259 if (!php || (len != sizeof(*php))) 260 return 0; | 277 /* FIXME: This is a bit sub-optimal, since we potentially scan 278 * over all the properties twice. */ 279 php = fdt_getprop(fdt, nodeoffset, "phandle", &len); 280 if (!php || (len != sizeof(*php))) { 281 php = fdt_getprop(fdt, nodeoffset, "linux,phandle", &len); 282 if (!php || (len != sizeof(*php))) 283 return 0; 284 } |
261 262 return fdt32_to_cpu(*php); 263} 264 | 285 286 return fdt32_to_cpu(*php); 287} 288 |
289const char *fdt_get_alias_namelen(const void *fdt, 290 const char *name, int namelen) 291{ 292 int aliasoffset; 293 294 aliasoffset = fdt_path_offset(fdt, "/aliases"); 295 if (aliasoffset < 0) 296 return NULL; 297 298 return fdt_getprop_namelen(fdt, aliasoffset, name, namelen, NULL); 299} 300 301const char *fdt_get_alias(const void *fdt, const char *name) 302{ 303 return fdt_get_alias_namelen(fdt, name, strlen(name)); 304} 305 |
|
265int fdt_get_path(const void *fdt, int nodeoffset, char *buf, int buflen) 266{ 267 int pdepth = 0, p = 0; 268 int offset, depth, namelen; 269 const char *name; 270 271 FDT_CHECK_HEADER(fdt); 272 273 if (buflen < 2) 274 return -FDT_ERR_NOSPACE; 275 276 for (offset = 0, depth = 0; 277 (offset >= 0) && (offset <= nodeoffset); 278 offset = fdt_next_node(fdt, offset, &depth)) { | 306int fdt_get_path(const void *fdt, int nodeoffset, char *buf, int buflen) 307{ 308 int pdepth = 0, p = 0; 309 int offset, depth, namelen; 310 const char *name; 311 312 FDT_CHECK_HEADER(fdt); 313 314 if (buflen < 2) 315 return -FDT_ERR_NOSPACE; 316 317 for (offset = 0, depth = 0; 318 (offset >= 0) && (offset <= nodeoffset); 319 offset = fdt_next_node(fdt, offset, &depth)) { |
279 if (pdepth < depth) 280 continue; /* overflowed buffer */ 281 | |
282 while (pdepth > depth) { 283 do { 284 p--; 285 } while (buf[p-1] != '/'); 286 pdepth--; 287 } 288 | 320 while (pdepth > depth) { 321 do { 322 p--; 323 } while (buf[p-1] != '/'); 324 pdepth--; 325 } 326 |
289 name = fdt_get_name(fdt, offset, &namelen); 290 if (!name) 291 return namelen; 292 if ((p + namelen + 1) <= buflen) { 293 memcpy(buf + p, name, namelen); 294 p += namelen; 295 buf[p++] = '/'; 296 pdepth++; | 327 if (pdepth >= depth) { 328 name = fdt_get_name(fdt, offset, &namelen); 329 if (!name) 330 return namelen; 331 if ((p + namelen + 1) <= buflen) { 332 memcpy(buf + p, name, namelen); 333 p += namelen; 334 buf[p++] = '/'; 335 pdepth++; 336 } |
297 } 298 299 if (offset == nodeoffset) { 300 if (pdepth < (depth + 1)) 301 return -FDT_ERR_NOSPACE; 302 303 if (p > 1) /* special case so that root path is "/", not "" */ 304 p--; 305 buf[p] = '\0'; | 337 } 338 339 if (offset == nodeoffset) { 340 if (pdepth < (depth + 1)) 341 return -FDT_ERR_NOSPACE; 342 343 if (p > 1) /* special case so that root path is "/", not "" */ 344 p--; 345 buf[p] = '\0'; |
306 return p; | 346 return 0; |
307 } 308 } 309 310 if ((offset == -FDT_ERR_NOTFOUND) || (offset >= 0)) 311 return -FDT_ERR_BADOFFSET; 312 else if (offset == -FDT_ERR_BADOFFSET) 313 return -FDT_ERR_BADSTRUCTURE; 314 --- 81 unchanged lines hidden (view full) --- 396 return offset; 397 } 398 399 return offset; /* error from fdt_next_node() */ 400} 401 402int fdt_node_offset_by_phandle(const void *fdt, uint32_t phandle) 403{ | 347 } 348 } 349 350 if ((offset == -FDT_ERR_NOTFOUND) || (offset >= 0)) 351 return -FDT_ERR_BADOFFSET; 352 else if (offset == -FDT_ERR_BADOFFSET) 353 return -FDT_ERR_BADSTRUCTURE; 354 --- 81 unchanged lines hidden (view full) --- 436 return offset; 437 } 438 439 return offset; /* error from fdt_next_node() */ 440} 441 442int fdt_node_offset_by_phandle(const void *fdt, uint32_t phandle) 443{ |
444 int offset; 445 |
|
404 if ((phandle == 0) || (phandle == -1)) 405 return -FDT_ERR_BADPHANDLE; | 446 if ((phandle == 0) || (phandle == -1)) 447 return -FDT_ERR_BADPHANDLE; |
406 phandle = cpu_to_fdt32(phandle); 407 return fdt_node_offset_by_prop_value(fdt, -1, "linux,phandle", 408 &phandle, sizeof(phandle)); | 448 449 FDT_CHECK_HEADER(fdt); 450 451 /* FIXME: The algorithm here is pretty horrible: we 452 * potentially scan each property of a node in 453 * fdt_get_phandle(), then if that didn't find what 454 * we want, we scan over them again making our way to the next 455 * node. Still it's the easiest to implement approach; 456 * performance can come later. */ 457 for (offset = fdt_next_node(fdt, -1, NULL); 458 offset >= 0; 459 offset = fdt_next_node(fdt, offset, NULL)) { 460 if (fdt_get_phandle(fdt, offset) == phandle) 461 return offset; 462 } 463 464 return offset; /* error from fdt_next_node() */ |
409} 410 | 465} 466 |
411int _stringlist_contains(const char *strlist, int listlen, const char *str) | 467static int _fdt_stringlist_contains(const char *strlist, int listlen, 468 const char *str) |
412{ 413 int len = strlen(str); 414 const char *p; 415 416 while (listlen >= len) { 417 if (memcmp(str, strlist, len+1) == 0) 418 return 1; 419 p = memchr(strlist, '\0', listlen); --- 9 unchanged lines hidden (view full) --- 429 const char *compatible) 430{ 431 const void *prop; 432 int len; 433 434 prop = fdt_getprop(fdt, nodeoffset, "compatible", &len); 435 if (!prop) 436 return len; | 469{ 470 int len = strlen(str); 471 const char *p; 472 473 while (listlen >= len) { 474 if (memcmp(str, strlist, len+1) == 0) 475 return 1; 476 p = memchr(strlist, '\0', listlen); --- 9 unchanged lines hidden (view full) --- 486 const char *compatible) 487{ 488 const void *prop; 489 int len; 490 491 prop = fdt_getprop(fdt, nodeoffset, "compatible", &len); 492 if (!prop) 493 return len; |
437 if (_stringlist_contains(prop, len, compatible)) | 494 if (_fdt_stringlist_contains(prop, len, compatible)) |
438 return 0; 439 else 440 return 1; 441} 442 443int fdt_node_offset_by_compatible(const void *fdt, int startoffset, 444 const char *compatible) 445{ --- 21 unchanged lines hidden --- | 495 return 0; 496 else 497 return 1; 498} 499 500int fdt_node_offset_by_compatible(const void *fdt, int startoffset, 501 const char *compatible) 502{ --- 21 unchanged lines hidden --- |