public inbox for devel@edk2.groups.io
 help / color / mirror / Atom feed
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
>


      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