EmbeddedPkg/Include/libfdt.h | 416 +++++++++++++++-- EmbeddedPkg/Include/libfdt_env.h | 4 + EmbeddedPkg/Library/FdtLib/FdtLib.inf | 1 + EmbeddedPkg/Library/FdtLib/Makefile.libfdt | 3 +- EmbeddedPkg/Library/FdtLib/fdt.c | 13 +- EmbeddedPkg/Library/FdtLib/fdt_addresses.c | 96 ++++ EmbeddedPkg/Library/FdtLib/fdt_empty_tree.c | 1 - EmbeddedPkg/Library/FdtLib/fdt_ro.c | 163 ++++++- EmbeddedPkg/Library/FdtLib/fdt_rw.c | 50 +- EmbeddedPkg/Library/FdtLib/fdt_strerror.c | 6 + EmbeddedPkg/Library/FdtLib/fdt_sw.c | 48 +- EmbeddedPkg/Library/FdtLib/fdt_wip.c | 33 +- EmbeddedPkg/Library/FdtLib/libfdt_internal.h | 6 +- EmbeddedPkg/Library/FdtLib/version.lds | 7 + 14 files changed, 760 insertions(+), 87 deletions(-)
Update the FdtLib so that new APIs provided by FdtLib like
fdt_address_cells, fdt_size_cells etc. can be used.
Reference code:
https://git.kernel.org/pub/scm/utils/dtc/dtc.git/tree/libfdt?h=v1.4.5
Cc: Leif Lindholm <leif.lindholm@linaro.org>
Cc: Ard Biesheuvel <ard.biesheuvel@linaro.org>
Contributed-under: TianoCore Contribution Agreement 1.1
Signed-off-by: Pankaj Bansal <pankaj.bansal@nxp.com>
---
Notes:
The source code has been copied under BSD license terms.
One file fdt_overlay.c which is part of libfdt has no license
header specified at the top of file.
Therefore that file and the references to functions defined in
that file have been removed.
EmbeddedPkg/Include/libfdt.h | 416 +++++++++++++++--
EmbeddedPkg/Include/libfdt_env.h | 4 +
EmbeddedPkg/Library/FdtLib/FdtLib.inf | 1 +
EmbeddedPkg/Library/FdtLib/Makefile.libfdt | 3 +-
EmbeddedPkg/Library/FdtLib/fdt.c | 13 +-
EmbeddedPkg/Library/FdtLib/fdt_addresses.c | 96 ++++
EmbeddedPkg/Library/FdtLib/fdt_empty_tree.c | 1 -
EmbeddedPkg/Library/FdtLib/fdt_ro.c | 163 ++++++-
EmbeddedPkg/Library/FdtLib/fdt_rw.c | 50 +-
EmbeddedPkg/Library/FdtLib/fdt_strerror.c | 6 +
EmbeddedPkg/Library/FdtLib/fdt_sw.c | 48 +-
EmbeddedPkg/Library/FdtLib/fdt_wip.c | 33 +-
EmbeddedPkg/Library/FdtLib/libfdt_internal.h | 6 +-
EmbeddedPkg/Library/FdtLib/version.lds | 7 +
14 files changed, 760 insertions(+), 87 deletions(-)
diff --git a/EmbeddedPkg/Include/libfdt.h b/EmbeddedPkg/Include/libfdt.h
index 212cb99..1aabec3 100644
--- a/EmbeddedPkg/Include/libfdt.h
+++ b/EmbeddedPkg/Include/libfdt.h
@@ -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
@@ -79,8 +79,10 @@
* (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
@@ -116,13 +118,34 @@
* 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_MAX 17
/**********************************************************************/
/* Low-level functions (you probably don't need these) */
/**********************************************************************/
+#ifndef SWIG /* This function is not useful in Python */
const void *fdt_offset_ptr(const void *fdt, int offset, unsigned int checklen);
+#endif
static inline void *fdt_offset_ptr_w(void *fdt, int offset, int checklen)
{
return (void *)(uintptr_t)fdt_offset_ptr(fdt, offset, checklen);
@@ -158,27 +181,54 @@ 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 */
/**********************************************************************/
-
#define fdt_get_header(fdt, field) \
(fdt32_to_cpu(((const struct fdt_header *)(fdt))->field))
-#define fdt_magic(fdt) (fdt_get_header(fdt, magic))
+#define fdt_magic(fdt) (fdt_get_header(fdt, magic))
#define fdt_totalsize(fdt) (fdt_get_header(fdt, totalsize))
#define fdt_off_dt_struct(fdt) (fdt_get_header(fdt, off_dt_struct))
#define fdt_off_dt_strings(fdt) (fdt_get_header(fdt, off_dt_strings))
#define fdt_off_mem_rsvmap(fdt) (fdt_get_header(fdt, off_mem_rsvmap))
#define fdt_version(fdt) (fdt_get_header(fdt, version))
-#define fdt_last_comp_version(fdt) (fdt_get_header(fdt, last_comp_version))
-#define fdt_boot_cpuid_phys(fdt) (fdt_get_header(fdt, boot_cpuid_phys))
-#define fdt_size_dt_strings(fdt) (fdt_get_header(fdt, size_dt_strings))
+#define fdt_last_comp_version(fdt) (fdt_get_header(fdt, last_comp_version))
+#define fdt_boot_cpuid_phys(fdt) (fdt_get_header(fdt, boot_cpuid_phys))
+#define fdt_size_dt_strings(fdt) (fdt_get_header(fdt, size_dt_strings))
#define fdt_size_dt_struct(fdt) (fdt_get_header(fdt, size_dt_struct))
#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);
@@ -249,6 +299,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
*
@@ -290,8 +355,10 @@ int fdt_get_mem_rsv(const void *fdt, int n, uint64_t *address, uint64_t *size);
* useful for finding subnodes based on a portion of a larger string,
* such as a full path.
*/
+#ifndef SWIG /* Not available in Python */
int fdt_subnode_offset_namelen(const void *fdt, int parentoffset,
const char *name, int namelen);
+#endif
/**
* fdt_subnode_offset - find a subnode of a given node
* @fdt: pointer to the device tree blob
@@ -308,8 +375,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,
@@ -318,6 +386,19 @@ 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.
+ */
+#ifndef SWIG /* Not available in Python */
+int fdt_path_offset_namelen(const void *fdt, const char *path, int namelen);
+#endif
+
+/**
* fdt_path_offset - find a tree node by its full path
* @fdt: pointer to the device tree blob
* @path: full path of the node to locate
@@ -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
@@ -406,6 +490,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
* @offset: offset of the property to retrieve
@@ -441,13 +552,15 @@ 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.
*/
+#ifndef SWIG /* Not available in Python */
const struct fdt_property *fdt_get_property_namelen(const void *fdt,
int nodeoffset,
const char *name,
int namelen, int *lenp);
+#endif
/**
* fdt_get_property - find a given property in a given node
@@ -469,7 +582,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,
@@ -517,8 +631,10 @@ static inline struct fdt_property *fdt_get_property_w(void *fdt, int nodeoffset,
* -FDT_ERR_BADSTRUCTURE,
* -FDT_ERR_TRUNCATED, standard meanings
*/
+#ifndef SWIG /* This function is not useful in Python */
const void *fdt_getprop_by_offset(const void *fdt, int offset,
const char **namep, int *lenp);
+#endif
/**
* fdt_getprop_namelen - get property value based on substring
@@ -531,8 +647,17 @@ const void *fdt_getprop_by_offset(const void *fdt, int offset,
* Identical to fdt_getprop(), but only examine the first namelen
* characters of name for matching the property name.
*/
+#ifndef SWIG /* Not available in Python */
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);
+}
+#endif
/**
* fdt_getprop - retrieve the value of a given property
@@ -554,7 +679,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,
@@ -592,11 +718,13 @@ uint32_t fdt_get_phandle(const void *fdt, int nodeoffset);
* Identical to fdt_get_alias(), but only examine the first namelen
* characters of name for matching the alias name.
*/
+#ifndef SWIG /* Not available in Python */
const char *fdt_get_alias_namelen(const void *fdt,
const char *name, int namelen);
+#endif
/**
- * 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
*
@@ -626,7 +754,7 @@ const char *fdt_get_alias(const void *fdt, const char *name);
* 0, on success
* buf contains the absolute path of the node at
* nodeoffset, as a NUL-terminated string.
- * -FDT_ERR_BADOFFSET, nodeoffset does not refer to a BEGIN_NODE tag
+ * -FDT_ERR_BADOFFSET, nodeoffset does not refer to a BEGIN_NODE tag
* -FDT_ERR_NOSPACE, the path of the given node is longer than (bufsize-1)
* characters and will not fit in the given buffer.
* -FDT_ERR_BADMAGIC,
@@ -656,11 +784,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_BADOFFSET, nodeoffset does not refer to a BEGIN_NODE tag
+ * -FDT_ERR_NOTFOUND, supernodedepth was greater than the depth of
+ * nodeoffset
* -FDT_ERR_BADMAGIC,
* -FDT_ERR_BADVERSION,
* -FDT_ERR_BADSTATE,
@@ -682,7 +810,7 @@ int fdt_supernode_atdepth_offset(const void *fdt, int nodeoffset,
*
* returns:
* depth of the node at nodeoffset (>=0), on success
- * -FDT_ERR_BADOFFSET, nodeoffset does not refer to a BEGIN_NODE tag
+ * -FDT_ERR_BADOFFSET, nodeoffset does not refer to a BEGIN_NODE tag
* -FDT_ERR_BADMAGIC,
* -FDT_ERR_BADVERSION,
* -FDT_ERR_BADSTATE,
@@ -705,7 +833,7 @@ int fdt_node_depth(const void *fdt, int nodeoffset);
* returns:
* structure block offset of the parent of the node at nodeoffset
* (>=0), on success
- * -FDT_ERR_BADOFFSET, nodeoffset does not refer to a BEGIN_NODE tag
+ * -FDT_ERR_BADOFFSET, nodeoffset does not refer to a BEGIN_NODE tag
* -FDT_ERR_BADMAGIC,
* -FDT_ERR_BADVERSION,
* -FDT_ERR_BADSTATE,
@@ -745,7 +873,7 @@ int fdt_parent_offset(const void *fdt, int nodeoffset);
* on success
* -FDT_ERR_NOTFOUND, no node matching the criterion exists in the
* tree after startoffset
- * -FDT_ERR_BADOFFSET, nodeoffset does not refer to a BEGIN_NODE tag
+ * -FDT_ERR_BADOFFSET, nodeoffset does not refer to a BEGIN_NODE tag
* -FDT_ERR_BADMAGIC,
* -FDT_ERR_BADVERSION,
* -FDT_ERR_BADSTATE,
@@ -792,7 +920,7 @@ int fdt_node_offset_by_phandle(const void *fdt, uint32_t phandle);
* 1, if the node has a 'compatible' property, but it does not list
* the given string
* -FDT_ERR_NOTFOUND, if the given node has no 'compatible' property
- * -FDT_ERR_BADOFFSET, if nodeoffset does not refer to a BEGIN_NODE tag
+ * -FDT_ERR_BADOFFSET, if nodeoffset does not refer to a BEGIN_NODE tag
* -FDT_ERR_BADMAGIC,
* -FDT_ERR_BADVERSION,
* -FDT_ERR_BADSTATE,
@@ -829,7 +957,7 @@ int fdt_node_check_compatible(const void *fdt, int nodeoffset,
* on success
* -FDT_ERR_NOTFOUND, no node matching the criterion exists in the
* tree after startoffset
- * -FDT_ERR_BADOFFSET, nodeoffset does not refer to a BEGIN_NODE tag
+ * -FDT_ERR_BADOFFSET, nodeoffset does not refer to a BEGIN_NODE tag
* -FDT_ERR_BADMAGIC,
* -FDT_ERR_BADVERSION,
* -FDT_ERR_BADSTATE,
@@ -852,11 +980,153 @@ 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.
+ */
+#ifndef SWIG /* Not available in Python */
+int fdt_setprop_inplace_namelen_partial(void *fdt, int nodeoffset,
+ const char *name, int namelen,
+ uint32_t idx, const void *val,
+ int len);
+#endif
+
+/**
* fdt_setprop_inplace - 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
@@ -884,8 +1154,10 @@ int fdt_stringlist_contains(const char *strlist, int listlen, const char *str);
* -FDT_ERR_BADSTRUCTURE,
* -FDT_ERR_TRUNCATED, standard meanings
*/
+#ifndef SWIG /* Not available in Python */
int fdt_setprop_inplace(void *fdt, int nodeoffset, const char *name,
const void *val, int len);
+#endif
/**
* fdt_setprop_inplace_u32 - change the value of a 32-bit integer property
@@ -1023,6 +1295,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 +1314,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);
@@ -1160,6 +1449,37 @@ int fdt_setprop(void *fdt, int nodeoffset, const char *name,
const void *val, int len);
/**
+ * fdt_setprop _placeholder - allocate space for a property
+ * @fdt: pointer to the device tree blob
+ * @nodeoffset: offset of the node whose property to change
+ * @name: name of the property to change
+ * @len: length of the property value
+ * @prop_data: return pointer to property data
+ *
+ * fdt_setprop_placeholer() allocates the named property in the given node.
+ * If the property exists it is resized. In either case a pointer to the
+ * property data is returned.
+ *
+ * This function may insert or delete data from the blob, and will
+ * therefore change the offsets of some existing nodes.
+ *
+ * returns:
+ * 0, on success
+ * -FDT_ERR_NOSPACE, there is insufficient free space in the blob to
+ * contain the new property value
+ * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag
+ * -FDT_ERR_BADLAYOUT,
+ * -FDT_ERR_BADMAGIC,
+ * -FDT_ERR_BADVERSION,
+ * -FDT_ERR_BADSTATE,
+ * -FDT_ERR_BADSTRUCTURE,
+ * -FDT_ERR_BADLAYOUT,
+ * -FDT_ERR_TRUNCATED, standard meanings
+ */
+int fdt_setprop_placeholder(void *fdt, int nodeoffset, const char *name,
+ int len, void **prop_data);
+
+/**
* fdt_setprop_u32 - set a property to a 32-bit integer
* @fdt: pointer to the device tree blob
* @nodeoffset: offset of the node whose property to change
@@ -1271,6 +1591,36 @@ static inline int fdt_setprop_cell(void *fdt, int nodeoffset, const char *name,
#define fdt_setprop_string(fdt, nodeoffset, name, str) \
fdt_setprop((fdt), (nodeoffset), (name), (str), strlen(str)+1)
+
+/**
+ * fdt_setprop_empty - set a property to an empty value
+ * @fdt: pointer to the device tree blob
+ * @nodeoffset: offset of the node whose property to change
+ * @name: name of the property to change
+ *
+ * fdt_setprop_empty() sets the value of the named property in the
+ * given node to an empty (zero length) value, or creates a new empty
+ * property if it does not already exist.
+ *
+ * This function may insert or delete data from the blob, and will
+ * therefore change the offsets of some existing nodes.
+ *
+ * returns:
+ * 0, on success
+ * -FDT_ERR_NOSPACE, there is insufficient free space in the blob to
+ * contain the new property value
+ * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag
+ * -FDT_ERR_BADLAYOUT,
+ * -FDT_ERR_BADMAGIC,
+ * -FDT_ERR_BADVERSION,
+ * -FDT_ERR_BADSTATE,
+ * -FDT_ERR_BADSTRUCTURE,
+ * -FDT_ERR_BADLAYOUT,
+ * -FDT_ERR_TRUNCATED, standard meanings
+ */
+#define fdt_setprop_empty(fdt, nodeoffset, name) \
+ fdt_setprop((fdt), (nodeoffset), (name), NULL, 0)
+
/**
* fdt_appendprop - append to or create a property
* @fdt: pointer to the device tree blob
@@ -1448,8 +1798,10 @@ int fdt_delprop(void *fdt, int nodeoffset, const char *name);
* creating subnodes based on a portion of a larger string, such as a
* full path.
*/
+#ifndef SWIG /* Not available in Python */
int fdt_add_subnode_namelen(void *fdt, int parentoffset,
const char *name, int namelen);
+#endif
/**
* fdt_add_subnode - creates a new node
@@ -1465,9 +1817,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
diff --git a/EmbeddedPkg/Include/libfdt_env.h b/EmbeddedPkg/Include/libfdt_env.h
index 3e24db9..d84a6a4 100644
--- a/EmbeddedPkg/Include/libfdt_env.h
+++ b/EmbeddedPkg/Include/libfdt_env.h
@@ -78,4 +78,8 @@ static inline char *strchr(const char *s, int c) {
return AsciiStrStr (s, pattern);
}
+static inline size_t strnlen (const char* str, size_t strsz ) {
+ return AsciiStrnLenS (str, strsz);
+}
+
#endif /* _LIBFDT_ENV_H */
diff --git a/EmbeddedPkg/Library/FdtLib/FdtLib.inf b/EmbeddedPkg/Library/FdtLib/FdtLib.inf
index f3da231..b26d374 100644
--- a/EmbeddedPkg/Library/FdtLib/FdtLib.inf
+++ b/EmbeddedPkg/Library/FdtLib/FdtLib.inf
@@ -32,6 +32,7 @@
fdt_sw.c
fdt_wip.c
fdt.c
+ fdt_addresses.c
[Packages]
MdePkg/MdePkg.dec
diff --git a/EmbeddedPkg/Library/FdtLib/Makefile.libfdt b/EmbeddedPkg/Library/FdtLib/Makefile.libfdt
index 91126c0..09c322e 100644
--- a/EmbeddedPkg/Library/FdtLib/Makefile.libfdt
+++ b/EmbeddedPkg/Library/FdtLib/Makefile.libfdt
@@ -6,5 +6,6 @@
LIBFDT_soname = libfdt.$(SHAREDLIB_EXT).1
LIBFDT_INCLUDES = fdt.h libfdt.h libfdt_env.h
LIBFDT_VERSION = version.lds
-LIBFDT_SRCS = fdt.c fdt_ro.c fdt_wip.c fdt_sw.c fdt_rw.c fdt_strerror.c fdt_empty_tree.c
+LIBFDT_SRCS = fdt.c fdt_ro.c fdt_wip.c fdt_sw.c fdt_rw.c fdt_strerror.c fdt_empty_tree.c \
+ fdt_addresses.c
LIBFDT_OBJS = $(LIBFDT_SRCS:%.c=%.o)
diff --git a/EmbeddedPkg/Library/FdtLib/fdt.c b/EmbeddedPkg/Library/FdtLib/fdt.c
index 9639528..29756a8 100644
--- a/EmbeddedPkg/Library/FdtLib/fdt.c
+++ b/EmbeddedPkg/Library/FdtLib/fdt.c
@@ -76,18 +76,19 @@ int fdt_check_header(const void *fdt)
const void *fdt_offset_ptr(const void *fdt, int offset, unsigned int len)
{
- const char *p;
+ unsigned absoffset = offset + fdt_off_dt_struct(fdt);
+
+ if ((absoffset < offset)
+ || ((absoffset + len) < absoffset)
+ || (absoffset + len) > fdt_totalsize(fdt))
+ return NULL;
if (fdt_version(fdt) >= 0x11)
if (((offset + len) < offset)
|| ((offset + len) > fdt_size_dt_struct(fdt)))
return NULL;
- p = _fdt_offset_ptr(fdt, offset);
-
- if (p + len < p)
- return NULL;
- return p;
+ return _fdt_offset_ptr(fdt, offset);
}
uint32_t fdt_next_tag(const void *fdt, int startoffset, int *nextoffset)
diff --git a/EmbeddedPkg/Library/FdtLib/fdt_addresses.c b/EmbeddedPkg/Library/FdtLib/fdt_addresses.c
new file mode 100644
index 0000000..f48da28
--- /dev/null
+++ b/EmbeddedPkg/Library/FdtLib/fdt_addresses.c
@@ -0,0 +1,96 @@
+/*
+ * libfdt - Flat Device Tree manipulation
+ * Copyright (C) 2014 David Gibson <david@gibson.dropbear.id.au>
+ *
+ * libfdt is dual licensed: you can use it either under the terms of
+ * the GPL, or the BSD license, at your option.
+ *
+ * a) This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
+ * MA 02110-1301 USA
+ *
+ * Alternatively,
+ *
+ * b) Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer.
+ * 2. Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+ * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#include "libfdt_env.h"
+
+#include <fdt.h>
+#include <libfdt.h>
+
+#include "libfdt_internal.h"
+
+int fdt_address_cells(const void *fdt, int nodeoffset)
+{
+ const fdt32_t *ac;
+ int val;
+ int len;
+
+ ac = fdt_getprop(fdt, nodeoffset, "#address-cells", &len);
+ if (!ac)
+ return 2;
+
+ if (len != sizeof(*ac))
+ return -FDT_ERR_BADNCELLS;
+
+ val = fdt32_to_cpu(*ac);
+ if ((val <= 0) || (val > FDT_MAX_NCELLS))
+ return -FDT_ERR_BADNCELLS;
+
+ return val;
+}
+
+int fdt_size_cells(const void *fdt, int nodeoffset)
+{
+ const fdt32_t *sc;
+ int val;
+ int len;
+
+ sc = fdt_getprop(fdt, nodeoffset, "#size-cells", &len);
+ if (!sc)
+ return 2;
+
+ if (len != sizeof(*sc))
+ return -FDT_ERR_BADNCELLS;
+
+ val = fdt32_to_cpu(*sc);
+ if ((val < 0) || (val > FDT_MAX_NCELLS))
+ return -FDT_ERR_BADNCELLS;
+
+ return val;
+}
diff --git a/EmbeddedPkg/Library/FdtLib/fdt_empty_tree.c b/EmbeddedPkg/Library/FdtLib/fdt_empty_tree.c
index f00a899..634b436 100644
--- a/EmbeddedPkg/Library/FdtLib/fdt_empty_tree.c
+++ b/EmbeddedPkg/Library/FdtLib/fdt_empty_tree.c
@@ -81,4 +81,3 @@ int fdt_create_empty_tree(void *buf, int bufsize)
return fdt_open_into(buf, buf, bufsize);
}
-
diff --git a/EmbeddedPkg/Library/FdtLib/fdt_ro.c b/EmbeddedPkg/Library/FdtLib/fdt_ro.c
index 2055891..9413f50 100644
--- a/EmbeddedPkg/Library/FdtLib/fdt_ro.c
+++ b/EmbeddedPkg/Library/FdtLib/fdt_ro.c
@@ -60,7 +60,7 @@ static int _fdt_nodename_eq(const void *fdt, int offset,
{
const char *p = fdt_offset_ptr(fdt, offset + FDT_TAGSIZE, len+1);
- if (! p)
+ if (!p)
/* short match */
return 0;
@@ -88,6 +88,32 @@ static int _fdt_string_eq(const void *fdt, int stroffset,
return (strlen(p) == len) && (memcmp(p, s, len) == 0);
}
+uint32_t fdt_get_max_phandle(const void *fdt)
+{
+ uint32_t max_phandle = 0;
+ int offset;
+
+ for (offset = fdt_next_node(fdt, -1, NULL);;
+ offset = fdt_next_node(fdt, offset, NULL)) {
+ uint32_t phandle;
+
+ if (offset == -FDT_ERR_NOTFOUND)
+ return max_phandle;
+
+ if (offset < 0)
+ return (uint32_t)-1;
+
+ phandle = fdt_get_phandle(fdt, offset);
+ if (phandle == (uint32_t)-1)
+ continue;
+
+ if (phandle > max_phandle)
+ max_phandle = phandle;
+ }
+
+ return 0;
+}
+
int fdt_get_mem_rsv(const void *fdt, int n, uint64_t *address, uint64_t *size)
{
FDT_CHECK_HEADER(fdt);
@@ -154,9 +180,9 @@ int fdt_subnode_offset(const void *fdt, int parentoffset,
return fdt_subnode_offset_namelen(fdt, parentoffset, name, strlen(name));
}
-int fdt_path_offset(const void *fdt, const char *path)
+int fdt_path_offset_namelen(const void *fdt, const char *path, int namelen)
{
- const char *end = path + strlen(path);
+ const char *end = path + namelen;
const char *p = path;
int offset = 0;
@@ -164,7 +190,7 @@ int fdt_path_offset(const void *fdt, const char *path)
/* see if we have an alias */
if (*path != '/') {
- const char *q = strchr(path, '/');
+ const char *q = memchr(path, '/', end - p);
if (!q)
q = end;
@@ -177,14 +203,15 @@ int fdt_path_offset(const void *fdt, const char *path)
p = q;
}
- while (*p) {
+ while (p < end) {
const char *q;
- while (*p == '/')
+ while (*p == '/') {
p++;
- if (! *p)
- return offset;
- q = strchr(p, '/');
+ if (p == end)
+ return offset;
+ }
+ q = memchr(p, '/', end - p);
if (! q)
q = end;
@@ -198,6 +225,11 @@ int fdt_path_offset(const void *fdt, const char *path)
return offset;
}
+int fdt_path_offset(const void *fdt, const char *path)
+{
+ return fdt_path_offset_namelen(fdt, path, strlen(path));
+}
+
const char *fdt_get_name(const void *fdt, int nodeoffset, int *len)
{
const struct fdt_node_header *nh = _fdt_offset_ptr(fdt, nodeoffset);
@@ -267,8 +299,7 @@ const struct fdt_property *fdt_get_property_namelen(const void *fdt,
(offset = fdt_next_property_offset(fdt, offset))) {
const struct fdt_property *prop;
- prop = fdt_get_property_by_offset(fdt, offset, lenp);
- if (!prop) {
+ if (!(prop = fdt_get_property_by_offset(fdt, offset, lenp))) {
offset = -FDT_ERR_INTERNAL;
break;
}
@@ -296,7 +327,7 @@ const void *fdt_getprop_namelen(const void *fdt, int nodeoffset,
const struct fdt_property *prop;
prop = fdt_get_property_namelen(fdt, nodeoffset, name, namelen, lenp);
- if (! prop)
+ if (!prop)
return NULL;
return prop->data;
@@ -495,7 +526,7 @@ int fdt_node_offset_by_phandle(const void *fdt, uint32_t phandle)
{
int offset;
- if ((phandle == 0) || (phandle == (uint32_t)-1))
+ if ((phandle == 0) || (phandle == -1))
return -FDT_ERR_BADPHANDLE;
FDT_CHECK_HEADER(fdt);
@@ -533,6 +564,106 @@ int fdt_stringlist_contains(const char *strlist, int listlen, const char *str)
return 0;
}
+int fdt_stringlist_count(const void *fdt, int nodeoffset, const char *property)
+{
+ const char *list, *end;
+ int length, count = 0;
+
+ list = fdt_getprop(fdt, nodeoffset, property, &length);
+ if (!list)
+ return length;
+
+ end = list + length;
+
+ while (list < end) {
+ length = strnlen(list, end - list) + 1;
+
+ /* Abort if the last string isn't properly NUL-terminated. */
+ if (list + length > end)
+ return -FDT_ERR_BADVALUE;
+
+ list += length;
+ count++;
+ }
+
+ return count;
+}
+
+int fdt_stringlist_search(const void *fdt, int nodeoffset, const char *property,
+ const char *string)
+{
+ int length, len, idx = 0;
+ const char *list, *end;
+
+ list = fdt_getprop(fdt, nodeoffset, property, &length);
+ if (!list)
+ return length;
+
+ len = strlen(string) + 1;
+ end = list + length;
+
+ while (list < end) {
+ length = strnlen(list, end - list) + 1;
+
+ /* Abort if the last string isn't properly NUL-terminated. */
+ if (list + length > end)
+ return -FDT_ERR_BADVALUE;
+
+ if (length == len && memcmp(list, string, length) == 0)
+ return idx;
+
+ list += length;
+ idx++;
+ }
+
+ return -FDT_ERR_NOTFOUND;
+}
+
+const char *fdt_stringlist_get(const void *fdt, int nodeoffset,
+ const char *property, int idx,
+ int *lenp)
+{
+ const char *list, *end;
+ int length;
+
+ list = fdt_getprop(fdt, nodeoffset, property, &length);
+ if (!list) {
+ if (lenp)
+ *lenp = length;
+
+ return NULL;
+ }
+
+ end = list + length;
+
+ while (list < end) {
+ length = strnlen(list, end - list) + 1;
+
+ /* Abort if the last string isn't properly NUL-terminated. */
+ if (list + length > end) {
+ if (lenp)
+ *lenp = -FDT_ERR_BADVALUE;
+
+ return NULL;
+ }
+
+ if (idx == 0) {
+ if (lenp)
+ *lenp = length - 1;
+
+ return list;
+ }
+
+ list += length;
+ idx--;
+ }
+
+ if (lenp)
+ *lenp = -FDT_ERR_NOTFOUND;
+
+ return NULL;
+}
+
int fdt_node_check_compatible(const void *fdt, int nodeoffset,
const char *compatible)
{
@@ -542,10 +673,8 @@ int fdt_node_check_compatible(const void *fdt, int nodeoffset,
prop = fdt_getprop(fdt, nodeoffset, "compatible", &len);
if (!prop)
return len;
- if (fdt_stringlist_contains(prop, len, compatible))
- return 0;
- else
- return 1;
+
+ return !fdt_stringlist_contains(prop, len, compatible);
}
int fdt_node_offset_by_compatible(const void *fdt, int startoffset,
diff --git a/EmbeddedPkg/Library/FdtLib/fdt_rw.c b/EmbeddedPkg/Library/FdtLib/fdt_rw.c
index 7a2bcf3..863f2b2 100644
--- a/EmbeddedPkg/Library/FdtLib/fdt_rw.c
+++ b/EmbeddedPkg/Library/FdtLib/fdt_rw.c
@@ -84,9 +84,9 @@ static int _fdt_rw_check_header(void *fdt)
#define FDT_RW_CHECK_HEADER(fdt) \
{ \
- int err; \
- if ((err = _fdt_rw_check_header(fdt)) != 0) \
- return err; \
+ int __err; \
+ if ((__err = _fdt_rw_check_header(fdt)) != 0) \
+ return __err; \
}
static inline int _fdt_data_size(void *fdt)
@@ -101,6 +101,8 @@ static int _fdt_splice(void *fdt, void *splicepoint, int oldlen, int newlen)
if (((p + oldlen) < p) || ((p + oldlen) > end))
return -FDT_ERR_BADOFFSET;
+ if ((p < (char *)fdt) || ((end - oldlen + newlen) < (char *)fdt))
+ return -FDT_ERR_BADOFFSET;
if ((end - oldlen + newlen) > ((char *)fdt + fdt_totalsize(fdt)))
return -FDT_ERR_NOSPACE;
memmove(p + newlen, p + oldlen, end - p - oldlen);
@@ -126,8 +128,7 @@ static int _fdt_splice_struct(void *fdt, void *p,
int delta = newlen - oldlen;
int err;
- err = _fdt_splice(fdt, p, oldlen, newlen);
- if (err)
+ if ((err = _fdt_splice(fdt, p, oldlen, newlen)))
return err;
fdt_set_size_dt_struct(fdt, fdt_size_dt_struct(fdt) + delta);
@@ -141,8 +142,7 @@ static int _fdt_splice_string(void *fdt, int newlen)
+ fdt_off_dt_strings(fdt) + fdt_size_dt_strings(fdt);
int err;
- err = _fdt_splice(fdt, p, 0, newlen);
- if (err)
+ if ((err = _fdt_splice(fdt, p, 0, newlen)))
return err;
fdt_set_size_dt_strings(fdt, fdt_size_dt_strings(fdt) + newlen);
@@ -191,17 +191,13 @@ int fdt_add_mem_rsv(void *fdt, uint64_t address, uint64_t size)
int fdt_del_mem_rsv(void *fdt, int n)
{
struct fdt_reserve_entry *re = _fdt_mem_rsv_w(fdt, n);
- int err;
FDT_RW_CHECK_HEADER(fdt);
if (n >= fdt_num_mem_rsv(fdt))
return -FDT_ERR_NOTFOUND;
- err = _fdt_splice_mem_rsv(fdt, re, 1, 0);
- if (err)
- return err;
- return 0;
+ return _fdt_splice_mem_rsv(fdt, re, 1, 0);
}
static int _fdt_resize_property(void *fdt, int nodeoffset, const char *name,
@@ -211,12 +207,11 @@ static int _fdt_resize_property(void *fdt, int nodeoffset, const char *name,
int err;
*prop = fdt_get_property_w(fdt, nodeoffset, name, &oldlen);
- if (! (*prop))
+ if (!*prop)
return oldlen;
- err = _fdt_splice_struct(fdt, (*prop)->data, FDT_TAGALIGN(oldlen),
- FDT_TAGALIGN(len));
- if (err)
+ if ((err = _fdt_splice_struct(fdt, (*prop)->data, FDT_TAGALIGN(oldlen),
+ FDT_TAGALIGN(len))))
return err;
(*prop)->len = cpu_to_fdt32(len);
@@ -274,8 +269,8 @@ int fdt_set_name(void *fdt, int nodeoffset, const char *name)
return 0;
}
-int fdt_setprop(void *fdt, int nodeoffset, const char *name,
- const void *val, int len)
+int fdt_setprop_placeholder(void *fdt, int nodeoffset, const char *name,
+ int len, void **prop_data)
{
struct fdt_property *prop;
int err;
@@ -288,7 +283,22 @@ int fdt_setprop(void *fdt, int nodeoffset, const char *name,
if (err)
return err;
- memcpy(prop->data, val, len);
+ *prop_data = prop->data;
+ return 0;
+}
+
+int fdt_setprop(void *fdt, int nodeoffset, const char *name,
+ const void *val, int len)
+{
+ void *prop_data;
+ int err;
+
+ err = fdt_setprop_placeholder(fdt, nodeoffset, name, len, &prop_data);
+ if (err)
+ return err;
+
+ if (len)
+ memcpy(prop_data, val, len);
return 0;
}
@@ -327,7 +337,7 @@ int fdt_delprop(void *fdt, int nodeoffset, const char *name)
FDT_RW_CHECK_HEADER(fdt);
prop = fdt_get_property_w(fdt, nodeoffset, name, &len);
- if (! prop)
+ if (!prop)
return len;
proplen = sizeof(*prop) + FDT_TAGALIGN(len);
diff --git a/EmbeddedPkg/Library/FdtLib/fdt_strerror.c b/EmbeddedPkg/Library/FdtLib/fdt_strerror.c
index a49793d..3041e2e 100644
--- a/EmbeddedPkg/Library/FdtLib/fdt_strerror.c
+++ b/EmbeddedPkg/Library/FdtLib/fdt_strerror.c
@@ -69,6 +69,7 @@ static struct fdt_errtabent fdt_errtable[] = {
FDT_ERRTABENT(FDT_ERR_BADOFFSET),
FDT_ERRTABENT(FDT_ERR_BADPATH),
+ FDT_ERRTABENT(FDT_ERR_BADPHANDLE),
FDT_ERRTABENT(FDT_ERR_BADSTATE),
FDT_ERRTABENT(FDT_ERR_TRUNCATED),
@@ -76,6 +77,11 @@ static struct fdt_errtabent fdt_errtable[] = {
FDT_ERRTABENT(FDT_ERR_BADVERSION),
FDT_ERRTABENT(FDT_ERR_BADSTRUCTURE),
FDT_ERRTABENT(FDT_ERR_BADLAYOUT),
+ FDT_ERRTABENT(FDT_ERR_INTERNAL),
+ FDT_ERRTABENT(FDT_ERR_BADNCELLS),
+ FDT_ERRTABENT(FDT_ERR_BADVALUE),
+ FDT_ERRTABENT(FDT_ERR_BADOVERLAY),
+ FDT_ERRTABENT(FDT_ERR_NOPHANDLES),
};
#define FDT_ERRTABSIZE (sizeof(fdt_errtable) / sizeof(fdt_errtable[0]))
diff --git a/EmbeddedPkg/Library/FdtLib/fdt_sw.c b/EmbeddedPkg/Library/FdtLib/fdt_sw.c
index 991919b..3c2c710 100644
--- a/EmbeddedPkg/Library/FdtLib/fdt_sw.c
+++ b/EmbeddedPkg/Library/FdtLib/fdt_sw.c
@@ -107,6 +107,38 @@ int fdt_create(void *buf, int bufsize)
return 0;
}
+int fdt_resize(void *fdt, void *buf, int bufsize)
+{
+ size_t headsize, tailsize;
+ char *oldtail, *newtail;
+
+ FDT_SW_CHECK_HEADER(fdt);
+
+ headsize = fdt_off_dt_struct(fdt);
+ tailsize = fdt_size_dt_strings(fdt);
+
+ if ((headsize + tailsize) > bufsize)
+ return -FDT_ERR_NOSPACE;
+
+ oldtail = (char *)fdt + fdt_totalsize(fdt) - tailsize;
+ newtail = (char *)buf + bufsize - tailsize;
+
+ /* Two cases to avoid clobbering data if the old and new
+ * buffers partially overlap */
+ if (buf <= fdt) {
+ memmove(buf, fdt, headsize);
+ memmove(newtail, oldtail, tailsize);
+ } else {
+ memmove(newtail, oldtail, tailsize);
+ memmove(buf, fdt, headsize);
+ }
+
+ fdt_set_off_dt_strings(buf, bufsize);
+ fdt_set_totalsize(buf, bufsize);
+
+ return 0;
+}
+
int fdt_add_reservemap_entry(void *fdt, uint64_t addr, uint64_t size)
{
struct fdt_reserve_entry *re;
@@ -188,7 +220,7 @@ static int _fdt_find_add_string(void *fdt, const char *s)
return offset;
}
-int fdt_property(void *fdt, const char *name, const void *val, int len)
+int fdt_property_placeholder(void *fdt, const char *name, int len, void **valp)
{
struct fdt_property *prop;
int nameoff;
@@ -206,7 +238,19 @@ int fdt_property(void *fdt, const char *name, const void *val, int len)
prop->tag = cpu_to_fdt32(FDT_PROP);
prop->nameoff = cpu_to_fdt32(nameoff);
prop->len = cpu_to_fdt32(len);
- memcpy(prop->data, val, len);
+ *valp = prop->data;
+ return 0;
+}
+
+int fdt_property(void *fdt, const char *name, const void *val, int len)
+{
+ void *ptr;
+ int ret;
+
+ ret = fdt_property_placeholder(fdt, name, len, &ptr);
+ if (ret)
+ return ret;
+ memcpy(ptr, val, len);
return 0;
}
diff --git a/EmbeddedPkg/Library/FdtLib/fdt_wip.c b/EmbeddedPkg/Library/FdtLib/fdt_wip.c
index 3f2b581..6e39807 100644
--- a/EmbeddedPkg/Library/FdtLib/fdt_wip.c
+++ b/EmbeddedPkg/Library/FdtLib/fdt_wip.c
@@ -55,21 +55,42 @@
#include "libfdt_internal.h"
+int fdt_setprop_inplace_namelen_partial(void *fdt, int nodeoffset,
+ const char *name, int namelen,
+ uint32_t idx, const void *val,
+ int len)
+{
+ void *propval;
+ int proplen;
+
+ propval = fdt_getprop_namelen_w(fdt, nodeoffset, name, namelen,
+ &proplen);
+ if (!propval)
+ return proplen;
+
+ if (proplen < (len + idx))
+ return -FDT_ERR_NOSPACE;
+
+ memcpy((char *)propval + idx, val, len);
+ return 0;
+}
+
int fdt_setprop_inplace(void *fdt, int nodeoffset, const char *name,
const void *val, int len)
{
- void *propval;
+ const void *propval;
int proplen;
- propval = fdt_getprop_w(fdt, nodeoffset, name, &proplen);
- if (! propval)
+ propval = fdt_getprop(fdt, nodeoffset, name, &proplen);
+ if (!propval)
return proplen;
if (proplen != len)
return -FDT_ERR_NOSPACE;
- memcpy(propval, val, len);
- return 0;
+ return fdt_setprop_inplace_namelen_partial(fdt, nodeoffset, name,
+ strlen(name), 0,
+ val, len);
}
static void _fdt_nop_region(void *start, int len)
@@ -86,7 +107,7 @@ int fdt_nop_property(void *fdt, int nodeoffset, const char *name)
int len;
prop = fdt_get_property_w(fdt, nodeoffset, name, &len);
- if (! prop)
+ if (!prop)
return len;
_fdt_nop_region(prop, len + sizeof(*prop));
diff --git a/EmbeddedPkg/Library/FdtLib/libfdt_internal.h b/EmbeddedPkg/Library/FdtLib/libfdt_internal.h
index 1545611..f82227a 100644
--- a/EmbeddedPkg/Library/FdtLib/libfdt_internal.h
+++ b/EmbeddedPkg/Library/FdtLib/libfdt_internal.h
@@ -57,9 +57,9 @@
#define FDT_CHECK_HEADER(fdt) \
{ \
- int err; \
- if ((err = fdt_check_header(fdt)) != 0) \
- return err; \
+ int __err; \
+ if ((__err = fdt_check_header(fdt)) != 0) \
+ return __err; \
}
int _fdt_check_node_offset(const void *fdt, int offset);
diff --git a/EmbeddedPkg/Library/FdtLib/version.lds b/EmbeddedPkg/Library/FdtLib/version.lds
index 80b322bed..1f4e1ea 100644
--- a/EmbeddedPkg/Library/FdtLib/version.lds
+++ b/EmbeddedPkg/Library/FdtLib/version.lds
@@ -8,6 +8,7 @@ LIBFDT_1.2 {
fdt_get_mem_rsv;
fdt_subnode_offset_namelen;
fdt_subnode_offset;
+ fdt_path_offset_namelen;
fdt_path_offset;
fdt_get_name;
fdt_get_property_namelen;
@@ -54,6 +55,12 @@ LIBFDT_1.2 {
fdt_get_property_by_offset;
fdt_getprop_by_offset;
fdt_next_property_offset;
+ fdt_first_subnode;
+ fdt_next_subnode;
+ fdt_address_cells;
+ fdt_size_cells;
+ fdt_stringlist_contains;
+ fdt_resize;
local:
*;
--
2.7.4
_______________________________________________
edk2-devel mailing list
edk2-devel@lists.01.org
https://lists.01.org/mailman/listinfo/edk2-devel
On 5 January 2018 at 11:17, Pankaj Bansal <pankaj.bansal@nxp.com> wrote: > Update the FdtLib so that new APIs provided by FdtLib like > fdt_address_cells, fdt_size_cells etc. can be used. > > Reference code: > https://git.kernel.org/pub/scm/utils/dtc/dtc.git/tree/libfdt?h=v1.4.5 > > Cc: Leif Lindholm <leif.lindholm@linaro.org> > Cc: Ard Biesheuvel <ard.biesheuvel@linaro.org> > Contributed-under: TianoCore Contribution Agreement 1.1 > Signed-off-by: Pankaj Bansal <pankaj.bansal@nxp.com> Reviewed-by: Ard Biesheuvel <ard.biesheuvel@linaro.org> Pushed as a099239015eb Thanks. > --- > > Notes: > The source code has been copied under BSD license terms. > One file fdt_overlay.c which is part of libfdt has no license > header specified at the top of file. > Therefore that file and the references to functions defined in > that file have been removed. > > EmbeddedPkg/Include/libfdt.h | 416 +++++++++++++++-- > EmbeddedPkg/Include/libfdt_env.h | 4 + > EmbeddedPkg/Library/FdtLib/FdtLib.inf | 1 + > EmbeddedPkg/Library/FdtLib/Makefile.libfdt | 3 +- > EmbeddedPkg/Library/FdtLib/fdt.c | 13 +- > EmbeddedPkg/Library/FdtLib/fdt_addresses.c | 96 ++++ > EmbeddedPkg/Library/FdtLib/fdt_empty_tree.c | 1 - > EmbeddedPkg/Library/FdtLib/fdt_ro.c | 163 ++++++- > EmbeddedPkg/Library/FdtLib/fdt_rw.c | 50 +- > EmbeddedPkg/Library/FdtLib/fdt_strerror.c | 6 + > EmbeddedPkg/Library/FdtLib/fdt_sw.c | 48 +- > EmbeddedPkg/Library/FdtLib/fdt_wip.c | 33 +- > EmbeddedPkg/Library/FdtLib/libfdt_internal.h | 6 +- > EmbeddedPkg/Library/FdtLib/version.lds | 7 + > 14 files changed, 760 insertions(+), 87 deletions(-) > > diff --git a/EmbeddedPkg/Include/libfdt.h b/EmbeddedPkg/Include/libfdt.h > index 212cb99..1aabec3 100644 > --- a/EmbeddedPkg/Include/libfdt.h > +++ b/EmbeddedPkg/Include/libfdt.h > @@ -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 > @@ -79,8 +79,10 @@ > * (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 > @@ -116,13 +118,34 @@ > * 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_MAX 17 > > /**********************************************************************/ > /* Low-level functions (you probably don't need these) */ > /**********************************************************************/ > > +#ifndef SWIG /* This function is not useful in Python */ > const void *fdt_offset_ptr(const void *fdt, int offset, unsigned int checklen); > +#endif > static inline void *fdt_offset_ptr_w(void *fdt, int offset, int checklen) > { > return (void *)(uintptr_t)fdt_offset_ptr(fdt, offset, checklen); > @@ -158,27 +181,54 @@ 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 */ > /**********************************************************************/ > - > #define fdt_get_header(fdt, field) \ > (fdt32_to_cpu(((const struct fdt_header *)(fdt))->field)) > -#define fdt_magic(fdt) (fdt_get_header(fdt, magic)) > +#define fdt_magic(fdt) (fdt_get_header(fdt, magic)) > #define fdt_totalsize(fdt) (fdt_get_header(fdt, totalsize)) > #define fdt_off_dt_struct(fdt) (fdt_get_header(fdt, off_dt_struct)) > #define fdt_off_dt_strings(fdt) (fdt_get_header(fdt, off_dt_strings)) > #define fdt_off_mem_rsvmap(fdt) (fdt_get_header(fdt, off_mem_rsvmap)) > #define fdt_version(fdt) (fdt_get_header(fdt, version)) > -#define fdt_last_comp_version(fdt) (fdt_get_header(fdt, last_comp_version)) > -#define fdt_boot_cpuid_phys(fdt) (fdt_get_header(fdt, boot_cpuid_phys)) > -#define fdt_size_dt_strings(fdt) (fdt_get_header(fdt, size_dt_strings)) > +#define fdt_last_comp_version(fdt) (fdt_get_header(fdt, last_comp_version)) > +#define fdt_boot_cpuid_phys(fdt) (fdt_get_header(fdt, boot_cpuid_phys)) > +#define fdt_size_dt_strings(fdt) (fdt_get_header(fdt, size_dt_strings)) > #define fdt_size_dt_struct(fdt) (fdt_get_header(fdt, size_dt_struct)) > > #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); > @@ -249,6 +299,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 > * > @@ -290,8 +355,10 @@ int fdt_get_mem_rsv(const void *fdt, int n, uint64_t *address, uint64_t *size); > * useful for finding subnodes based on a portion of a larger string, > * such as a full path. > */ > +#ifndef SWIG /* Not available in Python */ > int fdt_subnode_offset_namelen(const void *fdt, int parentoffset, > const char *name, int namelen); > +#endif > /** > * fdt_subnode_offset - find a subnode of a given node > * @fdt: pointer to the device tree blob > @@ -308,8 +375,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, > @@ -318,6 +386,19 @@ 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. > + */ > +#ifndef SWIG /* Not available in Python */ > +int fdt_path_offset_namelen(const void *fdt, const char *path, int namelen); > +#endif > + > +/** > * fdt_path_offset - find a tree node by its full path > * @fdt: pointer to the device tree blob > * @path: full path of the node to locate > @@ -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 > @@ -406,6 +490,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 > * @offset: offset of the property to retrieve > @@ -441,13 +552,15 @@ 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. > */ > +#ifndef SWIG /* Not available in Python */ > const struct fdt_property *fdt_get_property_namelen(const void *fdt, > int nodeoffset, > const char *name, > int namelen, int *lenp); > +#endif > > /** > * fdt_get_property - find a given property in a given node > @@ -469,7 +582,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, > @@ -517,8 +631,10 @@ static inline struct fdt_property *fdt_get_property_w(void *fdt, int nodeoffset, > * -FDT_ERR_BADSTRUCTURE, > * -FDT_ERR_TRUNCATED, standard meanings > */ > +#ifndef SWIG /* This function is not useful in Python */ > const void *fdt_getprop_by_offset(const void *fdt, int offset, > const char **namep, int *lenp); > +#endif > > /** > * fdt_getprop_namelen - get property value based on substring > @@ -531,8 +647,17 @@ const void *fdt_getprop_by_offset(const void *fdt, int offset, > * Identical to fdt_getprop(), but only examine the first namelen > * characters of name for matching the property name. > */ > +#ifndef SWIG /* Not available in Python */ > 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); > +} > +#endif > > /** > * fdt_getprop - retrieve the value of a given property > @@ -554,7 +679,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, > @@ -592,11 +718,13 @@ uint32_t fdt_get_phandle(const void *fdt, int nodeoffset); > * Identical to fdt_get_alias(), but only examine the first namelen > * characters of name for matching the alias name. > */ > +#ifndef SWIG /* Not available in Python */ > const char *fdt_get_alias_namelen(const void *fdt, > const char *name, int namelen); > +#endif > > /** > - * 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 > * > @@ -626,7 +754,7 @@ const char *fdt_get_alias(const void *fdt, const char *name); > * 0, on success > * buf contains the absolute path of the node at > * nodeoffset, as a NUL-terminated string. > - * -FDT_ERR_BADOFFSET, nodeoffset does not refer to a BEGIN_NODE tag > + * -FDT_ERR_BADOFFSET, nodeoffset does not refer to a BEGIN_NODE tag > * -FDT_ERR_NOSPACE, the path of the given node is longer than (bufsize-1) > * characters and will not fit in the given buffer. > * -FDT_ERR_BADMAGIC, > @@ -656,11 +784,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_BADOFFSET, nodeoffset does not refer to a BEGIN_NODE tag > + * -FDT_ERR_NOTFOUND, supernodedepth was greater than the depth of > + * nodeoffset > * -FDT_ERR_BADMAGIC, > * -FDT_ERR_BADVERSION, > * -FDT_ERR_BADSTATE, > @@ -682,7 +810,7 @@ int fdt_supernode_atdepth_offset(const void *fdt, int nodeoffset, > * > * returns: > * depth of the node at nodeoffset (>=0), on success > - * -FDT_ERR_BADOFFSET, nodeoffset does not refer to a BEGIN_NODE tag > + * -FDT_ERR_BADOFFSET, nodeoffset does not refer to a BEGIN_NODE tag > * -FDT_ERR_BADMAGIC, > * -FDT_ERR_BADVERSION, > * -FDT_ERR_BADSTATE, > @@ -705,7 +833,7 @@ int fdt_node_depth(const void *fdt, int nodeoffset); > * returns: > * structure block offset of the parent of the node at nodeoffset > * (>=0), on success > - * -FDT_ERR_BADOFFSET, nodeoffset does not refer to a BEGIN_NODE tag > + * -FDT_ERR_BADOFFSET, nodeoffset does not refer to a BEGIN_NODE tag > * -FDT_ERR_BADMAGIC, > * -FDT_ERR_BADVERSION, > * -FDT_ERR_BADSTATE, > @@ -745,7 +873,7 @@ int fdt_parent_offset(const void *fdt, int nodeoffset); > * on success > * -FDT_ERR_NOTFOUND, no node matching the criterion exists in the > * tree after startoffset > - * -FDT_ERR_BADOFFSET, nodeoffset does not refer to a BEGIN_NODE tag > + * -FDT_ERR_BADOFFSET, nodeoffset does not refer to a BEGIN_NODE tag > * -FDT_ERR_BADMAGIC, > * -FDT_ERR_BADVERSION, > * -FDT_ERR_BADSTATE, > @@ -792,7 +920,7 @@ int fdt_node_offset_by_phandle(const void *fdt, uint32_t phandle); > * 1, if the node has a 'compatible' property, but it does not list > * the given string > * -FDT_ERR_NOTFOUND, if the given node has no 'compatible' property > - * -FDT_ERR_BADOFFSET, if nodeoffset does not refer to a BEGIN_NODE tag > + * -FDT_ERR_BADOFFSET, if nodeoffset does not refer to a BEGIN_NODE tag > * -FDT_ERR_BADMAGIC, > * -FDT_ERR_BADVERSION, > * -FDT_ERR_BADSTATE, > @@ -829,7 +957,7 @@ int fdt_node_check_compatible(const void *fdt, int nodeoffset, > * on success > * -FDT_ERR_NOTFOUND, no node matching the criterion exists in the > * tree after startoffset > - * -FDT_ERR_BADOFFSET, nodeoffset does not refer to a BEGIN_NODE tag > + * -FDT_ERR_BADOFFSET, nodeoffset does not refer to a BEGIN_NODE tag > * -FDT_ERR_BADMAGIC, > * -FDT_ERR_BADVERSION, > * -FDT_ERR_BADSTATE, > @@ -852,11 +980,153 @@ 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. > + */ > +#ifndef SWIG /* Not available in Python */ > +int fdt_setprop_inplace_namelen_partial(void *fdt, int nodeoffset, > + const char *name, int namelen, > + uint32_t idx, const void *val, > + int len); > +#endif > + > +/** > * fdt_setprop_inplace - 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 > @@ -884,8 +1154,10 @@ int fdt_stringlist_contains(const char *strlist, int listlen, const char *str); > * -FDT_ERR_BADSTRUCTURE, > * -FDT_ERR_TRUNCATED, standard meanings > */ > +#ifndef SWIG /* Not available in Python */ > int fdt_setprop_inplace(void *fdt, int nodeoffset, const char *name, > const void *val, int len); > +#endif > > /** > * fdt_setprop_inplace_u32 - change the value of a 32-bit integer property > @@ -1023,6 +1295,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 +1314,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); > @@ -1160,6 +1449,37 @@ int fdt_setprop(void *fdt, int nodeoffset, const char *name, > const void *val, int len); > > /** > + * fdt_setprop _placeholder - allocate space for a property > + * @fdt: pointer to the device tree blob > + * @nodeoffset: offset of the node whose property to change > + * @name: name of the property to change > + * @len: length of the property value > + * @prop_data: return pointer to property data > + * > + * fdt_setprop_placeholer() allocates the named property in the given node. > + * If the property exists it is resized. In either case a pointer to the > + * property data is returned. > + * > + * This function may insert or delete data from the blob, and will > + * therefore change the offsets of some existing nodes. > + * > + * returns: > + * 0, on success > + * -FDT_ERR_NOSPACE, there is insufficient free space in the blob to > + * contain the new property value > + * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag > + * -FDT_ERR_BADLAYOUT, > + * -FDT_ERR_BADMAGIC, > + * -FDT_ERR_BADVERSION, > + * -FDT_ERR_BADSTATE, > + * -FDT_ERR_BADSTRUCTURE, > + * -FDT_ERR_BADLAYOUT, > + * -FDT_ERR_TRUNCATED, standard meanings > + */ > +int fdt_setprop_placeholder(void *fdt, int nodeoffset, const char *name, > + int len, void **prop_data); > + > +/** > * fdt_setprop_u32 - set a property to a 32-bit integer > * @fdt: pointer to the device tree blob > * @nodeoffset: offset of the node whose property to change > @@ -1271,6 +1591,36 @@ static inline int fdt_setprop_cell(void *fdt, int nodeoffset, const char *name, > #define fdt_setprop_string(fdt, nodeoffset, name, str) \ > fdt_setprop((fdt), (nodeoffset), (name), (str), strlen(str)+1) > > + > +/** > + * fdt_setprop_empty - set a property to an empty value > + * @fdt: pointer to the device tree blob > + * @nodeoffset: offset of the node whose property to change > + * @name: name of the property to change > + * > + * fdt_setprop_empty() sets the value of the named property in the > + * given node to an empty (zero length) value, or creates a new empty > + * property if it does not already exist. > + * > + * This function may insert or delete data from the blob, and will > + * therefore change the offsets of some existing nodes. > + * > + * returns: > + * 0, on success > + * -FDT_ERR_NOSPACE, there is insufficient free space in the blob to > + * contain the new property value > + * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag > + * -FDT_ERR_BADLAYOUT, > + * -FDT_ERR_BADMAGIC, > + * -FDT_ERR_BADVERSION, > + * -FDT_ERR_BADSTATE, > + * -FDT_ERR_BADSTRUCTURE, > + * -FDT_ERR_BADLAYOUT, > + * -FDT_ERR_TRUNCATED, standard meanings > + */ > +#define fdt_setprop_empty(fdt, nodeoffset, name) \ > + fdt_setprop((fdt), (nodeoffset), (name), NULL, 0) > + > /** > * fdt_appendprop - append to or create a property > * @fdt: pointer to the device tree blob > @@ -1448,8 +1798,10 @@ int fdt_delprop(void *fdt, int nodeoffset, const char *name); > * creating subnodes based on a portion of a larger string, such as a > * full path. > */ > +#ifndef SWIG /* Not available in Python */ > int fdt_add_subnode_namelen(void *fdt, int parentoffset, > const char *name, int namelen); > +#endif > > /** > * fdt_add_subnode - creates a new node > @@ -1465,9 +1817,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 > diff --git a/EmbeddedPkg/Include/libfdt_env.h b/EmbeddedPkg/Include/libfdt_env.h > index 3e24db9..d84a6a4 100644 > --- a/EmbeddedPkg/Include/libfdt_env.h > +++ b/EmbeddedPkg/Include/libfdt_env.h > @@ -78,4 +78,8 @@ static inline char *strchr(const char *s, int c) { > return AsciiStrStr (s, pattern); > } > > +static inline size_t strnlen (const char* str, size_t strsz ) { > + return AsciiStrnLenS (str, strsz); > +} > + > #endif /* _LIBFDT_ENV_H */ > diff --git a/EmbeddedPkg/Library/FdtLib/FdtLib.inf b/EmbeddedPkg/Library/FdtLib/FdtLib.inf > index f3da231..b26d374 100644 > --- a/EmbeddedPkg/Library/FdtLib/FdtLib.inf > +++ b/EmbeddedPkg/Library/FdtLib/FdtLib.inf > @@ -32,6 +32,7 @@ > fdt_sw.c > fdt_wip.c > fdt.c > + fdt_addresses.c > > [Packages] > MdePkg/MdePkg.dec > diff --git a/EmbeddedPkg/Library/FdtLib/Makefile.libfdt b/EmbeddedPkg/Library/FdtLib/Makefile.libfdt > index 91126c0..09c322e 100644 > --- a/EmbeddedPkg/Library/FdtLib/Makefile.libfdt > +++ b/EmbeddedPkg/Library/FdtLib/Makefile.libfdt > @@ -6,5 +6,6 @@ > LIBFDT_soname = libfdt.$(SHAREDLIB_EXT).1 > LIBFDT_INCLUDES = fdt.h libfdt.h libfdt_env.h > LIBFDT_VERSION = version.lds > -LIBFDT_SRCS = fdt.c fdt_ro.c fdt_wip.c fdt_sw.c fdt_rw.c fdt_strerror.c fdt_empty_tree.c > +LIBFDT_SRCS = fdt.c fdt_ro.c fdt_wip.c fdt_sw.c fdt_rw.c fdt_strerror.c fdt_empty_tree.c \ > + fdt_addresses.c > LIBFDT_OBJS = $(LIBFDT_SRCS:%.c=%.o) > diff --git a/EmbeddedPkg/Library/FdtLib/fdt.c b/EmbeddedPkg/Library/FdtLib/fdt.c > index 9639528..29756a8 100644 > --- a/EmbeddedPkg/Library/FdtLib/fdt.c > +++ b/EmbeddedPkg/Library/FdtLib/fdt.c > @@ -76,18 +76,19 @@ int fdt_check_header(const void *fdt) > > const void *fdt_offset_ptr(const void *fdt, int offset, unsigned int len) > { > - const char *p; > + unsigned absoffset = offset + fdt_off_dt_struct(fdt); > + > + if ((absoffset < offset) > + || ((absoffset + len) < absoffset) > + || (absoffset + len) > fdt_totalsize(fdt)) > + return NULL; > > if (fdt_version(fdt) >= 0x11) > if (((offset + len) < offset) > || ((offset + len) > fdt_size_dt_struct(fdt))) > return NULL; > > - p = _fdt_offset_ptr(fdt, offset); > - > - if (p + len < p) > - return NULL; > - return p; > + return _fdt_offset_ptr(fdt, offset); > } > > uint32_t fdt_next_tag(const void *fdt, int startoffset, int *nextoffset) > diff --git a/EmbeddedPkg/Library/FdtLib/fdt_addresses.c b/EmbeddedPkg/Library/FdtLib/fdt_addresses.c > new file mode 100644 > index 0000000..f48da28 > --- /dev/null > +++ b/EmbeddedPkg/Library/FdtLib/fdt_addresses.c > @@ -0,0 +1,96 @@ > +/* > + * libfdt - Flat Device Tree manipulation > + * Copyright (C) 2014 David Gibson <david@gibson.dropbear.id.au> > + * > + * libfdt is dual licensed: you can use it either under the terms of > + * the GPL, or the BSD license, at your option. > + * > + * a) This library is free software; you can redistribute it and/or > + * modify it under the terms of the GNU General Public License as > + * published by the Free Software Foundation; either version 2 of the > + * License, or (at your option) any later version. > + * > + * This library is distributed in the hope that it will be useful, > + * but WITHOUT ANY WARRANTY; without even the implied warranty of > + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the > + * GNU General Public License for more details. > + * > + * You should have received a copy of the GNU General Public > + * License along with this library; if not, write to the Free > + * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, > + * MA 02110-1301 USA > + * > + * Alternatively, > + * > + * b) Redistribution and use in source and binary forms, with or > + * without modification, are permitted provided that the following > + * conditions are met: > + * > + * 1. Redistributions of source code must retain the above > + * copyright notice, this list of conditions and the following > + * disclaimer. > + * 2. Redistributions in binary form must reproduce the above > + * copyright notice, this list of conditions and the following > + * disclaimer in the documentation and/or other materials > + * provided with the distribution. > + * > + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND > + * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, > + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF > + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE > + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR > + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, > + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT > + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; > + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) > + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN > + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR > + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, > + * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. > + */ > +#include "libfdt_env.h" > + > +#include <fdt.h> > +#include <libfdt.h> > + > +#include "libfdt_internal.h" > + > +int fdt_address_cells(const void *fdt, int nodeoffset) > +{ > + const fdt32_t *ac; > + int val; > + int len; > + > + ac = fdt_getprop(fdt, nodeoffset, "#address-cells", &len); > + if (!ac) > + return 2; > + > + if (len != sizeof(*ac)) > + return -FDT_ERR_BADNCELLS; > + > + val = fdt32_to_cpu(*ac); > + if ((val <= 0) || (val > FDT_MAX_NCELLS)) > + return -FDT_ERR_BADNCELLS; > + > + return val; > +} > + > +int fdt_size_cells(const void *fdt, int nodeoffset) > +{ > + const fdt32_t *sc; > + int val; > + int len; > + > + sc = fdt_getprop(fdt, nodeoffset, "#size-cells", &len); > + if (!sc) > + return 2; > + > + if (len != sizeof(*sc)) > + return -FDT_ERR_BADNCELLS; > + > + val = fdt32_to_cpu(*sc); > + if ((val < 0) || (val > FDT_MAX_NCELLS)) > + return -FDT_ERR_BADNCELLS; > + > + return val; > +} > diff --git a/EmbeddedPkg/Library/FdtLib/fdt_empty_tree.c b/EmbeddedPkg/Library/FdtLib/fdt_empty_tree.c > index f00a899..634b436 100644 > --- a/EmbeddedPkg/Library/FdtLib/fdt_empty_tree.c > +++ b/EmbeddedPkg/Library/FdtLib/fdt_empty_tree.c > @@ -81,4 +81,3 @@ int fdt_create_empty_tree(void *buf, int bufsize) > > return fdt_open_into(buf, buf, bufsize); > } > - > diff --git a/EmbeddedPkg/Library/FdtLib/fdt_ro.c b/EmbeddedPkg/Library/FdtLib/fdt_ro.c > index 2055891..9413f50 100644 > --- a/EmbeddedPkg/Library/FdtLib/fdt_ro.c > +++ b/EmbeddedPkg/Library/FdtLib/fdt_ro.c > @@ -60,7 +60,7 @@ static int _fdt_nodename_eq(const void *fdt, int offset, > { > const char *p = fdt_offset_ptr(fdt, offset + FDT_TAGSIZE, len+1); > > - if (! p) > + if (!p) > /* short match */ > return 0; > > @@ -88,6 +88,32 @@ static int _fdt_string_eq(const void *fdt, int stroffset, > return (strlen(p) == len) && (memcmp(p, s, len) == 0); > } > > +uint32_t fdt_get_max_phandle(const void *fdt) > +{ > + uint32_t max_phandle = 0; > + int offset; > + > + for (offset = fdt_next_node(fdt, -1, NULL);; > + offset = fdt_next_node(fdt, offset, NULL)) { > + uint32_t phandle; > + > + if (offset == -FDT_ERR_NOTFOUND) > + return max_phandle; > + > + if (offset < 0) > + return (uint32_t)-1; > + > + phandle = fdt_get_phandle(fdt, offset); > + if (phandle == (uint32_t)-1) > + continue; > + > + if (phandle > max_phandle) > + max_phandle = phandle; > + } > + > + return 0; > +} > + > int fdt_get_mem_rsv(const void *fdt, int n, uint64_t *address, uint64_t *size) > { > FDT_CHECK_HEADER(fdt); > @@ -154,9 +180,9 @@ int fdt_subnode_offset(const void *fdt, int parentoffset, > return fdt_subnode_offset_namelen(fdt, parentoffset, name, strlen(name)); > } > > -int fdt_path_offset(const void *fdt, const char *path) > +int fdt_path_offset_namelen(const void *fdt, const char *path, int namelen) > { > - const char *end = path + strlen(path); > + const char *end = path + namelen; > const char *p = path; > int offset = 0; > > @@ -164,7 +190,7 @@ int fdt_path_offset(const void *fdt, const char *path) > > /* see if we have an alias */ > if (*path != '/') { > - const char *q = strchr(path, '/'); > + const char *q = memchr(path, '/', end - p); > > if (!q) > q = end; > @@ -177,14 +203,15 @@ int fdt_path_offset(const void *fdt, const char *path) > p = q; > } > > - while (*p) { > + while (p < end) { > const char *q; > > - while (*p == '/') > + while (*p == '/') { > p++; > - if (! *p) > - return offset; > - q = strchr(p, '/'); > + if (p == end) > + return offset; > + } > + q = memchr(p, '/', end - p); > if (! q) > q = end; > > @@ -198,6 +225,11 @@ int fdt_path_offset(const void *fdt, const char *path) > return offset; > } > > +int fdt_path_offset(const void *fdt, const char *path) > +{ > + return fdt_path_offset_namelen(fdt, path, strlen(path)); > +} > + > const char *fdt_get_name(const void *fdt, int nodeoffset, int *len) > { > const struct fdt_node_header *nh = _fdt_offset_ptr(fdt, nodeoffset); > @@ -267,8 +299,7 @@ const struct fdt_property *fdt_get_property_namelen(const void *fdt, > (offset = fdt_next_property_offset(fdt, offset))) { > const struct fdt_property *prop; > > - prop = fdt_get_property_by_offset(fdt, offset, lenp); > - if (!prop) { > + if (!(prop = fdt_get_property_by_offset(fdt, offset, lenp))) { > offset = -FDT_ERR_INTERNAL; > break; > } > @@ -296,7 +327,7 @@ const void *fdt_getprop_namelen(const void *fdt, int nodeoffset, > const struct fdt_property *prop; > > prop = fdt_get_property_namelen(fdt, nodeoffset, name, namelen, lenp); > - if (! prop) > + if (!prop) > return NULL; > > return prop->data; > @@ -495,7 +526,7 @@ int fdt_node_offset_by_phandle(const void *fdt, uint32_t phandle) > { > int offset; > > - if ((phandle == 0) || (phandle == (uint32_t)-1)) > + if ((phandle == 0) || (phandle == -1)) > return -FDT_ERR_BADPHANDLE; > > FDT_CHECK_HEADER(fdt); > @@ -533,6 +564,106 @@ int fdt_stringlist_contains(const char *strlist, int listlen, const char *str) > return 0; > } > > +int fdt_stringlist_count(const void *fdt, int nodeoffset, const char *property) > +{ > + const char *list, *end; > + int length, count = 0; > + > + list = fdt_getprop(fdt, nodeoffset, property, &length); > + if (!list) > + return length; > + > + end = list + length; > + > + while (list < end) { > + length = strnlen(list, end - list) + 1; > + > + /* Abort if the last string isn't properly NUL-terminated. */ > + if (list + length > end) > + return -FDT_ERR_BADVALUE; > + > + list += length; > + count++; > + } > + > + return count; > +} > + > +int fdt_stringlist_search(const void *fdt, int nodeoffset, const char *property, > + const char *string) > +{ > + int length, len, idx = 0; > + const char *list, *end; > + > + list = fdt_getprop(fdt, nodeoffset, property, &length); > + if (!list) > + return length; > + > + len = strlen(string) + 1; > + end = list + length; > + > + while (list < end) { > + length = strnlen(list, end - list) + 1; > + > + /* Abort if the last string isn't properly NUL-terminated. */ > + if (list + length > end) > + return -FDT_ERR_BADVALUE; > + > + if (length == len && memcmp(list, string, length) == 0) > + return idx; > + > + list += length; > + idx++; > + } > + > + return -FDT_ERR_NOTFOUND; > +} > + > +const char *fdt_stringlist_get(const void *fdt, int nodeoffset, > + const char *property, int idx, > + int *lenp) > +{ > + const char *list, *end; > + int length; > + > + list = fdt_getprop(fdt, nodeoffset, property, &length); > + if (!list) { > + if (lenp) > + *lenp = length; > + > + return NULL; > + } > + > + end = list + length; > + > + while (list < end) { > + length = strnlen(list, end - list) + 1; > + > + /* Abort if the last string isn't properly NUL-terminated. */ > + if (list + length > end) { > + if (lenp) > + *lenp = -FDT_ERR_BADVALUE; > + > + return NULL; > + } > + > + if (idx == 0) { > + if (lenp) > + *lenp = length - 1; > + > + return list; > + } > + > + list += length; > + idx--; > + } > + > + if (lenp) > + *lenp = -FDT_ERR_NOTFOUND; > + > + return NULL; > +} > + > int fdt_node_check_compatible(const void *fdt, int nodeoffset, > const char *compatible) > { > @@ -542,10 +673,8 @@ int fdt_node_check_compatible(const void *fdt, int nodeoffset, > prop = fdt_getprop(fdt, nodeoffset, "compatible", &len); > if (!prop) > return len; > - if (fdt_stringlist_contains(prop, len, compatible)) > - return 0; > - else > - return 1; > + > + return !fdt_stringlist_contains(prop, len, compatible); > } > > int fdt_node_offset_by_compatible(const void *fdt, int startoffset, > diff --git a/EmbeddedPkg/Library/FdtLib/fdt_rw.c b/EmbeddedPkg/Library/FdtLib/fdt_rw.c > index 7a2bcf3..863f2b2 100644 > --- a/EmbeddedPkg/Library/FdtLib/fdt_rw.c > +++ b/EmbeddedPkg/Library/FdtLib/fdt_rw.c > @@ -84,9 +84,9 @@ static int _fdt_rw_check_header(void *fdt) > > #define FDT_RW_CHECK_HEADER(fdt) \ > { \ > - int err; \ > - if ((err = _fdt_rw_check_header(fdt)) != 0) \ > - return err; \ > + int __err; \ > + if ((__err = _fdt_rw_check_header(fdt)) != 0) \ > + return __err; \ > } > > static inline int _fdt_data_size(void *fdt) > @@ -101,6 +101,8 @@ static int _fdt_splice(void *fdt, void *splicepoint, int oldlen, int newlen) > > if (((p + oldlen) < p) || ((p + oldlen) > end)) > return -FDT_ERR_BADOFFSET; > + if ((p < (char *)fdt) || ((end - oldlen + newlen) < (char *)fdt)) > + return -FDT_ERR_BADOFFSET; > if ((end - oldlen + newlen) > ((char *)fdt + fdt_totalsize(fdt))) > return -FDT_ERR_NOSPACE; > memmove(p + newlen, p + oldlen, end - p - oldlen); > @@ -126,8 +128,7 @@ static int _fdt_splice_struct(void *fdt, void *p, > int delta = newlen - oldlen; > int err; > > - err = _fdt_splice(fdt, p, oldlen, newlen); > - if (err) > + if ((err = _fdt_splice(fdt, p, oldlen, newlen))) > return err; > > fdt_set_size_dt_struct(fdt, fdt_size_dt_struct(fdt) + delta); > @@ -141,8 +142,7 @@ static int _fdt_splice_string(void *fdt, int newlen) > + fdt_off_dt_strings(fdt) + fdt_size_dt_strings(fdt); > int err; > > - err = _fdt_splice(fdt, p, 0, newlen); > - if (err) > + if ((err = _fdt_splice(fdt, p, 0, newlen))) > return err; > > fdt_set_size_dt_strings(fdt, fdt_size_dt_strings(fdt) + newlen); > @@ -191,17 +191,13 @@ int fdt_add_mem_rsv(void *fdt, uint64_t address, uint64_t size) > int fdt_del_mem_rsv(void *fdt, int n) > { > struct fdt_reserve_entry *re = _fdt_mem_rsv_w(fdt, n); > - int err; > > FDT_RW_CHECK_HEADER(fdt); > > if (n >= fdt_num_mem_rsv(fdt)) > return -FDT_ERR_NOTFOUND; > > - err = _fdt_splice_mem_rsv(fdt, re, 1, 0); > - if (err) > - return err; > - return 0; > + return _fdt_splice_mem_rsv(fdt, re, 1, 0); > } > > static int _fdt_resize_property(void *fdt, int nodeoffset, const char *name, > @@ -211,12 +207,11 @@ static int _fdt_resize_property(void *fdt, int nodeoffset, const char *name, > int err; > > *prop = fdt_get_property_w(fdt, nodeoffset, name, &oldlen); > - if (! (*prop)) > + if (!*prop) > return oldlen; > > - err = _fdt_splice_struct(fdt, (*prop)->data, FDT_TAGALIGN(oldlen), > - FDT_TAGALIGN(len)); > - if (err) > + if ((err = _fdt_splice_struct(fdt, (*prop)->data, FDT_TAGALIGN(oldlen), > + FDT_TAGALIGN(len)))) > return err; > > (*prop)->len = cpu_to_fdt32(len); > @@ -274,8 +269,8 @@ int fdt_set_name(void *fdt, int nodeoffset, const char *name) > return 0; > } > > -int fdt_setprop(void *fdt, int nodeoffset, const char *name, > - const void *val, int len) > +int fdt_setprop_placeholder(void *fdt, int nodeoffset, const char *name, > + int len, void **prop_data) > { > struct fdt_property *prop; > int err; > @@ -288,7 +283,22 @@ int fdt_setprop(void *fdt, int nodeoffset, const char *name, > if (err) > return err; > > - memcpy(prop->data, val, len); > + *prop_data = prop->data; > + return 0; > +} > + > +int fdt_setprop(void *fdt, int nodeoffset, const char *name, > + const void *val, int len) > +{ > + void *prop_data; > + int err; > + > + err = fdt_setprop_placeholder(fdt, nodeoffset, name, len, &prop_data); > + if (err) > + return err; > + > + if (len) > + memcpy(prop_data, val, len); > return 0; > } > > @@ -327,7 +337,7 @@ int fdt_delprop(void *fdt, int nodeoffset, const char *name) > FDT_RW_CHECK_HEADER(fdt); > > prop = fdt_get_property_w(fdt, nodeoffset, name, &len); > - if (! prop) > + if (!prop) > return len; > > proplen = sizeof(*prop) + FDT_TAGALIGN(len); > diff --git a/EmbeddedPkg/Library/FdtLib/fdt_strerror.c b/EmbeddedPkg/Library/FdtLib/fdt_strerror.c > index a49793d..3041e2e 100644 > --- a/EmbeddedPkg/Library/FdtLib/fdt_strerror.c > +++ b/EmbeddedPkg/Library/FdtLib/fdt_strerror.c > @@ -69,6 +69,7 @@ static struct fdt_errtabent fdt_errtable[] = { > > FDT_ERRTABENT(FDT_ERR_BADOFFSET), > FDT_ERRTABENT(FDT_ERR_BADPATH), > + FDT_ERRTABENT(FDT_ERR_BADPHANDLE), > FDT_ERRTABENT(FDT_ERR_BADSTATE), > > FDT_ERRTABENT(FDT_ERR_TRUNCATED), > @@ -76,6 +77,11 @@ static struct fdt_errtabent fdt_errtable[] = { > FDT_ERRTABENT(FDT_ERR_BADVERSION), > FDT_ERRTABENT(FDT_ERR_BADSTRUCTURE), > FDT_ERRTABENT(FDT_ERR_BADLAYOUT), > + FDT_ERRTABENT(FDT_ERR_INTERNAL), > + FDT_ERRTABENT(FDT_ERR_BADNCELLS), > + FDT_ERRTABENT(FDT_ERR_BADVALUE), > + FDT_ERRTABENT(FDT_ERR_BADOVERLAY), > + FDT_ERRTABENT(FDT_ERR_NOPHANDLES), > }; > #define FDT_ERRTABSIZE (sizeof(fdt_errtable) / sizeof(fdt_errtable[0])) > > diff --git a/EmbeddedPkg/Library/FdtLib/fdt_sw.c b/EmbeddedPkg/Library/FdtLib/fdt_sw.c > index 991919b..3c2c710 100644 > --- a/EmbeddedPkg/Library/FdtLib/fdt_sw.c > +++ b/EmbeddedPkg/Library/FdtLib/fdt_sw.c > @@ -107,6 +107,38 @@ int fdt_create(void *buf, int bufsize) > return 0; > } > > +int fdt_resize(void *fdt, void *buf, int bufsize) > +{ > + size_t headsize, tailsize; > + char *oldtail, *newtail; > + > + FDT_SW_CHECK_HEADER(fdt); > + > + headsize = fdt_off_dt_struct(fdt); > + tailsize = fdt_size_dt_strings(fdt); > + > + if ((headsize + tailsize) > bufsize) > + return -FDT_ERR_NOSPACE; > + > + oldtail = (char *)fdt + fdt_totalsize(fdt) - tailsize; > + newtail = (char *)buf + bufsize - tailsize; > + > + /* Two cases to avoid clobbering data if the old and new > + * buffers partially overlap */ > + if (buf <= fdt) { > + memmove(buf, fdt, headsize); > + memmove(newtail, oldtail, tailsize); > + } else { > + memmove(newtail, oldtail, tailsize); > + memmove(buf, fdt, headsize); > + } > + > + fdt_set_off_dt_strings(buf, bufsize); > + fdt_set_totalsize(buf, bufsize); > + > + return 0; > +} > + > int fdt_add_reservemap_entry(void *fdt, uint64_t addr, uint64_t size) > { > struct fdt_reserve_entry *re; > @@ -188,7 +220,7 @@ static int _fdt_find_add_string(void *fdt, const char *s) > return offset; > } > > -int fdt_property(void *fdt, const char *name, const void *val, int len) > +int fdt_property_placeholder(void *fdt, const char *name, int len, void **valp) > { > struct fdt_property *prop; > int nameoff; > @@ -206,7 +238,19 @@ int fdt_property(void *fdt, const char *name, const void *val, int len) > prop->tag = cpu_to_fdt32(FDT_PROP); > prop->nameoff = cpu_to_fdt32(nameoff); > prop->len = cpu_to_fdt32(len); > - memcpy(prop->data, val, len); > + *valp = prop->data; > + return 0; > +} > + > +int fdt_property(void *fdt, const char *name, const void *val, int len) > +{ > + void *ptr; > + int ret; > + > + ret = fdt_property_placeholder(fdt, name, len, &ptr); > + if (ret) > + return ret; > + memcpy(ptr, val, len); > return 0; > } > > diff --git a/EmbeddedPkg/Library/FdtLib/fdt_wip.c b/EmbeddedPkg/Library/FdtLib/fdt_wip.c > index 3f2b581..6e39807 100644 > --- a/EmbeddedPkg/Library/FdtLib/fdt_wip.c > +++ b/EmbeddedPkg/Library/FdtLib/fdt_wip.c > @@ -55,21 +55,42 @@ > > #include "libfdt_internal.h" > > +int fdt_setprop_inplace_namelen_partial(void *fdt, int nodeoffset, > + const char *name, int namelen, > + uint32_t idx, const void *val, > + int len) > +{ > + void *propval; > + int proplen; > + > + propval = fdt_getprop_namelen_w(fdt, nodeoffset, name, namelen, > + &proplen); > + if (!propval) > + return proplen; > + > + if (proplen < (len + idx)) > + return -FDT_ERR_NOSPACE; > + > + memcpy((char *)propval + idx, val, len); > + return 0; > +} > + > int fdt_setprop_inplace(void *fdt, int nodeoffset, const char *name, > const void *val, int len) > { > - void *propval; > + const void *propval; > int proplen; > > - propval = fdt_getprop_w(fdt, nodeoffset, name, &proplen); > - if (! propval) > + propval = fdt_getprop(fdt, nodeoffset, name, &proplen); > + if (!propval) > return proplen; > > if (proplen != len) > return -FDT_ERR_NOSPACE; > > - memcpy(propval, val, len); > - return 0; > + return fdt_setprop_inplace_namelen_partial(fdt, nodeoffset, name, > + strlen(name), 0, > + val, len); > } > > static void _fdt_nop_region(void *start, int len) > @@ -86,7 +107,7 @@ int fdt_nop_property(void *fdt, int nodeoffset, const char *name) > int len; > > prop = fdt_get_property_w(fdt, nodeoffset, name, &len); > - if (! prop) > + if (!prop) > return len; > > _fdt_nop_region(prop, len + sizeof(*prop)); > diff --git a/EmbeddedPkg/Library/FdtLib/libfdt_internal.h b/EmbeddedPkg/Library/FdtLib/libfdt_internal.h > index 1545611..f82227a 100644 > --- a/EmbeddedPkg/Library/FdtLib/libfdt_internal.h > +++ b/EmbeddedPkg/Library/FdtLib/libfdt_internal.h > @@ -57,9 +57,9 @@ > > #define FDT_CHECK_HEADER(fdt) \ > { \ > - int err; \ > - if ((err = fdt_check_header(fdt)) != 0) \ > - return err; \ > + int __err; \ > + if ((__err = fdt_check_header(fdt)) != 0) \ > + return __err; \ > } > > int _fdt_check_node_offset(const void *fdt, int offset); > diff --git a/EmbeddedPkg/Library/FdtLib/version.lds b/EmbeddedPkg/Library/FdtLib/version.lds > index 80b322bed..1f4e1ea 100644 > --- a/EmbeddedPkg/Library/FdtLib/version.lds > +++ b/EmbeddedPkg/Library/FdtLib/version.lds > @@ -8,6 +8,7 @@ LIBFDT_1.2 { > fdt_get_mem_rsv; > fdt_subnode_offset_namelen; > fdt_subnode_offset; > + fdt_path_offset_namelen; > fdt_path_offset; > fdt_get_name; > fdt_get_property_namelen; > @@ -54,6 +55,12 @@ LIBFDT_1.2 { > fdt_get_property_by_offset; > fdt_getprop_by_offset; > fdt_next_property_offset; > + fdt_first_subnode; > + fdt_next_subnode; > + fdt_address_cells; > + fdt_size_cells; > + fdt_stringlist_contains; > + fdt_resize; > > local: > *; > -- > 2.7.4 > _______________________________________________ edk2-devel mailing list edk2-devel@lists.01.org https://lists.01.org/mailman/listinfo/edk2-devel
© 2016 - 2024 Red Hat, Inc.