]> git.ipfire.org Git - people/ms/u-boot.git/blobdiff - include/libfdt.h
travisci: Add support for ARC
[people/ms/u-boot.git] / include / libfdt.h
index 765d84f5e4574eaab187be553cdbd449bf22b819..e2bc2e00c184e6e163711b18e02aea340dd4b126 100644 (file)
@@ -61,7 +61,7 @@
 #define FDT_ERR_NOTFOUND       1
        /* FDT_ERR_NOTFOUND: The requested node or property does not exist */
 #define FDT_ERR_EXISTS         2
-       /* FDT_ERR_EXISTS: Attemped to create a node or property which
+       /* FDT_ERR_EXISTS: Attempted to create a node or property which
         * already exists */
 #define FDT_ERR_NOSPACE                3
        /* FDT_ERR_NOSPACE: Operation needed to expand the device
         * (e.g. missing a leading / for a function which requires an
         * absolute path) */
 #define FDT_ERR_BADPHANDLE     6
-       /* FDT_ERR_BADPHANDLE: Function was passed an invalid phandle
-        * value.  phandle values of 0 and -1 are not permitted. */
+       /* FDT_ERR_BADPHANDLE: Function was passed an invalid phandle.
+        * This can be caused either by an invalid phandle property
+        * length, or the phandle value was either 0 or -1, which are
+        * not permitted. */
 #define FDT_ERR_BADSTATE       7
        /* FDT_ERR_BADSTATE: Function was passed an incomplete device
         * tree created by the sequential-write functions, which is
         * Should never be returned, if it is, it indicates a bug in
         * libfdt itself. */
 
-#define FDT_ERR_MAX            13
+/* Errors in device tree content */
+#define FDT_ERR_BADNCELLS      14
+       /* FDT_ERR_BADNCELLS: Device tree has a #address-cells, #size-cells
+        * or similar property with a bad format or value */
+
+#define FDT_ERR_BADVALUE       15
+       /* FDT_ERR_BADVALUE: Device tree has a property with an unexpected
+        * value. For example: a property expected to contain a string list
+        * is not NUL-terminated within the length of its value. */
+
+#define FDT_ERR_BADOVERLAY     16
+       /* FDT_ERR_BADOVERLAY: The device tree overlay, while
+        * correctly structured, cannot be applied due to some
+        * unexpected or missing value, property or node. */
+
+#define FDT_ERR_NOPHANDLES     17
+       /* FDT_ERR_NOPHANDLES: The device tree doesn't have any
+        * phandle available anymore without causing an overflow */
+
+#define FDT_ERR_TOODEEP        18
+       /* FDT_ERR_TOODEEP: The depth of a node has exceeded the internal
+        * libfdt limit. This can happen if you have more than
+        * FDT_MAX_DEPTH nested nodes. */
+
+#define FDT_ERR_MAX            18
 
 /**********************************************************************/
 /* Low-level functions (you probably don't need these)                */
@@ -158,6 +184,34 @@ int fdt_first_subnode(const void *fdt, int offset);
  */
 int fdt_next_subnode(const void *fdt, int offset);
 
+/**
+ * fdt_for_each_subnode - iterate over all subnodes of a parent
+ *
+ * @node:      child node (int, lvalue)
+ * @fdt:       FDT blob (const void *)
+ * @parent:    parent node (int)
+ *
+ * This is actually a wrapper around a for loop and would be used like so:
+ *
+ *     fdt_for_each_subnode(node, fdt, parent) {
+ *             Use node
+ *             ...
+ *     }
+ *
+ *     if ((node < 0) && (node != -FDT_ERR_NOT_FOUND)) {
+ *             Error handling
+ *     }
+ *
+ * Note that this is implemented as a macro and @node is used as
+ * iterator in the loop. The parent variable be constant or even a
+ * literal.
+ *
+ */
+#define fdt_for_each_subnode(node, fdt, parent)                \
+       for (node = fdt_first_subnode(fdt, parent);     \
+            node >= 0;                                 \
+            node = fdt_next_subnode(fdt, node))
+
 /**********************************************************************/
 /* General functions                                                  */
 /**********************************************************************/
@@ -178,7 +232,7 @@ int fdt_next_subnode(const void *fdt, int offset);
 #define __fdt_set_hdr(name) \
        static inline void fdt_set_##name(void *fdt, uint32_t val) \
        { \
-               struct fdt_header *fdth = (struct fdt_header*)fdt; \
+               struct fdt_header *fdth = (struct fdt_header *)fdt; \
                fdth->name = cpu_to_fdt32(val); \
        }
 __fdt_set_hdr(magic);
@@ -248,6 +302,21 @@ int fdt_move(const void *fdt, void *buf, int bufsize);
  */
 const char *fdt_string(const void *fdt, int stroffset);
 
+/**
+ * fdt_get_max_phandle - retrieves the highest phandle in a tree
+ * @fdt: pointer to the device tree blob
+ *
+ * fdt_get_max_phandle retrieves the highest phandle in the given
+ * device tree. This will ignore badly formatted phandles, or phandles
+ * with a value of 0 or -1.
+ *
+ * returns:
+ *      the highest phandle on success
+ *      0, if no phandle was found in the device tree
+ *      -1, if an error occurred
+ */
+uint32_t fdt_get_max_phandle(const void *fdt);
+
 /**
  * fdt_num_mem_rsv - retrieve the number of memory reserve map entries
  * @fdt: pointer to the device tree blob
@@ -308,8 +377,9 @@ int fdt_subnode_offset_namelen(const void *fdt, int parentoffset,
  * returns:
  *     structure block offset of the requested subnode (>=0), on success
  *     -FDT_ERR_NOTFOUND, if the requested subnode does not exist
- *     -FDT_ERR_BADOFFSET, if parentoffset did not point to an FDT_BEGIN_NODE tag
- *      -FDT_ERR_BADMAGIC,
+ *     -FDT_ERR_BADOFFSET, if parentoffset did not point to an FDT_BEGIN_NODE
+ *             tag
+ *     -FDT_ERR_BADMAGIC,
  *     -FDT_ERR_BADVERSION,
  *     -FDT_ERR_BADSTATE,
  *     -FDT_ERR_BADSTRUCTURE,
@@ -317,6 +387,17 @@ int fdt_subnode_offset_namelen(const void *fdt, int parentoffset,
  */
 int fdt_subnode_offset(const void *fdt, int parentoffset, const char *name);
 
+/**
+ * fdt_path_offset_namelen - find a tree node by its full path
+ * @fdt: pointer to the device tree blob
+ * @path: full path of the node to locate
+ * @namelen: number of characters of path to consider
+ *
+ * Identical to fdt_path_offset(), but only consider the first namelen
+ * characters of path as the path name.
+ */
+int fdt_path_offset_namelen(const void *fdt, const char *path, int namelen);
+
 /**
  * fdt_path_offset - find a tree node by its full path
  * @fdt: pointer to the device tree blob
@@ -330,7 +411,8 @@ int fdt_subnode_offset(const void *fdt, int parentoffset, const char *name);
  * address).
  *
  * returns:
- *     structure block offset of the node with the requested path (>=0), on success
+ *     structure block offset of the node with the requested path (>=0), on
+ *             success
  *     -FDT_ERR_BADPATH, given path does not begin with '/' or is invalid
  *     -FDT_ERR_NOTFOUND, if the requested node does not exist
  *      -FDT_ERR_BADMAGIC,
@@ -354,10 +436,12 @@ int fdt_path_offset(const void *fdt, const char *path);
  *
  * returns:
  *     pointer to the node's name, on success
- *             If lenp is non-NULL, *lenp contains the length of that name (>=0)
+ *             If lenp is non-NULL, *lenp contains the length of that name
+ *                     (>=0)
  *     NULL, on error
  *             if lenp is non-NULL *lenp contains an error code (<0):
- *             -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag
+ *             -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE
+ *                     tag
  *             -FDT_ERR_BADMAGIC,
  *             -FDT_ERR_BADVERSION,
  *             -FDT_ERR_BADSTATE, standard meanings
@@ -405,6 +489,33 @@ int fdt_first_property_offset(const void *fdt, int nodeoffset);
  */
 int fdt_next_property_offset(const void *fdt, int offset);
 
+/**
+ * fdt_for_each_property_offset - iterate over all properties of a node
+ *
+ * @property_offset:   property offset (int, lvalue)
+ * @fdt:               FDT blob (const void *)
+ * @node:              node offset (int)
+ *
+ * This is actually a wrapper around a for loop and would be used like so:
+ *
+ *     fdt_for_each_property_offset(property, fdt, node) {
+ *             Use property
+ *             ...
+ *     }
+ *
+ *     if ((property < 0) && (property != -FDT_ERR_NOT_FOUND)) {
+ *             Error handling
+ *     }
+ *
+ * Note that this is implemented as a macro and property is used as
+ * iterator in the loop. The node variable can be constant or even a
+ * literal.
+ */
+#define fdt_for_each_property_offset(property, fdt, node)      \
+       for (property = fdt_first_property_offset(fdt, node);   \
+            property >= 0;                                     \
+            property = fdt_next_property_offset(fdt, property))
+
 /**
  * fdt_get_property_by_offset - retrieve the property at a given offset
  * @fdt: pointer to the device tree blob
@@ -441,8 +552,8 @@ const struct fdt_property *fdt_get_property_by_offset(const void *fdt,
  * @namelen: number of characters of name to consider
  * @lenp: pointer to an integer variable (will be overwritten) or NULL
  *
- * Identical to fdt_get_property_namelen(), but only examine the first
- * namelen characters of name for matching the property name.
+ * Identical to fdt_get_property(), but only examine the first namelen
+ * characters of name for matching the property name.
  */
 const struct fdt_property *fdt_get_property_namelen(const void *fdt,
                                                    int nodeoffset,
@@ -469,7 +580,8 @@ const struct fdt_property *fdt_get_property_namelen(const void *fdt,
  *     NULL, on error
  *             if lenp is non-NULL, *lenp contains an error code (<0):
  *             -FDT_ERR_NOTFOUND, node does not have named property
- *             -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag
+ *             -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE
+ *                     tag
  *             -FDT_ERR_BADMAGIC,
  *             -FDT_ERR_BADVERSION,
  *             -FDT_ERR_BADSTATE,
@@ -533,6 +645,13 @@ const void *fdt_getprop_by_offset(const void *fdt, int offset,
  */
 const void *fdt_getprop_namelen(const void *fdt, int nodeoffset,
                                const char *name, int namelen, int *lenp);
+static inline void *fdt_getprop_namelen_w(void *fdt, int nodeoffset,
+                                         const char *name, int namelen,
+                                         int *lenp)
+{
+       return (void *)(uintptr_t)fdt_getprop_namelen(fdt, nodeoffset, name,
+                                                     namelen, lenp);
+}
 
 /**
  * fdt_getprop - retrieve the value of a given property
@@ -554,7 +673,8 @@ const void *fdt_getprop_namelen(const void *fdt, int nodeoffset,
  *     NULL, on error
  *             if lenp is non-NULL, *lenp contains an error code (<0):
  *             -FDT_ERR_NOTFOUND, node does not have named property
- *             -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag
+ *             -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE
+ *                     tag
  *             -FDT_ERR_BADMAGIC,
  *             -FDT_ERR_BADVERSION,
  *             -FDT_ERR_BADSTATE,
@@ -596,7 +716,7 @@ const char *fdt_get_alias_namelen(const void *fdt,
                                  const char *name, int namelen);
 
 /**
- * fdt_get_alias - retreive the path referenced by a given alias
+ * fdt_get_alias - retrieve the path referenced by a given alias
  * @fdt: pointer to the device tree blob
  * @name: name of the alias th look up
  *
@@ -656,11 +776,11 @@ int fdt_get_path(const void *fdt, int nodeoffset, char *buf, int buflen);
  * structure from the start to nodeoffset.
  *
  * returns:
-
  *     structure block offset of the node at node offset's ancestor
  *             of depth supernodedepth (>=0), on success
  *     -FDT_ERR_BADOFFSET, nodeoffset does not refer to a BEGIN_NODE tag
-*      -FDT_ERR_NOTFOUND, supernodedepth was greater than the depth of nodeoffset
+ *     -FDT_ERR_NOTFOUND, supernodedepth was greater than the depth of
+ *             nodeoffset
  *     -FDT_ERR_BADMAGIC,
  *     -FDT_ERR_BADVERSION,
  *     -FDT_ERR_BADSTATE,
@@ -731,7 +851,7 @@ int fdt_parent_offset(const void *fdt, int nodeoffset);
  *     offset = fdt_node_offset_by_prop_value(fdt, -1, propname,
  *                                            propval, proplen);
  *     while (offset != -FDT_ERR_NOTFOUND) {
- *             ... other code here ...
+ *             // other code here
  *             offset = fdt_node_offset_by_prop_value(fdt, offset, propname,
  *                                                    propval, proplen);
  *     }
@@ -816,7 +936,7 @@ int fdt_node_check_compatible(const void *fdt, int nodeoffset,
  * idiom can be used:
  *     offset = fdt_node_offset_by_compatible(fdt, -1, compatible);
  *     while (offset != -FDT_ERR_NOTFOUND) {
- *             ... other code here ...
+ *             // other code here
  *             offset = fdt_node_offset_by_compatible(fdt, offset, compatible);
  *     }
  *
@@ -852,10 +972,150 @@ int fdt_node_offset_by_compatible(const void *fdt, int startoffset,
  */
 int fdt_stringlist_contains(const char *strlist, int listlen, const char *str);
 
+/**
+ * fdt_stringlist_count - count the number of strings in a string list
+ * @fdt: pointer to the device tree blob
+ * @nodeoffset: offset of a tree node
+ * @property: name of the property containing the string list
+ * @return:
+ *   the number of strings in the given property
+ *   -FDT_ERR_BADVALUE if the property value is not NUL-terminated
+ *   -FDT_ERR_NOTFOUND if the property does not exist
+ */
+int fdt_stringlist_count(const void *fdt, int nodeoffset, const char *property);
+
+/**
+ * fdt_stringlist_search - find a string in a string list and return its index
+ * @fdt: pointer to the device tree blob
+ * @nodeoffset: offset of a tree node
+ * @property: name of the property containing the string list
+ * @string: string to look up in the string list
+ *
+ * Note that it is possible for this function to succeed on property values
+ * that are not NUL-terminated. That's because the function will stop after
+ * finding the first occurrence of @string. This can for example happen with
+ * small-valued cell properties, such as #address-cells, when searching for
+ * the empty string.
+ *
+ * @return:
+ *   the index of the string in the list of strings
+ *   -FDT_ERR_BADVALUE if the property value is not NUL-terminated
+ *   -FDT_ERR_NOTFOUND if the property does not exist or does not contain
+ *                     the given string
+ */
+int fdt_stringlist_search(const void *fdt, int nodeoffset, const char *property,
+                         const char *string);
+
+/**
+ * fdt_stringlist_get() - obtain the string at a given index in a string list
+ * @fdt: pointer to the device tree blob
+ * @nodeoffset: offset of a tree node
+ * @property: name of the property containing the string list
+ * @index: index of the string to return
+ * @lenp: return location for the string length or an error code on failure
+ *
+ * Note that this will successfully extract strings from properties with
+ * non-NUL-terminated values. For example on small-valued cell properties
+ * this function will return the empty string.
+ *
+ * If non-NULL, the length of the string (on success) or a negative error-code
+ * (on failure) will be stored in the integer pointer to by lenp.
+ *
+ * @return:
+ *   A pointer to the string at the given index in the string list or NULL on
+ *   failure. On success the length of the string will be stored in the memory
+ *   location pointed to by the lenp parameter, if non-NULL. On failure one of
+ *   the following negative error codes will be returned in the lenp parameter
+ *   (if non-NULL):
+ *     -FDT_ERR_BADVALUE if the property value is not NUL-terminated
+ *     -FDT_ERR_NOTFOUND if the property does not exist
+ */
+const char *fdt_stringlist_get(const void *fdt, int nodeoffset,
+                              const char *property, int index,
+                              int *lenp);
+
+/**********************************************************************/
+/* Read-only functions (addressing related)                           */
+/**********************************************************************/
+
+/**
+ * FDT_MAX_NCELLS - maximum value for #address-cells and #size-cells
+ *
+ * This is the maximum value for #address-cells, #size-cells and
+ * similar properties that will be processed by libfdt.  IEE1275
+ * requires that OF implementations handle values up to 4.
+ * Implementations may support larger values, but in practice higher
+ * values aren't used.
+ */
+#define FDT_MAX_NCELLS         4
+
+/**
+ * fdt_address_cells - retrieve address size for a bus represented in the tree
+ * @fdt: pointer to the device tree blob
+ * @nodeoffset: offset of the node to find the address size for
+ *
+ * When the node has a valid #address-cells property, returns its value.
+ *
+ * returns:
+ *     0 <= n < FDT_MAX_NCELLS, on success
+ *      2, if the node has no #address-cells property
+ *      -FDT_ERR_BADNCELLS, if the node has a badly formatted or invalid
+ *             #address-cells property
+ *     -FDT_ERR_BADMAGIC,
+ *     -FDT_ERR_BADVERSION,
+ *     -FDT_ERR_BADSTATE,
+ *     -FDT_ERR_BADSTRUCTURE,
+ *     -FDT_ERR_TRUNCATED, standard meanings
+ */
+int fdt_address_cells(const void *fdt, int nodeoffset);
+
+/**
+ * fdt_size_cells - retrieve address range size for a bus represented in the
+ *                  tree
+ * @fdt: pointer to the device tree blob
+ * @nodeoffset: offset of the node to find the address range size for
+ *
+ * When the node has a valid #size-cells property, returns its value.
+ *
+ * returns:
+ *     0 <= n < FDT_MAX_NCELLS, on success
+ *      2, if the node has no #address-cells property
+ *      -FDT_ERR_BADNCELLS, if the node has a badly formatted or invalid
+ *             #size-cells property
+ *     -FDT_ERR_BADMAGIC,
+ *     -FDT_ERR_BADVERSION,
+ *     -FDT_ERR_BADSTATE,
+ *     -FDT_ERR_BADSTRUCTURE,
+ *     -FDT_ERR_TRUNCATED, standard meanings
+ */
+int fdt_size_cells(const void *fdt, int nodeoffset);
+
+
 /**********************************************************************/
 /* Write-in-place functions                                           */
 /**********************************************************************/
 
+/**
+ * fdt_setprop_inplace_namelen_partial - change a property's value,
+ *                                       but not its size
+ * @fdt: pointer to the device tree blob
+ * @nodeoffset: offset of the node whose property to change
+ * @name: name of the property to change
+ * @namelen: number of characters of name to consider
+ * @idx: index of the property to change in the array
+ * @val: pointer to data to replace the property value with
+ * @len: length of the property value
+ *
+ * Identical to fdt_setprop_inplace(), but modifies the given property
+ * starting from the given index, and using only the first characters
+ * of the name. It is useful when you want to manipulate only one value of
+ * an array and you have a string that doesn't end with \0.
+ */
+int fdt_setprop_inplace_namelen_partial(void *fdt, int nodeoffset,
+                                       const char *name, int namelen,
+                                       uint32_t idx, const void *val,
+                                       int len);
+
 /**
  * fdt_setprop_inplace - change a property's value, but not its size
  * @fdt: pointer to the device tree blob
@@ -1023,6 +1283,7 @@ int fdt_nop_node(void *fdt, int nodeoffset);
 /**********************************************************************/
 
 int fdt_create(void *buf, int bufsize);
+int fdt_resize(void *fdt, void *buf, int bufsize);
 int fdt_add_reservemap_entry(void *fdt, uint64_t addr, uint64_t size);
 int fdt_finish_reservemap(void *fdt);
 int fdt_begin_node(void *fdt, const char *name);
@@ -1041,6 +1302,22 @@ static inline int fdt_property_cell(void *fdt, const char *name, uint32_t val)
 {
        return fdt_property_u32(fdt, name, val);
 }
+
+/**
+ * fdt_property_placeholder - add a new property and return a ptr to its value
+ *
+ * @fdt: pointer to the device tree blob
+ * @name: name of property to add
+ * @len: length of property value in bytes
+ * @valp: returns a pointer to where where the value should be placed
+ *
+ * returns:
+ *     0, on success
+ *     -FDT_ERR_BADMAGIC,
+ *     -FDT_ERR_NOSPACE, standard meanings
+ */
+int fdt_property_placeholder(void *fdt, const char *name, int len, void **valp);
+
 #define fdt_property_string(fdt, name, str) \
        fdt_property(fdt, name, str, strlen(str)+1)
 int fdt_end_node(void *fdt);
@@ -1465,9 +1742,11 @@ int fdt_add_subnode_namelen(void *fdt, int parentoffset,
  * change the offsets of some existing nodes.
 
  * returns:
- *     structure block offset of the created nodeequested subnode (>=0), on success
+ *     structure block offset of the created nodeequested subnode (>=0), on
+ *             success
  *     -FDT_ERR_NOTFOUND, if the requested subnode does not exist
- *     -FDT_ERR_BADOFFSET, if parentoffset did not point to an FDT_BEGIN_NODE tag
+ *     -FDT_ERR_BADOFFSET, if parentoffset did not point to an FDT_BEGIN_NODE
+ *             tag
  *     -FDT_ERR_EXISTS, if the node at parentoffset already has a subnode of
  *             the given name
  *     -FDT_ERR_NOSPACE, if there is insufficient free space in the
@@ -1505,17 +1784,136 @@ int fdt_add_subnode(void *fdt, int parentoffset, const char *name);
  */
 int fdt_del_node(void *fdt, int nodeoffset);
 
+/**
+ * fdt_overlay_apply - Applies a DT overlay on a base DT
+ * @fdt: pointer to the base device tree blob
+ * @fdto: pointer to the device tree overlay blob
+ *
+ * fdt_overlay_apply() will apply the given device tree overlay on the
+ * given base device tree.
+ *
+ * Expect the base device tree to be modified, even if the function
+ * returns an error.
+ *
+ * returns:
+ *     0, on success
+ *     -FDT_ERR_NOSPACE, there's not enough space in the base device tree
+ *     -FDT_ERR_NOTFOUND, the overlay points to some inexistant nodes or
+ *             properties in the base DT
+ *     -FDT_ERR_BADPHANDLE,
+ *     -FDT_ERR_BADOVERLAY,
+ *     -FDT_ERR_NOPHANDLES,
+ *     -FDT_ERR_INTERNAL,
+ *     -FDT_ERR_BADLAYOUT,
+ *     -FDT_ERR_BADMAGIC,
+ *     -FDT_ERR_BADOFFSET,
+ *     -FDT_ERR_BADPATH,
+ *     -FDT_ERR_BADVERSION,
+ *     -FDT_ERR_BADSTRUCTURE,
+ *     -FDT_ERR_BADSTATE,
+ *     -FDT_ERR_TRUNCATED, standard meanings
+ */
+int fdt_overlay_apply(void *fdt, void *fdto);
+
 /**********************************************************************/
 /* Debugging / informational functions                                */
 /**********************************************************************/
 
 const char *fdt_strerror(int errval);
 
+/**
+ * fdt_remove_unused_strings() - Remove any unused strings from an FDT
+ *
+ * This creates a new device tree in @new with unused strings removed. The
+ * called can then use fdt_pack() to minimise the space consumed.
+ *
+ * @old:       Old device tree blog
+ * @new:       Place to put new device tree blob, which must be as large as
+ *             @old
+ * @return
+ *     0, on success
+ *     -FDT_ERR_BADOFFSET, corrupt device tree
+ *     -FDT_ERR_NOSPACE, out of space, which should not happen unless there
+ *             is something very wrong with the device tree input
+ */
+int fdt_remove_unused_strings(const void *old, void *new);
+
 struct fdt_region {
        int offset;
        int size;
 };
 
+/*
+ * Flags for fdt_find_regions()
+ *
+ * Add a region for the string table (always the last region)
+ */
+#define FDT_REG_ADD_STRING_TAB         (1 << 0)
+
+/*
+ * Add all supernodes of a matching node/property, useful for creating a
+ * valid subset tree
+ */
+#define FDT_REG_SUPERNODES             (1 << 1)
+
+/* Add the FDT_BEGIN_NODE tags of subnodes, including their names */
+#define FDT_REG_DIRECT_SUBNODES        (1 << 2)
+
+/* Add all subnodes of a matching node */
+#define FDT_REG_ALL_SUBNODES           (1 << 3)
+
+/* Add a region for the mem_rsvmap table (always the first region) */
+#define FDT_REG_ADD_MEM_RSVMAP         (1 << 4)
+
+/* Indicates what an fdt part is (node, property, value) */
+#define FDT_IS_NODE                    (1 << 0)
+#define FDT_IS_PROP                    (1 << 1)
+#define FDT_IS_VALUE                   (1 << 2)        /* not supported */
+#define FDT_IS_COMPAT                  (1 << 3)        /* used internally */
+#define FDT_NODE_HAS_PROP              (1 << 4)        /* node contains prop */
+
+#define FDT_ANY_GLOBAL         (FDT_IS_NODE | FDT_IS_PROP | FDT_IS_VALUE | \
+                                       FDT_IS_COMPAT)
+#define FDT_IS_ANY                     0x1f            /* all the above */
+
+/* We set a reasonable limit on the number of nested nodes */
+#define FDT_MAX_DEPTH                  32
+
+/* Decribes what we want to include from the current tag */
+enum want_t {
+       WANT_NOTHING,
+       WANT_NODES_ONLY,                /* No properties */
+       WANT_NODES_AND_PROPS,           /* Everything for one level */
+       WANT_ALL_NODES_AND_PROPS        /* Everything for all levels */
+};
+
+/* Keeps track of the state at parent nodes */
+struct fdt_subnode_stack {
+       int offset;             /* Offset of node */
+       enum want_t want;       /* The 'want' value here */
+       int included;           /* 1 if we included this node, 0 if not */
+};
+
+struct fdt_region_ptrs {
+       int depth;                      /* Current tree depth */
+       int done;                       /* What we have completed scanning */
+       enum want_t want;               /* What we are currently including */
+       char *end;                      /* Pointer to end of full node path */
+       int nextoffset;                 /* Next node offset to check */
+};
+
+/* The state of our finding algortihm */
+struct fdt_region_state {
+       struct fdt_subnode_stack stack[FDT_MAX_DEPTH];  /* node stack */
+       struct fdt_region *region;      /* Contains list of regions found */
+       int count;                      /* Numnber of regions found */
+       const void *fdt;                /* FDT blob */
+       int max_regions;                /* Maximum regions to find */
+       int can_merge;          /* 1 if we can merge with previous region */
+       int start;                      /* Start position of current region */
+       struct fdt_region_ptrs ptrs;    /* Pointers for what we are up to */
+};
+
 /**
  * fdt_find_regions() - find regions in device tree
  *
@@ -1575,4 +1973,165 @@ int fdt_find_regions(const void *fdt, char * const inc[], int inc_count,
                     struct fdt_region region[], int max_regions,
                     char *path, int path_len, int add_string_tab);
 
+/**
+ * fdt_first_region() - find regions in device tree
+ *
+ * Given a nodes and properties to include and properties to exclude, find
+ * the regions of the device tree which describe those included parts.
+ *
+ * The use for this function is twofold. Firstly it provides a convenient
+ * way of performing a structure-aware grep of the tree. For example it is
+ * possible to grep for a node and get all the properties associated with
+ * that node. Trees can be subsetted easily, by specifying the nodes that
+ * are required, and then writing out the regions returned by this function.
+ * This is useful for small resource-constrained systems, such as boot
+ * loaders, which want to use an FDT but do not need to know about all of
+ * it.
+ *
+ * Secondly it makes it easy to hash parts of the tree and detect changes.
+ * The intent is to get a list of regions which will be invariant provided
+ * those parts are invariant. For example, if you request a list of regions
+ * for all nodes but exclude the property "data", then you will get the
+ * same region contents regardless of any change to "data" properties.
+ *
+ * This function can be used to produce a byte-stream to send to a hashing
+ * function to verify that critical parts of the FDT have not changed.
+ * Note that semantically null changes in order could still cause false
+ * hash misses. Such reordering might happen if the tree is regenerated
+ * from source, and nodes are reordered (the bytes-stream will be emitted
+ * in a different order and mnay hash functions will detect this). However
+ * if an existing tree is modified using libfdt functions, such as
+ * fdt_add_subnode() and fdt_setprop(), then this problem is avoided.
+ *
+ * The nodes/properties to include/exclude are defined by a function
+ * provided by the caller. This function is called for each node and
+ * property, and must return:
+ *
+ *    0 - to exclude this part
+ *    1 - to include this part
+ *   -1 - for FDT_IS_PROP only: no information is available, so include
+ *             if its containing node is included
+ *
+ * The last case is only used to deal with properties. Often a property is
+ * included if its containing node is included - this is the case where
+ * -1 is returned.. However if the property is specifically required to be
+ * included/excluded, then 0 or 1 can be returned. Note that including a
+ * property when the FDT_REG_SUPERNODES flag is given will force its
+ * containing node to be included since it is not valid to have a property
+ * that is not in a node.
+ *
+ * Using the information provided, the inclusion of a node can be controlled
+ * either by a node name or its compatible string, or any other property
+ * that the function can determine.
+ *
+ * As an example, including node "/" means to include the root node and all
+ * root properties. A flag provides a way of also including supernodes (of
+ * which there is none for the root node), and another flag includes
+ * immediate subnodes, so in this case we would get the FDT_BEGIN_NODE and
+ * FDT_END_NODE of all subnodes of /.
+ *
+ * The subnode feature helps in a hashing situation since it prevents the
+ * root node from changing at all. Any change to non-excluded properties,
+ * names of subnodes or number of subnodes would be detected.
+ *
+ * When used with FITs this provides the ability to hash and sign parts of
+ * the FIT based on different configurations in the FIT. Then it is
+ * impossible to change anything about that configuration (include images
+ * attached to the configuration), but it may be possible to add new
+ * configurations, new images or new signatures within the existing
+ * framework.
+ *
+ * Adding new properties to a device tree may result in the string table
+ * being extended (if the new property names are different from those
+ * already added). This function can optionally include a region for
+ * the string table so that this can be part of the hash too. This is always
+ * the last region.
+ *
+ * The FDT also has a mem_rsvmap table which can also be included, and is
+ * always the first region if so.
+ *
+ * The device tree header is not included in the region list. Since the
+ * contents of the FDT are changing (shrinking, often), the caller will need
+ * to regenerate the header anyway.
+ *
+ * @fdt:       Device tree to check
+ * @h_include: Function to call to determine whether to include a part or
+ *             not:
+ *
+ *             @priv: Private pointer as passed to fdt_find_regions()
+ *             @fdt: Pointer to FDT blob
+ *             @offset: Offset of this node / property
+ *             @type: Type of this part, FDT_IS_...
+ *             @data: Pointer to data (node name, property name, compatible
+ *                     string, value (not yet supported)
+ *             @size: Size of data, or 0 if none
+ *             @return 0 to exclude, 1 to include, -1 if no information is
+ *             available
+ * @priv:      Private pointer passed to h_include
+ * @region:    Returns list of regions, sorted by offset
+ * @max_regions: Maximum length of region list
+ * @path:      Pointer to a temporary string for the function to use for
+ *             building path names
+ * @path_len:  Length of path, must be large enough to hold the longest
+ *             path in the tree
+ * @flags:     Various flags that control the region algortihm, see
+ *             FDT_REG_...
+ * @return number of regions in list. If this is >max_regions then the
+ * region array was exhausted. You should increase max_regions and try
+ * the call again. Only the first max_regions elements are available in the
+ * array.
+ *
+ * On error a -ve value is return, which can be:
+ *
+ *     -FDT_ERR_BADSTRUCTURE (too deep or more END tags than BEGIN tags
+ *     -FDT_ERR_BADLAYOUT
+ *     -FDT_ERR_NOSPACE (path area is too small)
+ */
+int fdt_first_region(const void *fdt,
+               int (*h_include)(void *priv, const void *fdt, int offset,
+                                int type, const char *data, int size),
+               void *priv, struct fdt_region *region,
+               char *path, int path_len, int flags,
+               struct fdt_region_state *info);
+
+/** fdt_next_region() - find next region
+ *
+ * See fdt_first_region() for full description. This function finds the
+ * next region according to the provided parameters, which must be the same
+ * as passed to fdt_first_region().
+ *
+ * This function can additionally return -FDT_ERR_NOTFOUND when there are no
+ * more regions
+ */
+int fdt_next_region(const void *fdt,
+               int (*h_include)(void *priv, const void *fdt, int offset,
+                                int type, const char *data, int size),
+               void *priv, struct fdt_region *region,
+               char *path, int path_len, int flags,
+               struct fdt_region_state *info);
+
+/**
+ * fdt_add_alias_regions() - find aliases that point to existing regions
+ *
+ * Once a device tree grep is complete some of the nodes will be present
+ * and some will have been dropped. This function checks all the alias nodes
+ * to figure out which points point to nodes which are still present. These
+ * aliases need to be kept, along with the nodes they reference.
+ *
+ * Given a list of regions function finds the aliases that still apply and
+ * adds more regions to the list for these. This function is called after
+ * fdt_next_region() has finished returning regions and requires the same
+ * state.
+ *
+ * @fdt:       Device tree file to reference
+ * @region:    List of regions that will be kept
+ * @count:     Number of regions
+ * @max_regions: Number of entries that can fit in @region
+ * @info:      Region state as returned from fdt_next_region()
+ * @return new number of regions in @region (i.e. count + the number added)
+ * or -FDT_ERR_NOSPACE if there was not enough space.
+ */
+int fdt_add_alias_regions(const void *fdt, struct fdt_region *region, int count,
+                         int max_regions, struct fdt_region_state *info);
+
 #endif /* _LIBFDT_H */