[U-Boot] [PATCH 4/4] fdt: Sync up to the latest libfdt
Adam Ford
aford173 at gmail.com
Tue Jan 7 12:43:24 CET 2020
On Sun, Oct 27, 2019 at 10:55 AM Simon Glass <sjg at chromium.org> wrote:
>
> Bring over the fdt from this commit:
>
> 430419c (origin/master) tests: fix some python warnings
>
> adding in the 'assumptions' series designed to reduce code size.
>
> Signed-off-by: Simon Glass <sjg at chromium.org>
I don't know how, but this patch broke the am3517_evm board. I
haven't had a chance to review other omap3 boards I have yet.
With this patch:
U-Boot SPL 2020.01-rc1-00163-gf0921f5098 (Jan 07 2020 - 05:31:57 -0600)
Trying to boot from MMC1
spl_register_fat_device: fat register err - -1
spl_register_fat_device: fat register err - -1
spl_load_image_fat: error reading image u-boot.img, err - -1
SPL: failed to boot from all boot devices
If I revert this patch on master, the am3517_evm boots just fine. I'm
open to trying stuff if you have ideas.
adam
> ---
>
> lib/libfdt/fdt_ro.c | 420 ++++++++++++++++++++-------
> scripts/dtc/libfdt/Makefile.libfdt | 7 +
> scripts/dtc/libfdt/fdt.c | 182 ++++++++----
> scripts/dtc/libfdt/fdt.h | 47 +--
> scripts/dtc/libfdt/fdt_addresses.c | 94 +++---
> scripts/dtc/libfdt/fdt_empty_tree.c | 47 +--
> scripts/dtc/libfdt/fdt_overlay.c | 91 ++----
> scripts/dtc/libfdt/fdt_ro.c | 341 +++++++++++++++-------
> scripts/dtc/libfdt/fdt_rw.c | 119 ++++----
> scripts/dtc/libfdt/fdt_strerror.c | 47 +--
> scripts/dtc/libfdt/fdt_sw.c | 241 ++++++++++-----
> scripts/dtc/libfdt/fdt_wip.c | 47 +--
> scripts/dtc/libfdt/libfdt.h | 268 +++++++++++++----
> scripts/dtc/libfdt/libfdt_env.h | 48 +--
> scripts/dtc/libfdt/libfdt_internal.h | 144 +++++----
> tools/libfdt/fdt_rw.c | 3 +-
> 16 files changed, 1275 insertions(+), 871 deletions(-)
>
> diff --git a/lib/libfdt/fdt_ro.c b/lib/libfdt/fdt_ro.c
> index 693de9aa5a..560041b603 100644
> --- a/lib/libfdt/fdt_ro.c
> +++ b/lib/libfdt/fdt_ro.c
> @@ -14,12 +14,13 @@
>
> #include "libfdt_internal.h"
>
> -static int _fdt_nodename_eq(const void *fdt, int offset,
> +static int fdt_nodename_eq_(const void *fdt, int offset,
> const char *s, int len)
> {
> - const char *p = fdt_offset_ptr(fdt, offset + FDT_TAGSIZE, len+1);
> + int olen;
> + const char *p = fdt_get_name(fdt, offset, &olen);
>
> - if (!p)
> + if (!p || (fdt_chk_extra() && olen < len))
> /* short match */
> return 0;
>
> @@ -34,46 +35,85 @@ static int _fdt_nodename_eq(const void *fdt, int offset,
> return 0;
> }
>
> -const char *fdt_string(const void *fdt, int stroffset)
> -{
> - return (const char *)fdt + fdt_off_dt_strings(fdt) + stroffset;
> -}
> -
> -static int _fdt_string_eq(const void *fdt, int stroffset,
> - const char *s, int len)
> +const char *fdt_get_string(const void *fdt, int stroffset, int *lenp)
> {
> - const char *p = fdt_string(fdt, stroffset);
> + int32_t totalsize;
> + uint32_t absoffset;
> + size_t len;
> + int err;
> + const char *s, *n;
>
> - return (strnlen(p, len + 1) == len) && (memcmp(p, s, len) == 0);
> -}
> + if (!fdt_chk_extra()) {
> + s = (const char *)fdt + fdt_off_dt_strings(fdt) + stroffset;
>
> -uint32_t fdt_get_max_phandle(const void *fdt)
> -{
> - uint32_t max_phandle = 0;
> - int offset;
> + if (lenp)
> + *lenp = strlen(s);
> + return s;
> + }
> + totalsize = fdt_ro_probe_(fdt);
> + err = totalsize;
> + if (totalsize < 0)
> + goto fail;
> +
> + err = -FDT_ERR_BADOFFSET;
> + absoffset = stroffset + fdt_off_dt_strings(fdt);
> + if (absoffset >= totalsize)
> + goto fail;
> + len = totalsize - absoffset;
> +
> + if (fdt_magic(fdt) == FDT_MAGIC) {
> + if (stroffset < 0)
> + goto fail;
> + if (!fdt_chk_version() || fdt_version(fdt) >= 17) {
> + if (stroffset >= fdt_size_dt_strings(fdt))
> + goto fail;
> + if ((fdt_size_dt_strings(fdt) - stroffset) < len)
> + len = fdt_size_dt_strings(fdt) - stroffset;
> + }
> + } else if (fdt_magic(fdt) == FDT_SW_MAGIC) {
> + if ((stroffset >= 0)
> + || (stroffset < -fdt_size_dt_strings(fdt)))
> + goto fail;
> + if ((-stroffset) < len)
> + len = -stroffset;
> + } else {
> + err = -FDT_ERR_INTERNAL;
> + goto fail;
> + }
>
> - for (offset = fdt_next_node(fdt, -1, NULL);;
> - offset = fdt_next_node(fdt, offset, NULL)) {
> - uint32_t phandle;
> + s = (const char *)fdt + absoffset;
> + n = memchr(s, '\0', len);
> + if (!n) {
> + /* missing terminating NULL */
> + err = -FDT_ERR_TRUNCATED;
> + goto fail;
> + }
>
> - if (offset == -FDT_ERR_NOTFOUND)
> - return max_phandle;
> + if (lenp)
> + *lenp = n - s;
> + return s;
>
> - if (offset < 0)
> - return (uint32_t)-1;
> +fail:
> + if (lenp)
> + *lenp = err;
> + return NULL;
> +}
>
> - phandle = fdt_get_phandle(fdt, offset);
> - if (phandle == (uint32_t)-1)
> - continue;
> +const char *fdt_string(const void *fdt, int stroffset)
> +{
> + return fdt_get_string(fdt, stroffset, NULL);
> +}
>
> - if (phandle > max_phandle)
> - max_phandle = phandle;
> - }
> +static int fdt_string_eq_(const void *fdt, int stroffset,
> + const char *s, int len)
> +{
> + int slen;
> + const char *p = fdt_get_string(fdt, stroffset, &slen);
>
> - return 0;
> + return p && (slen == len) && (memcmp(p, s, len) == 0);
> }
>
> -int fdt_generate_phandle(const void *fdt, uint32_t *phandle)
> +int fdt_find_max_phandle(const void *fdt, uint32_t *phandle)
> {
> uint32_t max = 0;
> int offset = -1;
> @@ -95,6 +135,21 @@ int fdt_generate_phandle(const void *fdt, uint32_t *phandle)
> max = value;
> }
>
> + if (phandle)
> + *phandle = max;
> +
> + return 0;
> +}
> +
> +int fdt_generate_phandle(const void *fdt, uint32_t *phandle)
> +{
> + uint32_t max;
> + int err;
> +
> + err = fdt_find_max_phandle(fdt, &max);
> + if (err < 0)
> + return err;
> +
> if (max == FDT_MAX_PHANDLE)
> return -FDT_ERR_NOPHANDLES;
>
> @@ -104,24 +159,48 @@ int fdt_generate_phandle(const void *fdt, uint32_t *phandle)
> return 0;
> }
>
> +static const struct fdt_reserve_entry *fdt_mem_rsv(const void *fdt, int n)
> +{
> + int offset = n * sizeof(struct fdt_reserve_entry);
> + int absoffset = fdt_off_mem_rsvmap(fdt) + offset;
> +
> + if (fdt_chk_extra()) {
> + if (absoffset < fdt_off_mem_rsvmap(fdt))
> + return NULL;
> + if (absoffset > fdt_totalsize(fdt) -
> + sizeof(struct fdt_reserve_entry))
> + return NULL;
> + }
> + return fdt_mem_rsv_(fdt, n);
> +}
> +
> int fdt_get_mem_rsv(const void *fdt, int n, uint64_t *address, uint64_t *size)
> {
> - FDT_CHECK_HEADER(fdt);
> - *address = fdt64_to_cpu(fdt_mem_rsv_(fdt, n)->address);
> - *size = fdt64_to_cpu(fdt_mem_rsv_(fdt, n)->size);
> + const struct fdt_reserve_entry *re;
> +
> + FDT_RO_PROBE(fdt);
> + re = fdt_mem_rsv(fdt, n);
> + if (fdt_chk_extra() && !re)
> + return -FDT_ERR_BADOFFSET;
> +
> + *address = fdt64_ld(&re->address);
> + *size = fdt64_ld(&re->size);
> return 0;
> }
>
> int fdt_num_mem_rsv(const void *fdt)
> {
> - int i = 0;
> + int i;
> + const struct fdt_reserve_entry *re;
>
> - while (fdt64_to_cpu(fdt_mem_rsv_(fdt, i)->size) != 0)
> - i++;
> - return i;
> + for (i = 0; (re = fdt_mem_rsv(fdt, i)) != NULL; i++) {
> + if (fdt64_ld(&re->size) == 0)
> + return i;
> + }
> + return -FDT_ERR_TRUNCATED;
> }
>
> -static int _nextprop(const void *fdt, int offset)
> +static int nextprop_(const void *fdt, int offset)
> {
> uint32_t tag;
> int nextoffset;
> @@ -150,13 +229,13 @@ int fdt_subnode_offset_namelen(const void *fdt, int offset,
> {
> int depth;
>
> - FDT_CHECK_HEADER(fdt);
> + FDT_RO_PROBE(fdt);
>
> for (depth = 0;
> (offset >= 0) && (depth >= 0);
> offset = fdt_next_node(fdt, offset, &depth))
> if ((depth == 1)
> - && _fdt_nodename_eq(fdt, offset, name, namelen))
> + && fdt_nodename_eq_(fdt, offset, name, namelen))
> return offset;
>
> if (depth < 0)
> @@ -170,36 +249,17 @@ int fdt_subnode_offset(const void *fdt, int parentoffset,
> return fdt_subnode_offset_namelen(fdt, parentoffset, name, strlen(name));
> }
>
> -/*
> - * Find the next of path separator, note we need to search for both '/' and ':'
> - * and then take the first one so that we do the right thing for e.g.
> - * "foo/bar:option" and "bar:option/otheroption", both of which happen, so
> - * first searching for either ':' or '/' does not work.
> - */
> -static const char *fdt_path_next_separator(const char *path, int len)
> -{
> - const void *sep1 = memchr(path, '/', len);
> - const void *sep2 = memchr(path, ':', len);
> -
> - if (sep1 && sep2)
> - return (sep1 < sep2) ? sep1 : sep2;
> - else if (sep1)
> - return sep1;
> - else
> - return sep2;
> -}
> -
> int fdt_path_offset_namelen(const void *fdt, const char *path, int namelen)
> {
> const char *end = path + namelen;
> const char *p = path;
> int offset = 0;
>
> - FDT_CHECK_HEADER(fdt);
> + FDT_RO_PROBE(fdt);
>
> /* see if we have an alias */
> if (*path != '/') {
> - const char *q = fdt_path_next_separator(path, namelen);
> + const char *q = memchr(path, '/', end - p);
>
> if (!q)
> q = end;
> @@ -212,17 +272,16 @@ int fdt_path_offset_namelen(const void *fdt, const char *path, int namelen)
> p = q;
> }
>
> - while (*p && (p < end)) {
> + while (p < end) {
> const char *q;
>
> - while (*p == '/')
> + while (*p == '/') {
> p++;
> -
> - if (*p == '\0' || *p == ':')
> - return offset;
> -
> - q = fdt_path_next_separator(p, end - p);
> - if (!q)
> + if (p == end)
> + return offset;
> + }
> + q = memchr(p, '/', end - p);
> + if (! q)
> q = end;
>
> offset = fdt_subnode_offset_namelen(fdt, offset, p, q-p);
> @@ -243,16 +302,35 @@ int fdt_path_offset(const void *fdt, const char *path)
> const char *fdt_get_name(const void *fdt, int nodeoffset, int *len)
> {
> const struct fdt_node_header *nh = fdt_offset_ptr_(fdt, nodeoffset);
> + const char *nameptr;
> int err;
>
> - if (((err = fdt_check_header(fdt)) != 0)
> - || ((err = fdt_check_node_offset_(fdt, nodeoffset)) < 0))
> + if (fdt_chk_extra() &&
> + (((err = fdt_ro_probe_(fdt)) < 0)
> + || ((err = fdt_check_node_offset_(fdt, nodeoffset)) < 0)))
> + goto fail;
> +
> + nameptr = nh->name;
> +
> + if (fdt_chk_version() && fdt_version(fdt) < 0x10) {
> + /*
> + * For old FDT versions, match the naming conventions of V16:
> + * give only the leaf name (after all /). The actual tree
> + * contents are loosely checked.
> + */
> + const char *leaf;
> + leaf = strrchr(nameptr, '/');
> + if (leaf == NULL) {
> + err = -FDT_ERR_BADSTRUCTURE;
> goto fail;
> + }
> + nameptr = leaf+1;
> + }
>
> if (len)
> - *len = strlen(nh->name);
> + *len = strlen(nameptr);
>
> - return nh->name;
> + return nameptr;
>
> fail:
> if (len)
> @@ -267,7 +345,7 @@ int fdt_first_property_offset(const void *fdt, int nodeoffset)
> if ((offset = fdt_check_node_offset_(fdt, nodeoffset)) < 0)
> return offset;
>
> - return _nextprop(fdt, offset);
> + return nextprop_(fdt, offset);
> }
>
> int fdt_next_property_offset(const void *fdt, int offset)
> @@ -275,17 +353,17 @@ int fdt_next_property_offset(const void *fdt, int offset)
> if ((offset = fdt_check_prop_offset_(fdt, offset)) < 0)
> return offset;
>
> - return _nextprop(fdt, offset);
> + return nextprop_(fdt, offset);
> }
>
> -const struct fdt_property *fdt_get_property_by_offset(const void *fdt,
> - int offset,
> - int *lenp)
> +static const struct fdt_property *fdt_get_property_by_offset_(const void *fdt,
> + int offset,
> + int *lenp)
> {
> int err;
> const struct fdt_property *prop;
>
> - if ((err = fdt_check_prop_offset_(fdt, offset)) < 0) {
> + if (fdt_chk_basic() && (err = fdt_check_prop_offset_(fdt, offset)) < 0) {
> if (lenp)
> *lenp = err;
> return NULL;
> @@ -294,28 +372,50 @@ const struct fdt_property *fdt_get_property_by_offset(const void *fdt,
> prop = fdt_offset_ptr_(fdt, offset);
>
> if (lenp)
> - *lenp = fdt32_to_cpu(prop->len);
> + *lenp = fdt32_ld(&prop->len);
>
> return prop;
> }
>
> -const struct fdt_property *fdt_get_property_namelen(const void *fdt,
> - int offset,
> - const char *name,
> - int namelen, int *lenp)
> +const struct fdt_property *fdt_get_property_by_offset(const void *fdt,
> + int offset,
> + int *lenp)
> +{
> + /* Prior to version 16, properties may need realignment
> + * and this API does not work. fdt_getprop_*() will, however. */
> +
> + if (fdt_chk_version() && fdt_version(fdt) < 0x10) {
> + if (lenp)
> + *lenp = -FDT_ERR_BADVERSION;
> + return NULL;
> + }
> +
> + return fdt_get_property_by_offset_(fdt, offset, lenp);
> +}
> +
> +static const struct fdt_property *fdt_get_property_namelen_(const void *fdt,
> + int offset,
> + const char *name,
> + int namelen,
> + int *lenp,
> + int *poffset)
> {
> for (offset = fdt_first_property_offset(fdt, offset);
> (offset >= 0);
> (offset = fdt_next_property_offset(fdt, offset))) {
> const struct fdt_property *prop;
>
> - if (!(prop = fdt_get_property_by_offset(fdt, offset, lenp))) {
> + prop = fdt_get_property_by_offset_(fdt, offset, lenp);
> + if (fdt_chk_extra() && !prop) {
> offset = -FDT_ERR_INTERNAL;
> break;
> }
> - if (_fdt_string_eq(fdt, fdt32_to_cpu(prop->nameoff),
> - name, namelen))
> + if (fdt_string_eq_(fdt, fdt32_ld(&prop->nameoff),
> + name, namelen)) {
> + if (poffset)
> + *poffset = offset;
> return prop;
> + }
> }
>
> if (lenp)
> @@ -323,6 +423,25 @@ const struct fdt_property *fdt_get_property_namelen(const void *fdt,
> return NULL;
> }
>
> +
> +const struct fdt_property *fdt_get_property_namelen(const void *fdt,
> + int offset,
> + const char *name,
> + int namelen, int *lenp)
> +{
> + /* Prior to version 16, properties may need realignment
> + * and this API does not work. fdt_getprop_*() will, however. */
> + if (fdt_chk_version() && fdt_version(fdt) < 0x10) {
> + if (lenp)
> + *lenp = -FDT_ERR_BADVERSION;
> + return NULL;
> + }
> +
> + return fdt_get_property_namelen_(fdt, offset, name, namelen, lenp,
> + NULL);
> +}
> +
> +
> const struct fdt_property *fdt_get_property(const void *fdt,
> int nodeoffset,
> const char *name, int *lenp)
> @@ -334,12 +453,18 @@ const struct fdt_property *fdt_get_property(const void *fdt,
> const void *fdt_getprop_namelen(const void *fdt, int nodeoffset,
> const char *name, int namelen, int *lenp)
> {
> + int poffset;
> const struct fdt_property *prop;
>
> - prop = fdt_get_property_namelen(fdt, nodeoffset, name, namelen, lenp);
> + prop = fdt_get_property_namelen_(fdt, nodeoffset, name, namelen, lenp,
> + &poffset);
> if (!prop)
> return NULL;
>
> + /* Handle realignment */
> + if (fdt_chk_version() && fdt_version(fdt) < 0x10 &&
> + (poffset + sizeof(*prop)) % 8 && fdt32_ld(&prop->len) >= 8)
> + return prop->data + 4;
> return prop->data;
> }
>
> @@ -348,11 +473,31 @@ const void *fdt_getprop_by_offset(const void *fdt, int offset,
> {
> const struct fdt_property *prop;
>
> - prop = fdt_get_property_by_offset(fdt, offset, lenp);
> + prop = fdt_get_property_by_offset_(fdt, offset, lenp);
> if (!prop)
> return NULL;
> - if (namep)
> - *namep = fdt_string(fdt, fdt32_to_cpu(prop->nameoff));
> + if (namep) {
> + const char *name;
> + int namelen;
> +
> + if (fdt_chk_extra()) {
> + name = fdt_get_string(fdt, fdt32_ld(&prop->nameoff),
> + &namelen);
> + if (!name) {
> + if (lenp)
> + *lenp = namelen;
> + return NULL;
> + }
> + *namep = name;
> + } else {
> + *namep = fdt_string(fdt, fdt32_ld(&prop->nameoff));
> + }
> + }
> +
> + /* Handle realignment */
> + if (fdt_chk_version() && fdt_version(fdt) < 0x10 &&
> + (offset + sizeof(*prop)) % 8 && fdt32_ld(&prop->len) >= 8)
> + return prop->data + 4;
> return prop->data;
> }
>
> @@ -376,7 +521,7 @@ uint32_t fdt_get_phandle(const void *fdt, int nodeoffset)
> return 0;
> }
>
> - return fdt32_to_cpu(*php);
> + return fdt32_ld(php);
> }
>
> const char *fdt_get_alias_namelen(const void *fdt,
> @@ -402,7 +547,7 @@ int fdt_get_path(const void *fdt, int nodeoffset, char *buf, int buflen)
> int offset, depth, namelen;
> const char *name;
>
> - FDT_CHECK_HEADER(fdt);
> + FDT_RO_PROBE(fdt);
>
> if (buflen < 2)
> return -FDT_ERR_NOSPACE;
> @@ -454,7 +599,7 @@ int fdt_supernode_atdepth_offset(const void *fdt, int nodeoffset,
> int offset, depth;
> int supernodeoffset = -FDT_ERR_INTERNAL;
>
> - FDT_CHECK_HEADER(fdt);
> + FDT_RO_PROBE(fdt);
>
> if (supernodedepth < 0)
> return -FDT_ERR_NOTFOUND;
> @@ -476,10 +621,12 @@ int fdt_supernode_atdepth_offset(const void *fdt, int nodeoffset,
> }
> }
>
> - if ((offset == -FDT_ERR_NOTFOUND) || (offset >= 0))
> - return -FDT_ERR_BADOFFSET;
> - else if (offset == -FDT_ERR_BADOFFSET)
> - return -FDT_ERR_BADSTRUCTURE;
> + if (fdt_chk_extra()) {
> + if ((offset == -FDT_ERR_NOTFOUND) || (offset >= 0))
> + return -FDT_ERR_BADOFFSET;
> + else if (offset == -FDT_ERR_BADOFFSET)
> + return -FDT_ERR_BADSTRUCTURE;
> + }
>
> return offset; /* error from fdt_next_node() */
> }
> @@ -491,7 +638,7 @@ int fdt_node_depth(const void *fdt, int nodeoffset)
>
> err = fdt_supernode_atdepth_offset(fdt, nodeoffset, 0, &nodedepth);
> if (err)
> - return (err < 0) ? err : -FDT_ERR_INTERNAL;
> + return (!fdt_chk_extra() || err < 0) ? err : -FDT_ERR_INTERNAL;
> return nodedepth;
> }
>
> @@ -513,7 +660,7 @@ int fdt_node_offset_by_prop_value(const void *fdt, int startoffset,
> const void *val;
> int len;
>
> - FDT_CHECK_HEADER(fdt);
> + FDT_RO_PROBE(fdt);
>
> /* FIXME: The algorithm here is pretty horrible: we scan each
> * property of a node in fdt_getprop(), then if that didn't
> @@ -539,7 +686,7 @@ int fdt_node_offset_by_phandle(const void *fdt, uint32_t phandle)
> if ((phandle == 0) || (phandle == -1))
> return -FDT_ERR_BADPHANDLE;
>
> - FDT_CHECK_HEADER(fdt);
> + FDT_RO_PROBE(fdt);
>
> /* FIXME: The algorithm here is pretty horrible: we
> * potentially scan each property of a node in
> @@ -692,7 +839,7 @@ int fdt_node_offset_by_compatible(const void *fdt, int startoffset,
> {
> int offset, err;
>
> - FDT_CHECK_HEADER(fdt);
> + FDT_RO_PROBE(fdt);
>
> /* FIXME: The algorithm here is pretty horrible: we scan each
> * property of a node in fdt_node_check_compatible(), then if
> @@ -711,3 +858,68 @@ int fdt_node_offset_by_compatible(const void *fdt, int startoffset,
>
> return offset; /* error from fdt_next_node() */
> }
> +
> +#if !defined(CHECK_LEVEL) || CHECK_LEVEL > 0
> +int fdt_check_full(const void *fdt, size_t bufsize)
> +{
> + int err;
> + int num_memrsv;
> + int offset, nextoffset = 0;
> + uint32_t tag;
> + unsigned depth = 0;
> + const void *prop;
> + const char *propname;
> +
> + if (bufsize < FDT_V1_SIZE)
> + return -FDT_ERR_TRUNCATED;
> + err = fdt_check_header(fdt);
> + if (err != 0)
> + return err;
> + if (bufsize < fdt_totalsize(fdt))
> + return -FDT_ERR_TRUNCATED;
> +
> + num_memrsv = fdt_num_mem_rsv(fdt);
> + if (num_memrsv < 0)
> + return num_memrsv;
> +
> + while (1) {
> + offset = nextoffset;
> + tag = fdt_next_tag(fdt, offset, &nextoffset);
> +
> + if (nextoffset < 0)
> + return nextoffset;
> +
> + switch (tag) {
> + case FDT_NOP:
> + break;
> +
> + case FDT_END:
> + if (depth != 0)
> + return -FDT_ERR_BADSTRUCTURE;
> + return 0;
> +
> + case FDT_BEGIN_NODE:
> + depth++;
> + if (depth > INT_MAX)
> + return -FDT_ERR_BADSTRUCTURE;
> + break;
> +
> + case FDT_END_NODE:
> + if (depth == 0)
> + return -FDT_ERR_BADSTRUCTURE;
> + depth--;
> + break;
> +
> + case FDT_PROP:
> + prop = fdt_getprop_by_offset(fdt, offset, &propname,
> + &err);
> + if (!prop)
> + return err;
> + break;
> +
> + default:
> + return -FDT_ERR_INTERNAL;
> + }
> + }
> +}
> +#endif
> diff --git a/scripts/dtc/libfdt/Makefile.libfdt b/scripts/dtc/libfdt/Makefile.libfdt
> index 098b3f36e6..e54639738c 100644
> --- a/scripts/dtc/libfdt/Makefile.libfdt
> +++ b/scripts/dtc/libfdt/Makefile.libfdt
> @@ -1,3 +1,4 @@
> +# SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-2-Clause)
> # Makefile.libfdt
> #
> # This is not a complete Makefile of itself. Instead, it is designed to
> @@ -9,3 +10,9 @@ 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 \
> fdt_addresses.c fdt_overlay.c
> LIBFDT_OBJS = $(LIBFDT_SRCS:%.c=%.o)
> +LIBFDT_LIB = libfdt-$(DTC_VERSION).$(SHAREDLIB_EXT)
> +
> +libfdt_clean:
> + @$(VECHO) CLEAN "(libfdt)"
> + rm -f $(STD_CLEANFILES:%=$(LIBFDT_dir)/%)
> + rm -f $(LIBFDT_dir)/$(LIBFDT_soname)
> diff --git a/scripts/dtc/libfdt/fdt.c b/scripts/dtc/libfdt/fdt.c
> index 7855a17877..8e4cce3b9b 100644
> --- a/scripts/dtc/libfdt/fdt.c
> +++ b/scripts/dtc/libfdt/fdt.c
> @@ -1,52 +1,7 @@
> +// SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-2-Clause)
> /*
> * libfdt - Flat Device Tree manipulation
> * Copyright (C) 2006 David Gibson, IBM Corporation.
> - *
> - * 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"
>
> @@ -55,14 +10,24 @@
>
> #include "libfdt_internal.h"
>
> -int fdt_check_header(const void *fdt)
> +/*
> + * Minimal sanity check for a read-only tree. fdt_ro_probe_() checks
> + * that the given buffer contains what appears to be a flattened
> + * device tree with sane information in its header.
> + */
> +int32_t fdt_ro_probe_(const void *fdt)
> {
> + uint32_t totalsize = fdt_totalsize(fdt);
> +
> if (fdt_magic(fdt) == FDT_MAGIC) {
> /* Complete tree */
> - if (fdt_version(fdt) < FDT_FIRST_SUPPORTED_VERSION)
> - return -FDT_ERR_BADVERSION;
> - if (fdt_last_comp_version(fdt) > FDT_LAST_SUPPORTED_VERSION)
> - return -FDT_ERR_BADVERSION;
> + if (fdt_chk_version()) {
> + if (fdt_version(fdt) < FDT_FIRST_SUPPORTED_VERSION)
> + return -FDT_ERR_BADVERSION;
> + if (fdt_last_comp_version(fdt) >
> + FDT_LAST_SUPPORTED_VERSION)
> + return -FDT_ERR_BADVERSION;
> + }
> } else if (fdt_magic(fdt) == FDT_SW_MAGIC) {
> /* Unfinished sequential-write blob */
> if (fdt_size_dt_struct(fdt) == 0)
> @@ -71,6 +36,96 @@ int fdt_check_header(const void *fdt)
> return -FDT_ERR_BADMAGIC;
> }
>
> + if (totalsize < INT32_MAX)
> + return totalsize;
> + else
> + return -FDT_ERR_TRUNCATED;
> +}
> +
> +static int check_off_(uint32_t hdrsize, uint32_t totalsize, uint32_t off)
> +{
> + return (off >= hdrsize) && (off <= totalsize);
> +}
> +
> +static int check_block_(uint32_t hdrsize, uint32_t totalsize,
> + uint32_t base, uint32_t size)
> +{
> + if (!check_off_(hdrsize, totalsize, base))
> + return 0; /* block start out of bounds */
> + if ((base + size) < base)
> + return 0; /* overflow */
> + if (!check_off_(hdrsize, totalsize, base + size))
> + return 0; /* block end out of bounds */
> + return 1;
> +}
> +
> +size_t fdt_header_size_(uint32_t version)
> +{
> + if (version <= 1)
> + return FDT_V1_SIZE;
> + else if (version <= 2)
> + return FDT_V2_SIZE;
> + else if (version <= 3)
> + return FDT_V3_SIZE;
> + else if (version <= 16)
> + return FDT_V16_SIZE;
> + else
> + return FDT_V17_SIZE;
> +}
> +
> +size_t fdt_header_size(const void *fdt)
> +{
> + return fdt_chk_version() ? fdt_header_size_(fdt_version(fdt)) :
> + FDT_V17_SIZE;
> +}
> +
> +int fdt_check_header(const void *fdt)
> +{
> + size_t hdrsize;
> +
> + if (fdt_magic(fdt) != FDT_MAGIC)
> + return -FDT_ERR_BADMAGIC;
> + if (fdt_chk_version()) {
> + if ((fdt_version(fdt) < FDT_FIRST_SUPPORTED_VERSION)
> + || (fdt_last_comp_version(fdt) >
> + FDT_LAST_SUPPORTED_VERSION))
> + return -FDT_ERR_BADVERSION;
> + if (fdt_version(fdt) < fdt_last_comp_version(fdt))
> + return -FDT_ERR_BADVERSION;
> + }
> + hdrsize = fdt_header_size(fdt);
> + if (fdt_chk_basic()) {
> +
> + if ((fdt_totalsize(fdt) < hdrsize)
> + || (fdt_totalsize(fdt) > INT_MAX))
> + return -FDT_ERR_TRUNCATED;
> +
> + /* Bounds check memrsv block */
> + if (!check_off_(hdrsize, fdt_totalsize(fdt),
> + fdt_off_mem_rsvmap(fdt)))
> + return -FDT_ERR_TRUNCATED;
> + }
> +
> + if (fdt_chk_extra()) {
> + /* Bounds check structure block */
> + if (fdt_chk_version() && fdt_version(fdt) < 17) {
> + if (!check_off_(hdrsize, fdt_totalsize(fdt),
> + fdt_off_dt_struct(fdt)))
> + return -FDT_ERR_TRUNCATED;
> + } else {
> + if (!check_block_(hdrsize, fdt_totalsize(fdt),
> + fdt_off_dt_struct(fdt),
> + fdt_size_dt_struct(fdt)))
> + return -FDT_ERR_TRUNCATED;
> + }
> +
> + /* Bounds check strings block */
> + if (!check_block_(hdrsize, fdt_totalsize(fdt),
> + fdt_off_dt_strings(fdt),
> + fdt_size_dt_strings(fdt)))
> + return -FDT_ERR_TRUNCATED;
> + }
> +
> return 0;
> }
>
> @@ -78,12 +133,13 @@ const void *fdt_offset_ptr(const void *fdt, int offset, unsigned int len)
> {
> unsigned absoffset = offset + fdt_off_dt_struct(fdt);
>
> - if ((absoffset < offset)
> - || ((absoffset + len) < absoffset)
> - || (absoffset + len) > fdt_totalsize(fdt))
> - return NULL;
> + if (fdt_chk_basic())
> + if ((absoffset < offset)
> + || ((absoffset + len) < absoffset)
> + || (absoffset + len) > fdt_totalsize(fdt))
> + return NULL;
>
> - if (fdt_version(fdt) >= 0x11)
> + if (!fdt_chk_version() || fdt_version(fdt) >= 0x11)
> if (((offset + len) < offset)
> || ((offset + len) > fdt_size_dt_struct(fdt)))
> return NULL;
> @@ -100,7 +156,7 @@ uint32_t fdt_next_tag(const void *fdt, int startoffset, int *nextoffset)
>
> *nextoffset = -FDT_ERR_TRUNCATED;
> tagp = fdt_offset_ptr(fdt, offset, FDT_TAGSIZE);
> - if (!tagp)
> + if (fdt_chk_basic() && !tagp)
> return FDT_END; /* premature end */
> tag = fdt32_to_cpu(*tagp);
> offset += FDT_TAGSIZE;
> @@ -112,18 +168,19 @@ uint32_t fdt_next_tag(const void *fdt, int startoffset, int *nextoffset)
> do {
> p = fdt_offset_ptr(fdt, offset++, 1);
> } while (p && (*p != '\0'));
> - if (!p)
> + if (fdt_chk_basic() && !p)
> return FDT_END; /* premature end */
> break;
>
> case FDT_PROP:
> lenp = fdt_offset_ptr(fdt, offset, sizeof(*lenp));
> - if (!lenp)
> + if (fdt_chk_basic() && !lenp)
> return FDT_END; /* premature end */
> /* skip-name offset, length and value */
> offset += sizeof(struct fdt_property) - FDT_TAGSIZE
> + fdt32_to_cpu(*lenp);
> - if (fdt_version(fdt) < 0x10 && fdt32_to_cpu(*lenp) >= 8 &&
> + if (fdt_chk_version() &&
> + fdt_version(fdt) < 0x10 && fdt32_to_cpu(*lenp) >= 8 &&
> ((offset - fdt32_to_cpu(*lenp)) % 8) != 0)
> offset += 4;
> break;
> @@ -137,7 +194,8 @@ uint32_t fdt_next_tag(const void *fdt, int startoffset, int *nextoffset)
> return FDT_END;
> }
>
> - if (!fdt_offset_ptr(fdt, startoffset, offset - startoffset))
> + if (fdt_chk_basic() &&
> + !fdt_offset_ptr(fdt, startoffset, offset - startoffset))
> return FDT_END; /* premature end */
>
> *nextoffset = FDT_TAGALIGN(offset);
> @@ -244,7 +302,7 @@ const char *fdt_find_string_(const char *strtab, int tabsize, const char *s)
>
> int fdt_move(const void *fdt, void *buf, int bufsize)
> {
> - FDT_CHECK_HEADER(fdt);
> + FDT_RO_PROBE(fdt);
>
> if (fdt_totalsize(fdt) > bufsize)
> return -FDT_ERR_NOSPACE;
> diff --git a/scripts/dtc/libfdt/fdt.h b/scripts/dtc/libfdt/fdt.h
> index 74961f9026..f2e68807f2 100644
> --- a/scripts/dtc/libfdt/fdt.h
> +++ b/scripts/dtc/libfdt/fdt.h
> @@ -1,55 +1,10 @@
> +/* SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-2-Clause) */
> #ifndef FDT_H
> #define FDT_H
> /*
> * libfdt - Flat Device Tree manipulation
> * Copyright (C) 2006 David Gibson, IBM Corporation.
> * Copyright 2012 Kim Phillips, Freescale Semiconductor.
> - *
> - * 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.
> */
>
> #ifndef __ASSEMBLY__
> diff --git a/scripts/dtc/libfdt/fdt_addresses.c b/scripts/dtc/libfdt/fdt_addresses.c
> index 788c143113..9a82cd0ba2 100644
> --- a/scripts/dtc/libfdt/fdt_addresses.c
> +++ b/scripts/dtc/libfdt/fdt_addresses.c
> @@ -1,53 +1,8 @@
> +// SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-2-Clause)
> /*
> * libfdt - Flat Device Tree manipulation
> * Copyright (C) 2014 David Gibson <david at gibson.dropbear.id.au>
> * Copyright (C) 2018 embedded brains GmbH
> - *
> - * 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"
>
> @@ -97,3 +52,50 @@ int fdt_size_cells(const void *fdt, int nodeoffset)
> return 1;
> return val;
> }
> +
> +/* This function assumes that [address|size]_cells is 1 or 2 */
> +int fdt_appendprop_addrrange(void *fdt, int parent, int nodeoffset,
> + const char *name, uint64_t addr, uint64_t size)
> +{
> + int addr_cells, size_cells, ret;
> + uint8_t data[sizeof(fdt64_t) * 2], *prop;
> +
> + ret = fdt_address_cells(fdt, parent);
> + if (ret < 0)
> + return ret;
> + addr_cells = ret;
> +
> + ret = fdt_size_cells(fdt, parent);
> + if (ret < 0)
> + return ret;
> + size_cells = ret;
> +
> + /* check validity of address */
> + prop = data;
> + if (addr_cells == 1) {
> + if ((addr > UINT32_MAX) || ((UINT32_MAX + 1 - addr) < size))
> + return -FDT_ERR_BADVALUE;
> +
> + fdt32_st(prop, (uint32_t)addr);
> + } else if (addr_cells == 2) {
> + fdt64_st(prop, addr);
> + } else {
> + return -FDT_ERR_BADNCELLS;
> + }
> +
> + /* check validity of size */
> + prop += addr_cells * sizeof(fdt32_t);
> + if (size_cells == 1) {
> + if (size > UINT32_MAX)
> + return -FDT_ERR_BADVALUE;
> +
> + fdt32_st(prop, (uint32_t)size);
> + } else if (size_cells == 2) {
> + fdt64_st(prop, size);
> + } else {
> + return -FDT_ERR_BADNCELLS;
> + }
> +
> + return fdt_appendprop(fdt, nodeoffset, name, data,
> + (addr_cells + size_cells) * sizeof(fdt32_t));
> +}
> diff --git a/scripts/dtc/libfdt/fdt_empty_tree.c b/scripts/dtc/libfdt/fdt_empty_tree.c
> index f2ae9b77c2..49d54d44b8 100644
> --- a/scripts/dtc/libfdt/fdt_empty_tree.c
> +++ b/scripts/dtc/libfdt/fdt_empty_tree.c
> @@ -1,52 +1,7 @@
> +// SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-2-Clause)
> /*
> * libfdt - Flat Device Tree manipulation
> * Copyright (C) 2012 David Gibson, IBM Corporation.
> - *
> - * 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"
>
> diff --git a/scripts/dtc/libfdt/fdt_overlay.c b/scripts/dtc/libfdt/fdt_overlay.c
> index bf75388ec9..be71873366 100644
> --- a/scripts/dtc/libfdt/fdt_overlay.c
> +++ b/scripts/dtc/libfdt/fdt_overlay.c
> @@ -1,53 +1,8 @@
> +// SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-2-Clause)
> /*
> * libfdt - Flat Device Tree manipulation
> * Copyright (C) 2016 Free Electrons
> * Copyright (C) 2016 NextThing Co.
> - *
> - * 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"
>
> @@ -93,11 +48,11 @@ static uint32_t overlay_get_target_phandle(const void *fdto, int fragment)
> * @pathp: pointer which receives the path of the target (or NULL)
> *
> * overlay_get_target() retrieves the target offset in the base
> - * device tree of a fragment, no matter how the actual targetting is
> + * device tree of a fragment, no matter how the actual targeting is
> * done (through a phandle or a path)
> *
> * returns:
> - * the targetted node offset in the base device tree
> + * the targeted node offset in the base device tree
> * Negative error code on error
> */
> static int overlay_get_target(const void *fdt, const void *fdto,
> @@ -697,7 +652,7 @@ static int get_path_len(const void *fdt, int nodeoffset)
> int len = 0, namelen;
> const char *name;
>
> - FDT_CHECK_HEADER(fdt);
> + FDT_RO_PROBE(fdt);
>
> for (;;) {
> name = fdt_get_name(fdt, nodeoffset, &namelen);
> @@ -778,26 +733,36 @@ static int overlay_symbol_update(void *fdt, void *fdto)
> /* keep end marker to avoid strlen() */
> e = path + path_len;
>
> - /* format: /<fragment-name>/__overlay__/<relative-subnode-path> */
> -
> if (*path != '/')
> return -FDT_ERR_BADVALUE;
>
> /* get fragment name first */
> s = strchr(path + 1, '/');
> - if (!s)
> - return -FDT_ERR_BADOVERLAY;
> + if (!s) {
> + /* Symbol refers to something that won't end
> + * up in the target tree */
> + continue;
> + }
>
> frag_name = path + 1;
> frag_name_len = s - path - 1;
>
> /* verify format; safe since "s" lies in \0 terminated prop */
> len = sizeof("/__overlay__/") - 1;
> - if ((e - s) < len || memcmp(s, "/__overlay__/", len))
> - return -FDT_ERR_BADOVERLAY;
> -
> - rel_path = s + len;
> - rel_path_len = e - rel_path;
> + if ((e - s) > len && (memcmp(s, "/__overlay__/", len) == 0)) {
> + /* /<fragment-name>/__overlay__/<relative-subnode-path> */
> + rel_path = s + len;
> + rel_path_len = e - rel_path;
> + } else if ((e - s) == len
> + && (memcmp(s, "/__overlay__", len - 1) == 0)) {
> + /* /<fragment-name>/__overlay__ */
> + rel_path = "";
> + rel_path_len = 0;
> + } else {
> + /* Symbol refers to something that won't end
> + * up in the target tree */
> + continue;
> + }
>
> /* find the fragment index in which the symbol lies */
> ret = fdt_subnode_offset_namelen(fdto, 0, frag_name,
> @@ -863,11 +828,15 @@ static int overlay_symbol_update(void *fdt, void *fdto)
>
> int fdt_overlay_apply(void *fdt, void *fdto)
> {
> - uint32_t delta = fdt_get_max_phandle(fdt);
> + uint32_t delta;
> int ret;
>
> - FDT_CHECK_HEADER(fdt);
> - FDT_CHECK_HEADER(fdto);
> + FDT_RO_PROBE(fdt);
> + FDT_RO_PROBE(fdto);
> +
> + ret = fdt_find_max_phandle(fdt, &delta);
> + if (ret)
> + goto err;
>
> ret = overlay_adjust_local_phandles(fdto, delta);
> if (ret)
> diff --git a/scripts/dtc/libfdt/fdt_ro.c b/scripts/dtc/libfdt/fdt_ro.c
> index dc499884e4..e398815485 100644
> --- a/scripts/dtc/libfdt/fdt_ro.c
> +++ b/scripts/dtc/libfdt/fdt_ro.c
> @@ -1,52 +1,7 @@
> +// SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-2-Clause)
> /*
> * libfdt - Flat Device Tree manipulation
> * Copyright (C) 2006 David Gibson, IBM Corporation.
> - *
> - * 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"
>
> @@ -61,7 +16,7 @@ static int fdt_nodename_eq_(const void *fdt, int offset,
> int olen;
> const char *p = fdt_get_name(fdt, offset, &olen);
>
> - if (!p || olen < len)
> + if (!p || (fdt_chk_extra() && olen < len))
> /* short match */
> return 0;
>
> @@ -76,46 +31,85 @@ static int fdt_nodename_eq_(const void *fdt, int offset,
> return 0;
> }
>
> -const char *fdt_string(const void *fdt, int stroffset)
> -{
> - return (const char *)fdt + fdt_off_dt_strings(fdt) + stroffset;
> -}
> -
> -static int fdt_string_eq_(const void *fdt, int stroffset,
> - const char *s, int len)
> +const char *fdt_get_string(const void *fdt, int stroffset, int *lenp)
> {
> - const char *p = fdt_string(fdt, stroffset);
> + int32_t totalsize;
> + uint32_t absoffset;
> + size_t len;
> + int err;
> + const char *s, *n;
>
> - return (strlen(p) == len) && (memcmp(p, s, len) == 0);
> -}
> + if (!fdt_chk_extra()) {
> + s = (const char *)fdt + fdt_off_dt_strings(fdt) + stroffset;
>
> -uint32_t fdt_get_max_phandle(const void *fdt)
> -{
> - uint32_t max_phandle = 0;
> - int offset;
> + if (lenp)
> + *lenp = strlen(s);
> + return s;
> + }
> + totalsize = fdt_ro_probe_(fdt);
> + err = totalsize;
> + if (totalsize < 0)
> + goto fail;
> +
> + err = -FDT_ERR_BADOFFSET;
> + absoffset = stroffset + fdt_off_dt_strings(fdt);
> + if (absoffset >= totalsize)
> + goto fail;
> + len = totalsize - absoffset;
> +
> + if (fdt_magic(fdt) == FDT_MAGIC) {
> + if (stroffset < 0)
> + goto fail;
> + if (!fdt_chk_version() || fdt_version(fdt) >= 17) {
> + if (stroffset >= fdt_size_dt_strings(fdt))
> + goto fail;
> + if ((fdt_size_dt_strings(fdt) - stroffset) < len)
> + len = fdt_size_dt_strings(fdt) - stroffset;
> + }
> + } else if (fdt_magic(fdt) == FDT_SW_MAGIC) {
> + if ((stroffset >= 0)
> + || (stroffset < -fdt_size_dt_strings(fdt)))
> + goto fail;
> + if ((-stroffset) < len)
> + len = -stroffset;
> + } else {
> + err = -FDT_ERR_INTERNAL;
> + goto fail;
> + }
>
> - for (offset = fdt_next_node(fdt, -1, NULL);;
> - offset = fdt_next_node(fdt, offset, NULL)) {
> - uint32_t phandle;
> + s = (const char *)fdt + absoffset;
> + n = memchr(s, '\0', len);
> + if (!n) {
> + /* missing terminating NULL */
> + err = -FDT_ERR_TRUNCATED;
> + goto fail;
> + }
>
> - if (offset == -FDT_ERR_NOTFOUND)
> - return max_phandle;
> + if (lenp)
> + *lenp = n - s;
> + return s;
>
> - if (offset < 0)
> - return (uint32_t)-1;
> +fail:
> + if (lenp)
> + *lenp = err;
> + return NULL;
> +}
>
> - phandle = fdt_get_phandle(fdt, offset);
> - if (phandle == (uint32_t)-1)
> - continue;
> +const char *fdt_string(const void *fdt, int stroffset)
> +{
> + return fdt_get_string(fdt, stroffset, NULL);
> +}
>
> - if (phandle > max_phandle)
> - max_phandle = phandle;
> - }
> +static int fdt_string_eq_(const void *fdt, int stroffset,
> + const char *s, int len)
> +{
> + int slen;
> + const char *p = fdt_get_string(fdt, stroffset, &slen);
>
> - return 0;
> + return p && (slen == len) && (memcmp(p, s, len) == 0);
> }
>
> -int fdt_generate_phandle(const void *fdt, uint32_t *phandle)
> +int fdt_find_max_phandle(const void *fdt, uint32_t *phandle)
> {
> uint32_t max = 0;
> int offset = -1;
> @@ -137,6 +131,21 @@ int fdt_generate_phandle(const void *fdt, uint32_t *phandle)
> max = value;
> }
>
> + if (phandle)
> + *phandle = max;
> +
> + return 0;
> +}
> +
> +int fdt_generate_phandle(const void *fdt, uint32_t *phandle)
> +{
> + uint32_t max;
> + int err;
> +
> + err = fdt_find_max_phandle(fdt, &max);
> + if (err < 0)
> + return err;
> +
> if (max == FDT_MAX_PHANDLE)
> return -FDT_ERR_NOPHANDLES;
>
> @@ -146,21 +155,45 @@ int fdt_generate_phandle(const void *fdt, uint32_t *phandle)
> return 0;
> }
>
> +static const struct fdt_reserve_entry *fdt_mem_rsv(const void *fdt, int n)
> +{
> + int offset = n * sizeof(struct fdt_reserve_entry);
> + int absoffset = fdt_off_mem_rsvmap(fdt) + offset;
> +
> + if (fdt_chk_extra()) {
> + if (absoffset < fdt_off_mem_rsvmap(fdt))
> + return NULL;
> + if (absoffset > fdt_totalsize(fdt) -
> + sizeof(struct fdt_reserve_entry))
> + return NULL;
> + }
> + return fdt_mem_rsv_(fdt, n);
> +}
> +
> int fdt_get_mem_rsv(const void *fdt, int n, uint64_t *address, uint64_t *size)
> {
> - FDT_CHECK_HEADER(fdt);
> - *address = fdt64_to_cpu(fdt_mem_rsv_(fdt, n)->address);
> - *size = fdt64_to_cpu(fdt_mem_rsv_(fdt, n)->size);
> + const struct fdt_reserve_entry *re;
> +
> + FDT_RO_PROBE(fdt);
> + re = fdt_mem_rsv(fdt, n);
> + if (fdt_chk_extra() && !re)
> + return -FDT_ERR_BADOFFSET;
> +
> + *address = fdt64_ld(&re->address);
> + *size = fdt64_ld(&re->size);
> return 0;
> }
>
> int fdt_num_mem_rsv(const void *fdt)
> {
> - int i = 0;
> + int i;
> + const struct fdt_reserve_entry *re;
>
> - while (fdt64_to_cpu(fdt_mem_rsv_(fdt, i)->size) != 0)
> - i++;
> - return i;
> + for (i = 0; (re = fdt_mem_rsv(fdt, i)) != NULL; i++) {
> + if (fdt64_ld(&re->size) == 0)
> + return i;
> + }
> + return -FDT_ERR_TRUNCATED;
> }
>
> static int nextprop_(const void *fdt, int offset)
> @@ -192,7 +225,7 @@ int fdt_subnode_offset_namelen(const void *fdt, int offset,
> {
> int depth;
>
> - FDT_CHECK_HEADER(fdt);
> + FDT_RO_PROBE(fdt);
>
> for (depth = 0;
> (offset >= 0) && (depth >= 0);
> @@ -218,7 +251,7 @@ int fdt_path_offset_namelen(const void *fdt, const char *path, int namelen)
> const char *p = path;
> int offset = 0;
>
> - FDT_CHECK_HEADER(fdt);
> + FDT_RO_PROBE(fdt);
>
> /* see if we have an alias */
> if (*path != '/') {
> @@ -268,13 +301,14 @@ const char *fdt_get_name(const void *fdt, int nodeoffset, int *len)
> const char *nameptr;
> int err;
>
> - if (((err = fdt_check_header(fdt)) != 0)
> - || ((err = fdt_check_node_offset_(fdt, nodeoffset)) < 0))
> - goto fail;
> + if (fdt_chk_extra() &&
> + (((err = fdt_ro_probe_(fdt)) < 0)
> + || ((err = fdt_check_node_offset_(fdt, nodeoffset)) < 0)))
> + goto fail;
>
> nameptr = nh->name;
>
> - if (fdt_version(fdt) < 0x10) {
> + if (fdt_chk_version() && fdt_version(fdt) < 0x10) {
> /*
> * For old FDT versions, match the naming conventions of V16:
> * give only the leaf name (after all /). The actual tree
> @@ -325,7 +359,7 @@ static const struct fdt_property *fdt_get_property_by_offset_(const void *fdt,
> int err;
> const struct fdt_property *prop;
>
> - if ((err = fdt_check_prop_offset_(fdt, offset)) < 0) {
> + if (fdt_chk_basic() && (err = fdt_check_prop_offset_(fdt, offset)) < 0) {
> if (lenp)
> *lenp = err;
> return NULL;
> @@ -334,7 +368,7 @@ static const struct fdt_property *fdt_get_property_by_offset_(const void *fdt,
> prop = fdt_offset_ptr_(fdt, offset);
>
> if (lenp)
> - *lenp = fdt32_to_cpu(prop->len);
> + *lenp = fdt32_ld(&prop->len);
>
> return prop;
> }
> @@ -346,7 +380,7 @@ const struct fdt_property *fdt_get_property_by_offset(const void *fdt,
> /* Prior to version 16, properties may need realignment
> * and this API does not work. fdt_getprop_*() will, however. */
>
> - if (fdt_version(fdt) < 0x10) {
> + if (fdt_chk_version() && fdt_version(fdt) < 0x10) {
> if (lenp)
> *lenp = -FDT_ERR_BADVERSION;
> return NULL;
> @@ -367,11 +401,12 @@ static const struct fdt_property *fdt_get_property_namelen_(const void *fdt,
> (offset = fdt_next_property_offset(fdt, offset))) {
> const struct fdt_property *prop;
>
> - if (!(prop = fdt_get_property_by_offset_(fdt, offset, lenp))) {
> + prop = fdt_get_property_by_offset_(fdt, offset, lenp);
> + if (fdt_chk_extra() && !prop) {
> offset = -FDT_ERR_INTERNAL;
> break;
> }
> - if (fdt_string_eq_(fdt, fdt32_to_cpu(prop->nameoff),
> + if (fdt_string_eq_(fdt, fdt32_ld(&prop->nameoff),
> name, namelen)) {
> if (poffset)
> *poffset = offset;
> @@ -392,7 +427,7 @@ const struct fdt_property *fdt_get_property_namelen(const void *fdt,
> {
> /* Prior to version 16, properties may need realignment
> * and this API does not work. fdt_getprop_*() will, however. */
> - if (fdt_version(fdt) < 0x10) {
> + if (fdt_chk_version() && fdt_version(fdt) < 0x10) {
> if (lenp)
> *lenp = -FDT_ERR_BADVERSION;
> return NULL;
> @@ -423,8 +458,8 @@ const void *fdt_getprop_namelen(const void *fdt, int nodeoffset,
> return NULL;
>
> /* Handle realignment */
> - if (fdt_version(fdt) < 0x10 && (poffset + sizeof(*prop)) % 8 &&
> - fdt32_to_cpu(prop->len) >= 8)
> + if (fdt_chk_version() && fdt_version(fdt) < 0x10 &&
> + (poffset + sizeof(*prop)) % 8 && fdt32_ld(&prop->len) >= 8)
> return prop->data + 4;
> return prop->data;
> }
> @@ -437,12 +472,27 @@ const void *fdt_getprop_by_offset(const void *fdt, int offset,
> prop = fdt_get_property_by_offset_(fdt, offset, lenp);
> if (!prop)
> return NULL;
> - if (namep)
> - *namep = fdt_string(fdt, fdt32_to_cpu(prop->nameoff));
> + if (namep) {
> + const char *name;
> + int namelen;
> +
> + if (fdt_chk_extra()) {
> + name = fdt_get_string(fdt, fdt32_ld(&prop->nameoff),
> + &namelen);
> + if (!name) {
> + if (lenp)
> + *lenp = namelen;
> + return NULL;
> + }
> + *namep = name;
> + } else {
> + *namep = fdt_string(fdt, fdt32_ld(&prop->nameoff));
> + }
> + }
>
> /* Handle realignment */
> - if (fdt_version(fdt) < 0x10 && (offset + sizeof(*prop)) % 8 &&
> - fdt32_to_cpu(prop->len) >= 8)
> + if (fdt_chk_version() && fdt_version(fdt) < 0x10 &&
> + (offset + sizeof(*prop)) % 8 && fdt32_ld(&prop->len) >= 8)
> return prop->data + 4;
> return prop->data;
> }
> @@ -467,7 +517,7 @@ uint32_t fdt_get_phandle(const void *fdt, int nodeoffset)
> return 0;
> }
>
> - return fdt32_to_cpu(*php);
> + return fdt32_ld(php);
> }
>
> const char *fdt_get_alias_namelen(const void *fdt,
> @@ -493,7 +543,7 @@ int fdt_get_path(const void *fdt, int nodeoffset, char *buf, int buflen)
> int offset, depth, namelen;
> const char *name;
>
> - FDT_CHECK_HEADER(fdt);
> + FDT_RO_PROBE(fdt);
>
> if (buflen < 2)
> return -FDT_ERR_NOSPACE;
> @@ -545,7 +595,7 @@ int fdt_supernode_atdepth_offset(const void *fdt, int nodeoffset,
> int offset, depth;
> int supernodeoffset = -FDT_ERR_INTERNAL;
>
> - FDT_CHECK_HEADER(fdt);
> + FDT_RO_PROBE(fdt);
>
> if (supernodedepth < 0)
> return -FDT_ERR_NOTFOUND;
> @@ -567,10 +617,12 @@ int fdt_supernode_atdepth_offset(const void *fdt, int nodeoffset,
> }
> }
>
> - if ((offset == -FDT_ERR_NOTFOUND) || (offset >= 0))
> - return -FDT_ERR_BADOFFSET;
> - else if (offset == -FDT_ERR_BADOFFSET)
> - return -FDT_ERR_BADSTRUCTURE;
> + if (fdt_chk_extra()) {
> + if ((offset == -FDT_ERR_NOTFOUND) || (offset >= 0))
> + return -FDT_ERR_BADOFFSET;
> + else if (offset == -FDT_ERR_BADOFFSET)
> + return -FDT_ERR_BADSTRUCTURE;
> + }
>
> return offset; /* error from fdt_next_node() */
> }
> @@ -582,7 +634,7 @@ int fdt_node_depth(const void *fdt, int nodeoffset)
>
> err = fdt_supernode_atdepth_offset(fdt, nodeoffset, 0, &nodedepth);
> if (err)
> - return (err < 0) ? err : -FDT_ERR_INTERNAL;
> + return (!fdt_chk_extra() || err < 0) ? err : -FDT_ERR_INTERNAL;
> return nodedepth;
> }
>
> @@ -604,7 +656,7 @@ int fdt_node_offset_by_prop_value(const void *fdt, int startoffset,
> const void *val;
> int len;
>
> - FDT_CHECK_HEADER(fdt);
> + FDT_RO_PROBE(fdt);
>
> /* FIXME: The algorithm here is pretty horrible: we scan each
> * property of a node in fdt_getprop(), then if that didn't
> @@ -630,7 +682,7 @@ int fdt_node_offset_by_phandle(const void *fdt, uint32_t phandle)
> if ((phandle == 0) || (phandle == -1))
> return -FDT_ERR_BADPHANDLE;
>
> - FDT_CHECK_HEADER(fdt);
> + FDT_RO_PROBE(fdt);
>
> /* FIXME: The algorithm here is pretty horrible: we
> * potentially scan each property of a node in
> @@ -783,7 +835,7 @@ int fdt_node_offset_by_compatible(const void *fdt, int startoffset,
> {
> int offset, err;
>
> - FDT_CHECK_HEADER(fdt);
> + FDT_RO_PROBE(fdt);
>
> /* FIXME: The algorithm here is pretty horrible: we scan each
> * property of a node in fdt_node_check_compatible(), then if
> @@ -802,3 +854,68 @@ int fdt_node_offset_by_compatible(const void *fdt, int startoffset,
>
> return offset; /* error from fdt_next_node() */
> }
> +
> +#if !defined(FDT_ASSUME_MASK) || FDT_ASSUME_MASK != 0xff
> +int fdt_check_full(const void *fdt, size_t bufsize)
> +{
> + int err;
> + int num_memrsv;
> + int offset, nextoffset = 0;
> + uint32_t tag;
> + unsigned depth = 0;
> + const void *prop;
> + const char *propname;
> +
> + if (bufsize < FDT_V1_SIZE)
> + return -FDT_ERR_TRUNCATED;
> + err = fdt_check_header(fdt);
> + if (err != 0)
> + return err;
> + if (bufsize < fdt_totalsize(fdt))
> + return -FDT_ERR_TRUNCATED;
> +
> + num_memrsv = fdt_num_mem_rsv(fdt);
> + if (num_memrsv < 0)
> + return num_memrsv;
> +
> + while (1) {
> + offset = nextoffset;
> + tag = fdt_next_tag(fdt, offset, &nextoffset);
> +
> + if (nextoffset < 0)
> + return nextoffset;
> +
> + switch (tag) {
> + case FDT_NOP:
> + break;
> +
> + case FDT_END:
> + if (depth != 0)
> + return -FDT_ERR_BADSTRUCTURE;
> + return 0;
> +
> + case FDT_BEGIN_NODE:
> + depth++;
> + if (depth > INT_MAX)
> + return -FDT_ERR_BADSTRUCTURE;
> + break;
> +
> + case FDT_END_NODE:
> + if (depth == 0)
> + return -FDT_ERR_BADSTRUCTURE;
> + depth--;
> + break;
> +
> + case FDT_PROP:
> + prop = fdt_getprop_by_offset(fdt, offset, &propname,
> + &err);
> + if (!prop)
> + return err;
> + break;
> +
> + default:
> + return -FDT_ERR_INTERNAL;
> + }
> + }
> +}
> +#endif
> diff --git a/scripts/dtc/libfdt/fdt_rw.c b/scripts/dtc/libfdt/fdt_rw.c
> index 9b829051e4..08e2981a44 100644
> --- a/scripts/dtc/libfdt/fdt_rw.c
> +++ b/scripts/dtc/libfdt/fdt_rw.c
> @@ -1,52 +1,7 @@
> +// SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-2-Clause)
> /*
> * libfdt - Flat Device Tree manipulation
> * Copyright (C) 2006 David Gibson, IBM Corporation.
> - *
> - * 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"
>
> @@ -58,6 +13,8 @@
> static int fdt_blocks_misordered_(const void *fdt,
> int mem_rsv_size, int struct_size)
> {
> + if (!fdt_chk_basic())
> + return false;
> return (fdt_off_mem_rsvmap(fdt) < FDT_ALIGN(sizeof(struct fdt_header), 8))
> || (fdt_off_dt_struct(fdt) <
> (fdt_off_mem_rsvmap(fdt) + mem_rsv_size))
> @@ -67,25 +24,27 @@ static int fdt_blocks_misordered_(const void *fdt,
> (fdt_off_dt_strings(fdt) + fdt_size_dt_strings(fdt)));
> }
>
> -static int fdt_rw_check_header_(void *fdt)
> +static int fdt_rw_probe_(void *fdt)
> {
> - FDT_CHECK_HEADER(fdt);
> + if (!fdt_chk_basic())
> + return 0;
> + FDT_RO_PROBE(fdt);
>
> - if (fdt_version(fdt) < 17)
> + if (fdt_chk_version() && fdt_version(fdt) < 17)
> return -FDT_ERR_BADVERSION;
> if (fdt_blocks_misordered_(fdt, sizeof(struct fdt_reserve_entry),
> fdt_size_dt_struct(fdt)))
> return -FDT_ERR_BADLAYOUT;
> - if (fdt_version(fdt) > 17)
> + if (fdt_chk_version() && fdt_version(fdt) > 17)
> fdt_set_version(fdt, 17);
>
> return 0;
> }
>
> -#define FDT_RW_CHECK_HEADER(fdt) \
> +#define FDT_RW_PROBE(fdt) \
> { \
> int err_; \
> - if ((err_ = fdt_rw_check_header_(fdt)) != 0) \
> + if (fdt_chk_extra() && (err_ = fdt_rw_probe_(fdt)) != 0) \
> return err_; \
> }
>
> @@ -136,6 +95,14 @@ static int fdt_splice_struct_(void *fdt, void *p,
> return 0;
> }
>
> +/* Must only be used to roll back in case of error */
> +static void fdt_del_last_string_(void *fdt, const char *s)
> +{
> + int newlen = strlen(s) + 1;
> +
> + fdt_set_size_dt_strings(fdt, fdt_size_dt_strings(fdt) - newlen);
> +}
> +
> static int fdt_splice_string_(void *fdt, int newlen)
> {
> void *p = (char *)fdt
> @@ -149,7 +116,16 @@ static int fdt_splice_string_(void *fdt, int newlen)
> return 0;
> }
>
> -static int fdt_find_add_string_(void *fdt, const char *s)
> +/**
> + * fdt_find_add_string_() - Find or allocate a string
> + *
> + * @fdt: pointer to the device tree to check/adjust
> + * @s: string to find/add
> + * @allocated: Set to 0 if the string was found, 1 if not found and so
> + * allocated. Ignored if !fdt_chk_basic()
> + * @return offset of string in the string table (whether found or added)
> + */
> +static int fdt_find_add_string_(void *fdt, const char *s, int *allocated)
> {
> char *strtab = (char *)fdt + fdt_off_dt_strings(fdt);
> const char *p;
> @@ -157,6 +133,9 @@ static int fdt_find_add_string_(void *fdt, const char *s)
> int len = strlen(s) + 1;
> int err;
>
> + if (fdt_chk_basic())
> + *allocated = 0;
> +
> p = fdt_find_string_(strtab, fdt_size_dt_strings(fdt), s);
> if (p)
> /* found it */
> @@ -167,6 +146,9 @@ static int fdt_find_add_string_(void *fdt, const char *s)
> if (err)
> return err;
>
> + if (fdt_chk_basic())
> + *allocated = 1;
> +
> memcpy(new, s, len);
> return (new - strtab);
> }
> @@ -176,7 +158,7 @@ int fdt_add_mem_rsv(void *fdt, uint64_t address, uint64_t size)
> struct fdt_reserve_entry *re;
> int err;
>
> - FDT_RW_CHECK_HEADER(fdt);
> + FDT_RW_PROBE(fdt);
>
> re = fdt_mem_rsv_w_(fdt, fdt_num_mem_rsv(fdt));
> err = fdt_splice_mem_rsv_(fdt, re, 0, 1);
> @@ -192,7 +174,7 @@ int fdt_del_mem_rsv(void *fdt, int n)
> {
> struct fdt_reserve_entry *re = fdt_mem_rsv_w_(fdt, n);
>
> - FDT_RW_CHECK_HEADER(fdt);
> + FDT_RW_PROBE(fdt);
>
> if (n >= fdt_num_mem_rsv(fdt))
> return -FDT_ERR_NOTFOUND;
> @@ -225,11 +207,12 @@ static int fdt_add_property_(void *fdt, int nodeoffset, const char *name,
> int nextoffset;
> int namestroff;
> int err;
> + int allocated;
>
> if ((nextoffset = fdt_check_node_offset_(fdt, nodeoffset)) < 0)
> return nextoffset;
>
> - namestroff = fdt_find_add_string_(fdt, name);
> + namestroff = fdt_find_add_string_(fdt, name, &allocated);
> if (namestroff < 0)
> return namestroff;
>
> @@ -237,8 +220,12 @@ static int fdt_add_property_(void *fdt, int nodeoffset, const char *name,
> proplen = sizeof(**prop) + FDT_TAGALIGN(len);
>
> err = fdt_splice_struct_(fdt, *prop, 0, proplen);
> - if (err)
> + if (err) {
> + /* Delete the string if we failed to add it */
> + if (fdt_chk_basic() && allocated)
> + fdt_del_last_string_(fdt, name);
> return err;
> + }
>
> (*prop)->tag = cpu_to_fdt32(FDT_PROP);
> (*prop)->nameoff = cpu_to_fdt32(namestroff);
> @@ -252,7 +239,7 @@ int fdt_set_name(void *fdt, int nodeoffset, const char *name)
> int oldlen, newlen;
> int err;
>
> - FDT_RW_CHECK_HEADER(fdt);
> + FDT_RW_PROBE(fdt);
>
> namep = (char *)(uintptr_t)fdt_get_name(fdt, nodeoffset, &oldlen);
> if (!namep)
> @@ -275,7 +262,7 @@ int fdt_setprop_placeholder(void *fdt, int nodeoffset, const char *name,
> struct fdt_property *prop;
> int err;
>
> - FDT_RW_CHECK_HEADER(fdt);
> + FDT_RW_PROBE(fdt);
>
> err = fdt_resize_property_(fdt, nodeoffset, name, len, &prop);
> if (err == -FDT_ERR_NOTFOUND)
> @@ -308,7 +295,7 @@ int fdt_appendprop(void *fdt, int nodeoffset, const char *name,
> struct fdt_property *prop;
> int err, oldlen, newlen;
>
> - FDT_RW_CHECK_HEADER(fdt);
> + FDT_RW_PROBE(fdt);
>
> prop = fdt_get_property_w(fdt, nodeoffset, name, &oldlen);
> if (prop) {
> @@ -334,7 +321,7 @@ int fdt_delprop(void *fdt, int nodeoffset, const char *name)
> struct fdt_property *prop;
> int len, proplen;
>
> - FDT_RW_CHECK_HEADER(fdt);
> + FDT_RW_PROBE(fdt);
>
> prop = fdt_get_property_w(fdt, nodeoffset, name, &len);
> if (!prop)
> @@ -354,7 +341,7 @@ int fdt_add_subnode_namelen(void *fdt, int parentoffset,
> uint32_t tag;
> fdt32_t *endtag;
>
> - FDT_RW_CHECK_HEADER(fdt);
> + FDT_RW_PROBE(fdt);
>
> offset = fdt_subnode_offset_namelen(fdt, parentoffset, name, namelen);
> if (offset >= 0)
> @@ -394,7 +381,7 @@ int fdt_del_node(void *fdt, int nodeoffset)
> {
> int endoffset;
>
> - FDT_RW_CHECK_HEADER(fdt);
> + FDT_RW_PROBE(fdt);
>
> endoffset = fdt_node_end_offset_(fdt, nodeoffset);
> if (endoffset < 0)
> @@ -435,12 +422,12 @@ int fdt_open_into(const void *fdt, void *buf, int bufsize)
> const char *fdtend = fdtstart + fdt_totalsize(fdt);
> char *tmp;
>
> - FDT_CHECK_HEADER(fdt);
> + FDT_RO_PROBE(fdt);
>
> mem_rsv_size = (fdt_num_mem_rsv(fdt)+1)
> * sizeof(struct fdt_reserve_entry);
>
> - if (fdt_version(fdt) >= 17) {
> + if (!fdt_chk_version() || fdt_version(fdt) >= 17) {
> struct_size = fdt_size_dt_struct(fdt);
> } else {
> struct_size = 0;
> @@ -494,7 +481,7 @@ int fdt_pack(void *fdt)
> {
> int mem_rsv_size;
>
> - FDT_RW_CHECK_HEADER(fdt);
> + FDT_RW_PROBE(fdt);
>
> mem_rsv_size = (fdt_num_mem_rsv(fdt)+1)
> * sizeof(struct fdt_reserve_entry);
> diff --git a/scripts/dtc/libfdt/fdt_strerror.c b/scripts/dtc/libfdt/fdt_strerror.c
> index 9677a1887e..768db66ead 100644
> --- a/scripts/dtc/libfdt/fdt_strerror.c
> +++ b/scripts/dtc/libfdt/fdt_strerror.c
> @@ -1,51 +1,7 @@
> +// SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-2-Clause)
> /*
> * libfdt - Flat Device Tree manipulation
> * Copyright (C) 2006 David Gibson, IBM Corporation.
> - *
> - * 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"
> @@ -82,6 +38,7 @@ static struct fdt_errtabent fdt_errtable[] = {
> FDT_ERRTABENT(FDT_ERR_BADVALUE),
> FDT_ERRTABENT(FDT_ERR_BADOVERLAY),
> FDT_ERRTABENT(FDT_ERR_NOPHANDLES),
> + FDT_ERRTABENT(FDT_ERR_BADFLAGS),
> };
> #define FDT_ERRTABSIZE (sizeof(fdt_errtable) / sizeof(fdt_errtable[0]))
>
> diff --git a/scripts/dtc/libfdt/fdt_sw.c b/scripts/dtc/libfdt/fdt_sw.c
> index d8ef748a72..a8c924675a 100644
> --- a/scripts/dtc/libfdt/fdt_sw.c
> +++ b/scripts/dtc/libfdt/fdt_sw.c
> @@ -1,52 +1,7 @@
> +// SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-2-Clause)
> /*
> * libfdt - Flat Device Tree manipulation
> * Copyright (C) 2006 David Gibson, IBM Corporation.
> - *
> - * 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"
>
> @@ -55,21 +10,90 @@
>
> #include "libfdt_internal.h"
>
> -static int fdt_sw_check_header_(void *fdt)
> +static int fdt_sw_probe_(void *fdt)
> +{
> + if (fdt_chk_basic()) {
> + if (fdt_magic(fdt) == FDT_MAGIC)
> + return -FDT_ERR_BADSTATE;
> + else if (fdt_magic(fdt) != FDT_SW_MAGIC)
> + return -FDT_ERR_BADMAGIC;
> + }
> +
> + return 0;
> +}
> +
> +#define FDT_SW_PROBE(fdt) \
> + { \
> + int err; \
> + if (fdt_chk_basic() && (err = fdt_sw_probe_(fdt)) != 0) \
> + return err; \
> + }
> +
> +/* 'memrsv' state: Initial state after fdt_create()
> + *
> + * Allowed functions:
> + * fdt_add_reservmap_entry()
> + * fdt_finish_reservemap() [moves to 'struct' state]
> + */
> +static int fdt_sw_probe_memrsv_(void *fdt)
> +{
> + int err = fdt_sw_probe_(fdt);
> + if (err)
> + return err;
> +
> + if (fdt_chk_extra() && fdt_off_dt_strings(fdt) != 0)
> + return -FDT_ERR_BADSTATE;
> + return 0;
> +}
> +
> +#define FDT_SW_PROBE_MEMRSV(fdt) \
> + { \
> + int err; \
> + if (fdt_chk_extra() && (err = fdt_sw_probe_memrsv_(fdt)) != 0) \
> + return err; \
> + }
> +
> +/* 'struct' state: Enter this state after fdt_finish_reservemap()
> + *
> + * Allowed functions:
> + * fdt_begin_node()
> + * fdt_end_node()
> + * fdt_property*()
> + * fdt_finish() [moves to 'complete' state]
> + */
> +static int fdt_sw_probe_struct_(void *fdt)
> {
> - if (fdt_magic(fdt) != FDT_SW_MAGIC)
> - return -FDT_ERR_BADMAGIC;
> - /* FIXME: should check more details about the header state */
> + int err;
> +
> + if (!fdt_chk_extra())
> + return 0;
> + err = fdt_sw_probe_(fdt);
> + if (err)
> + return err;
> +
> + if (fdt_off_dt_strings(fdt) != fdt_totalsize(fdt))
> + return -FDT_ERR_BADSTATE;
> return 0;
> }
>
> -#define FDT_SW_CHECK_HEADER(fdt) \
> +#define FDT_SW_PROBE_STRUCT(fdt) \
> { \
> int err; \
> - if ((err = fdt_sw_check_header_(fdt)) != 0) \
> + if (fdt_chk_extra() && (err = fdt_sw_probe_struct_(fdt)) != 0) \
> return err; \
> }
>
> +static inline uint32_t sw_flags(void *fdt)
> +{
> + /* assert: (fdt_magic(fdt) == FDT_SW_MAGIC) */
> + return fdt_last_comp_version(fdt);
> +}
> +
> +/* 'complete' state: Enter this state after fdt_finish()
> + *
> + * Allowed functions: none
> + */
> +
> static void *fdt_grab_space_(void *fdt, size_t len)
> {
> int offset = fdt_size_dt_struct(fdt);
> @@ -85,38 +109,58 @@ static void *fdt_grab_space_(void *fdt, size_t len)
> return fdt_offset_ptr_w_(fdt, offset);
> }
>
> -int fdt_create(void *buf, int bufsize)
> +int fdt_create_with_flags(void *buf, int bufsize, uint32_t flags)
> {
> + const size_t hdrsize = FDT_ALIGN(sizeof(struct fdt_header),
> + sizeof(struct fdt_reserve_entry));
> void *fdt = buf;
>
> - if (bufsize < sizeof(struct fdt_header))
> + if (bufsize < hdrsize)
> return -FDT_ERR_NOSPACE;
>
> + if (flags & ~FDT_CREATE_FLAGS_ALL)
> + return -FDT_ERR_BADFLAGS;
> +
> memset(buf, 0, bufsize);
>
> + /*
> + * magic and last_comp_version keep intermediate state during the fdt
> + * creation process, which is replaced with the proper FDT format by
> + * fdt_finish().
> + *
> + * flags should be accessed with sw_flags().
> + */
> fdt_set_magic(fdt, FDT_SW_MAGIC);
> fdt_set_version(fdt, FDT_LAST_SUPPORTED_VERSION);
> - fdt_set_last_comp_version(fdt, FDT_FIRST_SUPPORTED_VERSION);
> + fdt_set_last_comp_version(fdt, flags);
> +
> fdt_set_totalsize(fdt, bufsize);
>
> - fdt_set_off_mem_rsvmap(fdt, FDT_ALIGN(sizeof(struct fdt_header),
> - sizeof(struct fdt_reserve_entry)));
> + fdt_set_off_mem_rsvmap(fdt, hdrsize);
> fdt_set_off_dt_struct(fdt, fdt_off_mem_rsvmap(fdt));
> - fdt_set_off_dt_strings(fdt, bufsize);
> + fdt_set_off_dt_strings(fdt, 0);
>
> return 0;
> }
>
> +int fdt_create(void *buf, int bufsize)
> +{
> + return fdt_create_with_flags(buf, bufsize, 0);
> +}
> +
> int fdt_resize(void *fdt, void *buf, int bufsize)
> {
> size_t headsize, tailsize;
> char *oldtail, *newtail;
>
> - FDT_SW_CHECK_HEADER(fdt);
> + FDT_SW_PROBE(fdt);
>
> headsize = fdt_off_dt_struct(fdt) + fdt_size_dt_struct(fdt);
> tailsize = fdt_size_dt_strings(fdt);
>
> + if (fdt_chk_extra() && (headsize + tailsize) > fdt_totalsize(fdt))
> + return -FDT_ERR_INTERNAL;
> +
> if ((headsize + tailsize) > bufsize)
> return -FDT_ERR_NOSPACE;
>
> @@ -133,8 +177,9 @@ int fdt_resize(void *fdt, void *buf, int bufsize)
> memmove(buf, fdt, headsize);
> }
>
> - fdt_set_off_dt_strings(buf, bufsize);
> fdt_set_totalsize(buf, bufsize);
> + if (fdt_off_dt_strings(buf))
> + fdt_set_off_dt_strings(buf, bufsize);
>
> return 0;
> }
> @@ -144,10 +189,7 @@ int fdt_add_reservemap_entry(void *fdt, uint64_t addr, uint64_t size)
> struct fdt_reserve_entry *re;
> int offset;
>
> - FDT_SW_CHECK_HEADER(fdt);
> -
> - if (fdt_size_dt_struct(fdt))
> - return -FDT_ERR_BADSTATE;
> + FDT_SW_PROBE_MEMRSV(fdt);
>
> offset = fdt_off_dt_struct(fdt);
> if ((offset + sizeof(*re)) > fdt_totalsize(fdt))
> @@ -164,16 +206,23 @@ int fdt_add_reservemap_entry(void *fdt, uint64_t addr, uint64_t size)
>
> int fdt_finish_reservemap(void *fdt)
> {
> - return fdt_add_reservemap_entry(fdt, 0, 0);
> + int err = fdt_add_reservemap_entry(fdt, 0, 0);
> +
> + if (err)
> + return err;
> +
> + fdt_set_off_dt_strings(fdt, fdt_totalsize(fdt));
> + return 0;
> }
>
> int fdt_begin_node(void *fdt, const char *name)
> {
> struct fdt_node_header *nh;
> - int namelen = strlen(name) + 1;
> + int namelen;
>
> - FDT_SW_CHECK_HEADER(fdt);
> + FDT_SW_PROBE_STRUCT(fdt);
>
> + namelen = strlen(name) + 1;
> nh = fdt_grab_space_(fdt, sizeof(*nh) + FDT_TAGALIGN(namelen));
> if (! nh)
> return -FDT_ERR_NOSPACE;
> @@ -187,7 +236,7 @@ int fdt_end_node(void *fdt)
> {
> fdt32_t *en;
>
> - FDT_SW_CHECK_HEADER(fdt);
> + FDT_SW_PROBE_STRUCT(fdt);
>
> en = fdt_grab_space_(fdt, FDT_TAGSIZE);
> if (! en)
> @@ -197,19 +246,13 @@ int fdt_end_node(void *fdt)
> return 0;
> }
>
> -static int fdt_find_add_string_(void *fdt, const char *s)
> +static int fdt_add_string_(void *fdt, const char *s)
> {
> char *strtab = (char *)fdt + fdt_totalsize(fdt);
> - const char *p;
> int strtabsize = fdt_size_dt_strings(fdt);
> int len = strlen(s) + 1;
> int struct_top, offset;
>
> - p = fdt_find_string_(strtab - strtabsize, strtabsize, s);
> - if (p)
> - return p - strtab;
> -
> - /* Add it */
> offset = -strtabsize - len;
> struct_top = fdt_off_dt_struct(fdt) + fdt_size_dt_struct(fdt);
> if (fdt_totalsize(fdt) + offset < struct_top)
> @@ -220,20 +263,56 @@ static int fdt_find_add_string_(void *fdt, const char *s)
> return offset;
> }
>
> +/* Must only be used to roll back in case of error */
> +static void fdt_del_last_string_(void *fdt, const char *s)
> +{
> + int strtabsize = fdt_size_dt_strings(fdt);
> + int len = strlen(s) + 1;
> +
> + fdt_set_size_dt_strings(fdt, strtabsize - len);
> +}
> +
> +static int fdt_find_add_string_(void *fdt, const char *s, int *allocated)
> +{
> + char *strtab = (char *)fdt + fdt_totalsize(fdt);
> + int strtabsize = fdt_size_dt_strings(fdt);
> + const char *p;
> +
> + *allocated = 0;
> +
> + p = fdt_find_string_(strtab - strtabsize, strtabsize, s);
> + if (p)
> + return p - strtab;
> +
> + *allocated = 1;
> +
> + return fdt_add_string_(fdt, s);
> +}
> +
> int fdt_property_placeholder(void *fdt, const char *name, int len, void **valp)
> {
> struct fdt_property *prop;
> int nameoff;
> + int allocated;
>
> - FDT_SW_CHECK_HEADER(fdt);
> + FDT_SW_PROBE_STRUCT(fdt);
>
> - nameoff = fdt_find_add_string_(fdt, name);
> + /* String de-duplication can be slow, _NO_NAME_DEDUP skips it */
> + if (sw_flags(fdt) & FDT_CREATE_FLAG_NO_NAME_DEDUP) {
> + allocated = 1;
> + nameoff = fdt_add_string_(fdt, name);
> + } else {
> + nameoff = fdt_find_add_string_(fdt, name, &allocated);
> + }
> if (nameoff == 0)
> return -FDT_ERR_NOSPACE;
>
> prop = fdt_grab_space_(fdt, sizeof(*prop) + FDT_TAGALIGN(len));
> - if (! prop)
> + if (! prop) {
> + if (allocated)
> + fdt_del_last_string_(fdt, name);
> return -FDT_ERR_NOSPACE;
> + }
>
> prop->tag = cpu_to_fdt32(FDT_PROP);
> prop->nameoff = cpu_to_fdt32(nameoff);
> @@ -262,7 +341,7 @@ int fdt_finish(void *fdt)
> uint32_t tag;
> int offset, nextoffset;
>
> - FDT_SW_CHECK_HEADER(fdt);
> + FDT_SW_PROBE_STRUCT(fdt);
>
> /* Add terminator */
> end = fdt_grab_space_(fdt, sizeof(*end));
> @@ -295,6 +374,10 @@ int fdt_finish(void *fdt)
>
> /* Finally, adjust the header */
> fdt_set_totalsize(fdt, newstroffset + fdt_size_dt_strings(fdt));
> +
> + /* And fix up fields that were keeping intermediate state. */
> + fdt_set_last_comp_version(fdt, FDT_FIRST_SUPPORTED_VERSION);
> fdt_set_magic(fdt, FDT_MAGIC);
> +
> return 0;
> }
> diff --git a/scripts/dtc/libfdt/fdt_wip.c b/scripts/dtc/libfdt/fdt_wip.c
> index 534c1cbbb2..f64139e0b3 100644
> --- a/scripts/dtc/libfdt/fdt_wip.c
> +++ b/scripts/dtc/libfdt/fdt_wip.c
> @@ -1,52 +1,7 @@
> +// SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-2-Clause)
> /*
> * libfdt - Flat Device Tree manipulation
> * Copyright (C) 2006 David Gibson, IBM Corporation.
> - *
> - * 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"
>
> diff --git a/scripts/dtc/libfdt/libfdt.h b/scripts/dtc/libfdt/libfdt.h
> index c400f2f5d5..36fadcdea5 100644
> --- a/scripts/dtc/libfdt/libfdt.h
> +++ b/scripts/dtc/libfdt/libfdt.h
> @@ -1,54 +1,9 @@
> +/* SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-2-Clause) */
> #ifndef LIBFDT_H
> #define LIBFDT_H
> /*
> * libfdt - Flat Device Tree manipulation
> * Copyright (C) 2006 David Gibson, IBM Corporation.
> - *
> - * 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"
> @@ -90,8 +45,9 @@
>
> /* Error codes: codes for bad device tree blobs */
> #define FDT_ERR_TRUNCATED 8
> - /* FDT_ERR_TRUNCATED: Structure block of the given device tree
> - * ends without an FDT_END tag. */
> + /* FDT_ERR_TRUNCATED: FDT or a sub-block is improperly
> + * terminated (overflows, goes outside allowed bounds, or
> + * isn't properly terminated). */
> #define FDT_ERR_BADMAGIC 9
> /* FDT_ERR_BADMAGIC: Given "device tree" appears not to be a
> * device tree at all - it is missing the flattened device
> @@ -137,7 +93,11 @@
> /* FDT_ERR_NOPHANDLES: The device tree doesn't have any
> * phandle available anymore without causing an overflow */
>
> -#define FDT_ERR_MAX 17
> +#define FDT_ERR_BADFLAGS 18
> + /* FDT_ERR_BADFLAGS: The function was passed a flags field that
> + * contains invalid flags or an invalid combination of flags. */
> +
> +#define FDT_ERR_MAX 18
>
> /* constants */
> #define FDT_MAX_PHANDLE 0xfffffffe
> @@ -157,6 +117,61 @@ static inline void *fdt_offset_ptr_w(void *fdt, int offset, int checklen)
>
> uint32_t fdt_next_tag(const void *fdt, int offset, int *nextoffset);
>
> +/*
> + * Alignment helpers:
> + * These helpers access words from a device tree blob. They're
> + * built to work even with unaligned pointers on platforms (ike
> + * ARM) that don't like unaligned loads and stores
> + */
> +
> +static inline uint32_t fdt32_ld(const fdt32_t *p)
> +{
> + const uint8_t *bp = (const uint8_t *)p;
> +
> + return ((uint32_t)bp[0] << 24)
> + | ((uint32_t)bp[1] << 16)
> + | ((uint32_t)bp[2] << 8)
> + | bp[3];
> +}
> +
> +static inline void fdt32_st(void *property, uint32_t value)
> +{
> + uint8_t *bp = (uint8_t *)property;
> +
> + bp[0] = value >> 24;
> + bp[1] = (value >> 16) & 0xff;
> + bp[2] = (value >> 8) & 0xff;
> + bp[3] = value & 0xff;
> +}
> +
> +static inline uint64_t fdt64_ld(const fdt64_t *p)
> +{
> + const uint8_t *bp = (const uint8_t *)p;
> +
> + return ((uint64_t)bp[0] << 56)
> + | ((uint64_t)bp[1] << 48)
> + | ((uint64_t)bp[2] << 40)
> + | ((uint64_t)bp[3] << 32)
> + | ((uint64_t)bp[4] << 24)
> + | ((uint64_t)bp[5] << 16)
> + | ((uint64_t)bp[6] << 8)
> + | bp[7];
> +}
> +
> +static inline void fdt64_st(void *property, uint64_t value)
> +{
> + uint8_t *bp = (uint8_t *)property;
> +
> + bp[0] = value >> 56;
> + bp[1] = (value >> 48) & 0xff;
> + bp[2] = (value >> 40) & 0xff;
> + bp[3] = (value >> 32) & 0xff;
> + bp[4] = (value >> 24) & 0xff;
> + bp[5] = (value >> 16) & 0xff;
> + bp[6] = (value >> 8) & 0xff;
> + bp[7] = value & 0xff;
> +}
> +
> /**********************************************************************/
> /* Traversal functions */
> /**********************************************************************/
> @@ -199,7 +214,7 @@ int fdt_next_subnode(const void *fdt, int offset);
> * ...
> * }
> *
> - * if ((node < 0) && (node != -FDT_ERR_NOT_FOUND)) {
> + * if ((node < 0) && (node != -FDT_ERR_NOTFOUND)) {
> * Error handling
> * }
> *
> @@ -217,7 +232,7 @@ int fdt_next_subnode(const void *fdt, int offset);
> /* General functions */
> /**********************************************************************/
> #define fdt_get_header(fdt, field) \
> - (fdt32_to_cpu(((const struct fdt_header *)(fdt))->field))
> + (fdt32_ld(&((const struct fdt_header *)(fdt))->field))
> #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))
> @@ -248,18 +263,32 @@ fdt_set_hdr_(size_dt_struct);
> #undef fdt_set_hdr_
>
> /**
> - * fdt_check_header - sanity check a device tree or possible device tree
> + * fdt_header_size - return the size of the tree's header
> + * @fdt: pointer to a flattened device tree
> + */
> +size_t fdt_header_size(const void *fdt);
> +
> +/**
> + * fdt_header_size_ - internal function which takes a version number
> + */
> +size_t fdt_header_size_(uint32_t version);
> +
> +/**
> + * fdt_check_header - sanity check a device tree header
> +
> * @fdt: pointer to data which might be a flattened device tree
> *
> * fdt_check_header() checks that the given buffer contains what
> - * appears to be a flattened device tree with sane information in its
> - * header.
> + * appears to be a flattened device tree, and that the header contains
> + * valid information (to the extent that can be determined from the
> + * header alone).
> *
> * returns:
> * 0, if the buffer appears to contain a valid device tree
> * -FDT_ERR_BADMAGIC,
> * -FDT_ERR_BADVERSION,
> - * -FDT_ERR_BADSTATE, standard meanings, as above
> + * -FDT_ERR_BADSTATE,
> + * -FDT_ERR_TRUNCATED, standard meanings, as above
> */
> int fdt_check_header(const void *fdt);
>
> @@ -288,6 +317,24 @@ int fdt_move(const void *fdt, void *buf, int bufsize);
> /* Read-only functions */
> /**********************************************************************/
>
> +int fdt_check_full(const void *fdt, size_t bufsize);
> +
> +/**
> + * fdt_get_string - retrieve a string from the strings block of a device tree
> + * @fdt: pointer to the device tree blob
> + * @stroffset: offset of the string within the strings block (native endian)
> + * @lenp: optional pointer to return the string's length
> + *
> + * fdt_get_string() retrieves a pointer to a single string from the
> + * strings block of the device tree blob at fdt, and optionally also
> + * returns the string's length in *lenp.
> + *
> + * returns:
> + * a pointer to the string, on success
> + * NULL, if stroffset is out of bounds, or doesn't point to a valid string
> + */
> +const char *fdt_get_string(const void *fdt, int stroffset, int *lenp);
> +
> /**
> * fdt_string - retrieve a string from the strings block of a device tree
> * @fdt: pointer to the device tree blob
> @@ -298,10 +345,24 @@ int fdt_move(const void *fdt, void *buf, int bufsize);
> *
> * returns:
> * a pointer to the string, on success
> - * NULL, if stroffset is out of bounds
> + * NULL, if stroffset is out of bounds, or doesn't point to a valid string
> */
> const char *fdt_string(const void *fdt, int stroffset);
>
> +/**
> + * fdt_find_max_phandle - find and return the highest phandle in a tree
> + * @fdt: pointer to the device tree blob
> + * @phandle: return location for the highest phandle value found in the tree
> + *
> + * fdt_find_max_phandle() finds the highest phandle value in the given device
> + * tree. The value returned in @phandle is only valid if the function returns
> + * success.
> + *
> + * returns:
> + * 0 on success or a negative error code on failure
> + */
> +int fdt_find_max_phandle(const void *fdt, uint32_t *phandle);
> +
> /**
> * fdt_get_max_phandle - retrieves the highest phandle in a tree
> * @fdt: pointer to the device tree blob
> @@ -310,12 +371,24 @@ const char *fdt_string(const void *fdt, int stroffset);
> * device tree. This will ignore badly formatted phandles, or phandles
> * with a value of 0 or -1.
> *
> + * This function is deprecated in favour of fdt_find_max_phandle().
> + *
> * 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);
> +static inline uint32_t fdt_get_max_phandle(const void *fdt)
> +{
> + uint32_t phandle;
> + int err;
> +
> + err = fdt_find_max_phandle(fdt, &phandle);
> + if (err < 0)
> + return (uint32_t)-1;
> +
> + return phandle;
> +}
>
> /**
> * fdt_generate_phandle - return a new, unused phandle for a device tree blob
> @@ -522,7 +595,7 @@ int fdt_next_property_offset(const void *fdt, int offset);
> * ...
> * }
> *
> - * if ((property < 0) && (property != -FDT_ERR_NOT_FOUND)) {
> + * if ((property < 0) && (property != -FDT_ERR_NOTFOUND)) {
> * Error handling
> * }
> *
> @@ -625,7 +698,7 @@ static inline struct fdt_property *fdt_get_property_w(void *fdt, int nodeoffset,
> /**
> * fdt_getprop_by_offset - retrieve the value of a property at a given offset
> * @fdt: pointer to the device tree blob
> - * @ffset: offset of the property to read
> + * @offset: offset of the property to read
> * @namep: pointer to a string variable (will be overwritten) or NULL
> * @lenp: pointer to an integer variable (will be overwritten) or NULL
> *
> @@ -734,7 +807,7 @@ uint32_t fdt_get_phandle(const void *fdt, int nodeoffset);
> /**
> * fdt_get_alias_namelen - get alias based on substring
> * @fdt: pointer to the device tree blob
> - * @name: name of the alias to look up
> + * @name: name of the alias th look up
> * @namelen: number of characters of name to consider
> *
> * Identical to fdt_get_alias(), but only examine the first namelen
> @@ -1316,7 +1389,45 @@ int fdt_nop_node(void *fdt, int nodeoffset);
> /* Sequential write functions */
> /**********************************************************************/
>
> +/* fdt_create_with_flags flags */
> +#define FDT_CREATE_FLAG_NO_NAME_DEDUP 0x1
> + /* FDT_CREATE_FLAG_NO_NAME_DEDUP: Do not try to de-duplicate property
> + * names in the fdt. This can result in faster creation times, but
> + * a larger fdt. */
> +
> +#define FDT_CREATE_FLAGS_ALL (FDT_CREATE_FLAG_NO_NAME_DEDUP)
> +
> +/**
> + * fdt_create_with_flags - begin creation of a new fdt
> + * @fdt: pointer to memory allocated where fdt will be created
> + * @bufsize: size of the memory space at fdt
> + * @flags: a valid combination of FDT_CREATE_FLAG_ flags, or 0.
> + *
> + * fdt_create_with_flags() begins the process of creating a new fdt with
> + * the sequential write interface.
> + *
> + * fdt creation process must end with fdt_finished() to produce a valid fdt.
> + *
> + * returns:
> + * 0, on success
> + * -FDT_ERR_NOSPACE, bufsize is insufficient for a minimal fdt
> + * -FDT_ERR_BADFLAGS, flags is not valid
> + */
> +int fdt_create_with_flags(void *buf, int bufsize, uint32_t flags);
> +
> +/**
> + * fdt_create - begin creation of a new fdt
> + * @fdt: pointer to memory allocated where fdt will be created
> + * @bufsize: size of the memory space at fdt
> + *
> + * fdt_create() is equivalent to fdt_create_with_flags() with flags=0.
> + *
> + * returns:
> + * 0, on success
> + * -FDT_ERR_NOSPACE, bufsize is insufficient for a minimal fdt
> + */
> 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);
> @@ -1787,6 +1898,43 @@ static inline int fdt_appendprop_cell(void *fdt, int nodeoffset,
> #define fdt_appendprop_string(fdt, nodeoffset, name, str) \
> fdt_appendprop((fdt), (nodeoffset), (name), (str), strlen(str)+1)
>
> +/**
> + * fdt_appendprop_addrrange - append a address range property
> + * @fdt: pointer to the device tree blob
> + * @parent: offset of the parent node
> + * @nodeoffset: offset of the node to add a property at
> + * @name: name of property
> + * @addr: start address of a given range
> + * @size: size of a given range
> + *
> + * fdt_appendprop_addrrange() appends an address range value (start
> + * address and size) to the value of the named property in the given
> + * node, or creates a new property with that value if it does not
> + * already exist.
> + * If "name" is not specified, a default "reg" is used.
> + * Cell sizes are determined by parent's #address-cells and #size-cells.
> + *
> + * This function may insert data into the blob, and will therefore
> + * change the offsets of some existing nodes.
> + *
> + * returns:
> + * 0, on success
> + * -FDT_ERR_BADLAYOUT,
> + * -FDT_ERR_BADMAGIC,
> + * -FDT_ERR_BADNCELLS, if the node has a badly formatted or invalid
> + * #address-cells property
> + * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag
> + * -FDT_ERR_BADSTATE,
> + * -FDT_ERR_BADSTRUCTURE,
> + * -FDT_ERR_BADVERSION,
> + * -FDT_ERR_BADVALUE, addr or size doesn't fit to respective cells size
> + * -FDT_ERR_NOSPACE, there is insufficient free space in the blob to
> + * contain a new property
> + * -FDT_ERR_TRUNCATED, standard meanings
> + */
> +int fdt_appendprop_addrrange(void *fdt, int parent, int nodeoffset,
> + const char *name, uint64_t addr, uint64_t size);
> +
> /**
> * fdt_delprop - delete a property
> * @fdt: pointer to the device tree blob
> diff --git a/scripts/dtc/libfdt/libfdt_env.h b/scripts/dtc/libfdt/libfdt_env.h
> index 3ff9e28630..73b6d40450 100644
> --- a/scripts/dtc/libfdt/libfdt_env.h
> +++ b/scripts/dtc/libfdt/libfdt_env.h
> @@ -1,55 +1,10 @@
> +/* SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-2-Clause) */
> #ifndef LIBFDT_ENV_H
> #define LIBFDT_ENV_H
> /*
> * libfdt - Flat Device Tree manipulation
> * Copyright (C) 2006 David Gibson, IBM Corporation.
> * Copyright 2012 Kim Phillips, Freescale Semiconductor.
> - *
> - * 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 <stdbool.h>
> @@ -57,6 +12,7 @@
> #include <stdint.h>
> #include <stdlib.h>
> #include <string.h>
> +#include <limits.h>
>
> #ifdef __CHECKER__
> #define FDT_FORCE __attribute__((force))
> diff --git a/scripts/dtc/libfdt/libfdt_internal.h b/scripts/dtc/libfdt/libfdt_internal.h
> index 7681e19229..5436e2ceea 100644
> --- a/scripts/dtc/libfdt/libfdt_internal.h
> +++ b/scripts/dtc/libfdt/libfdt_internal.h
> @@ -1,65 +1,24 @@
> +/* SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-2-Clause) */
> #ifndef LIBFDT_INTERNAL_H
> #define LIBFDT_INTERNAL_H
> /*
> * libfdt - Flat Device Tree manipulation
> * Copyright (C) 2006 David Gibson, IBM Corporation.
> - *
> - * 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 <fdt.h>
>
> #define FDT_ALIGN(x, a) (((x) + (a) - 1) & ~((a) - 1))
> #define FDT_TAGALIGN(x) (FDT_ALIGN((x), FDT_TAGSIZE))
>
> -#define FDT_CHECK_HEADER(fdt) \
> - { \
> - int err_; \
> - if ((err_ = fdt_check_header(fdt)) != 0) \
> - return err_; \
> +int fdt_ro_probe_(const void *fdt);
> +#define FDT_RO_PROBE(fdt) \
> + { \
> + int totalsize_; \
> + if (fdt_chk_basic()) { \
> + totalsize_ = fdt_ro_probe_(fdt); \
> + if (totalsize_ < 0) \
> + return totalsize_; \
> + } \
> }
>
> int fdt_check_node_offset_(const void *fdt, int offset);
> @@ -92,4 +51,87 @@ static inline struct fdt_reserve_entry *fdt_mem_rsv_w_(void *fdt, int n)
>
> #define FDT_SW_MAGIC (~FDT_MAGIC)
>
> +/**********************************************************************/
> +/* Checking controls */
> +/**********************************************************************/
> +
> +#ifndef FDT_ASSUME_MASK
> +#define FDT_ASSUME_MASK 0
> +#endif
> +
> +/*
> + * Defines assumptions which can be enabled. Each of these can be enabled
> + * individually. For maximum saftey, don't enable any assumptions!
> + *
> + * For minimal code size and no safety, use FDT_ASSUME_PERFECT at your own risk.
> + * You should have another method of validating the device tree, such as a
> + * signature or hash check before using libfdt.
> + *
> + * For situations where security is not a concern it may be safe to enable
> + * FDT_ASSUME_FRIENDLY.
> + */
> +enum {
> + /*
> + * This does essentially no checks. Only the latest device-tree
> + * version is correctly handled. Incosistencies or errors in the device
> + * tree may cause undefined behaviour or crashes.
> + *
> + * If an error occurs when modifying the tree it may leave the tree in
> + * an intermediate (but valid) state. As an example, adding a property
> + * where there is insufficient space may result in the property name
> + * being added to the string table even though the property itself is
> + * not added to the struct section.
> + *
> + * Only use this if you have a fully validated device tree with
> + * the latest supported version and wish to minimise code size.
> + */
> + FDT_ASSUME_PERFECT = 0xff,
> +
> + /*
> + * This assumes that the device tree is sane. i.e. header metadata
> + * and basic hierarchy are correct.
> + *
> + * These checks will be sufficient if you have a valid device tree with
> + * no internal inconsistencies. With this assumption, libfdt will
> + * generally not return -FDT_ERR_INTERNAL, -FDT_ERR_BADLAYOUT, etc.
> + */
> + FDT_ASSUME_SANE = 1 << 0,
> +
> + /*
> + * This disables checks for device-tree version and removes all code
> + * which handles older versions.
> + *
> + * Only enable this if you know you have a device tree with the latest
> + * version.
> + */
> + FDT_ASSUME_LATEST = 1 << 1,
> +
> + /*
> + * This disables any extensive checking of parameters and the device
> + * tree, making various assumptions about correctness. Normal device
> + * trees produced by libfdt and the compiler should be handled safely.
> + * Malicious device trees and complete garbage may cause libfdt to
> + * behave badly or crash.
> + */
> + FDT_ASSUME_FRIENDLY = 1 << 2,
> +};
> +
> +/** fdt_chk_basic() - see if basic checking of params and DT data is enabled */
> +static inline bool fdt_chk_basic(void)
> +{
> + return !(FDT_ASSUME_MASK & FDT_ASSUME_SANE);
> +}
> +
> +/** fdt_chk_version() - see if we need to handle old versions of the DT */
> +static inline bool fdt_chk_version(void)
> +{
> + return !(FDT_ASSUME_MASK & FDT_ASSUME_LATEST);
> +}
> +
> +/** fdt_chk_extra() - see if extra checking is enabled */
> +static inline bool fdt_chk_extra(void)
> +{
> + return !(FDT_ASSUME_MASK & FDT_ASSUME_FRIENDLY);
> +}
> +
> #endif /* LIBFDT_INTERNAL_H */
> diff --git a/tools/libfdt/fdt_rw.c b/tools/libfdt/fdt_rw.c
> index 68fc7c8c88..7189f01429 100644
> --- a/tools/libfdt/fdt_rw.c
> +++ b/tools/libfdt/fdt_rw.c
> @@ -11,6 +11,7 @@ int fdt_remove_unused_strings(const void *old, void *new)
> const char *str;
> int ret;
> int tag = FDT_PROP;
> + int allocated;
>
> /* Make a copy and remove the strings */
> memcpy(new, old, size);
> @@ -25,7 +26,7 @@ int fdt_remove_unused_strings(const void *old, void *new)
> new_prop = (struct fdt_property *)(unsigned long)
> fdt_get_property_by_offset(new, offset, NULL);
> str = fdt_string(old, fdt32_to_cpu(old_prop->nameoff));
> - ret = fdt_find_add_string_(new, str);
> + ret = fdt_find_add_string_(new, str, &allocated);
> if (ret < 0)
> return ret;
> new_prop->nameoff = cpu_to_fdt32(ret);
> --
> 2.24.0.rc0.303.g954a862665-goog
>
> _______________________________________________
> U-Boot mailing list
> U-Boot at lists.denx.de
> https://lists.denx.de/listinfo/u-boot
More information about the U-Boot
mailing list