From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received-SPF: Pass (sender SPF authorized) identity=mailfrom; client-ip=2607:f8b0:4001:c0b::230; helo=mail-it0-x230.google.com; envelope-from=ard.biesheuvel@linaro.org; receiver=edk2-devel@lists.01.org Received: from mail-it0-x230.google.com (mail-it0-x230.google.com [IPv6:2607:f8b0:4001:c0b::230]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by ml01.01.org (Postfix) with ESMTPS id 189AC2236BA8E for ; Fri, 5 Jan 2018 07:01:18 -0800 (PST) Received: by mail-it0-x230.google.com with SMTP id f143so1963276itb.0 for ; Fri, 05 Jan 2018 07:06:25 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=mime-version:in-reply-to:references:from:date:message-id:subject:to :cc; bh=re7hAq4toMCShaTe5inkXZ9aWwzVP1/yYcJ13WfnVSc=; b=Wp5L8HUg9mooM9piHJKiprXunDOqIEoKegUS2GW5U4r2QQqO5i7vZnmnApDRl+OEUX knwJUOjORZ3tboPI4noSpDiuZsvap0msHow3y6hMQfAFUMqFD3n1GFYrflKStjo03DZJ nScbXHzP/W2+vv9Qvb5MDYY1pC+JeHMuLi/TE= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:mime-version:in-reply-to:references:from:date :message-id:subject:to:cc; bh=re7hAq4toMCShaTe5inkXZ9aWwzVP1/yYcJ13WfnVSc=; b=s5khez7Uuytf2qhPKP3bF5ehAKJGM9cKhVlefYaO0LpsnEAr36fS6BblykjhoV3TaL zX89i7ompHxHhzy6wMu48l7GzJQHffuENWL23RoBb01cp6Uz17xKoMo76i6uDKocTXwi lh+6/Th9NEZiA+SZ4FZutpHe2phwv06arbfPg/eQ8HIH1FxYaQ9XGVUweYZ2UmLCYZFg 1fVd26np4W2KmpG4j8/Zpets4Ky25Ze6YQSogdd4izLqfmtatVsOIf86rye4DRn+dfk3 UpBqY77WhF09UOlGPd9Mv8QcoNtPp7W6zJY19QKcYRn2FkeH1+M7s11n9JFnuFJeuUFD Ntbw== X-Gm-Message-State: AKGB3mI/XKCWrONXWxuKSvMbkEzwR/UpYrFNrLZuloWDHLpADlglUlvR nu4J6N7mfJcH47R/XLBeow1ndm1OF+gAEGwFYWV0UA== X-Google-Smtp-Source: ACJfBouShWx4AKqFC0LW1bjg9yL94LQI1G1+L5uULP0u+0TUVMDXxr4XktjJc7yJuHU7TC0v760GjQGG7/fVHwL88Bc= X-Received: by 10.36.65.142 with SMTP id b14mr3335032itd.34.1515164783014; Fri, 05 Jan 2018 07:06:23 -0800 (PST) MIME-Version: 1.0 Received: by 10.107.37.197 with HTTP; Fri, 5 Jan 2018 07:06:22 -0800 (PST) In-Reply-To: <1515151057-26162-1-git-send-email-pankaj.bansal@nxp.com> References: <1515151057-26162-1-git-send-email-pankaj.bansal@nxp.com> From: Ard Biesheuvel Date: Fri, 5 Jan 2018 15:06:22 +0000 Message-ID: To: Pankaj Bansal Cc: Leif Lindholm , "edk2-devel@lists.01.org" , Varun Sethi Subject: Re: [PATCH] EmbeddedPkg/FdtLib: Update FdtLib to v1.4.5 X-BeenThere: edk2-devel@lists.01.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: EDK II Development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Fri, 05 Jan 2018 15:01:19 -0000 Content-Type: text/plain; charset="UTF-8" On 5 January 2018 at 11:17, Pankaj Bansal 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 > Cc: Ard Biesheuvel > Contributed-under: TianoCore Contribution Agreement 1.1 > Signed-off-by: Pankaj Bansal Reviewed-by: Ard Biesheuvel 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 > + * > + * 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 > +#include > + > +#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 >