On Tue, Jan 7, 2020 at 5:43 AM Adam Ford <aford...@gmail.com> wrote: > > On Sun, Oct 27, 2019 at 10:55 AM Simon Glass <s...@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 <s...@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.
Go ahead and disregard that message. I pulled in the latest master after 2020.01 and the issue appears to have resolved itself. I didn't bisect, but I'm happy it works again. :-) adam > > 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 <da...@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@lists.denx.de > > https://lists.denx.de/listinfo/u-boot