[PATCH] libfdt: Upgrade to v1.6.0 release
Anup Patel
Anup.Patel at wdc.com
Sat Dec 12 23:48:08 EST 2020
> -----Original Message-----
> From: opensbi <opensbi-bounces at lists.infradead.org> On Behalf Of Dimitri
> John Ledkov
> Sent: 10 December 2020 16:34
> To: opensbi at lists.infradead.org
> Cc: Dimitri John Ledkov <xnox at ubuntu.com>
> Subject: [PATCH] libfdt: Upgrade to v1.6.0 release
>
> Sync with libfdt v1.6.0 release source codes.
>
> Signed-off-by: Dimitri John Ledkov <xnox at ubuntu.com>
> ---
> Also submitted on github at https://github.com/riscv/opensbi/pull/186/files
>
> lib/utils/libfdt/Makefile.libfdt | 2 +-
> lib/utils/libfdt/fdt.c | 99 ++++++++++++--------
> lib/utils/libfdt/fdt_check.c | 74 +++++++++++++++
> lib/utils/libfdt/fdt_overlay.c | 2 +-
> lib/utils/libfdt/fdt_ro.c | 143 ++++++++++-------------------
> lib/utils/libfdt/fdt_rw.c | 29 ++++--
> lib/utils/libfdt/fdt_sw.c | 19 ++--
> lib/utils/libfdt/libfdt.h | 13 +--
> lib/utils/libfdt/libfdt_internal.h | 126 ++++++++++++++++++++++++-
> lib/utils/libfdt/objects.mk | 2 +-
> lib/utils/libfdt/version.lds | 1 +
> 11 files changed, 356 insertions(+), 154 deletions(-) create mode 100644
> lib/utils/libfdt/fdt_check.c
>
> diff --git a/lib/utils/libfdt/Makefile.libfdt b/lib/utils/libfdt/Makefile.libfdt
> index e546397..b6d8fc0 100644
> --- a/lib/utils/libfdt/Makefile.libfdt
> +++ b/lib/utils/libfdt/Makefile.libfdt
> @@ -8,7 +8,7 @@ LIBFDT_soname = libfdt.$(SHAREDLIB_EXT).1
> LIBFDT_INCLUDES = fdt.h libfdt.h libfdt_env.h LIBFDT_VERSION = version.lds
> LIBFDT_SRCS = fdt.c fdt_ro.c fdt_wip.c fdt_sw.c fdt_rw.c fdt_strerror.c
> fdt_empty_tree.c \
> - fdt_addresses.c fdt_overlay.c
> + fdt_addresses.c fdt_overlay.c fdt_check.c
> LIBFDT_OBJS = $(LIBFDT_SRCS:%.c=%.o)
> LIBFDT_LIB = libfdt-$(DTC_VERSION).$(SHAREDLIB_EXT)
>
> diff --git a/lib/utils/libfdt/fdt.c b/lib/utils/libfdt/fdt.c index d6ce7c0..c28fcc1
> 100644
> --- a/lib/utils/libfdt/fdt.c
> +++ b/lib/utils/libfdt/fdt.c
> @@ -19,15 +19,21 @@ int32_t fdt_ro_probe_(const void *fdt) {
> uint32_t totalsize = fdt_totalsize(fdt);
>
> + if (can_assume(VALID_DTB))
> + return totalsize;
> +
> 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 (!can_assume(LATEST)) {
> + 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)
> + if (!can_assume(VALID_INPUT) && fdt_size_dt_struct(fdt)
> == 0)
> return -FDT_ERR_BADSTATE;
> } else {
> return -FDT_ERR_BADMAGIC;
> @@ -70,44 +76,59 @@ size_t fdt_header_size_(uint32_t version)
> return FDT_V17_SIZE;
> }
>
> +size_t fdt_header_size(const void *fdt) {
> + return can_assume(LATEST) ? FDT_V17_SIZE :
> + fdt_header_size_(fdt_version(fdt));
> +}
> +
> int fdt_check_header(const void *fdt)
> {
> size_t hdrsize;
>
> if (fdt_magic(fdt) != FDT_MAGIC)
> return -FDT_ERR_BADMAGIC;
> + if (!can_assume(LATEST)) {
> + 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_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;
> -
> - if ((fdt_totalsize(fdt) < hdrsize)
> - || (fdt_totalsize(fdt) > INT_MAX))
> - return -FDT_ERR_TRUNCATED;
> + if (!can_assume(VALID_DTB)) {
>
> - /* Bounds check memrsv block */
> - if (!check_off_(hdrsize, fdt_totalsize(fdt),
> fdt_off_mem_rsvmap(fdt)))
> - return -FDT_ERR_TRUNCATED;
> + if ((fdt_totalsize(fdt) < hdrsize)
> + || (fdt_totalsize(fdt) > INT_MAX))
> + return -FDT_ERR_TRUNCATED;
>
> - /* Bounds check structure block */
> - if (fdt_version(fdt) < 17) {
> + /* Bounds check memrsv block */
> if (!check_off_(hdrsize, fdt_totalsize(fdt),
> - fdt_off_dt_struct(fdt)))
> + fdt_off_mem_rsvmap(fdt)))
> return -FDT_ERR_TRUNCATED;
> - } else {
> + }
> +
> + if (!can_assume(VALID_DTB)) {
> + /* Bounds check structure block */
> + if (!can_assume(LATEST) && 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_struct(fdt),
> - fdt_size_dt_struct(fdt)))
> + fdt_off_dt_strings(fdt),
> + fdt_size_dt_strings(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;
> }
>
> @@ -115,12 +136,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 (!can_assume(VALID_INPUT))
> + if ((absoffset < offset)
> + || ((absoffset + len) < absoffset)
> + || (absoffset + len) > fdt_totalsize(fdt))
> + return NULL;
>
> - if (fdt_version(fdt) >= 0x11)
> + if (can_assume(LATEST) || fdt_version(fdt) >= 0x11)
> if (((offset + len) < offset)
> || ((offset + len) > fdt_size_dt_struct(fdt)))
> return NULL;
> @@ -137,7 +159,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 (!can_assume(VALID_DTB) && !tagp)
> return FDT_END; /* premature end */
> tag = fdt32_to_cpu(*tagp);
> offset += FDT_TAGSIZE;
> @@ -149,18 +171,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 (!can_assume(VALID_DTB) && !p)
> return FDT_END; /* premature end */
> break;
>
> case FDT_PROP:
> lenp = fdt_offset_ptr(fdt, offset, sizeof(*lenp));
> - if (!lenp)
> + if (!can_assume(VALID_DTB) && !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 (!can_assume(LATEST) &&
> + fdt_version(fdt) < 0x10 && fdt32_to_cpu(*lenp) >= 8 &&
> ((offset - fdt32_to_cpu(*lenp)) % 8) != 0)
> offset += 4;
> break;
> @@ -183,6 +206,8 @@ uint32_t fdt_next_tag(const void *fdt, int startoffset,
> int *nextoffset)
>
> int fdt_check_node_offset_(const void *fdt, int offset) {
> + if (can_assume(VALID_INPUT))
> + return offset;
> if ((offset < 0) || (offset % FDT_TAGSIZE)
> || (fdt_next_tag(fdt, offset, &offset) != FDT_BEGIN_NODE))
> return -FDT_ERR_BADOFFSET;
> diff --git a/lib/utils/libfdt/fdt_check.c b/lib/utils/libfdt/fdt_check.c new file
> mode 100644 index 0000000..7f6a96c
> --- /dev/null
> +++ b/lib/utils/libfdt/fdt_check.c
> @@ -0,0 +1,74 @@
> +// SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-2-Clause)
> +/*
> + * libfdt - Flat Device Tree manipulation
> + * Copyright (C) 2006 David Gibson, IBM Corporation.
> + */
> +#include "libfdt_env.h"
> +
> +#include <fdt.h>
> +#include <libfdt.h>
> +
> +#include "libfdt_internal.h"
> +
> +int fdt_check_full(const void *fdt, size_t bufsize) {
> + int err;
> + int num_memrsv;
> + int offset, nextoffset = 0;
> + uint32_t tag;
> + unsigned int 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;
> + }
> + }
> +}
> diff --git a/lib/utils/libfdt/fdt_overlay.c b/lib/utils/libfdt/fdt_overlay.c index
> be71873..b310e49 100644
> --- a/lib/utils/libfdt/fdt_overlay.c
> +++ b/lib/utils/libfdt/fdt_overlay.c
> @@ -752,7 +752,7 @@ static int overlay_symbol_update(void *fdt, void
> *fdto)
> 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;
> + rel_path_len = e - rel_path - 1;
> } else if ((e - s) == len
> && (memcmp(s, "/__overlay__", len - 1) == 0)) {
> /* /<fragment-name>/__overlay__ */
> diff --git a/lib/utils/libfdt/fdt_ro.c b/lib/utils/libfdt/fdt_ro.c index
> a5c2797..e03570a 100644
> --- a/lib/utils/libfdt/fdt_ro.c
> +++ b/lib/utils/libfdt/fdt_ro.c
> @@ -33,17 +33,26 @@ static int fdt_nodename_eq_(const void *fdt, int
> offset,
>
> const char *fdt_get_string(const void *fdt, int stroffset, int *lenp) {
> - int32_t totalsize = fdt_ro_probe_(fdt);
> - uint32_t absoffset = stroffset + fdt_off_dt_strings(fdt);
> + int32_t totalsize;
> + uint32_t absoffset;
> size_t len;
> int err;
> const char *s, *n;
>
> + if (can_assume(VALID_INPUT)) {
> + s = (const char *)fdt + fdt_off_dt_strings(fdt) + stroffset;
> +
> + 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;
> @@ -51,7 +60,7 @@ const char *fdt_get_string(const void *fdt, int stroffset,
> int *lenp)
> if (fdt_magic(fdt) == FDT_MAGIC) {
> if (stroffset < 0)
> goto fail;
> - if (fdt_version(fdt) >= 17) {
> + if (can_assume(LATEST) || fdt_version(fdt) >= 17) {
> if (stroffset >= fdt_size_dt_strings(fdt))
> goto fail;
> if ((fdt_size_dt_strings(fdt) - stroffset) < len) @@ -
> 151,10 +160,13 @@ 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 (absoffset < fdt_off_mem_rsvmap(fdt))
> - return NULL;
> - if (absoffset > fdt_totalsize(fdt) - sizeof(struct fdt_reserve_entry))
> - return NULL;
> + if (!can_assume(VALID_INPUT)) {
> + 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);
> }
>
> @@ -164,7 +176,7 @@ int fdt_get_mem_rsv(const void *fdt, int n, uint64_t
> *address, uint64_t *size)
>
> FDT_RO_PROBE(fdt);
> re = fdt_mem_rsv(fdt, n);
> - if (!re)
> + if (!can_assume(VALID_INPUT) && !re)
> return -FDT_ERR_BADOFFSET;
>
> *address = fdt64_ld(&re->address);
> @@ -295,7 +307,7 @@ const char *fdt_get_name(const void *fdt, int
> nodeoffset, int *len)
>
> nameptr = nh->name;
>
> - if (fdt_version(fdt) < 0x10) {
> + if (!can_assume(LATEST) && fdt_version(fdt) < 0x10) {
> /*
> * For old FDT versions, match the naming conventions of
> V16:
> * give only the leaf name (after all /). The actual tree @@ -
> 346,7 +358,8 @@ 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 (!can_assume(VALID_INPUT) &&
> + (err = fdt_check_prop_offset_(fdt, offset)) < 0) {
> if (lenp)
> *lenp = err;
> return NULL;
> @@ -367,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 (!can_assume(LATEST) && fdt_version(fdt) < 0x10) {
> if (lenp)
> *lenp = -FDT_ERR_BADVERSION;
> return NULL;
> @@ -388,7 +401,8 @@ 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 (!can_assume(LIBFDT_FLAWLESS) && !prop) {
> offset = -FDT_ERR_INTERNAL;
> break;
> }
> @@ -413,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 (!can_assume(LATEST) && fdt_version(fdt) < 0x10) {
> if (lenp)
> *lenp = -FDT_ERR_BADVERSION;
> return NULL;
> @@ -444,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_ld(&prop->len) >= 8)
> + if (!can_assume(LATEST) && fdt_version(fdt) < 0x10 &&
> + (poffset + sizeof(*prop)) % 8 && fdt32_ld(&prop->len) >= 8)
> return prop->data + 4;
> return prop->data;
> }
> @@ -461,19 +475,24 @@ const void *fdt_getprop_by_offset(const void
> *fdt, int offset,
> if (namep) {
> const char *name;
> int namelen;
> - name = fdt_get_string(fdt, fdt32_ld(&prop->nameoff),
> - &namelen);
> - if (!name) {
> - if (lenp)
> - *lenp = namelen;
> - return NULL;
> +
> + if (!can_assume(VALID_INPUT)) {
> + 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));
> }
> - *namep = name;
> }
>
> /* Handle realignment */
> - if (fdt_version(fdt) < 0x10 && (offset + sizeof(*prop)) % 8 &&
> - fdt32_ld(&prop->len) >= 8)
> + if (!can_assume(LATEST) && fdt_version(fdt) < 0x10 &&
> + (offset + sizeof(*prop)) % 8 && fdt32_ld(&prop->len) >= 8)
> return prop->data + 4;
> return prop->data;
> }
> @@ -598,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 (!can_assume(VALID_INPUT)) {
> + 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() */ } @@ -613,7 +634,8
> @@ 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 (can_assume(LIBFDT_FLAWLESS) || err < 0) ? err :
> + -FDT_ERR_INTERNAL;
> return nodedepth;
> }
>
> @@ -833,66 +855,3 @@ int fdt_node_offset_by_compatible(const void *fdt,
> int startoffset,
>
> return offset; /* error from fdt_next_node() */ }
> -
> -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;
> - }
> - }
> -}
> diff --git a/lib/utils/libfdt/fdt_rw.c b/lib/utils/libfdt/fdt_rw.c index
> 8795947..1385425 100644
> --- a/lib/utils/libfdt/fdt_rw.c
> +++ b/lib/utils/libfdt/fdt_rw.c
> @@ -24,14 +24,16 @@ static int fdt_blocks_misordered_(const void *fdt,
>
> static int fdt_rw_probe_(void *fdt)
> {
> + if (can_assume(VALID_DTB))
> + return 0;
> FDT_RO_PROBE(fdt);
>
> - if (fdt_version(fdt) < 17)
> + if (!can_assume(LATEST) && 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 (!can_assume(LATEST) && fdt_version(fdt) > 17)
> fdt_set_version(fdt, 17);
>
> return 0;
> @@ -112,6 +114,15 @@ static int fdt_splice_string_(void *fdt, int newlen)
> return 0;
> }
>
> +/**
> + * 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 can_assume(NO_ROLLBACK)
> + * @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); @@ -120,7
> +131,8 @@ static int fdt_find_add_string_(void *fdt, const char *s, int
> *allocated)
> int len = strlen(s) + 1;
> int err;
>
> - *allocated = 0;
> + if (!can_assume(NO_ROLLBACK))
> + *allocated = 0;
>
> p = fdt_find_string_(strtab, fdt_size_dt_strings(fdt), s);
> if (p)
> @@ -132,7 +144,8 @@ static int fdt_find_add_string_(void *fdt, const char
> *s, int *allocated)
> if (err)
> return err;
>
> - *allocated = 1;
> + if (!can_assume(NO_ROLLBACK))
> + *allocated = 1;
>
> memcpy(new, s, len);
> return (new - strtab);
> @@ -206,7 +219,8 @@ static int fdt_add_property_(void *fdt, int
> nodeoffset, const char *name,
>
> err = fdt_splice_struct_(fdt, *prop, 0, proplen);
> if (err) {
> - if (allocated)
> + /* Delete the string if we failed to add it */
> + if (!can_assume(NO_ROLLBACK) && allocated)
> fdt_del_last_string_(fdt, name);
> return err;
> }
> @@ -411,7 +425,7 @@ int fdt_open_into(const void *fdt, void *buf, int
> bufsize)
> mem_rsv_size = (fdt_num_mem_rsv(fdt)+1)
> * sizeof(struct fdt_reserve_entry);
>
> - if (fdt_version(fdt) >= 17) {
> + if (can_assume(LATEST) || fdt_version(fdt) >= 17) {
> struct_size = fdt_size_dt_struct(fdt);
> } else {
> struct_size = 0;
> @@ -421,7 +435,8 @@ int fdt_open_into(const void *fdt, void *buf, int
> bufsize)
> return struct_size;
> }
>
> - if (!fdt_blocks_misordered_(fdt, mem_rsv_size, struct_size)) {
> + if (can_assume(LIBFDT_ORDER) |
> + !fdt_blocks_misordered_(fdt, mem_rsv_size, struct_size)) {
> /* no further work necessary */
> err = fdt_move(fdt, buf, bufsize);
> if (err)
> diff --git a/lib/utils/libfdt/fdt_sw.c b/lib/utils/libfdt/fdt_sw.c index
> 76bea22..26759d5 100644
> --- a/lib/utils/libfdt/fdt_sw.c
> +++ b/lib/utils/libfdt/fdt_sw.c
> @@ -12,10 +12,13 @@
>
> static int fdt_sw_probe_(void *fdt)
> {
> - if (fdt_magic(fdt) == FDT_MAGIC)
> - return -FDT_ERR_BADSTATE;
> - else if (fdt_magic(fdt) != FDT_SW_MAGIC)
> - return -FDT_ERR_BADMAGIC;
> + if (!can_assume(VALID_INPUT)) {
> + if (fdt_magic(fdt) == FDT_MAGIC)
> + return -FDT_ERR_BADSTATE;
> + else if (fdt_magic(fdt) != FDT_SW_MAGIC)
> + return -FDT_ERR_BADMAGIC;
> + }
> +
> return 0;
> }
>
> @@ -38,7 +41,7 @@ static int fdt_sw_probe_memrsv_(void *fdt)
> if (err)
> return err;
>
> - if (fdt_off_dt_strings(fdt) != 0)
> + if (!can_assume(VALID_INPUT) && fdt_off_dt_strings(fdt) != 0)
> return -FDT_ERR_BADSTATE;
> return 0;
> }
> @@ -64,7 +67,8 @@ static int fdt_sw_probe_struct_(void *fdt)
> if (err)
> return err;
>
> - if (fdt_off_dt_strings(fdt) != fdt_totalsize(fdt))
> + if (!can_assume(VALID_INPUT) &&
> + fdt_off_dt_strings(fdt) != fdt_totalsize(fdt))
> return -FDT_ERR_BADSTATE;
> return 0;
> }
> @@ -151,7 +155,8 @@ int fdt_resize(void *fdt, void *buf, int bufsize)
> headsize = fdt_off_dt_struct(fdt) + fdt_size_dt_struct(fdt);
> tailsize = fdt_size_dt_strings(fdt);
>
> - if ((headsize + tailsize) > fdt_totalsize(fdt))
> + if (!can_assume(VALID_DTB) &&
> + headsize + tailsize > fdt_totalsize(fdt))
> return -FDT_ERR_INTERNAL;
>
> if ((headsize + tailsize) > bufsize)
> diff --git a/lib/utils/libfdt/libfdt.h b/lib/utils/libfdt/libfdt.h index
> 8037f39..48f375c 100644
> --- a/lib/utils/libfdt/libfdt.h
> +++ b/lib/utils/libfdt/libfdt.h
> @@ -136,7 +136,7 @@ static inline uint32_t fdt32_ld(const fdt32_t *p)
>
> static inline void fdt32_st(void *property, uint32_t value) {
> - uint8_t *bp = property;
> + uint8_t *bp = (uint8_t *)property;
>
> bp[0] = value >> 24;
> bp[1] = (value >> 16) & 0xff;
> @@ -160,7 +160,7 @@ static inline uint64_t fdt64_ld(const fdt64_t *p)
>
> static inline void fdt64_st(void *property, uint64_t value) {
> - uint8_t *bp = property;
> + uint8_t *bp = (uint8_t *)property;
>
> bp[0] = value >> 56;
> bp[1] = (value >> 48) & 0xff;
> @@ -266,11 +266,12 @@ fdt_set_hdr_(size_dt_struct);
> * 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); -static inline size_t
> fdt_header_size(const void *fdt) -{
> - return fdt_header_size_(fdt_version(fdt));
> -}
>
> /**
> * fdt_check_header - sanity check a device tree header diff --git
> a/lib/utils/libfdt/libfdt_internal.h b/lib/utils/libfdt/libfdt_internal.h
> index 741eeb3..d4e0bd4 100644
> --- a/lib/utils/libfdt/libfdt_internal.h
> +++ b/lib/utils/libfdt/libfdt_internal.h
> @@ -10,10 +10,10 @@
> #define FDT_ALIGN(x, a) (((x) + (a) - 1) & ~((a) - 1))
> #define FDT_TAGALIGN(x) (FDT_ALIGN((x), FDT_TAGSIZE))
>
> -int fdt_ro_probe_(const void *fdt);
> +int32_t fdt_ro_probe_(const void *fdt);
> #define FDT_RO_PROBE(fdt) \
> { \
> - int totalsize_; \
> + int32_t totalsize_; \
> if ((totalsize_ = fdt_ro_probe_(fdt)) < 0) \
> return totalsize_; \
> }
> @@ -48,4 +48,126 @@ 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 safety, don't enable any assumptions!
> + *
> + * For minimal code size and no safety, use 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
> + * ASSUME_SANE.
> + */
> +enum {
> + /*
> + * This does essentially no checks. Only the latest device-tree
> + * version is correctly handled. Inconsistencies or errors in the device
> + * tree may cause undefined behaviour or crashes. Invalid
> parameters
> + * passed to libfdt may do the same.
> + *
> + * 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.
> + */
> + ASSUME_PERFECT = 0xff,
> +
> + /*
> + * This assumes that the device tree is sane. i.e. header metadata
> + * and basic hierarchy are correct.
> + *
> + * With this assumption enabled, 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.
> Truncated
> + * device trees (e.g. those only partially loaded) can also cause
> + * problems.
> + *
> + * Note: Only checks that relate exclusively to the device tree itself
> + * (not the parameters passed to libfdt) are disabled by this
> + * assumption. This includes checking headers, tags and the like.
> + */
> + ASSUME_VALID_DTB = 1 << 0,
> +
> + /*
> + * This builds on ASSUME_VALID_DTB and further assumes that libfdt
> + * functions are called with valid parameters, i.e. not trigger
> + * FDT_ERR_BADOFFSET or offsets that are out of bounds. It disables
> any
> + * extensive checking of parameters and the device tree, making
> various
> + * assumptions about correctness.
> + *
> + * It doesn't make sense to enable this assumption unless
> + * ASSUME_VALID_DTB is also enabled.
> + */
> + ASSUME_VALID_INPUT = 1 << 1,
> +
> + /*
> + * 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.
> + */
> + ASSUME_LATEST = 1 << 2,
> +
> + /*
> + * This assumes that it is OK for a failed addition to the device tree,
> + * due to lack of space or some other problem, to skip any rollback
> + * steps (such as dropping the property name from the string table).
> + * This is safe to enable in most circumstances, even though it may
> + * leave the tree in a sub-optimal state.
> + */
> + ASSUME_NO_ROLLBACK = 1 << 3,
> +
> + /*
> + * This assumes that the device tree components appear in a
> 'convenient'
> + * order, i.e. the memory reservation block first, then the structure
> + * block and finally the string block.
> + *
> + * This order is not specified by the device-tree specification,
> + * but is expected by libfdt. The device-tree compiler always created
> + * device trees with this order.
> + *
> + * This assumption disables a check in fdt_open_into() and removes
> the
> + * ability to fix the problem there. This is safe if you know that the
> + * device tree is correctly ordered. See fdt_blocks_misordered_().
> + */
> + ASSUME_LIBFDT_ORDER = 1 << 4,
> +
> + /*
> + * This assumes that libfdt itself does not have any internal bugs. It
> + * drops certain checks that should never be needed unless libfdt has
> an
> + * undiscovered bug.
> + *
> + * This can generally be considered safe to enable.
> + */
> + ASSUME_LIBFDT_FLAWLESS = 1 << 5,
> +};
> +
> +/**
> + * can_assume_() - check if a particular assumption is enabled
> + *
> + * @mask: Mask to check (ASSUME_...)
> + * @return true if that assumption is enabled, else false */ static
> +inline bool can_assume_(int mask) {
> + return FDT_ASSUME_MASK & mask;
> +}
> +
> +/** helper macros for checking assumptions */
> +#define can_assume(_assume) can_assume_(ASSUME_ ##
> _assume)
> +
> #endif /* LIBFDT_INTERNAL_H */
> diff --git a/lib/utils/libfdt/objects.mk b/lib/utils/libfdt/objects.mk index
> 8156cde..8c060df 100644
> --- a/lib/utils/libfdt/objects.mk
> +++ b/lib/utils/libfdt/objects.mk
> @@ -7,7 +7,7 @@
> # Atish Patra<atish.patra at wdc.com>
> #
>
> -libfdt_files = fdt.o fdt_addresses.o fdt_empty_tree.o fdt_ro.o fdt_rw.o \
> +libfdt_files = fdt.o fdt_addresses.o fdt_check.o fdt_empty_tree.o
> +fdt_ro.o fdt_rw.o \
> fdt_strerror.o fdt_sw.o fdt_wip.o $(foreach file, $(libfdt_files), \
> $(eval CFLAGS_$(file) = -I$(src)/../../utils/libfdt)) diff --git
> a/lib/utils/libfdt/version.lds b/lib/utils/libfdt/version.lds index
> ae32924..7ab85f1 100644
> --- a/lib/utils/libfdt/version.lds
> +++ b/lib/utils/libfdt/version.lds
> @@ -20,6 +20,7 @@ LIBFDT_1.2 {
> fdt_get_alias_namelen;
> fdt_get_alias;
> fdt_get_path;
> + fdt_header_size;
> fdt_supernode_atdepth_offset;
> fdt_node_depth;
> fdt_parent_offset;
> --
> 2.27.0
>
>
> --
> opensbi mailing list
> opensbi at lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/opensbi
Looks good to me.
Reviewed-by: Anup Patel <anup.patel at wdc.com>
I have replaced "libfdt:" subject prefix with "lib: utils/libfdt:"
at time of applying this patch.
Applied this patch to riscv/opensbi repo.
Thanks,
Anup
More information about the opensbi
mailing list