1 #ifndef _LIBFDT_H 2 #define _LIBFDT_H 3 /* 4 * libfdt - Flat Device Tree manipulation 5 * Copyright (C) 2006 David Gibson, IBM Corporation. 6 * 7 * libfdt is dual licensed: you can use it either under the terms of 8 * the GPL, or the BSD license, at your option. 9 * 10 * a) This library is free software; you can redistribute it and/or 11 * modify it under the terms of the GNU General Public License as 12 * published by the Free Software Foundation; either version 2 of the 13 * License, or (at your option) any later version. 14 * 15 * This library is distributed in the hope that it will be useful, 16 * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 * GNU General Public License for more details. 19 * 20 * You should have received a copy of the GNU General Public 21 * License along with this library; if not, write to the Free 22 * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, 23 * MA 02110-1301 USA 24 * 25 * Alternatively, 26 * 27 * b) Redistribution and use in source and binary forms, with or 28 * without modification, are permitted provided that the following 29 * conditions are met: 30 * 31 * 1. Redistributions of source code must retain the above 32 * copyright notice, this list of conditions and the following 33 * disclaimer. 34 * 2. Redistributions in binary form must reproduce the above 35 * copyright notice, this list of conditions and the following 36 * disclaimer in the documentation and/or other materials 37 * provided with the distribution. 38 * 39 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND 40 * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, 41 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 42 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 43 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 44 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 45 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 46 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 47 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 48 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 49 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 50 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, 51 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 52 */ 53 54 #include <libfdt_env.h> 55 #include <fdt.h> 56 57 #define FDT_FIRST_SUPPORTED_VERSION 0x10 58 #define FDT_LAST_SUPPORTED_VERSION 0x11 59 60 /* Error codes: informative error codes */ 61 #define FDT_ERR_NOTFOUND 1 62 /* FDT_ERR_NOTFOUND: The requested node or property does not exist */ 63 #define FDT_ERR_EXISTS 2 64 /* FDT_ERR_EXISTS: Attempted to create a node or property which 65 * already exists */ 66 #define FDT_ERR_NOSPACE 3 67 /* FDT_ERR_NOSPACE: Operation needed to expand the device 68 * tree, but its buffer did not have sufficient space to 69 * contain the expanded tree. Use fdt_open_into() to move the 70 * device tree to a buffer with more space. */ 71 72 /* Error codes: codes for bad parameters */ 73 #define FDT_ERR_BADOFFSET 4 74 /* FDT_ERR_BADOFFSET: Function was passed a structure block 75 * offset which is out-of-bounds, or which points to an 76 * unsuitable part of the structure for the operation. */ 77 #define FDT_ERR_BADPATH 5 78 /* FDT_ERR_BADPATH: Function was passed a badly formatted path 79 * (e.g. missing a leading / for a function which requires an 80 * absolute path) */ 81 #define FDT_ERR_BADPHANDLE 6 82 /* FDT_ERR_BADPHANDLE: Function was passed an invalid phandle 83 * value. phandle values of 0 and -1 are not permitted. */ 84 #define FDT_ERR_BADSTATE 7 85 /* FDT_ERR_BADSTATE: Function was passed an incomplete device 86 * tree created by the sequential-write functions, which is 87 * not sufficiently complete for the requested operation. */ 88 89 /* Error codes: codes for bad device tree blobs */ 90 #define FDT_ERR_TRUNCATED 8 91 /* FDT_ERR_TRUNCATED: Structure block of the given device tree 92 * ends without an FDT_END tag. */ 93 #define FDT_ERR_BADMAGIC 9 94 /* FDT_ERR_BADMAGIC: Given "device tree" appears not to be a 95 * device tree at all - it is missing the flattened device 96 * tree magic number. */ 97 #define FDT_ERR_BADVERSION 10 98 /* FDT_ERR_BADVERSION: Given device tree has a version which 99 * can't be handled by the requested operation. For 100 * read-write functions, this may mean that fdt_open_into() is 101 * required to convert the tree to the expected version. */ 102 #define FDT_ERR_BADSTRUCTURE 11 103 /* FDT_ERR_BADSTRUCTURE: Given device tree has a corrupt 104 * structure block or other serious error (e.g. misnested 105 * nodes, or subnodes preceding properties). */ 106 #define FDT_ERR_BADLAYOUT 12 107 /* FDT_ERR_BADLAYOUT: For read-write functions, the given 108 * device tree has it's sub-blocks in an order that the 109 * function can't handle (memory reserve map, then structure, 110 * then strings). Use fdt_open_into() to reorganize the tree 111 * into a form suitable for the read-write operations. */ 112 113 /* "Can't happen" error indicating a bug in libfdt */ 114 #define FDT_ERR_INTERNAL 13 115 /* FDT_ERR_INTERNAL: libfdt has failed an internal assertion. 116 * Should never be returned, if it is, it indicates a bug in 117 * libfdt itself. */ 118 119 #define FDT_ERR_MAX 13 120 121 /**********************************************************************/ 122 /* Low-level functions (you probably don't need these) */ 123 /**********************************************************************/ 124 125 const void *fdt_offset_ptr(const void *fdt, int offset, int checklen); 126 static inline void *fdt_offset_ptr_w(void *fdt, int offset, int checklen) 127 { 128 return (void *)(uintptr_t)fdt_offset_ptr(fdt, offset, checklen); 129 } 130 131 uint32_t fdt_next_tag(const void *fdt, int offset, int *nextoffset); 132 133 /**********************************************************************/ 134 /* Traversal functions */ 135 /**********************************************************************/ 136 137 int fdt_next_node(const void *fdt, int offset, int *depth); 138 139 /**********************************************************************/ 140 /* General functions */ 141 /**********************************************************************/ 142 143 #define fdt_get_header(fdt, field) \ 144 (fdt32_to_cpu(((const struct fdt_header *)(fdt))->field)) 145 #define fdt_magic(fdt) (fdt_get_header(fdt, magic)) 146 #define fdt_totalsize(fdt) (fdt_get_header(fdt, totalsize)) 147 #define fdt_off_dt_struct(fdt) (fdt_get_header(fdt, off_dt_struct)) 148 #define fdt_off_dt_strings(fdt) (fdt_get_header(fdt, off_dt_strings)) 149 #define fdt_off_mem_rsvmap(fdt) (fdt_get_header(fdt, off_mem_rsvmap)) 150 #define fdt_version(fdt) (fdt_get_header(fdt, version)) 151 #define fdt_last_comp_version(fdt) (fdt_get_header(fdt, last_comp_version)) 152 #define fdt_boot_cpuid_phys(fdt) (fdt_get_header(fdt, boot_cpuid_phys)) 153 #define fdt_size_dt_strings(fdt) (fdt_get_header(fdt, size_dt_strings)) 154 #define fdt_size_dt_struct(fdt) (fdt_get_header(fdt, size_dt_struct)) 155 156 #define __fdt_set_hdr(name) \ 157 static inline void fdt_set_##name(void *fdt, uint32_t val) \ 158 { \ 159 struct fdt_header *fdth = fdt; \ 160 fdth->name = cpu_to_fdt32(val); \ 161 } 162 __fdt_set_hdr(magic); 163 __fdt_set_hdr(totalsize); 164 __fdt_set_hdr(off_dt_struct); 165 __fdt_set_hdr(off_dt_strings); 166 __fdt_set_hdr(off_mem_rsvmap); 167 __fdt_set_hdr(version); 168 __fdt_set_hdr(last_comp_version); 169 __fdt_set_hdr(boot_cpuid_phys); 170 __fdt_set_hdr(size_dt_strings); 171 __fdt_set_hdr(size_dt_struct); 172 #undef __fdt_set_hdr 173 174 /** 175 * fdt_check_header - sanity check a device tree or possible device tree 176 * @fdt: pointer to data which might be a flattened device tree 177 * 178 * fdt_check_header() checks that the given buffer contains what 179 * appears to be a flattened device tree with sane information in its 180 * header. 181 * 182 * returns: 183 * 0, if the buffer appears to contain a valid device tree 184 * -FDT_ERR_BADMAGIC, 185 * -FDT_ERR_BADVERSION, 186 * -FDT_ERR_BADSTATE, standard meanings, as above 187 */ 188 int fdt_check_header(const void *fdt); 189 190 /** 191 * fdt_move - move a device tree around in memory 192 * @fdt: pointer to the device tree to move 193 * @buf: pointer to memory where the device is to be moved 194 * @bufsize: size of the memory space at buf 195 * 196 * fdt_move() relocates, if possible, the device tree blob located at 197 * fdt to the buffer at buf of size bufsize. The buffer may overlap 198 * with the existing device tree blob at fdt. Therefore, 199 * fdt_move(fdt, fdt, fdt_totalsize(fdt)) 200 * should always succeed. 201 * 202 * returns: 203 * 0, on success 204 * -FDT_ERR_NOSPACE, bufsize is insufficient to contain the device tree 205 * -FDT_ERR_BADMAGIC, 206 * -FDT_ERR_BADVERSION, 207 * -FDT_ERR_BADSTATE, standard meanings 208 */ 209 int fdt_move(const void *fdt, void *buf, int bufsize); 210 211 /**********************************************************************/ 212 /* Read-only functions */ 213 /**********************************************************************/ 214 215 /** 216 * fdt_string - retrieve a string from the strings block of a device tree 217 * @fdt: pointer to the device tree blob 218 * @stroffset: offset of the string within the strings block (native endian) 219 * 220 * fdt_string() retrieves a pointer to a single string from the 221 * strings block of the device tree blob at fdt. 222 * 223 * returns: 224 * a pointer to the string, on success 225 * NULL, if stroffset is out of bounds 226 */ 227 const char *fdt_string(const void *fdt, int stroffset); 228 229 /** 230 * fdt_num_mem_rsv - retrieve the number of memory reserve map entries 231 * @fdt: pointer to the device tree blob 232 * 233 * Returns the number of entries in the device tree blob's memory 234 * reservation map. This does not include the terminating 0,0 entry 235 * or any other (0,0) entries reserved for expansion. 236 * 237 * returns: 238 * the number of entries 239 */ 240 int fdt_num_mem_rsv(const void *fdt); 241 242 /** 243 * fdt_get_mem_rsv - retrieve one memory reserve map entry 244 * @fdt: pointer to the device tree blob 245 * @address, @size: pointers to 64-bit variables 246 * 247 * On success, *address and *size will contain the address and size of 248 * the n-th reserve map entry from the device tree blob, in 249 * native-endian format. 250 * 251 * returns: 252 * 0, on success 253 * -FDT_ERR_BADMAGIC, 254 * -FDT_ERR_BADVERSION, 255 * -FDT_ERR_BADSTATE, standard meanings 256 */ 257 int fdt_get_mem_rsv(const void *fdt, int n, uint64_t *address, uint64_t *size); 258 259 /** 260 * fdt_subnode_offset_namelen - find a subnode based on substring 261 * @fdt: pointer to the device tree blob 262 * @parentoffset: structure block offset of a node 263 * @name: name of the subnode to locate 264 * @namelen: number of characters of name to consider 265 * 266 * Identical to fdt_subnode_offset(), but only examine the first 267 * namelen characters of name for matching the subnode name. This is 268 * useful for finding subnodes based on a portion of a larger string, 269 * such as a full path. 270 */ 271 int fdt_subnode_offset_namelen(const void *fdt, int parentoffset, 272 const char *name, int namelen); 273 /** 274 * fdt_subnode_offset - find a subnode of a given node 275 * @fdt: pointer to the device tree blob 276 * @parentoffset: structure block offset of a node 277 * @name: name of the subnode to locate 278 * 279 * fdt_subnode_offset() finds a subnode of the node at structure block 280 * offset parentoffset with the given name. name may include a unit 281 * address, in which case fdt_subnode_offset() will find the subnode 282 * with that unit address, or the unit address may be omitted, in 283 * which case fdt_subnode_offset() will find an arbitrary subnode 284 * whose name excluding unit address matches the given name. 285 * 286 * returns: 287 * structure block offset of the requested subnode (>=0), on success 288 * -FDT_ERR_NOTFOUND, if the requested subnode does not exist 289 * -FDT_ERR_BADOFFSET, if parentoffset did not point to an FDT_BEGIN_NODE tag 290 * -FDT_ERR_BADMAGIC, 291 * -FDT_ERR_BADVERSION, 292 * -FDT_ERR_BADSTATE, 293 * -FDT_ERR_BADSTRUCTURE, 294 * -FDT_ERR_TRUNCATED, standard meanings. 295 */ 296 int fdt_subnode_offset(const void *fdt, int parentoffset, const char *name); 297 298 /** 299 * fdt_path_offset - find a tree node by its full path 300 * @fdt: pointer to the device tree blob 301 * @path: full path of the node to locate 302 * 303 * fdt_path_offset() finds a node of a given path in the device tree. 304 * Each path component may omit the unit address portion, but the 305 * results of this are undefined if any such path component is 306 * ambiguous (that is if there are multiple nodes at the relevant 307 * level matching the given component, differentiated only by unit 308 * address). 309 * 310 * returns: 311 * structure block offset of the node with the requested path (>=0), on success 312 * -FDT_ERR_BADPATH, given path does not begin with '/' or is invalid 313 * -FDT_ERR_NOTFOUND, if the requested node does not exist 314 * -FDT_ERR_BADMAGIC, 315 * -FDT_ERR_BADVERSION, 316 * -FDT_ERR_BADSTATE, 317 * -FDT_ERR_BADSTRUCTURE, 318 * -FDT_ERR_TRUNCATED, standard meanings. 319 */ 320 int fdt_path_offset(const void *fdt, const char *path); 321 322 /** 323 * fdt_get_name - retrieve the name of a given node 324 * @fdt: pointer to the device tree blob 325 * @nodeoffset: structure block offset of the starting node 326 * @lenp: pointer to an integer variable (will be overwritten) or NULL 327 * 328 * fdt_get_name() retrieves the name (including unit address) of the 329 * device tree node at structure block offset nodeoffset. If lenp is 330 * non-NULL, the length of this name is also returned, in the integer 331 * pointed to by lenp. 332 * 333 * returns: 334 * pointer to the node's name, on success 335 * If lenp is non-NULL, *lenp contains the length of that name (>=0) 336 * NULL, on error 337 * if lenp is non-NULL *lenp contains an error code (<0): 338 * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag 339 * -FDT_ERR_BADMAGIC, 340 * -FDT_ERR_BADVERSION, 341 * -FDT_ERR_BADSTATE, standard meanings 342 */ 343 const char *fdt_get_name(const void *fdt, int nodeoffset, int *lenp); 344 345 /** 346 * fdt_get_property - find a given property in a given node 347 * @fdt: pointer to the device tree blob 348 * @nodeoffset: offset of the node whose property to find 349 * @name: name of the property to find 350 * @lenp: pointer to an integer variable (will be overwritten) or NULL 351 * 352 * fdt_get_property() retrieves a pointer to the fdt_property 353 * structure within the device tree blob corresponding to the property 354 * named 'name' of the node at offset nodeoffset. If lenp is 355 * non-NULL, the length of the property value is also returned, in the 356 * integer pointed to by lenp. 357 * 358 * returns: 359 * pointer to the structure representing the property 360 * if lenp is non-NULL, *lenp contains the length of the property 361 * value (>=0) 362 * NULL, on error 363 * if lenp is non-NULL, *lenp contains an error code (<0): 364 * -FDT_ERR_NOTFOUND, node does not have named property 365 * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag 366 * -FDT_ERR_BADMAGIC, 367 * -FDT_ERR_BADVERSION, 368 * -FDT_ERR_BADSTATE, 369 * -FDT_ERR_BADSTRUCTURE, 370 * -FDT_ERR_TRUNCATED, standard meanings 371 */ 372 const struct fdt_property *fdt_get_property(const void *fdt, int nodeoffset, 373 const char *name, int *lenp); 374 static inline struct fdt_property *fdt_get_property_w(void *fdt, int nodeoffset, 375 const char *name, 376 int *lenp) 377 { 378 return (struct fdt_property *)(uintptr_t) 379 fdt_get_property(fdt, nodeoffset, name, lenp); 380 } 381 382 /** 383 * fdt_getprop - retrieve the value of a given property 384 * @fdt: pointer to the device tree blob 385 * @nodeoffset: offset of the node whose property to find 386 * @name: name of the property to find 387 * @lenp: pointer to an integer variable (will be overwritten) or NULL 388 * 389 * fdt_getprop() retrieves a pointer to the value of the property 390 * named 'name' of the node at offset nodeoffset (this will be a 391 * pointer to within the device blob itself, not a copy of the value). 392 * If lenp is non-NULL, the length of the property value is also 393 * returned, in the integer pointed to by lenp. 394 * 395 * returns: 396 * pointer to the property's value 397 * if lenp is non-NULL, *lenp contains the length of the property 398 * value (>=0) 399 * NULL, on error 400 * if lenp is non-NULL, *lenp contains an error code (<0): 401 * -FDT_ERR_NOTFOUND, node does not have named property 402 * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag 403 * -FDT_ERR_BADMAGIC, 404 * -FDT_ERR_BADVERSION, 405 * -FDT_ERR_BADSTATE, 406 * -FDT_ERR_BADSTRUCTURE, 407 * -FDT_ERR_TRUNCATED, standard meanings 408 */ 409 const void *fdt_getprop(const void *fdt, int nodeoffset, 410 const char *name, int *lenp); 411 static inline void *fdt_getprop_w(void *fdt, int nodeoffset, 412 const char *name, int *lenp) 413 { 414 return (void *)(uintptr_t)fdt_getprop(fdt, nodeoffset, name, lenp); 415 } 416 417 /** 418 * fdt_get_phandle - retrieve the phandle of a given node 419 * @fdt: pointer to the device tree blob 420 * @nodeoffset: structure block offset of the node 421 * 422 * fdt_get_phandle() retrieves the phandle of the device tree node at 423 * structure block offset nodeoffset. 424 * 425 * returns: 426 * the phandle of the node at nodeoffset, on success (!= 0, != -1) 427 * 0, if the node has no phandle, or another error occurs 428 */ 429 uint32_t fdt_get_phandle(const void *fdt, int nodeoffset); 430 431 /** 432 * fdt_get_path - determine the full path of a node 433 * @fdt: pointer to the device tree blob 434 * @nodeoffset: offset of the node whose path to find 435 * @buf: character buffer to contain the returned path (will be overwritten) 436 * @buflen: size of the character buffer at buf 437 * 438 * fdt_get_path() computes the full path of the node at offset 439 * nodeoffset, and records that path in the buffer at buf. 440 * 441 * NOTE: This function is expensive, as it must scan the device tree 442 * structure from the start to nodeoffset. 443 * 444 * returns: 445 * 0, on success 446 * buf contains the absolute path of the node at 447 * nodeoffset, as a NUL-terminated string. 448 * -FDT_ERR_BADOFFSET, nodeoffset does not refer to a BEGIN_NODE tag 449 * -FDT_ERR_NOSPACE, the path of the given node is longer than (bufsize-1) 450 * characters and will not fit in the given buffer. 451 * -FDT_ERR_BADMAGIC, 452 * -FDT_ERR_BADVERSION, 453 * -FDT_ERR_BADSTATE, 454 * -FDT_ERR_BADSTRUCTURE, standard meanings 455 */ 456 int fdt_get_path(const void *fdt, int nodeoffset, char *buf, int buflen); 457 458 /** 459 * fdt_supernode_atdepth_offset - find a specific ancestor of a node 460 * @fdt: pointer to the device tree blob 461 * @nodeoffset: offset of the node whose parent to find 462 * @supernodedepth: depth of the ancestor to find 463 * @nodedepth: pointer to an integer variable (will be overwritten) or NULL 464 * 465 * fdt_supernode_atdepth_offset() finds an ancestor of the given node 466 * at a specific depth from the root (where the root itself has depth 467 * 0, its immediate subnodes depth 1 and so forth). So 468 * fdt_supernode_atdepth_offset(fdt, nodeoffset, 0, NULL); 469 * will always return 0, the offset of the root node. If the node at 470 * nodeoffset has depth D, then: 471 * fdt_supernode_atdepth_offset(fdt, nodeoffset, D, NULL); 472 * will return nodeoffset itself. 473 * 474 * NOTE: This function is expensive, as it must scan the device tree 475 * structure from the start to nodeoffset. 476 * 477 * returns: 478 479 * structure block offset of the node at node offset's ancestor 480 * of depth supernodedepth (>=0), on success 481 * -FDT_ERR_BADOFFSET, nodeoffset does not refer to a BEGIN_NODE tag 482 * -FDT_ERR_NOTFOUND, supernodedepth was greater than the depth of nodeoffset 483 * -FDT_ERR_BADMAGIC, 484 * -FDT_ERR_BADVERSION, 485 * -FDT_ERR_BADSTATE, 486 * -FDT_ERR_BADSTRUCTURE, standard meanings 487 */ 488 int fdt_supernode_atdepth_offset(const void *fdt, int nodeoffset, 489 int supernodedepth, int *nodedepth); 490 491 /** 492 * fdt_node_depth - find the depth of a given node 493 * @fdt: pointer to the device tree blob 494 * @nodeoffset: offset of the node whose parent to find 495 * 496 * fdt_node_depth() finds the depth of a given node. The root node 497 * has depth 0, its immediate subnodes depth 1 and so forth. 498 * 499 * NOTE: This function is expensive, as it must scan the device tree 500 * structure from the start to nodeoffset. 501 * 502 * returns: 503 * depth of the node at nodeoffset (>=0), on success 504 * -FDT_ERR_BADOFFSET, nodeoffset does not refer to a BEGIN_NODE tag 505 * -FDT_ERR_BADMAGIC, 506 * -FDT_ERR_BADVERSION, 507 * -FDT_ERR_BADSTATE, 508 * -FDT_ERR_BADSTRUCTURE, standard meanings 509 */ 510 int fdt_node_depth(const void *fdt, int nodeoffset); 511 512 /** 513 * fdt_parent_offset - find the parent of a given node 514 * @fdt: pointer to the device tree blob 515 * @nodeoffset: offset of the node whose parent to find 516 * 517 * fdt_parent_offset() locates the parent node of a given node (that 518 * is, it finds the offset of the node which contains the node at 519 * nodeoffset as a subnode). 520 * 521 * NOTE: This function is expensive, as it must scan the device tree 522 * structure from the start to nodeoffset, *twice*. 523 * 524 * returns: 525 * structure block offset of the parent of the node at nodeoffset 526 * (>=0), on success 527 * -FDT_ERR_BADOFFSET, nodeoffset does not refer to a BEGIN_NODE tag 528 * -FDT_ERR_BADMAGIC, 529 * -FDT_ERR_BADVERSION, 530 * -FDT_ERR_BADSTATE, 531 * -FDT_ERR_BADSTRUCTURE, standard meanings 532 */ 533 int fdt_parent_offset(const void *fdt, int nodeoffset); 534 535 /** 536 * fdt_node_offset_by_prop_value - find nodes with a given property value 537 * @fdt: pointer to the device tree blob 538 * @startoffset: only find nodes after this offset 539 * @propname: property name to check 540 * @propval: property value to search for 541 * @proplen: length of the value in propval 542 * 543 * fdt_node_offset_by_prop_value() returns the offset of the first 544 * node after startoffset, which has a property named propname whose 545 * value is of length proplen and has value equal to propval; or if 546 * startoffset is -1, the very first such node in the tree. 547 * 548 * To iterate through all nodes matching the criterion, the following 549 * idiom can be used: 550 * offset = fdt_node_offset_by_prop_value(fdt, -1, propname, 551 * propval, proplen); 552 * while (offset != -FDT_ERR_NOTFOUND) { 553 * // other code here 554 * offset = fdt_node_offset_by_prop_value(fdt, offset, propname, 555 * propval, proplen); 556 * } 557 * 558 * Note the -1 in the first call to the function, if 0 is used here 559 * instead, the function will never locate the root node, even if it 560 * matches the criterion. 561 * 562 * returns: 563 * structure block offset of the located node (>= 0, >startoffset), 564 * on success 565 * -FDT_ERR_NOTFOUND, no node matching the criterion exists in the 566 * tree after startoffset 567 * -FDT_ERR_BADOFFSET, nodeoffset does not refer to a BEGIN_NODE tag 568 * -FDT_ERR_BADMAGIC, 569 * -FDT_ERR_BADVERSION, 570 * -FDT_ERR_BADSTATE, 571 * -FDT_ERR_BADSTRUCTURE, standard meanings 572 */ 573 int fdt_node_offset_by_prop_value(const void *fdt, int startoffset, 574 const char *propname, 575 const void *propval, int proplen); 576 577 /** 578 * fdt_node_offset_by_phandle - find the node with a given phandle 579 * @fdt: pointer to the device tree blob 580 * @phandle: phandle value 581 * 582 * fdt_node_offset_by_phandle() returns the offset of the node 583 * which has the given phandle value. If there is more than one node 584 * in the tree with the given phandle (an invalid tree), results are 585 * undefined. 586 * 587 * returns: 588 * structure block offset of the located node (>= 0), on success 589 * -FDT_ERR_NOTFOUND, no node with that phandle exists 590 * -FDT_ERR_BADPHANDLE, given phandle value was invalid (0 or -1) 591 * -FDT_ERR_BADMAGIC, 592 * -FDT_ERR_BADVERSION, 593 * -FDT_ERR_BADSTATE, 594 * -FDT_ERR_BADSTRUCTURE, standard meanings 595 */ 596 int fdt_node_offset_by_phandle(const void *fdt, uint32_t phandle); 597 598 /** 599 * fdt_node_check_compatible: check a node's compatible property 600 * @fdt: pointer to the device tree blob 601 * @nodeoffset: offset of a tree node 602 * @compatible: string to match against 603 * 604 * 605 * fdt_node_check_compatible() returns 0 if the given node contains a 606 * 'compatible' property with the given string as one of its elements, 607 * it returns non-zero otherwise, or on error. 608 * 609 * returns: 610 * 0, if the node has a 'compatible' property listing the given string 611 * 1, if the node has a 'compatible' property, but it does not list 612 * the given string 613 * -FDT_ERR_NOTFOUND, if the given node has no 'compatible' property 614 * -FDT_ERR_BADOFFSET, if nodeoffset does not refer to a BEGIN_NODE tag 615 * -FDT_ERR_BADMAGIC, 616 * -FDT_ERR_BADVERSION, 617 * -FDT_ERR_BADSTATE, 618 * -FDT_ERR_BADSTRUCTURE, standard meanings 619 */ 620 int fdt_node_check_compatible(const void *fdt, int nodeoffset, 621 const char *compatible); 622 623 /** 624 * fdt_node_offset_by_compatible - find nodes with a given 'compatible' value 625 * @fdt: pointer to the device tree blob 626 * @startoffset: only find nodes after this offset 627 * @compatible: 'compatible' string to match against 628 * 629 * fdt_node_offset_by_compatible() returns the offset of the first 630 * node after startoffset, which has a 'compatible' property which 631 * lists the given compatible string; or if startoffset is -1, the 632 * very first such node in the tree. 633 * 634 * To iterate through all nodes matching the criterion, the following 635 * idiom can be used: 636 * offset = fdt_node_offset_by_compatible(fdt, -1, compatible); 637 * while (offset != -FDT_ERR_NOTFOUND) { 638 * // other code here 639 * offset = fdt_node_offset_by_compatible(fdt, offset, compatible); 640 * } 641 * 642 * Note the -1 in the first call to the function, if 0 is used here 643 * instead, the function will never locate the root node, even if it 644 * matches the criterion. 645 * 646 * returns: 647 * structure block offset of the located node (>= 0, >startoffset), 648 * on success 649 * -FDT_ERR_NOTFOUND, no node matching the criterion exists in the 650 * tree after startoffset 651 * -FDT_ERR_BADOFFSET, nodeoffset does not refer to a BEGIN_NODE tag 652 * -FDT_ERR_BADMAGIC, 653 * -FDT_ERR_BADVERSION, 654 * -FDT_ERR_BADSTATE, 655 * -FDT_ERR_BADSTRUCTURE, standard meanings 656 */ 657 int fdt_node_offset_by_compatible(const void *fdt, int startoffset, 658 const char *compatible); 659 660 /**********************************************************************/ 661 /* Write-in-place functions */ 662 /**********************************************************************/ 663 664 /** 665 * fdt_setprop_inplace - change a property's value, but not its size 666 * @fdt: pointer to the device tree blob 667 * @nodeoffset: offset of the node whose property to change 668 * @name: name of the property to change 669 * @val: pointer to data to replace the property value with 670 * @len: length of the property value 671 * 672 * fdt_setprop_inplace() replaces the value of a given property with 673 * the data in val, of length len. This function cannot change the 674 * size of a property, and so will only work if len is equal to the 675 * current length of the property. 676 * 677 * This function will alter only the bytes in the blob which contain 678 * the given property value, and will not alter or move any other part 679 * of the tree. 680 * 681 * returns: 682 * 0, on success 683 * -FDT_ERR_NOSPACE, if len is not equal to the property's current length 684 * -FDT_ERR_NOTFOUND, node does not have the named property 685 * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag 686 * -FDT_ERR_BADMAGIC, 687 * -FDT_ERR_BADVERSION, 688 * -FDT_ERR_BADSTATE, 689 * -FDT_ERR_BADSTRUCTURE, 690 * -FDT_ERR_TRUNCATED, standard meanings 691 */ 692 int fdt_setprop_inplace(void *fdt, int nodeoffset, const char *name, 693 const void *val, int len); 694 695 /** 696 * fdt_setprop_inplace_cell - change the value of a single-cell property 697 * @fdt: pointer to the device tree blob 698 * @nodeoffset: offset of the node whose property to change 699 * @name: name of the property to change 700 * @val: cell (32-bit integer) value to replace the property with 701 * 702 * fdt_setprop_inplace_cell() replaces the value of a given property 703 * with the 32-bit integer cell value in val, converting val to 704 * big-endian if necessary. This function cannot change the size of a 705 * property, and so will only work if the property already exists and 706 * has length 4. 707 * 708 * This function will alter only the bytes in the blob which contain 709 * the given property value, and will not alter or move any other part 710 * of the tree. 711 * 712 * returns: 713 * 0, on success 714 * -FDT_ERR_NOSPACE, if the property's length is not equal to 4 715 * -FDT_ERR_NOTFOUND, node does not have the named property 716 * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag 717 * -FDT_ERR_BADMAGIC, 718 * -FDT_ERR_BADVERSION, 719 * -FDT_ERR_BADSTATE, 720 * -FDT_ERR_BADSTRUCTURE, 721 * -FDT_ERR_TRUNCATED, standard meanings 722 */ 723 static inline int fdt_setprop_inplace_cell(void *fdt, int nodeoffset, 724 const char *name, uint32_t val) 725 { 726 val = cpu_to_fdt32(val); 727 return fdt_setprop_inplace(fdt, nodeoffset, name, &val, sizeof(val)); 728 } 729 730 /** 731 * fdt_nop_property - replace a property with nop tags 732 * @fdt: pointer to the device tree blob 733 * @nodeoffset: offset of the node whose property to nop 734 * @name: name of the property to nop 735 * 736 * fdt_nop_property() will replace a given property's representation 737 * in the blob with FDT_NOP tags, effectively removing it from the 738 * tree. 739 * 740 * This function will alter only the bytes in the blob which contain 741 * the property, and will not alter or move any other part of the 742 * tree. 743 * 744 * returns: 745 * 0, on success 746 * -FDT_ERR_NOTFOUND, node does not have the named property 747 * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag 748 * -FDT_ERR_BADMAGIC, 749 * -FDT_ERR_BADVERSION, 750 * -FDT_ERR_BADSTATE, 751 * -FDT_ERR_BADSTRUCTURE, 752 * -FDT_ERR_TRUNCATED, standard meanings 753 */ 754 int fdt_nop_property(void *fdt, int nodeoffset, const char *name); 755 756 /** 757 * fdt_nop_node - replace a node (subtree) with nop tags 758 * @fdt: pointer to the device tree blob 759 * @nodeoffset: offset of the node to nop 760 * 761 * fdt_nop_node() will replace a given node's representation in the 762 * blob, including all its subnodes, if any, with FDT_NOP tags, 763 * effectively removing it from the tree. 764 * 765 * This function will alter only the bytes in the blob which contain 766 * the node and its properties and subnodes, and will not alter or 767 * move any other part of the tree. 768 * 769 * returns: 770 * 0, on success 771 * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag 772 * -FDT_ERR_BADMAGIC, 773 * -FDT_ERR_BADVERSION, 774 * -FDT_ERR_BADSTATE, 775 * -FDT_ERR_BADSTRUCTURE, 776 * -FDT_ERR_TRUNCATED, standard meanings 777 */ 778 int fdt_nop_node(void *fdt, int nodeoffset); 779 780 /**********************************************************************/ 781 /* Sequential write functions */ 782 /**********************************************************************/ 783 784 int fdt_create(void *buf, int bufsize); 785 int fdt_add_reservemap_entry(void *fdt, uint64_t addr, uint64_t size); 786 int fdt_finish_reservemap(void *fdt); 787 int fdt_begin_node(void *fdt, const char *name); 788 int fdt_property(void *fdt, const char *name, const void *val, int len); 789 static inline int fdt_property_cell(void *fdt, const char *name, uint32_t val) 790 { 791 val = cpu_to_fdt32(val); 792 return fdt_property(fdt, name, &val, sizeof(val)); 793 } 794 #define fdt_property_string(fdt, name, str) \ 795 fdt_property(fdt, name, str, strlen(str)+1) 796 int fdt_end_node(void *fdt); 797 int fdt_finish(void *fdt); 798 799 /**********************************************************************/ 800 /* Read-write functions */ 801 /**********************************************************************/ 802 803 int fdt_open_into(const void *fdt, void *buf, int bufsize); 804 int fdt_pack(void *fdt); 805 806 /** 807 * fdt_add_mem_rsv - add one memory reserve map entry 808 * @fdt: pointer to the device tree blob 809 * @address, @size: 64-bit values (native endian) 810 * 811 * Adds a reserve map entry to the given blob reserving a region at 812 * address address of length size. 813 * 814 * This function will insert data into the reserve map and will 815 * therefore change the indexes of some entries in the table. 816 * 817 * returns: 818 * 0, on success 819 * -FDT_ERR_NOSPACE, there is insufficient free space in the blob to 820 * contain the new reservation entry 821 * -FDT_ERR_BADMAGIC, 822 * -FDT_ERR_BADVERSION, 823 * -FDT_ERR_BADSTATE, 824 * -FDT_ERR_BADSTRUCTURE, 825 * -FDT_ERR_BADLAYOUT, 826 * -FDT_ERR_TRUNCATED, standard meanings 827 */ 828 int fdt_add_mem_rsv(void *fdt, uint64_t address, uint64_t size); 829 830 /** 831 * fdt_del_mem_rsv - remove a memory reserve map entry 832 * @fdt: pointer to the device tree blob 833 * @n: entry to remove 834 * 835 * fdt_del_mem_rsv() removes the n-th memory reserve map entry from 836 * the blob. 837 * 838 * This function will delete data from the reservation table and will 839 * therefore change the indexes of some entries in the table. 840 * 841 * returns: 842 * 0, on success 843 * -FDT_ERR_NOTFOUND, there is no entry of the given index (i.e. there 844 * are less than n+1 reserve map entries) 845 * -FDT_ERR_BADMAGIC, 846 * -FDT_ERR_BADVERSION, 847 * -FDT_ERR_BADSTATE, 848 * -FDT_ERR_BADSTRUCTURE, 849 * -FDT_ERR_BADLAYOUT, 850 * -FDT_ERR_TRUNCATED, standard meanings 851 */ 852 int fdt_del_mem_rsv(void *fdt, int n); 853 854 /** 855 * fdt_set_name - change the name of a given node 856 * @fdt: pointer to the device tree blob 857 * @nodeoffset: structure block offset of a node 858 * @name: name to give the node 859 * 860 * fdt_set_name() replaces the name (including unit address, if any) 861 * of the given node with the given string. NOTE: this function can't 862 * efficiently check if the new name is unique amongst the given 863 * node's siblings; results are undefined if this function is invoked 864 * with a name equal to one of the given node's siblings. 865 * 866 * This function may insert or delete data from the blob, and will 867 * therefore change the offsets of some existing nodes. 868 * 869 * returns: 870 * 0, on success 871 * -FDT_ERR_NOSPACE, there is insufficient free space in the blob 872 * to contain the new name 873 * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag 874 * -FDT_ERR_BADMAGIC, 875 * -FDT_ERR_BADVERSION, 876 * -FDT_ERR_BADSTATE, standard meanings 877 */ 878 int fdt_set_name(void *fdt, int nodeoffset, const char *name); 879 880 /** 881 * fdt_setprop - create or change a property 882 * @fdt: pointer to the device tree blob 883 * @nodeoffset: offset of the node whose property to change 884 * @name: name of the property to change 885 * @val: pointer to data to set the property value to 886 * @len: length of the property value 887 * 888 * fdt_setprop() sets the value of the named property in the given 889 * node to the given value and length, creating the property if it 890 * does not already exist. 891 * 892 * This function may insert or delete data from the blob, and will 893 * therefore change the offsets of some existing nodes. 894 * 895 * returns: 896 * 0, on success 897 * -FDT_ERR_NOSPACE, there is insufficient free space in the blob to 898 * contain the new property value 899 * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag 900 * -FDT_ERR_BADLAYOUT, 901 * -FDT_ERR_BADMAGIC, 902 * -FDT_ERR_BADVERSION, 903 * -FDT_ERR_BADSTATE, 904 * -FDT_ERR_BADSTRUCTURE, 905 * -FDT_ERR_BADLAYOUT, 906 * -FDT_ERR_TRUNCATED, standard meanings 907 */ 908 int fdt_setprop(void *fdt, int nodeoffset, const char *name, 909 const void *val, int len); 910 911 /** 912 * fdt_setprop_cell - set a property to a single cell value 913 * @fdt: pointer to the device tree blob 914 * @nodeoffset: offset of the node whose property to change 915 * @name: name of the property to change 916 * @val: 32-bit integer value for the property (native endian) 917 * 918 * fdt_setprop_cell() sets the value of the named property in the 919 * given node to the given cell value (converting to big-endian if 920 * necessary), or creates a new property with that value if it does 921 * not already exist. 922 * 923 * This function may insert or delete data from the blob, and will 924 * therefore change the offsets of some existing nodes. 925 * 926 * returns: 927 * 0, on success 928 * -FDT_ERR_NOSPACE, there is insufficient free space in the blob to 929 * contain the new property value 930 * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag 931 * -FDT_ERR_BADLAYOUT, 932 * -FDT_ERR_BADMAGIC, 933 * -FDT_ERR_BADVERSION, 934 * -FDT_ERR_BADSTATE, 935 * -FDT_ERR_BADSTRUCTURE, 936 * -FDT_ERR_BADLAYOUT, 937 * -FDT_ERR_TRUNCATED, standard meanings 938 */ 939 static inline int fdt_setprop_cell(void *fdt, int nodeoffset, const char *name, 940 uint32_t val) 941 { 942 val = cpu_to_fdt32(val); 943 return fdt_setprop(fdt, nodeoffset, name, &val, sizeof(val)); 944 } 945 946 /** 947 * fdt_setprop_string - set a property to a string value 948 * @fdt: pointer to the device tree blob 949 * @nodeoffset: offset of the node whose property to change 950 * @name: name of the property to change 951 * @str: string value for the property 952 * 953 * fdt_setprop_string() sets the value of the named property in the 954 * given node to the given string value (using the length of the 955 * string to determine the new length of the property), or creates a 956 * new property with that value if it does not already exist. 957 * 958 * This function may insert or delete data from the blob, and will 959 * therefore change the offsets of some existing nodes. 960 * 961 * returns: 962 * 0, on success 963 * -FDT_ERR_NOSPACE, there is insufficient free space in the blob to 964 * contain the new property value 965 * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag 966 * -FDT_ERR_BADLAYOUT, 967 * -FDT_ERR_BADMAGIC, 968 * -FDT_ERR_BADVERSION, 969 * -FDT_ERR_BADSTATE, 970 * -FDT_ERR_BADSTRUCTURE, 971 * -FDT_ERR_BADLAYOUT, 972 * -FDT_ERR_TRUNCATED, standard meanings 973 */ 974 #define fdt_setprop_string(fdt, nodeoffset, name, str) \ 975 fdt_setprop((fdt), (nodeoffset), (name), (str), strlen(str)+1) 976 977 /** 978 * fdt_delprop - delete a property 979 * @fdt: pointer to the device tree blob 980 * @nodeoffset: offset of the node whose property to nop 981 * @name: name of the property to nop 982 * 983 * fdt_del_property() will delete the given property. 984 * 985 * This function will delete data from the blob, and will therefore 986 * change the offsets of some existing nodes. 987 * 988 * returns: 989 * 0, on success 990 * -FDT_ERR_NOTFOUND, node does not have the named property 991 * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag 992 * -FDT_ERR_BADLAYOUT, 993 * -FDT_ERR_BADMAGIC, 994 * -FDT_ERR_BADVERSION, 995 * -FDT_ERR_BADSTATE, 996 * -FDT_ERR_BADSTRUCTURE, 997 * -FDT_ERR_TRUNCATED, standard meanings 998 */ 999 int fdt_delprop(void *fdt, int nodeoffset, const char *name); 1000 1001 /** 1002 * fdt_add_subnode_namelen - creates a new node based on substring 1003 * @fdt: pointer to the device tree blob 1004 * @parentoffset: structure block offset of a node 1005 * @name: name of the subnode to locate 1006 * @namelen: number of characters of name to consider 1007 * 1008 * Identical to fdt_add_subnode(), but use only the first namelen 1009 * characters of name as the name of the new node. This is useful for 1010 * creating subnodes based on a portion of a larger string, such as a 1011 * full path. 1012 */ 1013 int fdt_add_subnode_namelen(void *fdt, int parentoffset, 1014 const char *name, int namelen); 1015 1016 /** 1017 * fdt_add_subnode - creates a new node 1018 * @fdt: pointer to the device tree blob 1019 * @parentoffset: structure block offset of a node 1020 * @name: name of the subnode to locate 1021 * 1022 * fdt_add_subnode() creates a new node as a subnode of the node at 1023 * structure block offset parentoffset, with the given name (which 1024 * should include the unit address, if any). 1025 * 1026 * This function will insert data into the blob, and will therefore 1027 * change the offsets of some existing nodes. 1028 1029 * returns: 1030 * structure block offset of the created nodeequested subnode (>=0), on success 1031 * -FDT_ERR_NOTFOUND, if the requested subnode does not exist 1032 * -FDT_ERR_BADOFFSET, if parentoffset did not point to an FDT_BEGIN_NODE tag 1033 * -FDT_ERR_EXISTS, if the node at parentoffset already has a subnode of 1034 * the given name 1035 * -FDT_ERR_NOSPACE, if there is insufficient free space in the 1036 * blob to contain the new node 1037 * -FDT_ERR_NOSPACE 1038 * -FDT_ERR_BADLAYOUT 1039 * -FDT_ERR_BADMAGIC, 1040 * -FDT_ERR_BADVERSION, 1041 * -FDT_ERR_BADSTATE, 1042 * -FDT_ERR_BADSTRUCTURE, 1043 * -FDT_ERR_TRUNCATED, standard meanings. 1044 */ 1045 int fdt_add_subnode(void *fdt, int parentoffset, const char *name); 1046 1047 /** 1048 * fdt_del_node - delete a node (subtree) 1049 * @fdt: pointer to the device tree blob 1050 * @nodeoffset: offset of the node to nop 1051 * 1052 * fdt_del_node() will remove the given node, including all its 1053 * subnodes if any, from the blob. 1054 * 1055 * This function will delete data from the blob, and will therefore 1056 * change the offsets of some existing nodes. 1057 * 1058 * returns: 1059 * 0, on success 1060 * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag 1061 * -FDT_ERR_BADLAYOUT, 1062 * -FDT_ERR_BADMAGIC, 1063 * -FDT_ERR_BADVERSION, 1064 * -FDT_ERR_BADSTATE, 1065 * -FDT_ERR_BADSTRUCTURE, 1066 * -FDT_ERR_TRUNCATED, standard meanings 1067 */ 1068 int fdt_del_node(void *fdt, int nodeoffset); 1069 1070 /**********************************************************************/ 1071 /* Debugging / informational functions */ 1072 /**********************************************************************/ 1073 1074 const char *fdt_strerror(int errval); 1075 1076 #endif /* _LIBFDT_H */ 1077