#ifndef _LIBFDT_H1#define _LIBFDT_H2/*3* libfdt - Flat Device Tree manipulation4* Copyright (C) 2006 David Gibson, IBM Corporation.5*6* libfdt is dual licensed: you can use it either under the terms of7* the GPL, or the BSD license, at your option.8*9* a) This library is free software; you can redistribute it and/or10* modify it under the terms of the GNU General Public License as11* published by the Free Software Foundation; either version 2 of the12* License, or (at your option) any later version.13*14* This library is distributed in the hope that it will be useful,15* but WITHOUT ANY WARRANTY; without even the implied warranty of16* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the17* GNU General Public License for more details.18*19* You should have received a copy of the GNU General Public20* License along with this library; if not, write to the Free21* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,22* MA 02110-1301 USA23*24* Alternatively,25*26* b) Redistribution and use in source and binary forms, with or27* without modification, are permitted provided that the following28* conditions are met:29*30* 1. Redistributions of source code must retain the above31* copyright notice, this list of conditions and the following32* disclaimer.33* 2. Redistributions in binary form must reproduce the above34* copyright notice, this list of conditions and the following35* disclaimer in the documentation and/or other materials36* provided with the distribution.37*38* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND39* CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,40* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF41* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE42* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR43* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,44* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT45* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;46* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)47* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN48* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR49* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,50* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.51*/5253#include <libfdt_env.h>54#include <fdt.h>5556#define FDT_FIRST_SUPPORTED_VERSION 0x1057#define FDT_LAST_SUPPORTED_VERSION 0x115859/* Error codes: informative error codes */60#define FDT_ERR_NOTFOUND 161/* FDT_ERR_NOTFOUND: The requested node or property does not exist */62#define FDT_ERR_EXISTS 263/* FDT_ERR_EXISTS: Attempted to create a node or property which64* already exists */65#define FDT_ERR_NOSPACE 366/* FDT_ERR_NOSPACE: Operation needed to expand the device67* tree, but its buffer did not have sufficient space to68* contain the expanded tree. Use fdt_open_into() to move the69* device tree to a buffer with more space. */7071/* Error codes: codes for bad parameters */72#define FDT_ERR_BADOFFSET 473/* FDT_ERR_BADOFFSET: Function was passed a structure block74* offset which is out-of-bounds, or which points to an75* unsuitable part of the structure for the operation. */76#define FDT_ERR_BADPATH 577/* FDT_ERR_BADPATH: Function was passed a badly formatted path78* (e.g. missing a leading / for a function which requires an79* absolute path) */80#define FDT_ERR_BADPHANDLE 681/* FDT_ERR_BADPHANDLE: Function was passed an invalid phandle82* value. phandle values of 0 and -1 are not permitted. */83#define FDT_ERR_BADSTATE 784/* FDT_ERR_BADSTATE: Function was passed an incomplete device85* tree created by the sequential-write functions, which is86* not sufficiently complete for the requested operation. */8788/* Error codes: codes for bad device tree blobs */89#define FDT_ERR_TRUNCATED 890/* FDT_ERR_TRUNCATED: Structure block of the given device tree91* ends without an FDT_END tag. */92#define FDT_ERR_BADMAGIC 993/* FDT_ERR_BADMAGIC: Given "device tree" appears not to be a94* device tree at all - it is missing the flattened device95* tree magic number. */96#define FDT_ERR_BADVERSION 1097/* FDT_ERR_BADVERSION: Given device tree has a version which98* can't be handled by the requested operation. For99* read-write functions, this may mean that fdt_open_into() is100* required to convert the tree to the expected version. */101#define FDT_ERR_BADSTRUCTURE 11102/* FDT_ERR_BADSTRUCTURE: Given device tree has a corrupt103* structure block or other serious error (e.g. misnested104* nodes, or subnodes preceding properties). */105#define FDT_ERR_BADLAYOUT 12106/* FDT_ERR_BADLAYOUT: For read-write functions, the given107* device tree has it's sub-blocks in an order that the108* function can't handle (memory reserve map, then structure,109* then strings). Use fdt_open_into() to reorganize the tree110* into a form suitable for the read-write operations. */111112/* "Can't happen" error indicating a bug in libfdt */113#define FDT_ERR_INTERNAL 13114/* FDT_ERR_INTERNAL: libfdt has failed an internal assertion.115* Should never be returned, if it is, it indicates a bug in116* libfdt itself. */117118#define FDT_ERR_MAX 13119120/**********************************************************************/121/* Low-level functions (you probably don't need these) */122/**********************************************************************/123124const void *fdt_offset_ptr(const void *fdt, int offset, int checklen);125static inline void *fdt_offset_ptr_w(void *fdt, int offset, int checklen)126{127return (void *)(uintptr_t)fdt_offset_ptr(fdt, offset, checklen);128}129130uint32_t fdt_next_tag(const void *fdt, int offset, int *nextoffset);131132/**********************************************************************/133/* Traversal functions */134/**********************************************************************/135136int fdt_next_node(const void *fdt, int offset, int *depth);137138/**********************************************************************/139/* General functions */140/**********************************************************************/141142#define fdt_get_header(fdt, field) \143(fdt32_to_cpu(((const struct fdt_header *)(fdt))->field))144#define fdt_magic(fdt) (fdt_get_header(fdt, magic))145#define fdt_totalsize(fdt) (fdt_get_header(fdt, totalsize))146#define fdt_off_dt_struct(fdt) (fdt_get_header(fdt, off_dt_struct))147#define fdt_off_dt_strings(fdt) (fdt_get_header(fdt, off_dt_strings))148#define fdt_off_mem_rsvmap(fdt) (fdt_get_header(fdt, off_mem_rsvmap))149#define fdt_version(fdt) (fdt_get_header(fdt, version))150#define fdt_last_comp_version(fdt) (fdt_get_header(fdt, last_comp_version))151#define fdt_boot_cpuid_phys(fdt) (fdt_get_header(fdt, boot_cpuid_phys))152#define fdt_size_dt_strings(fdt) (fdt_get_header(fdt, size_dt_strings))153#define fdt_size_dt_struct(fdt) (fdt_get_header(fdt, size_dt_struct))154155#define __fdt_set_hdr(name) \156static inline void fdt_set_##name(void *fdt, uint32_t val) \157{ \158struct fdt_header *fdth = fdt; \159fdth->name = cpu_to_fdt32(val); \160}161__fdt_set_hdr(magic);162__fdt_set_hdr(totalsize);163__fdt_set_hdr(off_dt_struct);164__fdt_set_hdr(off_dt_strings);165__fdt_set_hdr(off_mem_rsvmap);166__fdt_set_hdr(version);167__fdt_set_hdr(last_comp_version);168__fdt_set_hdr(boot_cpuid_phys);169__fdt_set_hdr(size_dt_strings);170__fdt_set_hdr(size_dt_struct);171#undef __fdt_set_hdr172173/**174* fdt_check_header - sanity check a device tree or possible device tree175* @fdt: pointer to data which might be a flattened device tree176*177* fdt_check_header() checks that the given buffer contains what178* appears to be a flattened device tree with sane information in its179* header.180*181* returns:182* 0, if the buffer appears to contain a valid device tree183* -FDT_ERR_BADMAGIC,184* -FDT_ERR_BADVERSION,185* -FDT_ERR_BADSTATE, standard meanings, as above186*/187int fdt_check_header(const void *fdt);188189/**190* fdt_move - move a device tree around in memory191* @fdt: pointer to the device tree to move192* @buf: pointer to memory where the device is to be moved193* @bufsize: size of the memory space at buf194*195* fdt_move() relocates, if possible, the device tree blob located at196* fdt to the buffer at buf of size bufsize. The buffer may overlap197* with the existing device tree blob at fdt. Therefore,198* fdt_move(fdt, fdt, fdt_totalsize(fdt))199* should always succeed.200*201* returns:202* 0, on success203* -FDT_ERR_NOSPACE, bufsize is insufficient to contain the device tree204* -FDT_ERR_BADMAGIC,205* -FDT_ERR_BADVERSION,206* -FDT_ERR_BADSTATE, standard meanings207*/208int fdt_move(const void *fdt, void *buf, int bufsize);209210/**********************************************************************/211/* Read-only functions */212/**********************************************************************/213214/**215* fdt_string - retrieve a string from the strings block of a device tree216* @fdt: pointer to the device tree blob217* @stroffset: offset of the string within the strings block (native endian)218*219* fdt_string() retrieves a pointer to a single string from the220* strings block of the device tree blob at fdt.221*222* returns:223* a pointer to the string, on success224* NULL, if stroffset is out of bounds225*/226const char *fdt_string(const void *fdt, int stroffset);227228/**229* fdt_num_mem_rsv - retrieve the number of memory reserve map entries230* @fdt: pointer to the device tree blob231*232* Returns the number of entries in the device tree blob's memory233* reservation map. This does not include the terminating 0,0 entry234* or any other (0,0) entries reserved for expansion.235*236* returns:237* the number of entries238*/239int fdt_num_mem_rsv(const void *fdt);240241/**242* fdt_get_mem_rsv - retrieve one memory reserve map entry243* @fdt: pointer to the device tree blob244* @address, @size: pointers to 64-bit variables245*246* On success, *address and *size will contain the address and size of247* the n-th reserve map entry from the device tree blob, in248* native-endian format.249*250* returns:251* 0, on success252* -FDT_ERR_BADMAGIC,253* -FDT_ERR_BADVERSION,254* -FDT_ERR_BADSTATE, standard meanings255*/256int fdt_get_mem_rsv(const void *fdt, int n, uint64_t *address, uint64_t *size);257258/**259* fdt_subnode_offset_namelen - find a subnode based on substring260* @fdt: pointer to the device tree blob261* @parentoffset: structure block offset of a node262* @name: name of the subnode to locate263* @namelen: number of characters of name to consider264*265* Identical to fdt_subnode_offset(), but only examine the first266* namelen characters of name for matching the subnode name. This is267* useful for finding subnodes based on a portion of a larger string,268* such as a full path.269*/270int fdt_subnode_offset_namelen(const void *fdt, int parentoffset,271const char *name, int namelen);272/**273* fdt_subnode_offset - find a subnode of a given node274* @fdt: pointer to the device tree blob275* @parentoffset: structure block offset of a node276* @name: name of the subnode to locate277*278* fdt_subnode_offset() finds a subnode of the node at structure block279* offset parentoffset with the given name. name may include a unit280* address, in which case fdt_subnode_offset() will find the subnode281* with that unit address, or the unit address may be omitted, in282* which case fdt_subnode_offset() will find an arbitrary subnode283* whose name excluding unit address matches the given name.284*285* returns:286* structure block offset of the requested subnode (>=0), on success287* -FDT_ERR_NOTFOUND, if the requested subnode does not exist288* -FDT_ERR_BADOFFSET, if parentoffset did not point to an FDT_BEGIN_NODE tag289* -FDT_ERR_BADMAGIC,290* -FDT_ERR_BADVERSION,291* -FDT_ERR_BADSTATE,292* -FDT_ERR_BADSTRUCTURE,293* -FDT_ERR_TRUNCATED, standard meanings.294*/295int fdt_subnode_offset(const void *fdt, int parentoffset, const char *name);296297/**298* fdt_path_offset - find a tree node by its full path299* @fdt: pointer to the device tree blob300* @path: full path of the node to locate301*302* fdt_path_offset() finds a node of a given path in the device tree.303* Each path component may omit the unit address portion, but the304* results of this are undefined if any such path component is305* ambiguous (that is if there are multiple nodes at the relevant306* level matching the given component, differentiated only by unit307* address).308*309* returns:310* structure block offset of the node with the requested path (>=0), on success311* -FDT_ERR_BADPATH, given path does not begin with '/' or is invalid312* -FDT_ERR_NOTFOUND, if the requested node does not exist313* -FDT_ERR_BADMAGIC,314* -FDT_ERR_BADVERSION,315* -FDT_ERR_BADSTATE,316* -FDT_ERR_BADSTRUCTURE,317* -FDT_ERR_TRUNCATED, standard meanings.318*/319int fdt_path_offset(const void *fdt, const char *path);320321/**322* fdt_get_name - retrieve the name of a given node323* @fdt: pointer to the device tree blob324* @nodeoffset: structure block offset of the starting node325* @lenp: pointer to an integer variable (will be overwritten) or NULL326*327* fdt_get_name() retrieves the name (including unit address) of the328* device tree node at structure block offset nodeoffset. If lenp is329* non-NULL, the length of this name is also returned, in the integer330* pointed to by lenp.331*332* returns:333* pointer to the node's name, on success334* If lenp is non-NULL, *lenp contains the length of that name (>=0)335* NULL, on error336* if lenp is non-NULL *lenp contains an error code (<0):337* -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag338* -FDT_ERR_BADMAGIC,339* -FDT_ERR_BADVERSION,340* -FDT_ERR_BADSTATE, standard meanings341*/342const char *fdt_get_name(const void *fdt, int nodeoffset, int *lenp);343344/**345* fdt_get_property - find a given property in a given node346* @fdt: pointer to the device tree blob347* @nodeoffset: offset of the node whose property to find348* @name: name of the property to find349* @lenp: pointer to an integer variable (will be overwritten) or NULL350*351* fdt_get_property() retrieves a pointer to the fdt_property352* structure within the device tree blob corresponding to the property353* named 'name' of the node at offset nodeoffset. If lenp is354* non-NULL, the length of the property value is also returned, in the355* integer pointed to by lenp.356*357* returns:358* pointer to the structure representing the property359* if lenp is non-NULL, *lenp contains the length of the property360* value (>=0)361* NULL, on error362* if lenp is non-NULL, *lenp contains an error code (<0):363* -FDT_ERR_NOTFOUND, node does not have named property364* -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag365* -FDT_ERR_BADMAGIC,366* -FDT_ERR_BADVERSION,367* -FDT_ERR_BADSTATE,368* -FDT_ERR_BADSTRUCTURE,369* -FDT_ERR_TRUNCATED, standard meanings370*/371const struct fdt_property *fdt_get_property(const void *fdt, int nodeoffset,372const char *name, int *lenp);373static inline struct fdt_property *fdt_get_property_w(void *fdt, int nodeoffset,374const char *name,375int *lenp)376{377return (struct fdt_property *)(uintptr_t)378fdt_get_property(fdt, nodeoffset, name, lenp);379}380381/**382* fdt_getprop - retrieve the value of a given property383* @fdt: pointer to the device tree blob384* @nodeoffset: offset of the node whose property to find385* @name: name of the property to find386* @lenp: pointer to an integer variable (will be overwritten) or NULL387*388* fdt_getprop() retrieves a pointer to the value of the property389* named 'name' of the node at offset nodeoffset (this will be a390* pointer to within the device blob itself, not a copy of the value).391* If lenp is non-NULL, the length of the property value is also392* returned, in the integer pointed to by lenp.393*394* returns:395* pointer to the property's value396* if lenp is non-NULL, *lenp contains the length of the property397* value (>=0)398* NULL, on error399* if lenp is non-NULL, *lenp contains an error code (<0):400* -FDT_ERR_NOTFOUND, node does not have named property401* -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag402* -FDT_ERR_BADMAGIC,403* -FDT_ERR_BADVERSION,404* -FDT_ERR_BADSTATE,405* -FDT_ERR_BADSTRUCTURE,406* -FDT_ERR_TRUNCATED, standard meanings407*/408const void *fdt_getprop(const void *fdt, int nodeoffset,409const char *name, int *lenp);410static inline void *fdt_getprop_w(void *fdt, int nodeoffset,411const char *name, int *lenp)412{413return (void *)(uintptr_t)fdt_getprop(fdt, nodeoffset, name, lenp);414}415416/**417* fdt_get_phandle - retrieve the phandle of a given node418* @fdt: pointer to the device tree blob419* @nodeoffset: structure block offset of the node420*421* fdt_get_phandle() retrieves the phandle of the device tree node at422* structure block offset nodeoffset.423*424* returns:425* the phandle of the node at nodeoffset, on success (!= 0, != -1)426* 0, if the node has no phandle, or another error occurs427*/428uint32_t fdt_get_phandle(const void *fdt, int nodeoffset);429430/**431* fdt_get_path - determine the full path of a node432* @fdt: pointer to the device tree blob433* @nodeoffset: offset of the node whose path to find434* @buf: character buffer to contain the returned path (will be overwritten)435* @buflen: size of the character buffer at buf436*437* fdt_get_path() computes the full path of the node at offset438* nodeoffset, and records that path in the buffer at buf.439*440* NOTE: This function is expensive, as it must scan the device tree441* structure from the start to nodeoffset.442*443* returns:444* 0, on success445* buf contains the absolute path of the node at446* nodeoffset, as a NUL-terminated string.447* -FDT_ERR_BADOFFSET, nodeoffset does not refer to a BEGIN_NODE tag448* -FDT_ERR_NOSPACE, the path of the given node is longer than (bufsize-1)449* characters and will not fit in the given buffer.450* -FDT_ERR_BADMAGIC,451* -FDT_ERR_BADVERSION,452* -FDT_ERR_BADSTATE,453* -FDT_ERR_BADSTRUCTURE, standard meanings454*/455int fdt_get_path(const void *fdt, int nodeoffset, char *buf, int buflen);456457/**458* fdt_supernode_atdepth_offset - find a specific ancestor of a node459* @fdt: pointer to the device tree blob460* @nodeoffset: offset of the node whose parent to find461* @supernodedepth: depth of the ancestor to find462* @nodedepth: pointer to an integer variable (will be overwritten) or NULL463*464* fdt_supernode_atdepth_offset() finds an ancestor of the given node465* at a specific depth from the root (where the root itself has depth466* 0, its immediate subnodes depth 1 and so forth). So467* fdt_supernode_atdepth_offset(fdt, nodeoffset, 0, NULL);468* will always return 0, the offset of the root node. If the node at469* nodeoffset has depth D, then:470* fdt_supernode_atdepth_offset(fdt, nodeoffset, D, NULL);471* will return nodeoffset itself.472*473* NOTE: This function is expensive, as it must scan the device tree474* structure from the start to nodeoffset.475*476* returns:477478* structure block offset of the node at node offset's ancestor479* of depth supernodedepth (>=0), on success480* -FDT_ERR_BADOFFSET, nodeoffset does not refer to a BEGIN_NODE tag481* -FDT_ERR_NOTFOUND, supernodedepth was greater than the depth of nodeoffset482* -FDT_ERR_BADMAGIC,483* -FDT_ERR_BADVERSION,484* -FDT_ERR_BADSTATE,485* -FDT_ERR_BADSTRUCTURE, standard meanings486*/487int fdt_supernode_atdepth_offset(const void *fdt, int nodeoffset,488int supernodedepth, int *nodedepth);489490/**491* fdt_node_depth - find the depth of a given node492* @fdt: pointer to the device tree blob493* @nodeoffset: offset of the node whose parent to find494*495* fdt_node_depth() finds the depth of a given node. The root node496* has depth 0, its immediate subnodes depth 1 and so forth.497*498* NOTE: This function is expensive, as it must scan the device tree499* structure from the start to nodeoffset.500*501* returns:502* depth of the node at nodeoffset (>=0), on success503* -FDT_ERR_BADOFFSET, nodeoffset does not refer to a BEGIN_NODE tag504* -FDT_ERR_BADMAGIC,505* -FDT_ERR_BADVERSION,506* -FDT_ERR_BADSTATE,507* -FDT_ERR_BADSTRUCTURE, standard meanings508*/509int fdt_node_depth(const void *fdt, int nodeoffset);510511/**512* fdt_parent_offset - find the parent of a given node513* @fdt: pointer to the device tree blob514* @nodeoffset: offset of the node whose parent to find515*516* fdt_parent_offset() locates the parent node of a given node (that517* is, it finds the offset of the node which contains the node at518* nodeoffset as a subnode).519*520* NOTE: This function is expensive, as it must scan the device tree521* structure from the start to nodeoffset, *twice*.522*523* returns:524* structure block offset of the parent of the node at nodeoffset525* (>=0), on success526* -FDT_ERR_BADOFFSET, nodeoffset does not refer to a BEGIN_NODE tag527* -FDT_ERR_BADMAGIC,528* -FDT_ERR_BADVERSION,529* -FDT_ERR_BADSTATE,530* -FDT_ERR_BADSTRUCTURE, standard meanings531*/532int fdt_parent_offset(const void *fdt, int nodeoffset);533534/**535* fdt_node_offset_by_prop_value - find nodes with a given property value536* @fdt: pointer to the device tree blob537* @startoffset: only find nodes after this offset538* @propname: property name to check539* @propval: property value to search for540* @proplen: length of the value in propval541*542* fdt_node_offset_by_prop_value() returns the offset of the first543* node after startoffset, which has a property named propname whose544* value is of length proplen and has value equal to propval; or if545* startoffset is -1, the very first such node in the tree.546*547* To iterate through all nodes matching the criterion, the following548* idiom can be used:549* offset = fdt_node_offset_by_prop_value(fdt, -1, propname,550* propval, proplen);551* while (offset != -FDT_ERR_NOTFOUND) {552* // other code here553* offset = fdt_node_offset_by_prop_value(fdt, offset, propname,554* propval, proplen);555* }556*557* Note the -1 in the first call to the function, if 0 is used here558* instead, the function will never locate the root node, even if it559* matches the criterion.560*561* returns:562* structure block offset of the located node (>= 0, >startoffset),563* on success564* -FDT_ERR_NOTFOUND, no node matching the criterion exists in the565* tree after startoffset566* -FDT_ERR_BADOFFSET, nodeoffset does not refer to a BEGIN_NODE tag567* -FDT_ERR_BADMAGIC,568* -FDT_ERR_BADVERSION,569* -FDT_ERR_BADSTATE,570* -FDT_ERR_BADSTRUCTURE, standard meanings571*/572int fdt_node_offset_by_prop_value(const void *fdt, int startoffset,573const char *propname,574const void *propval, int proplen);575576/**577* fdt_node_offset_by_phandle - find the node with a given phandle578* @fdt: pointer to the device tree blob579* @phandle: phandle value580*581* fdt_node_offset_by_phandle() returns the offset of the node582* which has the given phandle value. If there is more than one node583* in the tree with the given phandle (an invalid tree), results are584* undefined.585*586* returns:587* structure block offset of the located node (>= 0), on success588* -FDT_ERR_NOTFOUND, no node with that phandle exists589* -FDT_ERR_BADPHANDLE, given phandle value was invalid (0 or -1)590* -FDT_ERR_BADMAGIC,591* -FDT_ERR_BADVERSION,592* -FDT_ERR_BADSTATE,593* -FDT_ERR_BADSTRUCTURE, standard meanings594*/595int fdt_node_offset_by_phandle(const void *fdt, uint32_t phandle);596597/**598* fdt_node_check_compatible: check a node's compatible property599* @fdt: pointer to the device tree blob600* @nodeoffset: offset of a tree node601* @compatible: string to match against602*603*604* fdt_node_check_compatible() returns 0 if the given node contains a605* 'compatible' property with the given string as one of its elements,606* it returns non-zero otherwise, or on error.607*608* returns:609* 0, if the node has a 'compatible' property listing the given string610* 1, if the node has a 'compatible' property, but it does not list611* the given string612* -FDT_ERR_NOTFOUND, if the given node has no 'compatible' property613* -FDT_ERR_BADOFFSET, if nodeoffset does not refer to a BEGIN_NODE tag614* -FDT_ERR_BADMAGIC,615* -FDT_ERR_BADVERSION,616* -FDT_ERR_BADSTATE,617* -FDT_ERR_BADSTRUCTURE, standard meanings618*/619int fdt_node_check_compatible(const void *fdt, int nodeoffset,620const char *compatible);621622/**623* fdt_node_offset_by_compatible - find nodes with a given 'compatible' value624* @fdt: pointer to the device tree blob625* @startoffset: only find nodes after this offset626* @compatible: 'compatible' string to match against627*628* fdt_node_offset_by_compatible() returns the offset of the first629* node after startoffset, which has a 'compatible' property which630* lists the given compatible string; or if startoffset is -1, the631* very first such node in the tree.632*633* To iterate through all nodes matching the criterion, the following634* idiom can be used:635* offset = fdt_node_offset_by_compatible(fdt, -1, compatible);636* while (offset != -FDT_ERR_NOTFOUND) {637* // other code here638* offset = fdt_node_offset_by_compatible(fdt, offset, compatible);639* }640*641* Note the -1 in the first call to the function, if 0 is used here642* instead, the function will never locate the root node, even if it643* matches the criterion.644*645* returns:646* structure block offset of the located node (>= 0, >startoffset),647* on success648* -FDT_ERR_NOTFOUND, no node matching the criterion exists in the649* tree after startoffset650* -FDT_ERR_BADOFFSET, nodeoffset does not refer to a BEGIN_NODE tag651* -FDT_ERR_BADMAGIC,652* -FDT_ERR_BADVERSION,653* -FDT_ERR_BADSTATE,654* -FDT_ERR_BADSTRUCTURE, standard meanings655*/656int fdt_node_offset_by_compatible(const void *fdt, int startoffset,657const char *compatible);658659/**********************************************************************/660/* Write-in-place functions */661/**********************************************************************/662663/**664* fdt_setprop_inplace - change a property's value, but not its size665* @fdt: pointer to the device tree blob666* @nodeoffset: offset of the node whose property to change667* @name: name of the property to change668* @val: pointer to data to replace the property value with669* @len: length of the property value670*671* fdt_setprop_inplace() replaces the value of a given property with672* the data in val, of length len. This function cannot change the673* size of a property, and so will only work if len is equal to the674* current length of the property.675*676* This function will alter only the bytes in the blob which contain677* the given property value, and will not alter or move any other part678* of the tree.679*680* returns:681* 0, on success682* -FDT_ERR_NOSPACE, if len is not equal to the property's current length683* -FDT_ERR_NOTFOUND, node does not have the named property684* -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag685* -FDT_ERR_BADMAGIC,686* -FDT_ERR_BADVERSION,687* -FDT_ERR_BADSTATE,688* -FDT_ERR_BADSTRUCTURE,689* -FDT_ERR_TRUNCATED, standard meanings690*/691int fdt_setprop_inplace(void *fdt, int nodeoffset, const char *name,692const void *val, int len);693694/**695* fdt_setprop_inplace_cell - change the value of a single-cell property696* @fdt: pointer to the device tree blob697* @nodeoffset: offset of the node whose property to change698* @name: name of the property to change699* @val: cell (32-bit integer) value to replace the property with700*701* fdt_setprop_inplace_cell() replaces the value of a given property702* with the 32-bit integer cell value in val, converting val to703* big-endian if necessary. This function cannot change the size of a704* property, and so will only work if the property already exists and705* has length 4.706*707* This function will alter only the bytes in the blob which contain708* the given property value, and will not alter or move any other part709* of the tree.710*711* returns:712* 0, on success713* -FDT_ERR_NOSPACE, if the property's length is not equal to 4714* -FDT_ERR_NOTFOUND, node does not have the named property715* -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag716* -FDT_ERR_BADMAGIC,717* -FDT_ERR_BADVERSION,718* -FDT_ERR_BADSTATE,719* -FDT_ERR_BADSTRUCTURE,720* -FDT_ERR_TRUNCATED, standard meanings721*/722static inline int fdt_setprop_inplace_cell(void *fdt, int nodeoffset,723const char *name, uint32_t val)724{725val = cpu_to_fdt32(val);726return fdt_setprop_inplace(fdt, nodeoffset, name, &val, sizeof(val));727}728729/**730* fdt_nop_property - replace a property with nop tags731* @fdt: pointer to the device tree blob732* @nodeoffset: offset of the node whose property to nop733* @name: name of the property to nop734*735* fdt_nop_property() will replace a given property's representation736* in the blob with FDT_NOP tags, effectively removing it from the737* tree.738*739* This function will alter only the bytes in the blob which contain740* the property, and will not alter or move any other part of the741* tree.742*743* returns:744* 0, on success745* -FDT_ERR_NOTFOUND, node does not have the named property746* -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag747* -FDT_ERR_BADMAGIC,748* -FDT_ERR_BADVERSION,749* -FDT_ERR_BADSTATE,750* -FDT_ERR_BADSTRUCTURE,751* -FDT_ERR_TRUNCATED, standard meanings752*/753int fdt_nop_property(void *fdt, int nodeoffset, const char *name);754755/**756* fdt_nop_node - replace a node (subtree) with nop tags757* @fdt: pointer to the device tree blob758* @nodeoffset: offset of the node to nop759*760* fdt_nop_node() will replace a given node's representation in the761* blob, including all its subnodes, if any, with FDT_NOP tags,762* effectively removing it from the tree.763*764* This function will alter only the bytes in the blob which contain765* the node and its properties and subnodes, and will not alter or766* move any other part of the tree.767*768* returns:769* 0, on success770* -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag771* -FDT_ERR_BADMAGIC,772* -FDT_ERR_BADVERSION,773* -FDT_ERR_BADSTATE,774* -FDT_ERR_BADSTRUCTURE,775* -FDT_ERR_TRUNCATED, standard meanings776*/777int fdt_nop_node(void *fdt, int nodeoffset);778779/**********************************************************************/780/* Sequential write functions */781/**********************************************************************/782783int fdt_create(void *buf, int bufsize);784int fdt_add_reservemap_entry(void *fdt, uint64_t addr, uint64_t size);785int fdt_finish_reservemap(void *fdt);786int fdt_begin_node(void *fdt, const char *name);787int fdt_property(void *fdt, const char *name, const void *val, int len);788static inline int fdt_property_cell(void *fdt, const char *name, uint32_t val)789{790val = cpu_to_fdt32(val);791return fdt_property(fdt, name, &val, sizeof(val));792}793#define fdt_property_string(fdt, name, str) \794fdt_property(fdt, name, str, strlen(str)+1)795int fdt_end_node(void *fdt);796int fdt_finish(void *fdt);797798/**********************************************************************/799/* Read-write functions */800/**********************************************************************/801802int fdt_open_into(const void *fdt, void *buf, int bufsize);803int fdt_pack(void *fdt);804805/**806* fdt_add_mem_rsv - add one memory reserve map entry807* @fdt: pointer to the device tree blob808* @address, @size: 64-bit values (native endian)809*810* Adds a reserve map entry to the given blob reserving a region at811* address address of length size.812*813* This function will insert data into the reserve map and will814* therefore change the indexes of some entries in the table.815*816* returns:817* 0, on success818* -FDT_ERR_NOSPACE, there is insufficient free space in the blob to819* contain the new reservation entry820* -FDT_ERR_BADMAGIC,821* -FDT_ERR_BADVERSION,822* -FDT_ERR_BADSTATE,823* -FDT_ERR_BADSTRUCTURE,824* -FDT_ERR_BADLAYOUT,825* -FDT_ERR_TRUNCATED, standard meanings826*/827int fdt_add_mem_rsv(void *fdt, uint64_t address, uint64_t size);828829/**830* fdt_del_mem_rsv - remove a memory reserve map entry831* @fdt: pointer to the device tree blob832* @n: entry to remove833*834* fdt_del_mem_rsv() removes the n-th memory reserve map entry from835* the blob.836*837* This function will delete data from the reservation table and will838* therefore change the indexes of some entries in the table.839*840* returns:841* 0, on success842* -FDT_ERR_NOTFOUND, there is no entry of the given index (i.e. there843* are less than n+1 reserve map entries)844* -FDT_ERR_BADMAGIC,845* -FDT_ERR_BADVERSION,846* -FDT_ERR_BADSTATE,847* -FDT_ERR_BADSTRUCTURE,848* -FDT_ERR_BADLAYOUT,849* -FDT_ERR_TRUNCATED, standard meanings850*/851int fdt_del_mem_rsv(void *fdt, int n);852853/**854* fdt_set_name - change the name of a given node855* @fdt: pointer to the device tree blob856* @nodeoffset: structure block offset of a node857* @name: name to give the node858*859* fdt_set_name() replaces the name (including unit address, if any)860* of the given node with the given string. NOTE: this function can't861* efficiently check if the new name is unique amongst the given862* node's siblings; results are undefined if this function is invoked863* with a name equal to one of the given node's siblings.864*865* This function may insert or delete data from the blob, and will866* therefore change the offsets of some existing nodes.867*868* returns:869* 0, on success870* -FDT_ERR_NOSPACE, there is insufficient free space in the blob871* to contain the new name872* -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag873* -FDT_ERR_BADMAGIC,874* -FDT_ERR_BADVERSION,875* -FDT_ERR_BADSTATE, standard meanings876*/877int fdt_set_name(void *fdt, int nodeoffset, const char *name);878879/**880* fdt_setprop - create or change a property881* @fdt: pointer to the device tree blob882* @nodeoffset: offset of the node whose property to change883* @name: name of the property to change884* @val: pointer to data to set the property value to885* @len: length of the property value886*887* fdt_setprop() sets the value of the named property in the given888* node to the given value and length, creating the property if it889* does not already exist.890*891* This function may insert or delete data from the blob, and will892* therefore change the offsets of some existing nodes.893*894* returns:895* 0, on success896* -FDT_ERR_NOSPACE, there is insufficient free space in the blob to897* contain the new property value898* -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag899* -FDT_ERR_BADLAYOUT,900* -FDT_ERR_BADMAGIC,901* -FDT_ERR_BADVERSION,902* -FDT_ERR_BADSTATE,903* -FDT_ERR_BADSTRUCTURE,904* -FDT_ERR_BADLAYOUT,905* -FDT_ERR_TRUNCATED, standard meanings906*/907int fdt_setprop(void *fdt, int nodeoffset, const char *name,908const void *val, int len);909910/**911* fdt_setprop_cell - set a property to a single cell value912* @fdt: pointer to the device tree blob913* @nodeoffset: offset of the node whose property to change914* @name: name of the property to change915* @val: 32-bit integer value for the property (native endian)916*917* fdt_setprop_cell() sets the value of the named property in the918* given node to the given cell value (converting to big-endian if919* necessary), or creates a new property with that value if it does920* not already exist.921*922* This function may insert or delete data from the blob, and will923* therefore change the offsets of some existing nodes.924*925* returns:926* 0, on success927* -FDT_ERR_NOSPACE, there is insufficient free space in the blob to928* contain the new property value929* -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag930* -FDT_ERR_BADLAYOUT,931* -FDT_ERR_BADMAGIC,932* -FDT_ERR_BADVERSION,933* -FDT_ERR_BADSTATE,934* -FDT_ERR_BADSTRUCTURE,935* -FDT_ERR_BADLAYOUT,936* -FDT_ERR_TRUNCATED, standard meanings937*/938static inline int fdt_setprop_cell(void *fdt, int nodeoffset, const char *name,939uint32_t val)940{941val = cpu_to_fdt32(val);942return fdt_setprop(fdt, nodeoffset, name, &val, sizeof(val));943}944945/**946* fdt_setprop_string - set a property to a string value947* @fdt: pointer to the device tree blob948* @nodeoffset: offset of the node whose property to change949* @name: name of the property to change950* @str: string value for the property951*952* fdt_setprop_string() sets the value of the named property in the953* given node to the given string value (using the length of the954* string to determine the new length of the property), or creates a955* new property with that value if it does not already exist.956*957* This function may insert or delete data from the blob, and will958* therefore change the offsets of some existing nodes.959*960* returns:961* 0, on success962* -FDT_ERR_NOSPACE, there is insufficient free space in the blob to963* contain the new property value964* -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag965* -FDT_ERR_BADLAYOUT,966* -FDT_ERR_BADMAGIC,967* -FDT_ERR_BADVERSION,968* -FDT_ERR_BADSTATE,969* -FDT_ERR_BADSTRUCTURE,970* -FDT_ERR_BADLAYOUT,971* -FDT_ERR_TRUNCATED, standard meanings972*/973#define fdt_setprop_string(fdt, nodeoffset, name, str) \974fdt_setprop((fdt), (nodeoffset), (name), (str), strlen(str)+1)975976/**977* fdt_delprop - delete a property978* @fdt: pointer to the device tree blob979* @nodeoffset: offset of the node whose property to nop980* @name: name of the property to nop981*982* fdt_del_property() will delete the given property.983*984* This function will delete data from the blob, and will therefore985* change the offsets of some existing nodes.986*987* returns:988* 0, on success989* -FDT_ERR_NOTFOUND, node does not have the named property990* -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag991* -FDT_ERR_BADLAYOUT,992* -FDT_ERR_BADMAGIC,993* -FDT_ERR_BADVERSION,994* -FDT_ERR_BADSTATE,995* -FDT_ERR_BADSTRUCTURE,996* -FDT_ERR_TRUNCATED, standard meanings997*/998int fdt_delprop(void *fdt, int nodeoffset, const char *name);9991000/**1001* fdt_add_subnode_namelen - creates a new node based on substring1002* @fdt: pointer to the device tree blob1003* @parentoffset: structure block offset of a node1004* @name: name of the subnode to locate1005* @namelen: number of characters of name to consider1006*1007* Identical to fdt_add_subnode(), but use only the first namelen1008* characters of name as the name of the new node. This is useful for1009* creating subnodes based on a portion of a larger string, such as a1010* full path.1011*/1012int fdt_add_subnode_namelen(void *fdt, int parentoffset,1013const char *name, int namelen);10141015/**1016* fdt_add_subnode - creates a new node1017* @fdt: pointer to the device tree blob1018* @parentoffset: structure block offset of a node1019* @name: name of the subnode to locate1020*1021* fdt_add_subnode() creates a new node as a subnode of the node at1022* structure block offset parentoffset, with the given name (which1023* should include the unit address, if any).1024*1025* This function will insert data into the blob, and will therefore1026* change the offsets of some existing nodes.10271028* returns:1029* structure block offset of the created nodeequested subnode (>=0), on success1030* -FDT_ERR_NOTFOUND, if the requested subnode does not exist1031* -FDT_ERR_BADOFFSET, if parentoffset did not point to an FDT_BEGIN_NODE tag1032* -FDT_ERR_EXISTS, if the node at parentoffset already has a subnode of1033* the given name1034* -FDT_ERR_NOSPACE, if there is insufficient free space in the1035* blob to contain the new node1036* -FDT_ERR_NOSPACE1037* -FDT_ERR_BADLAYOUT1038* -FDT_ERR_BADMAGIC,1039* -FDT_ERR_BADVERSION,1040* -FDT_ERR_BADSTATE,1041* -FDT_ERR_BADSTRUCTURE,1042* -FDT_ERR_TRUNCATED, standard meanings.1043*/1044int fdt_add_subnode(void *fdt, int parentoffset, const char *name);10451046/**1047* fdt_del_node - delete a node (subtree)1048* @fdt: pointer to the device tree blob1049* @nodeoffset: offset of the node to nop1050*1051* fdt_del_node() will remove the given node, including all its1052* subnodes if any, from the blob.1053*1054* This function will delete data from the blob, and will therefore1055* change the offsets of some existing nodes.1056*1057* returns:1058* 0, on success1059* -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag1060* -FDT_ERR_BADLAYOUT,1061* -FDT_ERR_BADMAGIC,1062* -FDT_ERR_BADVERSION,1063* -FDT_ERR_BADSTATE,1064* -FDT_ERR_BADSTRUCTURE,1065* -FDT_ERR_TRUNCATED, standard meanings1066*/1067int fdt_del_node(void *fdt, int nodeoffset);10681069/**********************************************************************/1070/* Debugging / informational functions */1071/**********************************************************************/10721073const char *fdt_strerror(int errval);10741075#endif /* _LIBFDT_H */107610771078