From 37fef5ab88d1134fd6b8b53090e0bfa442732e24 Mon Sep 17 00:00:00 2001 From: Tom Rini Date: Tue, 26 May 2026 14:19:27 -0600 Subject: dtc: Resync fdt_check_full() with upstream version v1.7.2-35-g52f07dcca47c In the upstream project, the function fdt_check_full has been moved from fdt_ro.c to its own file, fdt_check.c. This file is not included in the Linux kernel copy and so has not been synced over. As we do need and use the fdt_check_full function, bring that file over as of the current upstream we are synced to. Remove our copy of this function from fdt_ro.c and add fdt_check.o and 1-liner fdt_check.c where needed. Note that for now, this will increase size in some cases as upstream does not have a size reduction method here. Reviewed-by: Simon Glass Signed-off-by: Tom Rini --- scripts/dtc/libfdt/Makefile.libfdt | 2 +- scripts/dtc/libfdt/fdt_check.c | 96 ++++++++++++++++++++++++++++++++++++++ scripts/dtc/libfdt/fdt_ro.c | 88 ---------------------------------- 3 files changed, 97 insertions(+), 89 deletions(-) create mode 100644 scripts/dtc/libfdt/fdt_check.c (limited to 'scripts/dtc/libfdt') diff --git a/scripts/dtc/libfdt/Makefile.libfdt b/scripts/dtc/libfdt/Makefile.libfdt index e54639738c8..b6d8fc02dd0 100644 --- a/scripts/dtc/libfdt/Makefile.libfdt +++ b/scripts/dtc/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/scripts/dtc/libfdt/fdt_check.c b/scripts/dtc/libfdt/fdt_check.c new file mode 100644 index 00000000000..a21ebbc9239 --- /dev/null +++ b/scripts/dtc/libfdt/fdt_check.c @@ -0,0 +1,96 @@ +// 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 +#include + +#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; + bool expect_end = false; + + if (bufsize < FDT_V1_SIZE) + return -FDT_ERR_TRUNCATED; + if (bufsize < fdt_header_size(fdt)) + 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; + + /* If we see two root nodes, something is wrong */ + if (expect_end && tag != FDT_END) + return -FDT_ERR_BADSTRUCTURE; + + 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; + + /* The root node must have an empty name */ + if (depth == 1) { + const char *name; + int len; + + name = fdt_get_name(fdt, offset, &len); + if (!name) + return len; + + if (*name || len) + return -FDT_ERR_BADSTRUCTURE; + } + break; + + case FDT_END_NODE: + if (depth == 0) + return -FDT_ERR_BADSTRUCTURE; + depth--; + if (depth == 0) + expect_end = true; + 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/scripts/dtc/libfdt/fdt_ro.c b/scripts/dtc/libfdt/fdt_ro.c index 3e7e26b4398..065baa70735 100644 --- a/scripts/dtc/libfdt/fdt_ro.c +++ b/scripts/dtc/libfdt/fdt_ro.c @@ -884,91 +884,3 @@ 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; - bool expect_end = false; - - 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; - - /* If we see two root nodes, something is wrong */ - if (expect_end && tag != FDT_END) - return -FDT_ERR_BADLAYOUT; - - 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; - - /* The root node must have an empty name */ - if (depth == 1) { - const char *name; - int len; - - name = fdt_get_name(fdt, offset, &len); - if (*name || len) - return -FDT_ERR_BADLAYOUT; - } - break; - - case FDT_END_NODE: - if (depth == 0) - return -FDT_ERR_BADSTRUCTURE; - depth--; - if (depth == 0) - expect_end = true; - break; - - case FDT_PROP: - prop = fdt_getprop_by_offset(fdt, offset, &propname, - &err); - if (!prop) - return err; - break; - - default: - return -FDT_ERR_INTERNAL; - } - } -} -#else -int fdt_check_full(const void __always_unused *fdt, - size_t __always_unused bufsize) -{ - return 0; -} -#endif /* #if !defined(FDT_ASSUME_MASK) || FDT_ASSUME_MASK != 0xff */ -- cgit v1.3.1 From 487994d65cf305e943e4fd4efb56283f214f0611 Mon Sep 17 00:00:00 2001 From: Tom Rini Date: Tue, 26 May 2026 14:19:28 -0600 Subject: dtc: libfdt: Introduce a can_assume check in fdt_check_full The current upstream method of having a function omit various tests is to use the can_assume macro. Take the logic we had previously been using and instead make it a can_assume(PERFECT) check within fdt_check_full itself. Reviewed-by: Simon Glass Signed-off-by: Tom Rini --- scripts/dtc/libfdt/fdt_check.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'scripts/dtc/libfdt') diff --git a/scripts/dtc/libfdt/fdt_check.c b/scripts/dtc/libfdt/fdt_check.c index a21ebbc9239..7509c11d858 100644 --- a/scripts/dtc/libfdt/fdt_check.c +++ b/scripts/dtc/libfdt/fdt_check.c @@ -21,6 +21,8 @@ int fdt_check_full(const void *fdt, size_t bufsize) const char *propname; bool expect_end = false; + if (can_assume(PERFECT)) + return 0; if (bufsize < FDT_V1_SIZE) return -FDT_ERR_TRUNCATED; if (bufsize < fdt_header_size(fdt)) -- cgit v1.3.1