From: Ard Biesheuvel <ard.biesheuvel@linaro.org>
To: Pankaj Bansal <pankaj.bansal@nxp.com>
Cc: Leif Lindholm <leif.lindholm@linaro.org>,
"edk2-devel@lists.01.org" <edk2-devel@lists.01.org>,
Varun Sethi <V.Sethi@nxp.com>
Subject: Re: [PATCH] EmbeddedPkg/FdtLib: Update FdtLib to v1.4.5
Date: Fri, 5 Jan 2018 15:06:22 +0000 [thread overview]
Message-ID: <CAKv+Gu9q71J3sBpofXSRd_5sphjFxQG0cHMLdSTgEu+xevLobA@mail.gmail.com> (raw)
In-Reply-To: <1515151057-26162-1-git-send-email-pankaj.bansal@nxp.com>
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
>
prev parent reply other threads:[~2018-01-05 15:01 UTC|newest]
Thread overview: 2+ messages / expand[flat|nested] mbox.gz Atom feed top
2018-01-05 11:17 [PATCH] EmbeddedPkg/FdtLib: Update FdtLib to v1.4.5 Pankaj Bansal
2018-01-05 15:06 ` Ard Biesheuvel [this message]
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-list from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=CAKv+Gu9q71J3sBpofXSRd_5sphjFxQG0cHMLdSTgEu+xevLobA@mail.gmail.com \
--to=devel@edk2.groups.io \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox