All of lore.kernel.org
 help / color / mirror / Atom feed
* [U-Boot] [PATCH 0/4] fdt: Switch to the latest libfdt, sort-of
@ 2019-10-27 15:47 Simon Glass
  2019-10-27 15:47 ` [U-Boot] [PATCH 1/4] fdt: Add INT32_MAX to kernel.h for libfdt Simon Glass
                   ` (6 more replies)
  0 siblings, 7 replies; 18+ messages in thread
From: Simon Glass @ 2019-10-27 15:47 UTC (permalink / raw)
  To: u-boot

This series brings over the latest libfdt with some changes to deal with
the recent code-size bloat.

With this change U-Boot size increases about 2.5KB on 'rock' and SPL
reduces by about 128 bytes. This should be acceptable.

The 'assumptions' series is still under review, so we can sync that up
later when complete.


Simon Glass (4):
  fdt: Add INT32_MAX to kernel.h for libfdt
  fdt: Add Kconfig options to control code size
  mx6: tbs2910: Minimise libfdt code size
  fdt: Sync up to the latest libfdt

 configs/tbs2910_defconfig            |   1 +
 include/linux/kernel.h               |   2 +
 include/linux/libfdt_env.h           |   1 +
 lib/Kconfig                          |  33 +++
 lib/libfdt/Makefile                  |   3 +-
 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 +-
 21 files changed, 1314 insertions(+), 872 deletions(-)

-- 
2.24.0.rc0.303.g954a862665-goog

^ permalink raw reply	[flat|nested] 18+ messages in thread

* [U-Boot] [PATCH 1/4] fdt: Add INT32_MAX to kernel.h for libfdt
  2019-10-27 15:47 [U-Boot] [PATCH 0/4] fdt: Switch to the latest libfdt, sort-of Simon Glass
@ 2019-10-27 15:47 ` Simon Glass
  2019-10-30 17:01   ` Tom Rini
  2019-11-05 12:06   ` sjg at google.com
  2019-10-27 15:47 ` [U-Boot] [PATCH 2/4] fdt: Add Kconfig options to control code size Simon Glass
                   ` (5 subsequent siblings)
  6 siblings, 2 replies; 18+ messages in thread
From: Simon Glass @ 2019-10-27 15:47 UTC (permalink / raw)
  To: u-boot

Unfortunately libfdt needs this value now, which is present in the
stdint.h header. That file is just a placeholder in U-Boot and these sorts
of constants appear in the linux/kernel.h header instead.

To keep libfdt happy, add INT32_MAX too.

Signed-off-by: Simon Glass <sjg@chromium.org>
---

 include/linux/kernel.h     | 2 ++
 include/linux/libfdt_env.h | 1 +
 2 files changed, 3 insertions(+)

diff --git a/include/linux/kernel.h b/include/linux/kernel.h
index a85c15d8dc..5c7e5f635b 100644
--- a/include/linux/kernel.h
+++ b/include/linux/kernel.h
@@ -37,6 +37,8 @@
 #define UINT32_MAX	U32_MAX
 #define UINT64_MAX	U64_MAX
 
+#define INT32_MAX	S32_MAX
+
 #define STACK_MAGIC	0xdeadbeef
 
 #define REPEAT_BYTE(x)	((~0ul / 0xff) * (x))
diff --git a/include/linux/libfdt_env.h b/include/linux/libfdt_env.h
index e2bf79c7ee..cca7792acd 100644
--- a/include/linux/libfdt_env.h
+++ b/include/linux/libfdt_env.h
@@ -10,6 +10,7 @@
 #define LIBFDT_ENV_H
 
 #include <linux/string.h>
+#include <linux/kernel.h>
 
 #include <asm/byteorder.h>
 
-- 
2.24.0.rc0.303.g954a862665-goog

^ permalink raw reply related	[flat|nested] 18+ messages in thread

* [U-Boot] [PATCH 2/4] fdt: Add Kconfig options to control code size
  2019-10-27 15:47 [U-Boot] [PATCH 0/4] fdt: Switch to the latest libfdt, sort-of Simon Glass
  2019-10-27 15:47 ` [U-Boot] [PATCH 1/4] fdt: Add INT32_MAX to kernel.h for libfdt Simon Glass
@ 2019-10-27 15:47 ` Simon Glass
  2019-10-27 18:06   ` Heinrich Schuchardt
                     ` (2 more replies)
  2019-10-27 15:47 ` [U-Boot] [PATCH 3/4] mx6: tbs2910: Minimise libfdt " Simon Glass
                   ` (4 subsequent siblings)
  6 siblings, 3 replies; 18+ messages in thread
From: Simon Glass @ 2019-10-27 15:47 UTC (permalink / raw)
  To: u-boot

For better or worse libfdt recent grew a lot of code that checks the
validity of the device tree in great detail. When using unsigned or
unverified data this makes things safer, but it does add to code size.

Add some controls to select the trade-off between safety and code size.

Signed-off-by: Simon Glass <sjg@chromium.org>
---

 lib/Kconfig         | 33 +++++++++++++++++++++++++++++++++
 lib/libfdt/Makefile |  3 ++-
 2 files changed, 35 insertions(+), 1 deletion(-)

diff --git a/lib/Kconfig b/lib/Kconfig
index 135f0b372b..b8a8509d72 100644
--- a/lib/Kconfig
+++ b/lib/Kconfig
@@ -464,6 +464,17 @@ config OF_LIBFDT
 	  particular compatible nodes. The library operates on a flattened
 	  version of the device tree.
 
+config OF_LIBFDT_ASSUME_MASK
+	hex "Mask of conditions to assume for libfdt"
+	depends on OF_LIBFDT || FIT
+	default 0
+	help
+	  Use this to change the assumptions made by libfdt about the
+	  device tree it is working with. A value of 0 means that no assumptions
+	  are made, and libfdt is able to deal with malicious data. A value of
+	  0xff means all assumptions are made and any invalid data may cause
+	  unsafe execution. See FDT_ASSUME_PERFECT, etc. in libfdt_internal.h
+
 config OF_LIBFDT_OVERLAY
 	bool "Enable the FDT library overlay support"
 	depends on OF_LIBFDT
@@ -481,6 +492,17 @@ config SPL_OF_LIBFDT
 	  particular compatible nodes. The library operates on a flattened
 	  version of the device tree.
 
+config SPL_OF_LIBFDT_ASSUME_MASK
+	hex "Mask of conditions to assume for libfdt"
+	depends on SPL_OF_LIBFDT || FIT
+	default 0xff
+	help
+	  Use this to change the assumptions made by libfdt in SPL about the
+	  device tree it is working with. A value of 0 means that no assumptions
+	  are made, and libfdt is able to deal with malicious data. A value of
+	  0xff means all assumptions are made and any invalid data may cause
+	  unsafe execution. See FDT_ASSUME_PERFECT, etc. in libfdt_internal.h
+
 config TPL_OF_LIBFDT
 	bool "Enable the FDT library for TPL"
 	default y if TPL_OF_CONTROL
@@ -491,6 +513,17 @@ config TPL_OF_LIBFDT
 	  particular compatible nodes. The library operates on a flattened
 	  version of the device tree.
 
+config TPL_OF_LIBFDT_ASSUME_MASK
+	hex "Mask of conditions to assume for libfdt"
+	depends on TPL_OF_LIBFDT || FIT
+	default 0xff
+	help
+	  Use this to change the assumptions made by libfdt in TPL about the
+	  device tree it is working with. A value of 0 means that no assumptions
+	  are made, and libfdt is able to deal with malicious data. A value of
+	  0xff means all assumptions are made and any invalid data may cause
+	  unsafe execution. See FDT_ASSUME_PERFECT, etc. in libfdt_internal.h
+
 config FDT_FIXUP_PARTITIONS
 	bool "overwrite MTD partitions in DTS through defined in 'mtdparts'"
 	depends on OF_LIBFDT
diff --git a/lib/libfdt/Makefile b/lib/libfdt/Makefile
index ef5b6e29d4..5d3ae4e2f1 100644
--- a/lib/libfdt/Makefile
+++ b/lib/libfdt/Makefile
@@ -22,4 +22,5 @@ obj-y += fdt_ro.o
 # U-Boot own file
 obj-y += fdt_region.o
 
-ccflags-y := -I$(srctree)/scripts/dtc/libfdt
+ccflags-y := -I$(srctree)/scripts/dtc/libfdt \
+	-DFDT_ASSUME_MASK=$(CONFIG_$(SPL_TPL_)OF_LIBFDT_ASSUME_MASK)
-- 
2.24.0.rc0.303.g954a862665-goog

^ permalink raw reply related	[flat|nested] 18+ messages in thread

* [U-Boot] [PATCH 3/4] mx6: tbs2910: Minimise libfdt code size
  2019-10-27 15:47 [U-Boot] [PATCH 0/4] fdt: Switch to the latest libfdt, sort-of Simon Glass
  2019-10-27 15:47 ` [U-Boot] [PATCH 1/4] fdt: Add INT32_MAX to kernel.h for libfdt Simon Glass
  2019-10-27 15:47 ` [U-Boot] [PATCH 2/4] fdt: Add Kconfig options to control code size Simon Glass
@ 2019-10-27 15:47 ` Simon Glass
  2019-10-27 15:47 ` [U-Boot] [PATCH 4/4] fdt: Sync up to the latest libfdt Simon Glass
                   ` (3 subsequent siblings)
  6 siblings, 0 replies; 18+ messages in thread
From: Simon Glass @ 2019-10-27 15:47 UTC (permalink / raw)
  To: u-boot

This board appears to be very near its size limit and cannot accept the
new checking code in libfdt. Disable this code so this the board can
continue to build.

Signed-off-by: Simon Glass <sjg@chromium.org>
---

 configs/tbs2910_defconfig | 1 +
 1 file changed, 1 insertion(+)

diff --git a/configs/tbs2910_defconfig b/configs/tbs2910_defconfig
index 42e6f58eee..6d4d4c8f9f 100644
--- a/configs/tbs2910_defconfig
+++ b/configs/tbs2910_defconfig
@@ -78,4 +78,5 @@ CONFIG_USB_GADGET_DOWNLOAD=y
 CONFIG_I2C_EDID=y
 CONFIG_VIDEO_IPUV3=y
 CONFIG_VIDEO=y
+CONFIG_OF_LIBFDT_ASSUME_MASK=0xff
 # CONFIG_EFI_LOADER is not set
-- 
2.24.0.rc0.303.g954a862665-goog

^ permalink raw reply related	[flat|nested] 18+ messages in thread

* [U-Boot] [PATCH 4/4] fdt: Sync up to the latest libfdt
  2019-10-27 15:47 [U-Boot] [PATCH 0/4] fdt: Switch to the latest libfdt, sort-of Simon Glass
                   ` (2 preceding siblings ...)
  2019-10-27 15:47 ` [U-Boot] [PATCH 3/4] mx6: tbs2910: Minimise libfdt " Simon Glass
@ 2019-10-27 15:47 ` Simon Glass
  2020-01-07 11:43   ` Adam Ford
  2019-10-28 14:04 ` [U-Boot] [PATCH 0/4] fdt: Switch to the latest libfdt, sort-of Tom Rini
                   ` (2 subsequent siblings)
  6 siblings, 1 reply; 18+ messages in thread
From: Simon Glass @ 2019-10-27 15:47 UTC (permalink / raw)
  To: u-boot

Bring over the fdt from this commit:

430419c (origin/master) tests: fix some python warnings

adding in the 'assumptions' series designed to reduce code size.

Signed-off-by: Simon Glass <sjg@chromium.org>
---

 lib/libfdt/fdt_ro.c                  | 420 ++++++++++++++++++++-------
 scripts/dtc/libfdt/Makefile.libfdt   |   7 +
 scripts/dtc/libfdt/fdt.c             | 182 ++++++++----
 scripts/dtc/libfdt/fdt.h             |  47 +--
 scripts/dtc/libfdt/fdt_addresses.c   |  94 +++---
 scripts/dtc/libfdt/fdt_empty_tree.c  |  47 +--
 scripts/dtc/libfdt/fdt_overlay.c     |  91 ++----
 scripts/dtc/libfdt/fdt_ro.c          | 341 +++++++++++++++-------
 scripts/dtc/libfdt/fdt_rw.c          | 119 ++++----
 scripts/dtc/libfdt/fdt_strerror.c    |  47 +--
 scripts/dtc/libfdt/fdt_sw.c          | 241 ++++++++++-----
 scripts/dtc/libfdt/fdt_wip.c         |  47 +--
 scripts/dtc/libfdt/libfdt.h          | 268 +++++++++++++----
 scripts/dtc/libfdt/libfdt_env.h      |  48 +--
 scripts/dtc/libfdt/libfdt_internal.h | 144 +++++----
 tools/libfdt/fdt_rw.c                |   3 +-
 16 files changed, 1275 insertions(+), 871 deletions(-)

diff --git a/lib/libfdt/fdt_ro.c b/lib/libfdt/fdt_ro.c
index 693de9aa5a..560041b603 100644
--- a/lib/libfdt/fdt_ro.c
+++ b/lib/libfdt/fdt_ro.c
@@ -14,12 +14,13 @@
 
 #include "libfdt_internal.h"
 
-static int _fdt_nodename_eq(const void *fdt, int offset,
+static int fdt_nodename_eq_(const void *fdt, int offset,
 			    const char *s, int len)
 {
-	const char *p = fdt_offset_ptr(fdt, offset + FDT_TAGSIZE, len+1);
+	int olen;
+	const char *p = fdt_get_name(fdt, offset, &olen);
 
-	if (!p)
+	if (!p || (fdt_chk_extra() && olen < len))
 		/* short match */
 		return 0;
 
@@ -34,46 +35,85 @@ static int _fdt_nodename_eq(const void *fdt, int offset,
 		return 0;
 }
 
-const char *fdt_string(const void *fdt, int stroffset)
-{
-	return (const char *)fdt + fdt_off_dt_strings(fdt) + stroffset;
-}
-
-static int _fdt_string_eq(const void *fdt, int stroffset,
-			  const char *s, int len)
+const char *fdt_get_string(const void *fdt, int stroffset, int *lenp)
 {
-	const char *p = fdt_string(fdt, stroffset);
+	int32_t totalsize;
+	uint32_t absoffset;
+	size_t len;
+	int err;
+	const char *s, *n;
 
-	return (strnlen(p, len + 1) == len) && (memcmp(p, s, len) == 0);
-}
+	if (!fdt_chk_extra()) {
+		s = (const char *)fdt + fdt_off_dt_strings(fdt) + stroffset;
 
-uint32_t fdt_get_max_phandle(const void *fdt)
-{
-	uint32_t max_phandle = 0;
-	int offset;
+		if (lenp)
+			*lenp = strlen(s);
+		return s;
+	}
+	totalsize = fdt_ro_probe_(fdt);
+	err = totalsize;
+	if (totalsize < 0)
+		goto fail;
+
+	err = -FDT_ERR_BADOFFSET;
+	absoffset = stroffset + fdt_off_dt_strings(fdt);
+	if (absoffset >= totalsize)
+		goto fail;
+	len = totalsize - absoffset;
+
+	if (fdt_magic(fdt) == FDT_MAGIC) {
+		if (stroffset < 0)
+			goto fail;
+		if (!fdt_chk_version() || fdt_version(fdt) >= 17) {
+			if (stroffset >= fdt_size_dt_strings(fdt))
+				goto fail;
+			if ((fdt_size_dt_strings(fdt) - stroffset) < len)
+				len = fdt_size_dt_strings(fdt) - stroffset;
+		}
+	} else if (fdt_magic(fdt) == FDT_SW_MAGIC) {
+		if ((stroffset >= 0)
+		    || (stroffset < -fdt_size_dt_strings(fdt)))
+			goto fail;
+		if ((-stroffset) < len)
+			len = -stroffset;
+	} else {
+		err = -FDT_ERR_INTERNAL;
+		goto fail;
+	}
 
-	for (offset = fdt_next_node(fdt, -1, NULL);;
-	     offset = fdt_next_node(fdt, offset, NULL)) {
-		uint32_t phandle;
+	s = (const char *)fdt + absoffset;
+	n = memchr(s, '\0', len);
+	if (!n) {
+		/* missing terminating NULL */
+		err = -FDT_ERR_TRUNCATED;
+		goto fail;
+	}
 
-		if (offset == -FDT_ERR_NOTFOUND)
-			return max_phandle;
+	if (lenp)
+		*lenp = n - s;
+	return s;
 
-		if (offset < 0)
-			return (uint32_t)-1;
+fail:
+	if (lenp)
+		*lenp = err;
+	return NULL;
+}
 
-		phandle = fdt_get_phandle(fdt, offset);
-		if (phandle == (uint32_t)-1)
-			continue;
+const char *fdt_string(const void *fdt, int stroffset)
+{
+	return fdt_get_string(fdt, stroffset, NULL);
+}
 
-		if (phandle > max_phandle)
-			max_phandle = phandle;
-	}
+static int fdt_string_eq_(const void *fdt, int stroffset,
+			  const char *s, int len)
+{
+	int slen;
+	const char *p = fdt_get_string(fdt, stroffset, &slen);
 
-	return 0;
+	return p && (slen == len) && (memcmp(p, s, len) == 0);
 }
 
-int fdt_generate_phandle(const void *fdt, uint32_t *phandle)
+int fdt_find_max_phandle(const void *fdt, uint32_t *phandle)
 {
 	uint32_t max = 0;
 	int offset = -1;
@@ -95,6 +135,21 @@ int fdt_generate_phandle(const void *fdt, uint32_t *phandle)
 			max = value;
 	}
 
+	if (phandle)
+		*phandle = max;
+
+	return 0;
+}
+
+int fdt_generate_phandle(const void *fdt, uint32_t *phandle)
+{
+	uint32_t max;
+	int err;
+
+	err = fdt_find_max_phandle(fdt, &max);
+	if (err < 0)
+		return err;
+
 	if (max == FDT_MAX_PHANDLE)
 		return -FDT_ERR_NOPHANDLES;
 
@@ -104,24 +159,48 @@ int fdt_generate_phandle(const void *fdt, uint32_t *phandle)
 	return 0;
 }
 
+static const struct fdt_reserve_entry *fdt_mem_rsv(const void *fdt, int n)
+{
+	int offset = n * sizeof(struct fdt_reserve_entry);
+	int absoffset = fdt_off_mem_rsvmap(fdt) + offset;
+
+	if (fdt_chk_extra()) {
+		if (absoffset < fdt_off_mem_rsvmap(fdt))
+			return NULL;
+		if (absoffset > fdt_totalsize(fdt) -
+		    sizeof(struct fdt_reserve_entry))
+			return NULL;
+	}
+	return fdt_mem_rsv_(fdt, n);
+}
+
 int fdt_get_mem_rsv(const void *fdt, int n, uint64_t *address, uint64_t *size)
 {
-	FDT_CHECK_HEADER(fdt);
-	*address = fdt64_to_cpu(fdt_mem_rsv_(fdt, n)->address);
-	*size = fdt64_to_cpu(fdt_mem_rsv_(fdt, n)->size);
+	const struct fdt_reserve_entry *re;
+
+	FDT_RO_PROBE(fdt);
+	re = fdt_mem_rsv(fdt, n);
+	if (fdt_chk_extra() && !re)
+		return -FDT_ERR_BADOFFSET;
+
+	*address = fdt64_ld(&re->address);
+	*size = fdt64_ld(&re->size);
 	return 0;
 }
 
 int fdt_num_mem_rsv(const void *fdt)
 {
-	int i = 0;
+	int i;
+	const struct fdt_reserve_entry *re;
 
-	while (fdt64_to_cpu(fdt_mem_rsv_(fdt, i)->size) != 0)
-		i++;
-	return i;
+	for (i = 0; (re = fdt_mem_rsv(fdt, i)) != NULL; i++) {
+		if (fdt64_ld(&re->size) == 0)
+			return i;
+	}
+	return -FDT_ERR_TRUNCATED;
 }
 
-static int _nextprop(const void *fdt, int offset)
+static int nextprop_(const void *fdt, int offset)
 {
 	uint32_t tag;
 	int nextoffset;
@@ -150,13 +229,13 @@ int fdt_subnode_offset_namelen(const void *fdt, int offset,
 {
 	int depth;
 
-	FDT_CHECK_HEADER(fdt);
+	FDT_RO_PROBE(fdt);
 
 	for (depth = 0;
 	     (offset >= 0) && (depth >= 0);
 	     offset = fdt_next_node(fdt, offset, &depth))
 		if ((depth == 1)
-		    && _fdt_nodename_eq(fdt, offset, name, namelen))
+		    && fdt_nodename_eq_(fdt, offset, name, namelen))
 			return offset;
 
 	if (depth < 0)
@@ -170,36 +249,17 @@ int fdt_subnode_offset(const void *fdt, int parentoffset,
 	return fdt_subnode_offset_namelen(fdt, parentoffset, name, strlen(name));
 }
 
-/*
- * Find the next of path separator, note we need to search for both '/' and ':'
- * and then take the first one so that we do the right thing for e.g.
- * "foo/bar:option" and "bar:option/otheroption", both of which happen, so
- * first searching for either ':' or '/' does not work.
- */
-static const char *fdt_path_next_separator(const char *path, int len)
-{
-	const void *sep1 = memchr(path, '/', len);
-	const void *sep2 = memchr(path, ':', len);
-
-	if (sep1 && sep2)
-		return (sep1 < sep2) ? sep1 : sep2;
-	else if (sep1)
-		return sep1;
-	else
-		return sep2;
-}
-
 int fdt_path_offset_namelen(const void *fdt, const char *path, int namelen)
 {
 	const char *end = path + namelen;
 	const char *p = path;
 	int offset = 0;
 
-	FDT_CHECK_HEADER(fdt);
+	FDT_RO_PROBE(fdt);
 
 	/* see if we have an alias */
 	if (*path != '/') {
-		const char *q = fdt_path_next_separator(path, namelen);
+		const char *q = memchr(path, '/', end - p);
 
 		if (!q)
 			q = end;
@@ -212,17 +272,16 @@ int fdt_path_offset_namelen(const void *fdt, const char *path, int namelen)
 		p = q;
 	}
 
-	while (*p && (p < end)) {
+	while (p < end) {
 		const char *q;
 
-		while (*p == '/')
+		while (*p == '/') {
 			p++;
-
-		if (*p == '\0' || *p == ':')
-			return offset;
-
-		q = fdt_path_next_separator(p, end - p);
-		if (!q)
+			if (p == end)
+				return offset;
+		}
+		q = memchr(p, '/', end - p);
+		if (! q)
 			q = end;
 
 		offset = fdt_subnode_offset_namelen(fdt, offset, p, q-p);
@@ -243,16 +302,35 @@ int fdt_path_offset(const void *fdt, const char *path)
 const char *fdt_get_name(const void *fdt, int nodeoffset, int *len)
 {
 	const struct fdt_node_header *nh = fdt_offset_ptr_(fdt, nodeoffset);
+	const char *nameptr;
 	int err;
 
-	if (((err = fdt_check_header(fdt)) != 0)
-	    || ((err = fdt_check_node_offset_(fdt, nodeoffset)) < 0))
+	if (fdt_chk_extra() &&
+	    (((err = fdt_ro_probe_(fdt)) < 0)
+	     || ((err = fdt_check_node_offset_(fdt, nodeoffset)) < 0)))
+		goto fail;
+
+	nameptr = nh->name;
+
+	if (fdt_chk_version() && fdt_version(fdt) < 0x10) {
+		/*
+		 * For old FDT versions, match the naming conventions of V16:
+		 * give only the leaf name (after all /). The actual tree
+		 * contents are loosely checked.
+		 */
+		const char *leaf;
+		leaf = strrchr(nameptr, '/');
+		if (leaf == NULL) {
+			err = -FDT_ERR_BADSTRUCTURE;
 			goto fail;
+		}
+		nameptr = leaf+1;
+	}
 
 	if (len)
-		*len = strlen(nh->name);
+		*len = strlen(nameptr);
 
-	return nh->name;
+	return nameptr;
 
  fail:
 	if (len)
@@ -267,7 +345,7 @@ int fdt_first_property_offset(const void *fdt, int nodeoffset)
 	if ((offset = fdt_check_node_offset_(fdt, nodeoffset)) < 0)
 		return offset;
 
-	return _nextprop(fdt, offset);
+	return nextprop_(fdt, offset);
 }
 
 int fdt_next_property_offset(const void *fdt, int offset)
@@ -275,17 +353,17 @@ int fdt_next_property_offset(const void *fdt, int offset)
 	if ((offset = fdt_check_prop_offset_(fdt, offset)) < 0)
 		return offset;
 
-	return _nextprop(fdt, offset);
+	return nextprop_(fdt, offset);
 }
 
-const struct fdt_property *fdt_get_property_by_offset(const void *fdt,
-						      int offset,
-						      int *lenp)
+static const struct fdt_property *fdt_get_property_by_offset_(const void *fdt,
+						              int offset,
+						              int *lenp)
 {
 	int err;
 	const struct fdt_property *prop;
 
-	if ((err = fdt_check_prop_offset_(fdt, offset)) < 0) {
+	if (fdt_chk_basic() && (err = fdt_check_prop_offset_(fdt, offset)) < 0) {
 		if (lenp)
 			*lenp = err;
 		return NULL;
@@ -294,28 +372,50 @@ const struct fdt_property *fdt_get_property_by_offset(const void *fdt,
 	prop = fdt_offset_ptr_(fdt, offset);
 
 	if (lenp)
-		*lenp = fdt32_to_cpu(prop->len);
+		*lenp = fdt32_ld(&prop->len);
 
 	return prop;
 }
 
-const struct fdt_property *fdt_get_property_namelen(const void *fdt,
-						    int offset,
-						    const char *name,
-						    int namelen, int *lenp)
+const struct fdt_property *fdt_get_property_by_offset(const void *fdt,
+						      int offset,
+						      int *lenp)
+{
+	/* Prior to version 16, properties may need realignment
+	 * and this API does not work. fdt_getprop_*() will, however. */
+
+	if (fdt_chk_version() && fdt_version(fdt) < 0x10) {
+		if (lenp)
+			*lenp = -FDT_ERR_BADVERSION;
+		return NULL;
+	}
+
+	return fdt_get_property_by_offset_(fdt, offset, lenp);
+}
+
+static const struct fdt_property *fdt_get_property_namelen_(const void *fdt,
+						            int offset,
+						            const char *name,
+						            int namelen,
+							    int *lenp,
+							    int *poffset)
 {
 	for (offset = fdt_first_property_offset(fdt, offset);
 	     (offset >= 0);
 	     (offset = fdt_next_property_offset(fdt, offset))) {
 		const struct fdt_property *prop;
 
-		if (!(prop = fdt_get_property_by_offset(fdt, offset, lenp))) {
+		prop = fdt_get_property_by_offset_(fdt, offset, lenp);
+		if (fdt_chk_extra() && !prop) {
 			offset = -FDT_ERR_INTERNAL;
 			break;
 		}
-		if (_fdt_string_eq(fdt, fdt32_to_cpu(prop->nameoff),
-				   name, namelen))
+		if (fdt_string_eq_(fdt, fdt32_ld(&prop->nameoff),
+				   name, namelen)) {
+			if (poffset)
+				*poffset = offset;
 			return prop;
+		}
 	}
 
 	if (lenp)
@@ -323,6 +423,25 @@ const struct fdt_property *fdt_get_property_namelen(const void *fdt,
 	return NULL;
 }
 
+
+const struct fdt_property *fdt_get_property_namelen(const void *fdt,
+						    int offset,
+						    const char *name,
+						    int namelen, int *lenp)
+{
+	/* Prior to version 16, properties may need realignment
+	 * and this API does not work. fdt_getprop_*() will, however. */
+	if (fdt_chk_version() && fdt_version(fdt) < 0x10) {
+		if (lenp)
+			*lenp = -FDT_ERR_BADVERSION;
+		return NULL;
+	}
+
+	return fdt_get_property_namelen_(fdt, offset, name, namelen, lenp,
+					 NULL);
+}
+
+
 const struct fdt_property *fdt_get_property(const void *fdt,
 					    int nodeoffset,
 					    const char *name, int *lenp)
@@ -334,12 +453,18 @@ const struct fdt_property *fdt_get_property(const void *fdt,
 const void *fdt_getprop_namelen(const void *fdt, int nodeoffset,
 				const char *name, int namelen, int *lenp)
 {
+	int poffset;
 	const struct fdt_property *prop;
 
-	prop = fdt_get_property_namelen(fdt, nodeoffset, name, namelen, lenp);
+	prop = fdt_get_property_namelen_(fdt, nodeoffset, name, namelen, lenp,
+					 &poffset);
 	if (!prop)
 		return NULL;
 
+	/* Handle realignment */
+	if (fdt_chk_version() && fdt_version(fdt) < 0x10 &&
+	    (poffset + sizeof(*prop)) % 8 && fdt32_ld(&prop->len) >= 8)
+		return prop->data + 4;
 	return prop->data;
 }
 
@@ -348,11 +473,31 @@ const void *fdt_getprop_by_offset(const void *fdt, int offset,
 {
 	const struct fdt_property *prop;
 
-	prop = fdt_get_property_by_offset(fdt, offset, lenp);
+	prop = fdt_get_property_by_offset_(fdt, offset, lenp);
 	if (!prop)
 		return NULL;
-	if (namep)
-		*namep = fdt_string(fdt, fdt32_to_cpu(prop->nameoff));
+	if (namep) {
+		const char *name;
+		int namelen;
+
+		if (fdt_chk_extra()) {
+			name = fdt_get_string(fdt, fdt32_ld(&prop->nameoff),
+					      &namelen);
+			if (!name) {
+				if (lenp)
+					*lenp = namelen;
+				return NULL;
+			}
+			*namep = name;
+		} else {
+			*namep = fdt_string(fdt, fdt32_ld(&prop->nameoff));
+		}
+	}
+
+	/* Handle realignment */
+	if (fdt_chk_version() && fdt_version(fdt) < 0x10 &&
+	    (offset + sizeof(*prop)) % 8 && fdt32_ld(&prop->len) >= 8)
+		return prop->data + 4;
 	return prop->data;
 }
 
@@ -376,7 +521,7 @@ uint32_t fdt_get_phandle(const void *fdt, int nodeoffset)
 			return 0;
 	}
 
-	return fdt32_to_cpu(*php);
+	return fdt32_ld(php);
 }
 
 const char *fdt_get_alias_namelen(const void *fdt,
@@ -402,7 +547,7 @@ int fdt_get_path(const void *fdt, int nodeoffset, char *buf, int buflen)
 	int offset, depth, namelen;
 	const char *name;
 
-	FDT_CHECK_HEADER(fdt);
+	FDT_RO_PROBE(fdt);
 
 	if (buflen < 2)
 		return -FDT_ERR_NOSPACE;
@@ -454,7 +599,7 @@ int fdt_supernode_atdepth_offset(const void *fdt, int nodeoffset,
 	int offset, depth;
 	int supernodeoffset = -FDT_ERR_INTERNAL;
 
-	FDT_CHECK_HEADER(fdt);
+	FDT_RO_PROBE(fdt);
 
 	if (supernodedepth < 0)
 		return -FDT_ERR_NOTFOUND;
@@ -476,10 +621,12 @@ int fdt_supernode_atdepth_offset(const void *fdt, int nodeoffset,
 		}
 	}
 
-	if ((offset == -FDT_ERR_NOTFOUND) || (offset >= 0))
-		return -FDT_ERR_BADOFFSET;
-	else if (offset == -FDT_ERR_BADOFFSET)
-		return -FDT_ERR_BADSTRUCTURE;
+	if (fdt_chk_extra()) {
+		if ((offset == -FDT_ERR_NOTFOUND) || (offset >= 0))
+			return -FDT_ERR_BADOFFSET;
+		else if (offset == -FDT_ERR_BADOFFSET)
+			return -FDT_ERR_BADSTRUCTURE;
+	}
 
 	return offset; /* error from fdt_next_node() */
 }
@@ -491,7 +638,7 @@ int fdt_node_depth(const void *fdt, int nodeoffset)
 
 	err = fdt_supernode_atdepth_offset(fdt, nodeoffset, 0, &nodedepth);
 	if (err)
-		return (err < 0) ? err : -FDT_ERR_INTERNAL;
+		return (!fdt_chk_extra() || err < 0) ? err : -FDT_ERR_INTERNAL;
 	return nodedepth;
 }
 
@@ -513,7 +660,7 @@ int fdt_node_offset_by_prop_value(const void *fdt, int startoffset,
 	const void *val;
 	int len;
 
-	FDT_CHECK_HEADER(fdt);
+	FDT_RO_PROBE(fdt);
 
 	/* FIXME: The algorithm here is pretty horrible: we scan each
 	 * property of a node in fdt_getprop(), then if that didn't
@@ -539,7 +686,7 @@ int fdt_node_offset_by_phandle(const void *fdt, uint32_t phandle)
 	if ((phandle == 0) || (phandle == -1))
 		return -FDT_ERR_BADPHANDLE;
 
-	FDT_CHECK_HEADER(fdt);
+	FDT_RO_PROBE(fdt);
 
 	/* FIXME: The algorithm here is pretty horrible: we
 	 * potentially scan each property of a node in
@@ -692,7 +839,7 @@ int fdt_node_offset_by_compatible(const void *fdt, int startoffset,
 {
 	int offset, err;
 
-	FDT_CHECK_HEADER(fdt);
+	FDT_RO_PROBE(fdt);
 
 	/* FIXME: The algorithm here is pretty horrible: we scan each
 	 * property of a node in fdt_node_check_compatible(), then if
@@ -711,3 +858,68 @@ int fdt_node_offset_by_compatible(const void *fdt, int startoffset,
 
 	return offset; /* error from fdt_next_node() */
 }
+
+#if !defined(CHECK_LEVEL) || CHECK_LEVEL > 0
+int fdt_check_full(const void *fdt, size_t bufsize)
+{
+	int err;
+	int num_memrsv;
+	int offset, nextoffset = 0;
+	uint32_t tag;
+	unsigned depth = 0;
+	const void *prop;
+	const char *propname;
+
+	if (bufsize < FDT_V1_SIZE)
+		return -FDT_ERR_TRUNCATED;
+	err = fdt_check_header(fdt);
+	if (err != 0)
+		return err;
+	if (bufsize < fdt_totalsize(fdt))
+		return -FDT_ERR_TRUNCATED;
+
+	num_memrsv = fdt_num_mem_rsv(fdt);
+	if (num_memrsv < 0)
+		return num_memrsv;
+
+	while (1) {
+		offset = nextoffset;
+		tag = fdt_next_tag(fdt, offset, &nextoffset);
+
+		if (nextoffset < 0)
+			return nextoffset;
+
+		switch (tag) {
+		case FDT_NOP:
+			break;
+
+		case FDT_END:
+			if (depth != 0)
+				return -FDT_ERR_BADSTRUCTURE;
+			return 0;
+
+		case FDT_BEGIN_NODE:
+			depth++;
+			if (depth > INT_MAX)
+				return -FDT_ERR_BADSTRUCTURE;
+			break;
+
+		case FDT_END_NODE:
+			if (depth == 0)
+				return -FDT_ERR_BADSTRUCTURE;
+			depth--;
+			break;
+
+		case FDT_PROP:
+			prop = fdt_getprop_by_offset(fdt, offset, &propname,
+						     &err);
+			if (!prop)
+				return err;
+			break;
+
+		default:
+			return -FDT_ERR_INTERNAL;
+		}
+	}
+}
+#endif
diff --git a/scripts/dtc/libfdt/Makefile.libfdt b/scripts/dtc/libfdt/Makefile.libfdt
index 098b3f36e6..e54639738c 100644
--- a/scripts/dtc/libfdt/Makefile.libfdt
+++ b/scripts/dtc/libfdt/Makefile.libfdt
@@ -1,3 +1,4 @@
+# SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-2-Clause)
 # Makefile.libfdt
 #
 # This is not a complete Makefile of itself.  Instead, it is designed to
@@ -9,3 +10,9 @@ LIBFDT_VERSION = version.lds
 LIBFDT_SRCS = fdt.c fdt_ro.c fdt_wip.c fdt_sw.c fdt_rw.c fdt_strerror.c fdt_empty_tree.c \
 	fdt_addresses.c fdt_overlay.c
 LIBFDT_OBJS = $(LIBFDT_SRCS:%.c=%.o)
+LIBFDT_LIB = libfdt-$(DTC_VERSION).$(SHAREDLIB_EXT)
+
+libfdt_clean:
+	@$(VECHO) CLEAN "(libfdt)"
+	rm -f $(STD_CLEANFILES:%=$(LIBFDT_dir)/%)
+	rm -f $(LIBFDT_dir)/$(LIBFDT_soname)
diff --git a/scripts/dtc/libfdt/fdt.c b/scripts/dtc/libfdt/fdt.c
index 7855a17877..8e4cce3b9b 100644
--- a/scripts/dtc/libfdt/fdt.c
+++ b/scripts/dtc/libfdt/fdt.c
@@ -1,52 +1,7 @@
+// SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-2-Clause)
 /*
  * libfdt - Flat Device Tree manipulation
  * Copyright (C) 2006 David Gibson, IBM Corporation.
- *
- * libfdt is dual licensed: you can use it either under the terms of
- * the GPL, or the BSD license, at your option.
- *
- *  a) This library is free software; you can redistribute it and/or
- *     modify it under the terms of the GNU General Public License as
- *     published by the Free Software Foundation; either version 2 of the
- *     License, or (at your option) any later version.
- *
- *     This library is distributed in the hope that it will be useful,
- *     but WITHOUT ANY WARRANTY; without even the implied warranty of
- *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *     GNU General Public License for more details.
- *
- *     You should have received a copy of the GNU General Public
- *     License along with this library; if not, write to the Free
- *     Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
- *     MA 02110-1301 USA
- *
- * Alternatively,
- *
- *  b) Redistribution and use in source and binary forms, with or
- *     without modification, are permitted provided that the following
- *     conditions are met:
- *
- *     1. Redistributions of source code must retain the above
- *        copyright notice, this list of conditions and the following
- *        disclaimer.
- *     2. Redistributions in binary form must reproduce the above
- *        copyright notice, this list of conditions and the following
- *        disclaimer in the documentation and/or other materials
- *        provided with the distribution.
- *
- *     THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
- *     CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
- *     INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
- *     MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- *     DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
- *     CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- *     SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- *     NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- *     LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- *     HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- *     CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
- *     OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
- *     EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 #include "libfdt_env.h"
 
@@ -55,14 +10,24 @@
 
 #include "libfdt_internal.h"
 
-int fdt_check_header(const void *fdt)
+/*
+ * Minimal sanity check for a read-only tree. fdt_ro_probe_() checks
+ * that the given buffer contains what appears to be a flattened
+ * device tree with sane information in its header.
+ */
+int32_t fdt_ro_probe_(const void *fdt)
 {
+	uint32_t totalsize = fdt_totalsize(fdt);
+
 	if (fdt_magic(fdt) == FDT_MAGIC) {
 		/* Complete tree */
-		if (fdt_version(fdt) < FDT_FIRST_SUPPORTED_VERSION)
-			return -FDT_ERR_BADVERSION;
-		if (fdt_last_comp_version(fdt) > FDT_LAST_SUPPORTED_VERSION)
-			return -FDT_ERR_BADVERSION;
+		if (fdt_chk_version()) {
+			if (fdt_version(fdt) < FDT_FIRST_SUPPORTED_VERSION)
+				return -FDT_ERR_BADVERSION;
+			if (fdt_last_comp_version(fdt) >
+					FDT_LAST_SUPPORTED_VERSION)
+				return -FDT_ERR_BADVERSION;
+		}
 	} else if (fdt_magic(fdt) == FDT_SW_MAGIC) {
 		/* Unfinished sequential-write blob */
 		if (fdt_size_dt_struct(fdt) == 0)
@@ -71,6 +36,96 @@ int fdt_check_header(const void *fdt)
 		return -FDT_ERR_BADMAGIC;
 	}
 
+	if (totalsize < INT32_MAX)
+		return totalsize;
+	else
+		return -FDT_ERR_TRUNCATED;
+}
+
+static int check_off_(uint32_t hdrsize, uint32_t totalsize, uint32_t off)
+{
+	return (off >= hdrsize) && (off <= totalsize);
+}
+
+static int check_block_(uint32_t hdrsize, uint32_t totalsize,
+			uint32_t base, uint32_t size)
+{
+	if (!check_off_(hdrsize, totalsize, base))
+		return 0; /* block start out of bounds */
+	if ((base + size) < base)
+		return 0; /* overflow */
+	if (!check_off_(hdrsize, totalsize, base + size))
+		return 0; /* block end out of bounds */
+	return 1;
+}
+
+size_t fdt_header_size_(uint32_t version)
+{
+	if (version <= 1)
+		return FDT_V1_SIZE;
+	else if (version <= 2)
+		return FDT_V2_SIZE;
+	else if (version <= 3)
+		return FDT_V3_SIZE;
+	else if (version <= 16)
+		return FDT_V16_SIZE;
+	else
+		return FDT_V17_SIZE;
+}
+
+size_t fdt_header_size(const void *fdt)
+{
+	return fdt_chk_version() ? fdt_header_size_(fdt_version(fdt)) :
+		FDT_V17_SIZE;
+}
+
+int fdt_check_header(const void *fdt)
+{
+	size_t hdrsize;
+
+	if (fdt_magic(fdt) != FDT_MAGIC)
+		return -FDT_ERR_BADMAGIC;
+	if (fdt_chk_version()) {
+		if ((fdt_version(fdt) < FDT_FIRST_SUPPORTED_VERSION)
+		    || (fdt_last_comp_version(fdt) >
+			FDT_LAST_SUPPORTED_VERSION))
+			return -FDT_ERR_BADVERSION;
+		if (fdt_version(fdt) < fdt_last_comp_version(fdt))
+			return -FDT_ERR_BADVERSION;
+	}
+	hdrsize = fdt_header_size(fdt);
+	if (fdt_chk_basic()) {
+
+		if ((fdt_totalsize(fdt) < hdrsize)
+		    || (fdt_totalsize(fdt) > INT_MAX))
+			return -FDT_ERR_TRUNCATED;
+
+		/* Bounds check memrsv block */
+		if (!check_off_(hdrsize, fdt_totalsize(fdt),
+				fdt_off_mem_rsvmap(fdt)))
+			return -FDT_ERR_TRUNCATED;
+	}
+
+	if (fdt_chk_extra()) {
+		/* Bounds check structure block */
+		if (fdt_chk_version() && fdt_version(fdt) < 17) {
+			if (!check_off_(hdrsize, fdt_totalsize(fdt),
+					fdt_off_dt_struct(fdt)))
+				return -FDT_ERR_TRUNCATED;
+		} else {
+			if (!check_block_(hdrsize, fdt_totalsize(fdt),
+					  fdt_off_dt_struct(fdt),
+					  fdt_size_dt_struct(fdt)))
+				return -FDT_ERR_TRUNCATED;
+		}
+
+		/* Bounds check strings block */
+		if (!check_block_(hdrsize, fdt_totalsize(fdt),
+				  fdt_off_dt_strings(fdt),
+				  fdt_size_dt_strings(fdt)))
+			return -FDT_ERR_TRUNCATED;
+	}
+
 	return 0;
 }
 
@@ -78,12 +133,13 @@ const void *fdt_offset_ptr(const void *fdt, int offset, unsigned int len)
 {
 	unsigned absoffset = offset + fdt_off_dt_struct(fdt);
 
-	if ((absoffset < offset)
-	    || ((absoffset + len) < absoffset)
-	    || (absoffset + len) > fdt_totalsize(fdt))
-		return NULL;
+	if (fdt_chk_basic())
+		if ((absoffset < offset)
+		    || ((absoffset + len) < absoffset)
+		    || (absoffset + len) > fdt_totalsize(fdt))
+			return NULL;
 
-	if (fdt_version(fdt) >= 0x11)
+	if (!fdt_chk_version() || fdt_version(fdt) >= 0x11)
 		if (((offset + len) < offset)
 		    || ((offset + len) > fdt_size_dt_struct(fdt)))
 			return NULL;
@@ -100,7 +156,7 @@ uint32_t fdt_next_tag(const void *fdt, int startoffset, int *nextoffset)
 
 	*nextoffset = -FDT_ERR_TRUNCATED;
 	tagp = fdt_offset_ptr(fdt, offset, FDT_TAGSIZE);
-	if (!tagp)
+	if (fdt_chk_basic() && !tagp)
 		return FDT_END; /* premature end */
 	tag = fdt32_to_cpu(*tagp);
 	offset += FDT_TAGSIZE;
@@ -112,18 +168,19 @@ uint32_t fdt_next_tag(const void *fdt, int startoffset, int *nextoffset)
 		do {
 			p = fdt_offset_ptr(fdt, offset++, 1);
 		} while (p && (*p != '\0'));
-		if (!p)
+		if (fdt_chk_basic() && !p)
 			return FDT_END; /* premature end */
 		break;
 
 	case FDT_PROP:
 		lenp = fdt_offset_ptr(fdt, offset, sizeof(*lenp));
-		if (!lenp)
+		if (fdt_chk_basic() && !lenp)
 			return FDT_END; /* premature end */
 		/* skip-name offset, length and value */
 		offset += sizeof(struct fdt_property) - FDT_TAGSIZE
 			+ fdt32_to_cpu(*lenp);
-		if (fdt_version(fdt) < 0x10 && fdt32_to_cpu(*lenp) >= 8 &&
+		if (fdt_chk_version() &&
+		    fdt_version(fdt) < 0x10 && fdt32_to_cpu(*lenp) >= 8 &&
 		    ((offset - fdt32_to_cpu(*lenp)) % 8) != 0)
 			offset += 4;
 		break;
@@ -137,7 +194,8 @@ uint32_t fdt_next_tag(const void *fdt, int startoffset, int *nextoffset)
 		return FDT_END;
 	}
 
-	if (!fdt_offset_ptr(fdt, startoffset, offset - startoffset))
+	if (fdt_chk_basic() &&
+	    !fdt_offset_ptr(fdt, startoffset, offset - startoffset))
 		return FDT_END; /* premature end */
 
 	*nextoffset = FDT_TAGALIGN(offset);
@@ -244,7 +302,7 @@ const char *fdt_find_string_(const char *strtab, int tabsize, const char *s)
 
 int fdt_move(const void *fdt, void *buf, int bufsize)
 {
-	FDT_CHECK_HEADER(fdt);
+	FDT_RO_PROBE(fdt);
 
 	if (fdt_totalsize(fdt) > bufsize)
 		return -FDT_ERR_NOSPACE;
diff --git a/scripts/dtc/libfdt/fdt.h b/scripts/dtc/libfdt/fdt.h
index 74961f9026..f2e68807f2 100644
--- a/scripts/dtc/libfdt/fdt.h
+++ b/scripts/dtc/libfdt/fdt.h
@@ -1,55 +1,10 @@
+/* SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-2-Clause) */
 #ifndef FDT_H
 #define FDT_H
 /*
  * libfdt - Flat Device Tree manipulation
  * Copyright (C) 2006 David Gibson, IBM Corporation.
  * Copyright 2012 Kim Phillips, Freescale Semiconductor.
- *
- * libfdt is dual licensed: you can use it either under the terms of
- * the GPL, or the BSD license, at your option.
- *
- *  a) This library is free software; you can redistribute it and/or
- *     modify it under the terms of the GNU General Public License as
- *     published by the Free Software Foundation; either version 2 of the
- *     License, or (at your option) any later version.
- *
- *     This library is distributed in the hope that it will be useful,
- *     but WITHOUT ANY WARRANTY; without even the implied warranty of
- *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *     GNU General Public License for more details.
- *
- *     You should have received a copy of the GNU General Public
- *     License along with this library; if not, write to the Free
- *     Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
- *     MA 02110-1301 USA
- *
- * Alternatively,
- *
- *  b) Redistribution and use in source and binary forms, with or
- *     without modification, are permitted provided that the following
- *     conditions are met:
- *
- *     1. Redistributions of source code must retain the above
- *        copyright notice, this list of conditions and the following
- *        disclaimer.
- *     2. Redistributions in binary form must reproduce the above
- *        copyright notice, this list of conditions and the following
- *        disclaimer in the documentation and/or other materials
- *        provided with the distribution.
- *
- *     THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
- *     CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
- *     INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
- *     MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- *     DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
- *     CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- *     SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- *     NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- *     LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- *     HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- *     CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
- *     OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
- *     EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
 #ifndef __ASSEMBLY__
diff --git a/scripts/dtc/libfdt/fdt_addresses.c b/scripts/dtc/libfdt/fdt_addresses.c
index 788c143113..9a82cd0ba2 100644
--- a/scripts/dtc/libfdt/fdt_addresses.c
+++ b/scripts/dtc/libfdt/fdt_addresses.c
@@ -1,53 +1,8 @@
+// SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-2-Clause)
 /*
  * libfdt - Flat Device Tree manipulation
  * Copyright (C) 2014 David Gibson <david@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,@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@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

^ permalink raw reply related	[flat|nested] 18+ messages in thread

* [U-Boot] [PATCH 2/4] fdt: Add Kconfig options to control code size
  2019-10-27 15:47 ` [U-Boot] [PATCH 2/4] fdt: Add Kconfig options to control code size Simon Glass
@ 2019-10-27 18:06   ` Heinrich Schuchardt
  2019-10-27 18:49     ` Simon Glass
  2019-10-30 17:02   ` Tom Rini
  2019-11-05 12:06   ` sjg at google.com
  2 siblings, 1 reply; 18+ messages in thread
From: Heinrich Schuchardt @ 2019-10-27 18:06 UTC (permalink / raw)
  To: u-boot

On 10/27/19 4:47 PM, Simon Glass wrote:
> For better or worse libfdt recent grew a lot of code that checks the
> validity of the device tree in great detail. When using unsigned or
> unverified data this makes things safer, but it does add to code size.
>
> Add some controls to select the trade-off between safety and code size.
>
> Signed-off-by: Simon Glass <sjg@chromium.org>
> ---
>
>   lib/Kconfig         | 33 +++++++++++++++++++++++++++++++++
>   lib/libfdt/Makefile |  3 ++-
>   2 files changed, 35 insertions(+), 1 deletion(-)
>
> diff --git a/lib/Kconfig b/lib/Kconfig
> index 135f0b372b..b8a8509d72 100644
> --- a/lib/Kconfig
> +++ b/lib/Kconfig
> @@ -464,6 +464,17 @@ config OF_LIBFDT
>   	  particular compatible nodes. The library operates on a flattened
>   	  version of the device tree.
>
> +config OF_LIBFDT_ASSUME_MASK
> +	hex "Mask of conditions to assume for libfdt"
> +	depends on OF_LIBFDT || FIT
> +	default 0
> +	help
> +	  Use this to change the assumptions made by libfdt about the
> +	  device tree it is working with. A value of 0 means that no assumptions
> +	  are made, and libfdt is able to deal with malicious data. A value of

What do you mean by malicious here?

The checks in libfdt are about inconsistent FDT files. But they would
not discover malicious settings like a destructive voltage or frequency.

Would FDT_ASSUME_SANE match what we have been checking up to now? Why
not use 1 as the default here to reduce the code size of U-Boot?

> +	  0xff means all assumptions are made and any invalid data may cause
> +	  unsafe execution. See FDT_ASSUME_PERFECT, etc. in libfdt_internal.h
> +
>   config OF_LIBFDT_OVERLAY
>   	bool "Enable the FDT library overlay support"
>   	depends on OF_LIBFDT
> @@ -481,6 +492,17 @@ config SPL_OF_LIBFDT
>   	  particular compatible nodes. The library operates on a flattened
>   	  version of the device tree.
>
> +config SPL_OF_LIBFDT_ASSUME_MASK
> +	hex "Mask of conditions to assume for libfdt"
> +	depends on SPL_OF_LIBFDT || FIT
> +	default 0xff

On some devices the device tree is provided by the device (e.g. QEMU).
Is it wise to set FDT_ASSUME_LATEST in this case?

Best regards

Heinrich

> +	help
> +	  Use this to change the assumptions made by libfdt in SPL about the
> +	  device tree it is working with. A value of 0 means that no assumptions
> +	  are made, and libfdt is able to deal with malicious data. A value of
> +	  0xff means all assumptions are made and any invalid data may cause
> +	  unsafe execution. See FDT_ASSUME_PERFECT, etc. in libfdt_internal.h
> +
>   config TPL_OF_LIBFDT
>   	bool "Enable the FDT library for TPL"
>   	default y if TPL_OF_CONTROL
> @@ -491,6 +513,17 @@ config TPL_OF_LIBFDT
>   	  particular compatible nodes. The library operates on a flattened
>   	  version of the device tree.
>
> +config TPL_OF_LIBFDT_ASSUME_MASK
> +	hex "Mask of conditions to assume for libfdt"
> +	depends on TPL_OF_LIBFDT || FIT
> +	default 0xff
> +	help
> +	  Use this to change the assumptions made by libfdt in TPL about the
> +	  device tree it is working with. A value of 0 means that no assumptions
> +	  are made, and libfdt is able to deal with malicious data. A value of
> +	  0xff means all assumptions are made and any invalid data may cause
> +	  unsafe execution. See FDT_ASSUME_PERFECT, etc. in libfdt_internal.h
> +
>   config FDT_FIXUP_PARTITIONS
>   	bool "overwrite MTD partitions in DTS through defined in 'mtdparts'"
>   	depends on OF_LIBFDT
> diff --git a/lib/libfdt/Makefile b/lib/libfdt/Makefile
> index ef5b6e29d4..5d3ae4e2f1 100644
> --- a/lib/libfdt/Makefile
> +++ b/lib/libfdt/Makefile
> @@ -22,4 +22,5 @@ obj-y += fdt_ro.o
>   # U-Boot own file
>   obj-y += fdt_region.o
>
> -ccflags-y := -I$(srctree)/scripts/dtc/libfdt
> +ccflags-y := -I$(srctree)/scripts/dtc/libfdt \
> +	-DFDT_ASSUME_MASK=$(CONFIG_$(SPL_TPL_)OF_LIBFDT_ASSUME_MASK)
>

^ permalink raw reply	[flat|nested] 18+ messages in thread

* [U-Boot] [PATCH 2/4] fdt: Add Kconfig options to control code size
  2019-10-27 18:06   ` Heinrich Schuchardt
@ 2019-10-27 18:49     ` Simon Glass
  2019-10-28 14:01       ` Tom Rini
  0 siblings, 1 reply; 18+ messages in thread
From: Simon Glass @ 2019-10-27 18:49 UTC (permalink / raw)
  To: u-boot

Hi Heinrich,

On Sun, 27 Oct 2019 at 12:06, Heinrich Schuchardt <xypron.glpk@gmx.de> wrote:
>
> On 10/27/19 4:47 PM, Simon Glass wrote:
> > For better or worse libfdt recent grew a lot of code that checks the
> > validity of the device tree in great detail. When using unsigned or
> > unverified data this makes things safer, but it does add to code size.
> >
> > Add some controls to select the trade-off between safety and code size.
> >
> > Signed-off-by: Simon Glass <sjg@chromium.org>
> > ---
> >
> >   lib/Kconfig         | 33 +++++++++++++++++++++++++++++++++
> >   lib/libfdt/Makefile |  3 ++-
> >   2 files changed, 35 insertions(+), 1 deletion(-)
> >
> > diff --git a/lib/Kconfig b/lib/Kconfig
> > index 135f0b372b..b8a8509d72 100644
> > --- a/lib/Kconfig
> > +++ b/lib/Kconfig
> > @@ -464,6 +464,17 @@ config OF_LIBFDT
> >         particular compatible nodes. The library operates on a flattened
> >         version of the device tree.
> >
> > +config OF_LIBFDT_ASSUME_MASK
> > +     hex "Mask of conditions to assume for libfdt"
> > +     depends on OF_LIBFDT || FIT
> > +     default 0
> > +     help
> > +       Use this to change the assumptions made by libfdt about the
> > +       device tree it is working with. A value of 0 means that no assumptions
> > +       are made, and libfdt is able to deal with malicious data. A value of
>
> What do you mean by malicious here?

Someone trying to compromise the system with a carefully crafted DT.

>
> The checks in libfdt are about inconsistent FDT files. But they would
> not discover malicious settings like a destructive voltage or frequency.

That's right. To cover that people should probably use verified boot.

>
> Would FDT_ASSUME_SANE match what we have been checking up to now? Why
> not use 1 as the default here to reduce the code size of U-Boot?

Possibly. I'm open to changing this as the code size increase is a paind.

But most of the new checking code could be dropped by enabling
FDT_ASSUME_FRIENDLY. Take a look at that and see what you think.

>
> > +       0xff means all assumptions are made and any invalid data may cause
> > +       unsafe execution. See FDT_ASSUME_PERFECT, etc. in libfdt_internal.h
> > +
> >   config OF_LIBFDT_OVERLAY
> >       bool "Enable the FDT library overlay support"
> >       depends on OF_LIBFDT
> > @@ -481,6 +492,17 @@ config SPL_OF_LIBFDT
> >         particular compatible nodes. The library operates on a flattened
> >         version of the device tree.
> >
> > +config SPL_OF_LIBFDT_ASSUME_MASK
> > +     hex "Mask of conditions to assume for libfdt"
> > +     depends on SPL_OF_LIBFDT || FIT
> > +     default 0xff
>
> On some devices the device tree is provided by the device (e.g. QEMU).
> Is it wise to set FDT_ASSUME_LATEST in this case?

Well I think we have been on the current version for about 13 years,
so probably.

Regards,
Simon
[..]

^ permalink raw reply	[flat|nested] 18+ messages in thread

* [U-Boot] [PATCH 2/4] fdt: Add Kconfig options to control code size
  2019-10-27 18:49     ` Simon Glass
@ 2019-10-28 14:01       ` Tom Rini
  0 siblings, 0 replies; 18+ messages in thread
From: Tom Rini @ 2019-10-28 14:01 UTC (permalink / raw)
  To: u-boot

On Sun, Oct 27, 2019 at 12:49:28PM -0600, Simon Glass wrote:
> Hi Heinrich,
> 
> On Sun, 27 Oct 2019 at 12:06, Heinrich Schuchardt <xypron.glpk@gmx.de> wrote:
> >
> > On 10/27/19 4:47 PM, Simon Glass wrote:
> > > For better or worse libfdt recent grew a lot of code that checks the
> > > validity of the device tree in great detail. When using unsigned or
> > > unverified data this makes things safer, but it does add to code size.
> > >
> > > Add some controls to select the trade-off between safety and code size.
> > >
> > > Signed-off-by: Simon Glass <sjg@chromium.org>
> > > ---
> > >
> > >   lib/Kconfig         | 33 +++++++++++++++++++++++++++++++++
> > >   lib/libfdt/Makefile |  3 ++-
> > >   2 files changed, 35 insertions(+), 1 deletion(-)
> > >
> > > diff --git a/lib/Kconfig b/lib/Kconfig
> > > index 135f0b372b..b8a8509d72 100644
> > > --- a/lib/Kconfig
> > > +++ b/lib/Kconfig
> > > @@ -464,6 +464,17 @@ config OF_LIBFDT
> > >         particular compatible nodes. The library operates on a flattened
> > >         version of the device tree.
> > >
> > > +config OF_LIBFDT_ASSUME_MASK
> > > +     hex "Mask of conditions to assume for libfdt"
> > > +     depends on OF_LIBFDT || FIT
> > > +     default 0
> > > +     help
> > > +       Use this to change the assumptions made by libfdt about the
> > > +       device tree it is working with. A value of 0 means that no assumptions
> > > +       are made, and libfdt is able to deal with malicious data. A value of
> >
> > What do you mean by malicious here?
> 
> Someone trying to compromise the system with a carefully crafted DT.
> 
> >
> > The checks in libfdt are about inconsistent FDT files. But they would
> > not discover malicious settings like a destructive voltage or frequency.
> 
> That's right. To cover that people should probably use verified boot.

Right, so the help text can be clarified a little bit more to be clear
that it's checking for various types of formatting and construction
problems with that data only.

> > Would FDT_ASSUME_SANE match what we have been checking up to now? Why
> > not use 1 as the default here to reduce the code size of U-Boot?
> 
> Possibly. I'm open to changing this as the code size increase is a paind.
> 
> But most of the new checking code could be dropped by enabling
> FDT_ASSUME_FRIENDLY. Take a look at that and see what you think.

We also need to be careful as the defaults we push here are the defaults
that will be used when companies build their product on top.  I'm in
favor of the default being as much sanity checking as we an afford and
to note and allow for instances where other safeguards exist, or more
risk is tolerated to save some size.

-- 
Tom
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 833 bytes
Desc: not available
URL: <http://lists.denx.de/pipermail/u-boot/attachments/20191028/673801ae/attachment.sig>

^ permalink raw reply	[flat|nested] 18+ messages in thread

* [U-Boot] [PATCH 0/4] fdt: Switch to the latest libfdt, sort-of
  2019-10-27 15:47 [U-Boot] [PATCH 0/4] fdt: Switch to the latest libfdt, sort-of Simon Glass
                   ` (3 preceding siblings ...)
  2019-10-27 15:47 ` [U-Boot] [PATCH 4/4] fdt: Sync up to the latest libfdt Simon Glass
@ 2019-10-28 14:04 ` Tom Rini
  2019-10-29  3:37   ` Simon Glass
  2019-11-05 12:06 ` [U-Boot] [PATCH 4/4] fdt: Sync up to the latest libfdt sjg at google.com
  2019-11-05 12:06 ` [U-Boot] [PATCH 3/4] mx6: tbs2910: Minimise libfdt code size sjg at google.com
  6 siblings, 1 reply; 18+ messages in thread
From: Tom Rini @ 2019-10-28 14:04 UTC (permalink / raw)
  To: u-boot

On Sun, Oct 27, 2019 at 09:47:38AM -0600, Simon Glass wrote:

> This series brings over the latest libfdt with some changes to deal with
> the recent code-size bloat.
> 
> With this change U-Boot size increases about 2.5KB on 'rock' and SPL
> reduces by about 128 bytes. This should be acceptable.
> 
> The 'assumptions' series is still under review, so we can sync that up
> later when complete.

Does this address the problem you have when moving binman to python3 as
well?  Thanks!

-- 
Tom
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 833 bytes
Desc: not available
URL: <http://lists.denx.de/pipermail/u-boot/attachments/20191028/3fb48c7c/attachment.sig>

^ permalink raw reply	[flat|nested] 18+ messages in thread

* [U-Boot] [PATCH 0/4] fdt: Switch to the latest libfdt, sort-of
  2019-10-28 14:04 ` [U-Boot] [PATCH 0/4] fdt: Switch to the latest libfdt, sort-of Tom Rini
@ 2019-10-29  3:37   ` Simon Glass
  0 siblings, 0 replies; 18+ messages in thread
From: Simon Glass @ 2019-10-29  3:37 UTC (permalink / raw)
  To: u-boot

Hi Tom,

On Mon, 28 Oct 2019 at 08:04, Tom Rini <trini@konsulko.com> wrote:
>
> On Sun, Oct 27, 2019 at 09:47:38AM -0600, Simon Glass wrote:
>
> > This series brings over the latest libfdt with some changes to deal with
> > the recent code-size bloat.
> >
> > With this change U-Boot size increases about 2.5KB on 'rock' and SPL
> > reduces by about 128 bytes. This should be acceptable.
> >
> > The 'assumptions' series is still under review, so we can sync that up
> > later when complete.
>
> Does this address the problem you have when moving binman to python3 as
> well?  Thanks!

Yes it does, I figured that out.

Regards,
Simon

^ permalink raw reply	[flat|nested] 18+ messages in thread

* [U-Boot] [PATCH 1/4] fdt: Add INT32_MAX to kernel.h for libfdt
  2019-10-27 15:47 ` [U-Boot] [PATCH 1/4] fdt: Add INT32_MAX to kernel.h for libfdt Simon Glass
@ 2019-10-30 17:01   ` Tom Rini
  2019-11-05 12:06   ` sjg at google.com
  1 sibling, 0 replies; 18+ messages in thread
From: Tom Rini @ 2019-10-30 17:01 UTC (permalink / raw)
  To: u-boot

On Sun, Oct 27, 2019 at 09:47:39AM -0600, Simon Glass wrote:

> Unfortunately libfdt needs this value now, which is present in the
> stdint.h header. That file is just a placeholder in U-Boot and these sorts
> of constants appear in the linux/kernel.h header instead.
> 
> To keep libfdt happy, add INT32_MAX too.
> 
> Signed-off-by: Simon Glass <sjg@chromium.org>

Reviewed-by: Tom Rini <trini@konsulko.com>

-- 
Tom
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 833 bytes
Desc: not available
URL: <http://lists.denx.de/pipermail/u-boot/attachments/20191030/38f83d72/attachment.sig>

^ permalink raw reply	[flat|nested] 18+ messages in thread

* [U-Boot] [PATCH 2/4] fdt: Add Kconfig options to control code size
  2019-10-27 15:47 ` [U-Boot] [PATCH 2/4] fdt: Add Kconfig options to control code size Simon Glass
  2019-10-27 18:06   ` Heinrich Schuchardt
@ 2019-10-30 17:02   ` Tom Rini
  2019-11-05 12:06   ` sjg at google.com
  2 siblings, 0 replies; 18+ messages in thread
From: Tom Rini @ 2019-10-30 17:02 UTC (permalink / raw)
  To: u-boot

On Sun, Oct 27, 2019 at 09:47:40AM -0600, Simon Glass wrote:

> For better or worse libfdt recent grew a lot of code that checks the
> validity of the device tree in great detail. When using unsigned or
> unverified data this makes things safer, but it does add to code size.
> 
> Add some controls to select the trade-off between safety and code size.
> 
> Signed-off-by: Simon Glass <sjg@chromium.org>

Reviewed-by: Tom Rini <trini@konsulko.com>

-- 
Tom
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 833 bytes
Desc: not available
URL: <http://lists.denx.de/pipermail/u-boot/attachments/20191030/2e7775f5/attachment.sig>

^ permalink raw reply	[flat|nested] 18+ messages in thread

* [U-Boot] [PATCH 4/4] fdt: Sync up to the latest libfdt
  2019-10-27 15:47 [U-Boot] [PATCH 0/4] fdt: Switch to the latest libfdt, sort-of Simon Glass
                   ` (4 preceding siblings ...)
  2019-10-28 14:04 ` [U-Boot] [PATCH 0/4] fdt: Switch to the latest libfdt, sort-of Tom Rini
@ 2019-11-05 12:06 ` sjg at google.com
  2019-11-05 12:06 ` [U-Boot] [PATCH 3/4] mx6: tbs2910: Minimise libfdt code size sjg at google.com
  6 siblings, 0 replies; 18+ messages in thread
From: sjg at google.com @ 2019-11-05 12:06 UTC (permalink / raw)
  To: u-boot

Bring over the fdt from this commit:

430419c (origin/master) tests: fix some python warnings

adding in the 'assumptions' series designed to reduce code size.

Signed-off-by: Simon Glass <sjg@chromium.org>
---

 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(-)

Applied to u-boot-fdt

^ permalink raw reply	[flat|nested] 18+ messages in thread

* [U-Boot] [PATCH 3/4] mx6: tbs2910: Minimise libfdt code size
  2019-10-27 15:47 [U-Boot] [PATCH 0/4] fdt: Switch to the latest libfdt, sort-of Simon Glass
                   ` (5 preceding siblings ...)
  2019-11-05 12:06 ` [U-Boot] [PATCH 4/4] fdt: Sync up to the latest libfdt sjg at google.com
@ 2019-11-05 12:06 ` sjg at google.com
  6 siblings, 0 replies; 18+ messages in thread
From: sjg at google.com @ 2019-11-05 12:06 UTC (permalink / raw)
  To: u-boot

This board appears to be very near its size limit and cannot accept the
new checking code in libfdt. Disable this code so this the board can
continue to build.

Signed-off-by: Simon Glass <sjg@chromium.org>
---

 configs/tbs2910_defconfig | 1 +
 1 file changed, 1 insertion(+)

Applied to u-boot-fdt

^ permalink raw reply	[flat|nested] 18+ messages in thread

* [U-Boot] [PATCH 2/4] fdt: Add Kconfig options to control code size
  2019-10-27 15:47 ` [U-Boot] [PATCH 2/4] fdt: Add Kconfig options to control code size Simon Glass
  2019-10-27 18:06   ` Heinrich Schuchardt
  2019-10-30 17:02   ` Tom Rini
@ 2019-11-05 12:06   ` sjg at google.com
  2 siblings, 0 replies; 18+ messages in thread
From: sjg at google.com @ 2019-11-05 12:06 UTC (permalink / raw)
  To: u-boot

On Sun, Oct 27, 2019 at 09:47:40AM -0600, Simon Glass wrote:

> For better or worse libfdt recent grew a lot of code that checks the
> validity of the device tree in great detail. When using unsigned or
> unverified data this makes things safer, but it does add to code size.
>
> Add some controls to select the trade-off between safety and code size.
>
> Signed-off-by: Simon Glass <sjg@chromium.org>

Reviewed-by: Tom Rini <trini@konsulko.com>

-- 
Tom

Applied to u-boot-fdt

^ permalink raw reply	[flat|nested] 18+ messages in thread

* [U-Boot] [PATCH 1/4] fdt: Add INT32_MAX to kernel.h for libfdt
  2019-10-27 15:47 ` [U-Boot] [PATCH 1/4] fdt: Add INT32_MAX to kernel.h for libfdt Simon Glass
  2019-10-30 17:01   ` Tom Rini
@ 2019-11-05 12:06   ` sjg at google.com
  1 sibling, 0 replies; 18+ messages in thread
From: sjg at google.com @ 2019-11-05 12:06 UTC (permalink / raw)
  To: u-boot

On Sun, Oct 27, 2019 at 09:47:39AM -0600, Simon Glass wrote:

> Unfortunately libfdt needs this value now, which is present in the
> stdint.h header. That file is just a placeholder in U-Boot and these sorts
> of constants appear in the linux/kernel.h header instead.
>
> To keep libfdt happy, add INT32_MAX too.
>
> Signed-off-by: Simon Glass <sjg@chromium.org>

Reviewed-by: Tom Rini <trini@konsulko.com>

-- 
Tom

Applied to u-boot-fdt

^ permalink raw reply	[flat|nested] 18+ messages in thread

* [U-Boot] [PATCH 4/4] fdt: Sync up to the latest libfdt
  2019-10-27 15:47 ` [U-Boot] [PATCH 4/4] fdt: Sync up to the latest libfdt Simon Glass
@ 2020-01-07 11:43   ` Adam Ford
  2020-01-08 13:56     ` Adam Ford
  0 siblings, 1 reply; 18+ messages in thread
From: Adam Ford @ 2020-01-07 11:43 UTC (permalink / raw)
  To: u-boot

On Sun, Oct 27, 2019 at 10:55 AM Simon Glass <sjg@chromium.org> wrote:
>
> Bring over the fdt from this commit:
>
> 430419c (origin/master) tests: fix some python warnings
>
> adding in the 'assumptions' series designed to reduce code size.
>
> Signed-off-by: Simon Glass <sjg@chromium.org>

I don't know how, but this patch broke the am3517_evm board.  I
haven't had a chance to review other omap3 boards I have yet.

With this patch:

U-Boot SPL 2020.01-rc1-00163-gf0921f5098 (Jan 07 2020 - 05:31:57 -0600)
Trying to boot from MMC1
spl_register_fat_device: fat register err - -1
spl_register_fat_device: fat register err - -1
spl_load_image_fat: error reading image u-boot.img, err - -1
SPL: failed to boot from all boot devices


If I revert this patch on master, the am3517_evm boots just fine.  I'm
open to trying stuff if you have ideas.

adam

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

^ permalink raw reply	[flat|nested] 18+ messages in thread

* [U-Boot] [PATCH 4/4] fdt: Sync up to the latest libfdt
  2020-01-07 11:43   ` Adam Ford
@ 2020-01-08 13:56     ` Adam Ford
  0 siblings, 0 replies; 18+ messages in thread
From: Adam Ford @ 2020-01-08 13:56 UTC (permalink / raw)
  To: u-boot

On Tue, Jan 7, 2020 at 5:43 AM Adam Ford <aford173@gmail.com> wrote:
>
> On Sun, Oct 27, 2019 at 10:55 AM Simon Glass <sjg@chromium.org> wrote:
> >
> > Bring over the fdt from this commit:
> >
> > 430419c (origin/master) tests: fix some python warnings
> >
> > adding in the 'assumptions' series designed to reduce code size.
> >
> > Signed-off-by: Simon Glass <sjg@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 <david@gibson.dropbear.id.au>
> >   * Copyright (C) 2018 embedded brains GmbH
> > - *
> > - * libfdt is dual licensed: you can use it either under the terms of
> > - * the GPL, or the BSD license, at your option.
> > - *
> > - *  a) This library is free software; you can redistribute it and/or
> > - *     modify it under the terms of the GNU General Public License as
> > - *     published by the Free Software Foundation; either version 2 of the
> > - *     License, or (at your option) any later version.
> > - *
> > - *     This library is distributed in the hope that it will be useful,
> > - *     but WITHOUT ANY WARRANTY; without even the implied warranty of
> > - *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> > - *     GNU General Public License for more details.
> > - *
> > - *     You should have received a copy of the GNU General Public
> > - *     License along with this library; if not, write to the Free
> > - *     Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
> > - *     MA 02110-1301 USA
> > - *
> > - * Alternatively,
> > - *
> > - *  b) Redistribution and use in source and binary forms, with or
> > - *     without modification, are permitted provided that the following
> > - *     conditions are met:
> > - *
> > - *     1. Redistributions of source code must retain the above
> > - *        copyright notice, this list of conditions and the following
> > - *        disclaimer.
> > - *     2. Redistributions in binary form must reproduce the above
> > - *        copyright notice, this list of conditions and the following
> > - *        disclaimer in the documentation and/or other materials
> > - *        provided with the distribution.
> > - *
> > - *     THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
> > - *     CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
> > - *     INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
> > - *     MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
> > - *     DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
> > - *     CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
> > - *     SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
> > - *     NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
> > - *     LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
> > - *     HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
> > - *     CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
> > - *     OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
> > - *     EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
> >   */
> >  #include "libfdt_env.h"
> >
> > @@ -97,3 +52,50 @@ int fdt_size_cells(const void *fdt, int nodeoffset)
> >                 return 1;
> >         return val;
> >  }
> > +
> > +/* This function assumes that [address|size]_cells is 1 or 2 */
> > +int fdt_appendprop_addrrange(void *fdt, int parent, int nodeoffset,
> > +                            const char *name, uint64_t addr, uint64_t size)
> > +{
> > +       int addr_cells, size_cells, ret;
> > +       uint8_t data[sizeof(fdt64_t) * 2], *prop;
> > +
> > +       ret = fdt_address_cells(fdt, parent);
> > +       if (ret < 0)
> > +               return ret;
> > +       addr_cells = ret;
> > +
> > +       ret = fdt_size_cells(fdt, parent);
> > +       if (ret < 0)
> > +               return ret;
> > +       size_cells = ret;
> > +
> > +       /* check validity of address */
> > +       prop = data;
> > +       if (addr_cells == 1) {
> > +               if ((addr > UINT32_MAX) || ((UINT32_MAX + 1 - addr) < size))
> > +                       return -FDT_ERR_BADVALUE;
> > +
> > +               fdt32_st(prop, (uint32_t)addr);
> > +       } else if (addr_cells == 2) {
> > +               fdt64_st(prop, addr);
> > +       } else {
> > +               return -FDT_ERR_BADNCELLS;
> > +       }
> > +
> > +       /* check validity of size */
> > +       prop += addr_cells * sizeof(fdt32_t);
> > +       if (size_cells == 1) {
> > +               if (size > UINT32_MAX)
> > +                       return -FDT_ERR_BADVALUE;
> > +
> > +               fdt32_st(prop, (uint32_t)size);
> > +       } else if (size_cells == 2) {
> > +               fdt64_st(prop, size);
> > +       } else {
> > +               return -FDT_ERR_BADNCELLS;
> > +       }
> > +
> > +       return fdt_appendprop(fdt, nodeoffset, name, data,
> > +                             (addr_cells + size_cells) * sizeof(fdt32_t));
> > +}
> > diff --git a/scripts/dtc/libfdt/fdt_empty_tree.c b/scripts/dtc/libfdt/fdt_empty_tree.c
> > index f2ae9b77c2..49d54d44b8 100644
> > --- a/scripts/dtc/libfdt/fdt_empty_tree.c
> > +++ b/scripts/dtc/libfdt/fdt_empty_tree.c
> > @@ -1,52 +1,7 @@
> > +// SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-2-Clause)
> >  /*
> >   * libfdt - Flat Device Tree manipulation
> >   * Copyright (C) 2012 David Gibson, IBM Corporation.
> > - *
> > - * libfdt is dual licensed: you can use it either under the terms of
> > - * the GPL, or the BSD license, at your option.
> > - *
> > - *  a) This library is free software; you can redistribute it and/or
> > - *     modify it under the terms of the GNU General Public License as
> > - *     published by the Free Software Foundation; either version 2 of the
> > - *     License, or (at your option) any later version.
> > - *
> > - *     This library is distributed in the hope that it will be useful,
> > - *     but WITHOUT ANY WARRANTY; without even the implied warranty of
> > - *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> > - *     GNU General Public License for more details.
> > - *
> > - *     You should have received a copy of the GNU General Public
> > - *     License along with this library; if not, write to the Free
> > - *     Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
> > - *     MA 02110-1301 USA
> > - *
> > - * Alternatively,
> > - *
> > - *  b) Redistribution and use in source and binary forms, with or
> > - *     without modification, are permitted provided that the following
> > - *     conditions are met:
> > - *
> > - *     1. Redistributions of source code must retain the above
> > - *        copyright notice, this list of conditions and the following
> > - *        disclaimer.
> > - *     2. Redistributions in binary form must reproduce the above
> > - *        copyright notice, this list of conditions and the following
> > - *        disclaimer in the documentation and/or other materials
> > - *        provided with the distribution.
> > - *
> > - *     THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
> > - *     CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
> > - *     INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
> > - *     MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
> > - *     DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
> > - *     CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
> > - *     SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
> > - *     NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
> > - *     LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
> > - *     HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
> > - *     CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
> > - *     OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
> > - *     EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
> >   */
> >  #include "libfdt_env.h"
> >
> > diff --git a/scripts/dtc/libfdt/fdt_overlay.c b/scripts/dtc/libfdt/fdt_overlay.c
> > index bf75388ec9..be71873366 100644
> > --- a/scripts/dtc/libfdt/fdt_overlay.c
> > +++ b/scripts/dtc/libfdt/fdt_overlay.c
> > @@ -1,53 +1,8 @@
> > +// SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-2-Clause)
> >  /*
> >   * libfdt - Flat Device Tree manipulation
> >   * Copyright (C) 2016 Free Electrons
> >   * Copyright (C) 2016 NextThing Co.
> > - *
> > - * libfdt is dual licensed: you can use it either under the terms of
> > - * the GPL, or the BSD license, at your option.
> > - *
> > - *  a) This library is free software; you can redistribute it and/or
> > - *     modify it under the terms of the GNU General Public License as
> > - *     published by the Free Software Foundation; either version 2 of the
> > - *     License, or (at your option) any later version.
> > - *
> > - *     This library is distributed in the hope that it will be useful,
> > - *     but WITHOUT ANY WARRANTY; without even the implied warranty of
> > - *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> > - *     GNU General Public License for more details.
> > - *
> > - *     You should have received a copy of the GNU General Public
> > - *     License along with this library; if not, write to the Free
> > - *     Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
> > - *     MA 02110-1301 USA
> > - *
> > - * Alternatively,
> > - *
> > - *  b) Redistribution and use in source and binary forms, with or
> > - *     without modification, are permitted provided that the following
> > - *     conditions are met:
> > - *
> > - *     1. Redistributions of source code must retain the above
> > - *        copyright notice, this list of conditions and the following
> > - *        disclaimer.
> > - *     2. Redistributions in binary form must reproduce the above
> > - *        copyright notice, this list of conditions and the following
> > - *        disclaimer in the documentation and/or other materials
> > - *        provided with the distribution.
> > - *
> > - *     THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
> > - *     CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
> > - *     INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
> > - *     MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
> > - *     DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
> > - *     CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
> > - *     SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
> > - *     NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
> > - *     LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
> > - *     HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
> > - *     CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
> > - *     OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
> > - *     EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
> >   */
> >  #include "libfdt_env.h"
> >
> > @@ -93,11 +48,11 @@ static uint32_t overlay_get_target_phandle(const void *fdto, int fragment)
> >   * @pathp: pointer which receives the path of the target (or NULL)
> >   *
> >   * overlay_get_target() retrieves the target offset in the base
> > - * device tree of a fragment, no matter how the actual targetting is
> > + * device tree of a fragment, no matter how the actual targeting is
> >   * done (through a phandle or a path)
> >   *
> >   * returns:
> > - *      the targetted node offset in the base device tree
> > + *      the targeted node offset in the base device tree
> >   *      Negative error code on error
> >   */
> >  static int overlay_get_target(const void *fdt, const void *fdto,
> > @@ -697,7 +652,7 @@ static int get_path_len(const void *fdt, int nodeoffset)
> >         int len = 0, namelen;
> >         const char *name;
> >
> > -       FDT_CHECK_HEADER(fdt);
> > +       FDT_RO_PROBE(fdt);
> >
> >         for (;;) {
> >                 name = fdt_get_name(fdt, nodeoffset, &namelen);
> > @@ -778,26 +733,36 @@ static int overlay_symbol_update(void *fdt, void *fdto)
> >                 /* keep end marker to avoid strlen() */
> >                 e = path + path_len;
> >
> > -               /* format: /<fragment-name>/__overlay__/<relative-subnode-path> */
> > -
> >                 if (*path != '/')
> >                         return -FDT_ERR_BADVALUE;
> >
> >                 /* get fragment name first */
> >                 s = strchr(path + 1, '/');
> > -               if (!s)
> > -                       return -FDT_ERR_BADOVERLAY;
> > +               if (!s) {
> > +                       /* Symbol refers to something that won't end
> > +                        * up in the target tree */
> > +                       continue;
> > +               }
> >
> >                 frag_name = path + 1;
> >                 frag_name_len = s - path - 1;
> >
> >                 /* verify format; safe since "s" lies in \0 terminated prop */
> >                 len = sizeof("/__overlay__/") - 1;
> > -               if ((e - s) < len || memcmp(s, "/__overlay__/", len))
> > -                       return -FDT_ERR_BADOVERLAY;
> > -
> > -               rel_path = s + len;
> > -               rel_path_len = e - rel_path;
> > +               if ((e - s) > len && (memcmp(s, "/__overlay__/", len) == 0)) {
> > +                       /* /<fragment-name>/__overlay__/<relative-subnode-path> */
> > +                       rel_path = s + len;
> > +                       rel_path_len = e - rel_path;
> > +               } else if ((e - s) == len
> > +                          && (memcmp(s, "/__overlay__", len - 1) == 0)) {
> > +                       /* /<fragment-name>/__overlay__ */
> > +                       rel_path = "";
> > +                       rel_path_len = 0;
> > +               } else {
> > +                       /* Symbol refers to something that won't end
> > +                        * up in the target tree */
> > +                       continue;
> > +               }
> >
> >                 /* find the fragment index in which the symbol lies */
> >                 ret = fdt_subnode_offset_namelen(fdto, 0, frag_name,
> > @@ -863,11 +828,15 @@ static int overlay_symbol_update(void *fdt, void *fdto)
> >
> >  int fdt_overlay_apply(void *fdt, void *fdto)
> >  {
> > -       uint32_t delta = fdt_get_max_phandle(fdt);
> > +       uint32_t delta;
> >         int ret;
> >
> > -       FDT_CHECK_HEADER(fdt);
> > -       FDT_CHECK_HEADER(fdto);
> > +       FDT_RO_PROBE(fdt);
> > +       FDT_RO_PROBE(fdto);
> > +
> > +       ret = fdt_find_max_phandle(fdt, &delta);
> > +       if (ret)
> > +               goto err;
> >
> >         ret = overlay_adjust_local_phandles(fdto, delta);
> >         if (ret)
> > diff --git a/scripts/dtc/libfdt/fdt_ro.c b/scripts/dtc/libfdt/fdt_ro.c
> > index dc499884e4..e398815485 100644
> > --- a/scripts/dtc/libfdt/fdt_ro.c
> > +++ b/scripts/dtc/libfdt/fdt_ro.c
> > @@ -1,52 +1,7 @@
> > +// SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-2-Clause)
> >  /*
> >   * libfdt - Flat Device Tree manipulation
> >   * Copyright (C) 2006 David Gibson, IBM Corporation.
> > - *
> > - * libfdt is dual licensed: you can use it either under the terms of
> > - * the GPL, or the BSD license, at your option.
> > - *
> > - *  a) This library is free software; you can redistribute it and/or
> > - *     modify it under the terms of the GNU General Public License as
> > - *     published by the Free Software Foundation; either version 2 of the
> > - *     License, or (at your option) any later version.
> > - *
> > - *     This library is distributed in the hope that it will be useful,
> > - *     but WITHOUT ANY WARRANTY; without even the implied warranty of
> > - *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> > - *     GNU General Public License for more details.
> > - *
> > - *     You should have received a copy of the GNU General Public
> > - *     License along with this library; if not, write to the Free
> > - *     Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
> > - *     MA 02110-1301 USA
> > - *
> > - * Alternatively,
> > - *
> > - *  b) Redistribution and use in source and binary forms, with or
> > - *     without modification, are permitted provided that the following
> > - *     conditions are met:
> > - *
> > - *     1. Redistributions of source code must retain the above
> > - *        copyright notice, this list of conditions and the following
> > - *        disclaimer.
> > - *     2. Redistributions in binary form must reproduce the above
> > - *        copyright notice, this list of conditions and the following
> > - *        disclaimer in the documentation and/or other materials
> > - *        provided with the distribution.
> > - *
> > - *     THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
> > - *     CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
> > - *     INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
> > - *     MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
> > - *     DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
> > - *     CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
> > - *     SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
> > - *     NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
> > - *     LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
> > - *     HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
> > - *     CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
> > - *     OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
> > - *     EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
> >   */
> >  #include "libfdt_env.h"
> >
> > @@ -61,7 +16,7 @@ static int fdt_nodename_eq_(const void *fdt, int offset,
> >         int olen;
> >         const char *p = fdt_get_name(fdt, offset, &olen);
> >
> > -       if (!p || olen < len)
> > +       if (!p || (fdt_chk_extra() && olen < len))
> >                 /* short match */
> >                 return 0;
> >
> > @@ -76,46 +31,85 @@ static int fdt_nodename_eq_(const void *fdt, int offset,
> >                 return 0;
> >  }
> >
> > -const char *fdt_string(const void *fdt, int stroffset)
> > -{
> > -       return (const char *)fdt + fdt_off_dt_strings(fdt) + stroffset;
> > -}
> > -
> > -static int fdt_string_eq_(const void *fdt, int stroffset,
> > -                         const char *s, int len)
> > +const char *fdt_get_string(const void *fdt, int stroffset, int *lenp)
> >  {
> > -       const char *p = fdt_string(fdt, stroffset);
> > +       int32_t totalsize;
> > +       uint32_t absoffset;
> > +       size_t len;
> > +       int err;
> > +       const char *s, *n;
> >
> > -       return (strlen(p) == len) && (memcmp(p, s, len) == 0);
> > -}
> > +       if (!fdt_chk_extra()) {
> > +               s = (const char *)fdt + fdt_off_dt_strings(fdt) + stroffset;
> >
> > -uint32_t fdt_get_max_phandle(const void *fdt)
> > -{
> > -       uint32_t max_phandle = 0;
> > -       int offset;
> > +               if (lenp)
> > +                       *lenp = strlen(s);
> > +               return s;
> > +       }
> > +       totalsize = fdt_ro_probe_(fdt);
> > +       err = totalsize;
> > +       if (totalsize < 0)
> > +               goto fail;
> > +
> > +       err = -FDT_ERR_BADOFFSET;
> > +       absoffset = stroffset + fdt_off_dt_strings(fdt);
> > +       if (absoffset >= totalsize)
> > +               goto fail;
> > +       len = totalsize - absoffset;
> > +
> > +       if (fdt_magic(fdt) == FDT_MAGIC) {
> > +               if (stroffset < 0)
> > +                       goto fail;
> > +               if (!fdt_chk_version() || fdt_version(fdt) >= 17) {
> > +                       if (stroffset >= fdt_size_dt_strings(fdt))
> > +                               goto fail;
> > +                       if ((fdt_size_dt_strings(fdt) - stroffset) < len)
> > +                               len = fdt_size_dt_strings(fdt) - stroffset;
> > +               }
> > +       } else if (fdt_magic(fdt) == FDT_SW_MAGIC) {
> > +               if ((stroffset >= 0)
> > +                   || (stroffset < -fdt_size_dt_strings(fdt)))
> > +                       goto fail;
> > +               if ((-stroffset) < len)
> > +                       len = -stroffset;
> > +       } else {
> > +               err = -FDT_ERR_INTERNAL;
> > +               goto fail;
> > +       }
> >
> > -       for (offset = fdt_next_node(fdt, -1, NULL);;
> > -            offset = fdt_next_node(fdt, offset, NULL)) {
> > -               uint32_t phandle;
> > +       s = (const char *)fdt + absoffset;
> > +       n = memchr(s, '\0', len);
> > +       if (!n) {
> > +               /* missing terminating NULL */
> > +               err = -FDT_ERR_TRUNCATED;
> > +               goto fail;
> > +       }
> >
> > -               if (offset == -FDT_ERR_NOTFOUND)
> > -                       return max_phandle;
> > +       if (lenp)
> > +               *lenp = n - s;
> > +       return s;
> >
> > -               if (offset < 0)
> > -                       return (uint32_t)-1;
> > +fail:
> > +       if (lenp)
> > +               *lenp = err;
> > +       return NULL;
> > +}
> >
> > -               phandle = fdt_get_phandle(fdt, offset);
> > -               if (phandle == (uint32_t)-1)
> > -                       continue;
> > +const char *fdt_string(const void *fdt, int stroffset)
> > +{
> > +       return fdt_get_string(fdt, stroffset, NULL);
> > +}
> >
> > -               if (phandle > max_phandle)
> > -                       max_phandle = phandle;
> > -       }
> > +static int fdt_string_eq_(const void *fdt, int stroffset,
> > +                         const char *s, int len)
> > +{
> > +       int slen;
> > +       const char *p = fdt_get_string(fdt, stroffset, &slen);
> >
> > -       return 0;
> > +       return p && (slen == len) && (memcmp(p, s, len) == 0);
> >  }
> >
> > -int fdt_generate_phandle(const void *fdt, uint32_t *phandle)
> > +int fdt_find_max_phandle(const void *fdt, uint32_t *phandle)
> >  {
> >         uint32_t max = 0;
> >         int offset = -1;
> > @@ -137,6 +131,21 @@ int fdt_generate_phandle(const void *fdt, uint32_t *phandle)
> >                         max = value;
> >         }
> >
> > +       if (phandle)
> > +               *phandle = max;
> > +
> > +       return 0;
> > +}
> > +
> > +int fdt_generate_phandle(const void *fdt, uint32_t *phandle)
> > +{
> > +       uint32_t max;
> > +       int err;
> > +
> > +       err = fdt_find_max_phandle(fdt, &max);
> > +       if (err < 0)
> > +               return err;
> > +
> >         if (max == FDT_MAX_PHANDLE)
> >                 return -FDT_ERR_NOPHANDLES;
> >
> > @@ -146,21 +155,45 @@ int fdt_generate_phandle(const void *fdt, uint32_t *phandle)
> >         return 0;
> >  }
> >
> > +static const struct fdt_reserve_entry *fdt_mem_rsv(const void *fdt, int n)
> > +{
> > +       int offset = n * sizeof(struct fdt_reserve_entry);
> > +       int absoffset = fdt_off_mem_rsvmap(fdt) + offset;
> > +
> > +       if (fdt_chk_extra()) {
> > +               if (absoffset < fdt_off_mem_rsvmap(fdt))
> > +                       return NULL;
> > +               if (absoffset > fdt_totalsize(fdt) -
> > +                   sizeof(struct fdt_reserve_entry))
> > +                       return NULL;
> > +       }
> > +       return fdt_mem_rsv_(fdt, n);
> > +}
> > +
> >  int fdt_get_mem_rsv(const void *fdt, int n, uint64_t *address, uint64_t *size)
> >  {
> > -       FDT_CHECK_HEADER(fdt);
> > -       *address = fdt64_to_cpu(fdt_mem_rsv_(fdt, n)->address);
> > -       *size = fdt64_to_cpu(fdt_mem_rsv_(fdt, n)->size);
> > +       const struct fdt_reserve_entry *re;
> > +
> > +       FDT_RO_PROBE(fdt);
> > +       re = fdt_mem_rsv(fdt, n);
> > +       if (fdt_chk_extra() && !re)
> > +               return -FDT_ERR_BADOFFSET;
> > +
> > +       *address = fdt64_ld(&re->address);
> > +       *size = fdt64_ld(&re->size);
> >         return 0;
> >  }
> >
> >  int fdt_num_mem_rsv(const void *fdt)
> >  {
> > -       int i = 0;
> > +       int i;
> > +       const struct fdt_reserve_entry *re;
> >
> > -       while (fdt64_to_cpu(fdt_mem_rsv_(fdt, i)->size) != 0)
> > -               i++;
> > -       return i;
> > +       for (i = 0; (re = fdt_mem_rsv(fdt, i)) != NULL; i++) {
> > +               if (fdt64_ld(&re->size) == 0)
> > +                       return i;
> > +       }
> > +       return -FDT_ERR_TRUNCATED;
> >  }
> >
> >  static int nextprop_(const void *fdt, int offset)
> > @@ -192,7 +225,7 @@ int fdt_subnode_offset_namelen(const void *fdt, int offset,
> >  {
> >         int depth;
> >
> > -       FDT_CHECK_HEADER(fdt);
> > +       FDT_RO_PROBE(fdt);
> >
> >         for (depth = 0;
> >              (offset >= 0) && (depth >= 0);
> > @@ -218,7 +251,7 @@ int fdt_path_offset_namelen(const void *fdt, const char *path, int namelen)
> >         const char *p = path;
> >         int offset = 0;
> >
> > -       FDT_CHECK_HEADER(fdt);
> > +       FDT_RO_PROBE(fdt);
> >
> >         /* see if we have an alias */
> >         if (*path != '/') {
> > @@ -268,13 +301,14 @@ const char *fdt_get_name(const void *fdt, int nodeoffset, int *len)
> >         const char *nameptr;
> >         int err;
> >
> > -       if (((err = fdt_check_header(fdt)) != 0)
> > -           || ((err = fdt_check_node_offset_(fdt, nodeoffset)) < 0))
> > -                       goto fail;
> > +       if (fdt_chk_extra() &&
> > +           (((err = fdt_ro_probe_(fdt)) < 0)
> > +            || ((err = fdt_check_node_offset_(fdt, nodeoffset)) < 0)))
> > +               goto fail;
> >
> >         nameptr = nh->name;
> >
> > -       if (fdt_version(fdt) < 0x10) {
> > +       if (fdt_chk_version() && fdt_version(fdt) < 0x10) {
> >                 /*
> >                  * For old FDT versions, match the naming conventions of V16:
> >                  * give only the leaf name (after all /). The actual tree
> > @@ -325,7 +359,7 @@ static const struct fdt_property *fdt_get_property_by_offset_(const void *fdt,
> >         int err;
> >         const struct fdt_property *prop;
> >
> > -       if ((err = fdt_check_prop_offset_(fdt, offset)) < 0) {
> > +       if (fdt_chk_basic() && (err = fdt_check_prop_offset_(fdt, offset)) < 0) {
> >                 if (lenp)
> >                         *lenp = err;
> >                 return NULL;
> > @@ -334,7 +368,7 @@ static const struct fdt_property *fdt_get_property_by_offset_(const void *fdt,
> >         prop = fdt_offset_ptr_(fdt, offset);
> >
> >         if (lenp)
> > -               *lenp = fdt32_to_cpu(prop->len);
> > +               *lenp = fdt32_ld(&prop->len);
> >
> >         return prop;
> >  }
> > @@ -346,7 +380,7 @@ const struct fdt_property *fdt_get_property_by_offset(const void *fdt,
> >         /* Prior to version 16, properties may need realignment
> >          * and this API does not work. fdt_getprop_*() will, however. */
> >
> > -       if (fdt_version(fdt) < 0x10) {
> > +       if (fdt_chk_version() && fdt_version(fdt) < 0x10) {
> >                 if (lenp)
> >                         *lenp = -FDT_ERR_BADVERSION;
> >                 return NULL;
> > @@ -367,11 +401,12 @@ static const struct fdt_property *fdt_get_property_namelen_(const void *fdt,
> >              (offset = fdt_next_property_offset(fdt, offset))) {
> >                 const struct fdt_property *prop;
> >
> > -               if (!(prop = fdt_get_property_by_offset_(fdt, offset, lenp))) {
> > +               prop = fdt_get_property_by_offset_(fdt, offset, lenp);
> > +               if (fdt_chk_extra() && !prop) {
> >                         offset = -FDT_ERR_INTERNAL;
> >                         break;
> >                 }
> > -               if (fdt_string_eq_(fdt, fdt32_to_cpu(prop->nameoff),
> > +               if (fdt_string_eq_(fdt, fdt32_ld(&prop->nameoff),
> >                                    name, namelen)) {
> >                         if (poffset)
> >                                 *poffset = offset;
> > @@ -392,7 +427,7 @@ const struct fdt_property *fdt_get_property_namelen(const void *fdt,
> >  {
> >         /* Prior to version 16, properties may need realignment
> >          * and this API does not work. fdt_getprop_*() will, however. */
> > -       if (fdt_version(fdt) < 0x10) {
> > +       if (fdt_chk_version() && fdt_version(fdt) < 0x10) {
> >                 if (lenp)
> >                         *lenp = -FDT_ERR_BADVERSION;
> >                 return NULL;
> > @@ -423,8 +458,8 @@ const void *fdt_getprop_namelen(const void *fdt, int nodeoffset,
> >                 return NULL;
> >
> >         /* Handle realignment */
> > -       if (fdt_version(fdt) < 0x10 && (poffset + sizeof(*prop)) % 8 &&
> > -           fdt32_to_cpu(prop->len) >= 8)
> > +       if (fdt_chk_version() && fdt_version(fdt) < 0x10 &&
> > +           (poffset + sizeof(*prop)) % 8 && fdt32_ld(&prop->len) >= 8)
> >                 return prop->data + 4;
> >         return prop->data;
> >  }
> > @@ -437,12 +472,27 @@ const void *fdt_getprop_by_offset(const void *fdt, int offset,
> >         prop = fdt_get_property_by_offset_(fdt, offset, lenp);
> >         if (!prop)
> >                 return NULL;
> > -       if (namep)
> > -               *namep = fdt_string(fdt, fdt32_to_cpu(prop->nameoff));
> > +       if (namep) {
> > +               const char *name;
> > +               int namelen;
> > +
> > +               if (fdt_chk_extra()) {
> > +                       name = fdt_get_string(fdt, fdt32_ld(&prop->nameoff),
> > +                                             &namelen);
> > +                       if (!name) {
> > +                               if (lenp)
> > +                                       *lenp = namelen;
> > +                               return NULL;
> > +                       }
> > +                       *namep = name;
> > +               } else {
> > +                       *namep = fdt_string(fdt, fdt32_ld(&prop->nameoff));
> > +               }
> > +       }
> >
> >         /* Handle realignment */
> > -       if (fdt_version(fdt) < 0x10 && (offset + sizeof(*prop)) % 8 &&
> > -           fdt32_to_cpu(prop->len) >= 8)
> > +       if (fdt_chk_version() && fdt_version(fdt) < 0x10 &&
> > +           (offset + sizeof(*prop)) % 8 && fdt32_ld(&prop->len) >= 8)
> >                 return prop->data + 4;
> >         return prop->data;
> >  }
> > @@ -467,7 +517,7 @@ uint32_t fdt_get_phandle(const void *fdt, int nodeoffset)
> >                         return 0;
> >         }
> >
> > -       return fdt32_to_cpu(*php);
> > +       return fdt32_ld(php);
> >  }
> >
> >  const char *fdt_get_alias_namelen(const void *fdt,
> > @@ -493,7 +543,7 @@ int fdt_get_path(const void *fdt, int nodeoffset, char *buf, int buflen)
> >         int offset, depth, namelen;
> >         const char *name;
> >
> > -       FDT_CHECK_HEADER(fdt);
> > +       FDT_RO_PROBE(fdt);
> >
> >         if (buflen < 2)
> >                 return -FDT_ERR_NOSPACE;
> > @@ -545,7 +595,7 @@ int fdt_supernode_atdepth_offset(const void *fdt, int nodeoffset,
> >         int offset, depth;
> >         int supernodeoffset = -FDT_ERR_INTERNAL;
> >
> > -       FDT_CHECK_HEADER(fdt);
> > +       FDT_RO_PROBE(fdt);
> >
> >         if (supernodedepth < 0)
> >                 return -FDT_ERR_NOTFOUND;
> > @@ -567,10 +617,12 @@ int fdt_supernode_atdepth_offset(const void *fdt, int nodeoffset,
> >                 }
> >         }
> >
> > -       if ((offset == -FDT_ERR_NOTFOUND) || (offset >= 0))
> > -               return -FDT_ERR_BADOFFSET;
> > -       else if (offset == -FDT_ERR_BADOFFSET)
> > -               return -FDT_ERR_BADSTRUCTURE;
> > +       if (fdt_chk_extra()) {
> > +               if ((offset == -FDT_ERR_NOTFOUND) || (offset >= 0))
> > +                       return -FDT_ERR_BADOFFSET;
> > +               else if (offset == -FDT_ERR_BADOFFSET)
> > +                       return -FDT_ERR_BADSTRUCTURE;
> > +       }
> >
> >         return offset; /* error from fdt_next_node() */
> >  }
> > @@ -582,7 +634,7 @@ int fdt_node_depth(const void *fdt, int nodeoffset)
> >
> >         err = fdt_supernode_atdepth_offset(fdt, nodeoffset, 0, &nodedepth);
> >         if (err)
> > -               return (err < 0) ? err : -FDT_ERR_INTERNAL;
> > +               return (!fdt_chk_extra() || err < 0) ? err : -FDT_ERR_INTERNAL;
> >         return nodedepth;
> >  }
> >
> > @@ -604,7 +656,7 @@ int fdt_node_offset_by_prop_value(const void *fdt, int startoffset,
> >         const void *val;
> >         int len;
> >
> > -       FDT_CHECK_HEADER(fdt);
> > +       FDT_RO_PROBE(fdt);
> >
> >         /* FIXME: The algorithm here is pretty horrible: we scan each
> >          * property of a node in fdt_getprop(), then if that didn't
> > @@ -630,7 +682,7 @@ int fdt_node_offset_by_phandle(const void *fdt, uint32_t phandle)
> >         if ((phandle == 0) || (phandle == -1))
> >                 return -FDT_ERR_BADPHANDLE;
> >
> > -       FDT_CHECK_HEADER(fdt);
> > +       FDT_RO_PROBE(fdt);
> >
> >         /* FIXME: The algorithm here is pretty horrible: we
> >          * potentially scan each property of a node in
> > @@ -783,7 +835,7 @@ int fdt_node_offset_by_compatible(const void *fdt, int startoffset,
> >  {
> >         int offset, err;
> >
> > -       FDT_CHECK_HEADER(fdt);
> > +       FDT_RO_PROBE(fdt);
> >
> >         /* FIXME: The algorithm here is pretty horrible: we scan each
> >          * property of a node in fdt_node_check_compatible(), then if
> > @@ -802,3 +854,68 @@ int fdt_node_offset_by_compatible(const void *fdt, int startoffset,
> >
> >         return offset; /* error from fdt_next_node() */
> >  }
> > +
> > +#if !defined(FDT_ASSUME_MASK) || FDT_ASSUME_MASK != 0xff
> > +int fdt_check_full(const void *fdt, size_t bufsize)
> > +{
> > +       int err;
> > +       int num_memrsv;
> > +       int offset, nextoffset = 0;
> > +       uint32_t tag;
> > +       unsigned depth = 0;
> > +       const void *prop;
> > +       const char *propname;
> > +
> > +       if (bufsize < FDT_V1_SIZE)
> > +               return -FDT_ERR_TRUNCATED;
> > +       err = fdt_check_header(fdt);
> > +       if (err != 0)
> > +               return err;
> > +       if (bufsize < fdt_totalsize(fdt))
> > +               return -FDT_ERR_TRUNCATED;
> > +
> > +       num_memrsv = fdt_num_mem_rsv(fdt);
> > +       if (num_memrsv < 0)
> > +               return num_memrsv;
> > +
> > +       while (1) {
> > +               offset = nextoffset;
> > +               tag = fdt_next_tag(fdt, offset, &nextoffset);
> > +
> > +               if (nextoffset < 0)
> > +                       return nextoffset;
> > +
> > +               switch (tag) {
> > +               case FDT_NOP:
> > +                       break;
> > +
> > +               case FDT_END:
> > +                       if (depth != 0)
> > +                               return -FDT_ERR_BADSTRUCTURE;
> > +                       return 0;
> > +
> > +               case FDT_BEGIN_NODE:
> > +                       depth++;
> > +                       if (depth > INT_MAX)
> > +                               return -FDT_ERR_BADSTRUCTURE;
> > +                       break;
> > +
> > +               case FDT_END_NODE:
> > +                       if (depth == 0)
> > +                               return -FDT_ERR_BADSTRUCTURE;
> > +                       depth--;
> > +                       break;
> > +
> > +               case FDT_PROP:
> > +                       prop = fdt_getprop_by_offset(fdt, offset, &propname,
> > +                                                    &err);
> > +                       if (!prop)
> > +                               return err;
> > +                       break;
> > +
> > +               default:
> > +                       return -FDT_ERR_INTERNAL;
> > +               }
> > +       }
> > +}
> > +#endif
> > diff --git a/scripts/dtc/libfdt/fdt_rw.c b/scripts/dtc/libfdt/fdt_rw.c
> > index 9b829051e4..08e2981a44 100644
> > --- a/scripts/dtc/libfdt/fdt_rw.c
> > +++ b/scripts/dtc/libfdt/fdt_rw.c
> > @@ -1,52 +1,7 @@
> > +// SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-2-Clause)
> >  /*
> >   * libfdt - Flat Device Tree manipulation
> >   * Copyright (C) 2006 David Gibson, IBM Corporation.
> > - *
> > - * libfdt is dual licensed: you can use it either under the terms of
> > - * the GPL, or the BSD license, at your option.
> > - *
> > - *  a) This library is free software; you can redistribute it and/or
> > - *     modify it under the terms of the GNU General Public License as
> > - *     published by the Free Software Foundation; either version 2 of the
> > - *     License, or (at your option) any later version.
> > - *
> > - *     This library is distributed in the hope that it will be useful,
> > - *     but WITHOUT ANY WARRANTY; without even the implied warranty of
> > - *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> > - *     GNU General Public License for more details.
> > - *
> > - *     You should have received a copy of the GNU General Public
> > - *     License along with this library; if not, write to the Free
> > - *     Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
> > - *     MA 02110-1301 USA
> > - *
> > - * Alternatively,
> > - *
> > - *  b) Redistribution and use in source and binary forms, with or
> > - *     without modification, are permitted provided that the following
> > - *     conditions are met:
> > - *
> > - *     1. Redistributions of source code must retain the above
> > - *        copyright notice, this list of conditions and the following
> > - *        disclaimer.
> > - *     2. Redistributions in binary form must reproduce the above
> > - *        copyright notice, this list of conditions and the following
> > - *        disclaimer in the documentation and/or other materials
> > - *        provided with the distribution.
> > - *
> > - *     THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
> > - *     CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
> > - *     INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
> > - *     MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
> > - *     DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
> > - *     CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
> > - *     SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
> > - *     NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
> > - *     LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
> > - *     HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
> > - *     CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
> > - *     OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
> > - *     EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
> >   */
> >  #include "libfdt_env.h"
> >
> > @@ -58,6 +13,8 @@
> >  static int fdt_blocks_misordered_(const void *fdt,
> >                                   int mem_rsv_size, int struct_size)
> >  {
> > +       if (!fdt_chk_basic())
> > +               return false;
> >         return (fdt_off_mem_rsvmap(fdt) < FDT_ALIGN(sizeof(struct fdt_header), 8))
> >                 || (fdt_off_dt_struct(fdt) <
> >                     (fdt_off_mem_rsvmap(fdt) + mem_rsv_size))
> > @@ -67,25 +24,27 @@ static int fdt_blocks_misordered_(const void *fdt,
> >                     (fdt_off_dt_strings(fdt) + fdt_size_dt_strings(fdt)));
> >  }
> >
> > -static int fdt_rw_check_header_(void *fdt)
> > +static int fdt_rw_probe_(void *fdt)
> >  {
> > -       FDT_CHECK_HEADER(fdt);
> > +       if (!fdt_chk_basic())
> > +               return 0;
> > +       FDT_RO_PROBE(fdt);
> >
> > -       if (fdt_version(fdt) < 17)
> > +       if (fdt_chk_version() && fdt_version(fdt) < 17)
> >                 return -FDT_ERR_BADVERSION;
> >         if (fdt_blocks_misordered_(fdt, sizeof(struct fdt_reserve_entry),
> >                                    fdt_size_dt_struct(fdt)))
> >                 return -FDT_ERR_BADLAYOUT;
> > -       if (fdt_version(fdt) > 17)
> > +       if (fdt_chk_version() && fdt_version(fdt) > 17)
> >                 fdt_set_version(fdt, 17);
> >
> >         return 0;
> >  }
> >
> > -#define FDT_RW_CHECK_HEADER(fdt) \
> > +#define FDT_RW_PROBE(fdt) \
> >         { \
> >                 int err_; \
> > -               if ((err_ = fdt_rw_check_header_(fdt)) != 0) \
> > +               if (fdt_chk_extra() && (err_ = fdt_rw_probe_(fdt)) != 0) \
> >                         return err_; \
> >         }
> >
> > @@ -136,6 +95,14 @@ static int fdt_splice_struct_(void *fdt, void *p,
> >         return 0;
> >  }
> >
> > +/* Must only be used to roll back in case of error */
> > +static void fdt_del_last_string_(void *fdt, const char *s)
> > +{
> > +       int newlen = strlen(s) + 1;
> > +
> > +       fdt_set_size_dt_strings(fdt, fdt_size_dt_strings(fdt) - newlen);
> > +}
> > +
> >  static int fdt_splice_string_(void *fdt, int newlen)
> >  {
> >         void *p = (char *)fdt
> > @@ -149,7 +116,16 @@ static int fdt_splice_string_(void *fdt, int newlen)
> >         return 0;
> >  }
> >
> > -static int fdt_find_add_string_(void *fdt, const char *s)
> > +/**
> > + * fdt_find_add_string_() - Find or allocate a string
> > + *
> > + * @fdt: pointer to the device tree to check/adjust
> > + * @s: string to find/add
> > + * @allocated: Set to 0 if the string was found, 1 if not found and so
> > + *     allocated. Ignored if !fdt_chk_basic()
> > + * @return offset of string in the string table (whether found or added)
> > + */
> > +static int fdt_find_add_string_(void *fdt, const char *s, int *allocated)
> >  {
> >         char *strtab = (char *)fdt + fdt_off_dt_strings(fdt);
> >         const char *p;
> > @@ -157,6 +133,9 @@ static int fdt_find_add_string_(void *fdt, const char *s)
> >         int len = strlen(s) + 1;
> >         int err;
> >
> > +       if (fdt_chk_basic())
> > +               *allocated = 0;
> > +
> >         p = fdt_find_string_(strtab, fdt_size_dt_strings(fdt), s);
> >         if (p)
> >                 /* found it */
> > @@ -167,6 +146,9 @@ static int fdt_find_add_string_(void *fdt, const char *s)
> >         if (err)
> >                 return err;
> >
> > +       if (fdt_chk_basic())
> > +               *allocated = 1;
> > +
> >         memcpy(new, s, len);
> >         return (new - strtab);
> >  }
> > @@ -176,7 +158,7 @@ int fdt_add_mem_rsv(void *fdt, uint64_t address, uint64_t size)
> >         struct fdt_reserve_entry *re;
> >         int err;
> >
> > -       FDT_RW_CHECK_HEADER(fdt);
> > +       FDT_RW_PROBE(fdt);
> >
> >         re = fdt_mem_rsv_w_(fdt, fdt_num_mem_rsv(fdt));
> >         err = fdt_splice_mem_rsv_(fdt, re, 0, 1);
> > @@ -192,7 +174,7 @@ int fdt_del_mem_rsv(void *fdt, int n)
> >  {
> >         struct fdt_reserve_entry *re = fdt_mem_rsv_w_(fdt, n);
> >
> > -       FDT_RW_CHECK_HEADER(fdt);
> > +       FDT_RW_PROBE(fdt);
> >
> >         if (n >= fdt_num_mem_rsv(fdt))
> >                 return -FDT_ERR_NOTFOUND;
> > @@ -225,11 +207,12 @@ static int fdt_add_property_(void *fdt, int nodeoffset, const char *name,
> >         int nextoffset;
> >         int namestroff;
> >         int err;
> > +       int allocated;
> >
> >         if ((nextoffset = fdt_check_node_offset_(fdt, nodeoffset)) < 0)
> >                 return nextoffset;
> >
> > -       namestroff = fdt_find_add_string_(fdt, name);
> > +       namestroff = fdt_find_add_string_(fdt, name, &allocated);
> >         if (namestroff < 0)
> >                 return namestroff;
> >
> > @@ -237,8 +220,12 @@ static int fdt_add_property_(void *fdt, int nodeoffset, const char *name,
> >         proplen = sizeof(**prop) + FDT_TAGALIGN(len);
> >
> >         err = fdt_splice_struct_(fdt, *prop, 0, proplen);
> > -       if (err)
> > +       if (err) {
> > +               /* Delete the string if we failed to add it */
> > +               if (fdt_chk_basic() && allocated)
> > +                       fdt_del_last_string_(fdt, name);
> >                 return err;
> > +       }
> >
> >         (*prop)->tag = cpu_to_fdt32(FDT_PROP);
> >         (*prop)->nameoff = cpu_to_fdt32(namestroff);
> > @@ -252,7 +239,7 @@ int fdt_set_name(void *fdt, int nodeoffset, const char *name)
> >         int oldlen, newlen;
> >         int err;
> >
> > -       FDT_RW_CHECK_HEADER(fdt);
> > +       FDT_RW_PROBE(fdt);
> >
> >         namep = (char *)(uintptr_t)fdt_get_name(fdt, nodeoffset, &oldlen);
> >         if (!namep)
> > @@ -275,7 +262,7 @@ int fdt_setprop_placeholder(void *fdt, int nodeoffset, const char *name,
> >         struct fdt_property *prop;
> >         int err;
> >
> > -       FDT_RW_CHECK_HEADER(fdt);
> > +       FDT_RW_PROBE(fdt);
> >
> >         err = fdt_resize_property_(fdt, nodeoffset, name, len, &prop);
> >         if (err == -FDT_ERR_NOTFOUND)
> > @@ -308,7 +295,7 @@ int fdt_appendprop(void *fdt, int nodeoffset, const char *name,
> >         struct fdt_property *prop;
> >         int err, oldlen, newlen;
> >
> > -       FDT_RW_CHECK_HEADER(fdt);
> > +       FDT_RW_PROBE(fdt);
> >
> >         prop = fdt_get_property_w(fdt, nodeoffset, name, &oldlen);
> >         if (prop) {
> > @@ -334,7 +321,7 @@ int fdt_delprop(void *fdt, int nodeoffset, const char *name)
> >         struct fdt_property *prop;
> >         int len, proplen;
> >
> > -       FDT_RW_CHECK_HEADER(fdt);
> > +       FDT_RW_PROBE(fdt);
> >
> >         prop = fdt_get_property_w(fdt, nodeoffset, name, &len);
> >         if (!prop)
> > @@ -354,7 +341,7 @@ int fdt_add_subnode_namelen(void *fdt, int parentoffset,
> >         uint32_t tag;
> >         fdt32_t *endtag;
> >
> > -       FDT_RW_CHECK_HEADER(fdt);
> > +       FDT_RW_PROBE(fdt);
> >
> >         offset = fdt_subnode_offset_namelen(fdt, parentoffset, name, namelen);
> >         if (offset >= 0)
> > @@ -394,7 +381,7 @@ int fdt_del_node(void *fdt, int nodeoffset)
> >  {
> >         int endoffset;
> >
> > -       FDT_RW_CHECK_HEADER(fdt);
> > +       FDT_RW_PROBE(fdt);
> >
> >         endoffset = fdt_node_end_offset_(fdt, nodeoffset);
> >         if (endoffset < 0)
> > @@ -435,12 +422,12 @@ int fdt_open_into(const void *fdt, void *buf, int bufsize)
> >         const char *fdtend = fdtstart + fdt_totalsize(fdt);
> >         char *tmp;
> >
> > -       FDT_CHECK_HEADER(fdt);
> > +       FDT_RO_PROBE(fdt);
> >
> >         mem_rsv_size = (fdt_num_mem_rsv(fdt)+1)
> >                 * sizeof(struct fdt_reserve_entry);
> >
> > -       if (fdt_version(fdt) >= 17) {
> > +       if (!fdt_chk_version() || fdt_version(fdt) >= 17) {
> >                 struct_size = fdt_size_dt_struct(fdt);
> >         } else {
> >                 struct_size = 0;
> > @@ -494,7 +481,7 @@ int fdt_pack(void *fdt)
> >  {
> >         int mem_rsv_size;
> >
> > -       FDT_RW_CHECK_HEADER(fdt);
> > +       FDT_RW_PROBE(fdt);
> >
> >         mem_rsv_size = (fdt_num_mem_rsv(fdt)+1)
> >                 * sizeof(struct fdt_reserve_entry);
> > diff --git a/scripts/dtc/libfdt/fdt_strerror.c b/scripts/dtc/libfdt/fdt_strerror.c
> > index 9677a1887e..768db66ead 100644
> > --- a/scripts/dtc/libfdt/fdt_strerror.c
> > +++ b/scripts/dtc/libfdt/fdt_strerror.c
> > @@ -1,51 +1,7 @@
> > +// SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-2-Clause)
> >  /*
> >   * libfdt - Flat Device Tree manipulation
> >   * Copyright (C) 2006 David Gibson, IBM Corporation.
> > - *
> > - * libfdt is dual licensed: you can use it either under the terms of
> > - * the GPL, or the BSD license, at your option.
> > - *
> > - *  a) This library is free software; you can redistribute it and/or
> > - *     modify it under the terms of the GNU General Public License as
> > - *     published by the Free Software Foundation; either version 2 of the
> > - *     License, or (at your option) any later version.
> > - *
> > - *     This library is distributed in the hope that it will be useful,
> > - *     but WITHOUT ANY WARRANTY; without even the implied warranty of
> > - *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> > - *     GNU General Public License for more details.
> > - *
> > - *     You should have received a copy of the GNU General Public
> > - *     License along with this library; if not, write to the Free
> > - *     Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
> > - *     MA 02110-1301 USA
> > - *
> > - * Alternatively,
> > - *
> > - *  b) Redistribution and use in source and binary forms, with or
> > - *     without modification, are permitted provided that the following
> > - *     conditions are met:
> > - *
> > - *     1. Redistributions of source code must retain the above
> > - *        copyright notice, this list of conditions and the following
> > - *        disclaimer.
> > - *     2. Redistributions in binary form must reproduce the above
> > - *        copyright notice, this list of conditions and the following
> > - *        disclaimer in the documentation and/or other materials
> > - *        provided with the distribution.
> > - *
> > - *     THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
> > - *     CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
> > - *     INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
> > - *     MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
> > - *     DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
> > - *     CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
> > - *     SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
> > - *     NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
> > - *     LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
> > - *     HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
> > - *     CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
> > - *     OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
> >   *     EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
> >   */
> >  #include "libfdt_env.h"
> > @@ -82,6 +38,7 @@ static struct fdt_errtabent fdt_errtable[] = {
> >         FDT_ERRTABENT(FDT_ERR_BADVALUE),
> >         FDT_ERRTABENT(FDT_ERR_BADOVERLAY),
> >         FDT_ERRTABENT(FDT_ERR_NOPHANDLES),
> > +       FDT_ERRTABENT(FDT_ERR_BADFLAGS),
> >  };
> >  #define FDT_ERRTABSIZE (sizeof(fdt_errtable) / sizeof(fdt_errtable[0]))
> >
> > diff --git a/scripts/dtc/libfdt/fdt_sw.c b/scripts/dtc/libfdt/fdt_sw.c
> > index d8ef748a72..a8c924675a 100644
> > --- a/scripts/dtc/libfdt/fdt_sw.c
> > +++ b/scripts/dtc/libfdt/fdt_sw.c
> > @@ -1,52 +1,7 @@
> > +// SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-2-Clause)
> >  /*
> >   * libfdt - Flat Device Tree manipulation
> >   * Copyright (C) 2006 David Gibson, IBM Corporation.
> > - *
> > - * libfdt is dual licensed: you can use it either under the terms of
> > - * the GPL, or the BSD license, at your option.
> > - *
> > - *  a) This library is free software; you can redistribute it and/or
> > - *     modify it under the terms of the GNU General Public License as
> > - *     published by the Free Software Foundation; either version 2 of the
> > - *     License, or (at your option) any later version.
> > - *
> > - *     This library is distributed in the hope that it will be useful,
> > - *     but WITHOUT ANY WARRANTY; without even the implied warranty of
> > - *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> > - *     GNU General Public License for more details.
> > - *
> > - *     You should have received a copy of the GNU General Public
> > - *     License along with this library; if not, write to the Free
> > - *     Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
> > - *     MA 02110-1301 USA
> > - *
> > - * Alternatively,
> > - *
> > - *  b) Redistribution and use in source and binary forms, with or
> > - *     without modification, are permitted provided that the following
> > - *     conditions are met:
> > - *
> > - *     1. Redistributions of source code must retain the above
> > - *        copyright notice, this list of conditions and the following
> > - *        disclaimer.
> > - *     2. Redistributions in binary form must reproduce the above
> > - *        copyright notice, this list of conditions and the following
> > - *        disclaimer in the documentation and/or other materials
> > - *        provided with the distribution.
> > - *
> > - *     THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
> > - *     CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
> > - *     INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
> > - *     MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
> > - *     DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
> > - *     CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
> > - *     SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
> > - *     NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
> > - *     LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
> > - *     HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
> > - *     CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
> > - *     OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
> > - *     EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
> >   */
> >  #include "libfdt_env.h"
> >
> > @@ -55,21 +10,90 @@
> >
> >  #include "libfdt_internal.h"
> >
> > -static int fdt_sw_check_header_(void *fdt)
> > +static int fdt_sw_probe_(void *fdt)
> > +{
> > +       if (fdt_chk_basic()) {
> > +               if (fdt_magic(fdt) == FDT_MAGIC)
> > +                       return -FDT_ERR_BADSTATE;
> > +               else if (fdt_magic(fdt) != FDT_SW_MAGIC)
> > +                       return -FDT_ERR_BADMAGIC;
> > +       }
> > +
> > +       return 0;
> > +}
> > +
> > +#define FDT_SW_PROBE(fdt) \
> > +       { \
> > +               int err; \
> > +               if (fdt_chk_basic() && (err = fdt_sw_probe_(fdt)) != 0) \
> > +                       return err; \
> > +       }
> > +
> > +/* 'memrsv' state:     Initial state after fdt_create()
> > + *
> > + * Allowed functions:
> > + *     fdt_add_reservmap_entry()
> > + *     fdt_finish_reservemap()         [moves to 'struct' state]
> > + */
> > +static int fdt_sw_probe_memrsv_(void *fdt)
> > +{
> > +       int err = fdt_sw_probe_(fdt);
> > +       if (err)
> > +               return err;
> > +
> > +       if (fdt_chk_extra() && fdt_off_dt_strings(fdt) != 0)
> > +               return -FDT_ERR_BADSTATE;
> > +       return 0;
> > +}
> > +
> > +#define FDT_SW_PROBE_MEMRSV(fdt) \
> > +       { \
> > +               int err; \
> > +               if (fdt_chk_extra() && (err = fdt_sw_probe_memrsv_(fdt)) != 0) \
> > +                       return err; \
> > +       }
> > +
> > +/* 'struct' state:     Enter this state after fdt_finish_reservemap()
> > + *
> > + * Allowed functions:
> > + *     fdt_begin_node()
> > + *     fdt_end_node()
> > + *     fdt_property*()
> > + *     fdt_finish()                    [moves to 'complete' state]
> > + */
> > +static int fdt_sw_probe_struct_(void *fdt)
> >  {
> > -       if (fdt_magic(fdt) != FDT_SW_MAGIC)
> > -               return -FDT_ERR_BADMAGIC;
> > -       /* FIXME: should check more details about the header state */
> > +       int err;
> > +
> > +       if (!fdt_chk_extra())
> > +               return 0;
> > +       err = fdt_sw_probe_(fdt);
> > +       if (err)
> > +               return err;
> > +
> > +       if (fdt_off_dt_strings(fdt) != fdt_totalsize(fdt))
> > +               return -FDT_ERR_BADSTATE;
> >         return 0;
> >  }
> >
> > -#define FDT_SW_CHECK_HEADER(fdt) \
> > +#define FDT_SW_PROBE_STRUCT(fdt) \
> >         { \
> >                 int err; \
> > -               if ((err = fdt_sw_check_header_(fdt)) != 0) \
> > +               if (fdt_chk_extra() && (err = fdt_sw_probe_struct_(fdt)) != 0) \
> >                         return err; \
> >         }
> >
> > +static inline uint32_t sw_flags(void *fdt)
> > +{
> > +       /* assert: (fdt_magic(fdt) == FDT_SW_MAGIC) */
> > +       return fdt_last_comp_version(fdt);
> > +}
> > +
> > +/* 'complete' state:   Enter this state after fdt_finish()
> > + *
> > + * Allowed functions: none
> > + */
> > +
> >  static void *fdt_grab_space_(void *fdt, size_t len)
> >  {
> >         int offset = fdt_size_dt_struct(fdt);
> > @@ -85,38 +109,58 @@ static void *fdt_grab_space_(void *fdt, size_t len)
> >         return fdt_offset_ptr_w_(fdt, offset);
> >  }
> >
> > -int fdt_create(void *buf, int bufsize)
> > +int fdt_create_with_flags(void *buf, int bufsize, uint32_t flags)
> >  {
> > +       const size_t hdrsize = FDT_ALIGN(sizeof(struct fdt_header),
> > +                                        sizeof(struct fdt_reserve_entry));
> >         void *fdt = buf;
> >
> > -       if (bufsize < sizeof(struct fdt_header))
> > +       if (bufsize < hdrsize)
> >                 return -FDT_ERR_NOSPACE;
> >
> > +       if (flags & ~FDT_CREATE_FLAGS_ALL)
> > +               return -FDT_ERR_BADFLAGS;
> > +
> >         memset(buf, 0, bufsize);
> >
> > +       /*
> > +        * magic and last_comp_version keep intermediate state during the fdt
> > +        * creation process, which is replaced with the proper FDT format by
> > +        * fdt_finish().
> > +        *
> > +        * flags should be accessed with sw_flags().
> > +        */
> >         fdt_set_magic(fdt, FDT_SW_MAGIC);
> >         fdt_set_version(fdt, FDT_LAST_SUPPORTED_VERSION);
> > -       fdt_set_last_comp_version(fdt, FDT_FIRST_SUPPORTED_VERSION);
> > +       fdt_set_last_comp_version(fdt, flags);
> > +
> >         fdt_set_totalsize(fdt,  bufsize);
> >
> > -       fdt_set_off_mem_rsvmap(fdt, FDT_ALIGN(sizeof(struct fdt_header),
> > -                                             sizeof(struct fdt_reserve_entry)));
> > +       fdt_set_off_mem_rsvmap(fdt, hdrsize);
> >         fdt_set_off_dt_struct(fdt, fdt_off_mem_rsvmap(fdt));
> > -       fdt_set_off_dt_strings(fdt, bufsize);
> > +       fdt_set_off_dt_strings(fdt, 0);
> >
> >         return 0;
> >  }
> >
> > +int fdt_create(void *buf, int bufsize)
> > +{
> > +       return fdt_create_with_flags(buf, bufsize, 0);
> > +}
> > +
> >  int fdt_resize(void *fdt, void *buf, int bufsize)
> >  {
> >         size_t headsize, tailsize;
> >         char *oldtail, *newtail;
> >
> > -       FDT_SW_CHECK_HEADER(fdt);
> > +       FDT_SW_PROBE(fdt);
> >
> >         headsize = fdt_off_dt_struct(fdt) + fdt_size_dt_struct(fdt);
> >         tailsize = fdt_size_dt_strings(fdt);
> >
> > +       if (fdt_chk_extra() && (headsize + tailsize) > fdt_totalsize(fdt))
> > +               return -FDT_ERR_INTERNAL;
> > +
> >         if ((headsize + tailsize) > bufsize)
> >                 return -FDT_ERR_NOSPACE;
> >
> > @@ -133,8 +177,9 @@ int fdt_resize(void *fdt, void *buf, int bufsize)
> >                 memmove(buf, fdt, headsize);
> >         }
> >
> > -       fdt_set_off_dt_strings(buf, bufsize);
> >         fdt_set_totalsize(buf, bufsize);
> > +       if (fdt_off_dt_strings(buf))
> > +               fdt_set_off_dt_strings(buf, bufsize);
> >
> >         return 0;
> >  }
> > @@ -144,10 +189,7 @@ int fdt_add_reservemap_entry(void *fdt, uint64_t addr, uint64_t size)
> >         struct fdt_reserve_entry *re;
> >         int offset;
> >
> > -       FDT_SW_CHECK_HEADER(fdt);
> > -
> > -       if (fdt_size_dt_struct(fdt))
> > -               return -FDT_ERR_BADSTATE;
> > +       FDT_SW_PROBE_MEMRSV(fdt);
> >
> >         offset = fdt_off_dt_struct(fdt);
> >         if ((offset + sizeof(*re)) > fdt_totalsize(fdt))
> > @@ -164,16 +206,23 @@ int fdt_add_reservemap_entry(void *fdt, uint64_t addr, uint64_t size)
> >
> >  int fdt_finish_reservemap(void *fdt)
> >  {
> > -       return fdt_add_reservemap_entry(fdt, 0, 0);
> > +       int err = fdt_add_reservemap_entry(fdt, 0, 0);
> > +
> > +       if (err)
> > +               return err;
> > +
> > +       fdt_set_off_dt_strings(fdt, fdt_totalsize(fdt));
> > +       return 0;
> >  }
> >
> >  int fdt_begin_node(void *fdt, const char *name)
> >  {
> >         struct fdt_node_header *nh;
> > -       int namelen = strlen(name) + 1;
> > +       int namelen;
> >
> > -       FDT_SW_CHECK_HEADER(fdt);
> > +       FDT_SW_PROBE_STRUCT(fdt);
> >
> > +       namelen = strlen(name) + 1;
> >         nh = fdt_grab_space_(fdt, sizeof(*nh) + FDT_TAGALIGN(namelen));
> >         if (! nh)
> >                 return -FDT_ERR_NOSPACE;
> > @@ -187,7 +236,7 @@ int fdt_end_node(void *fdt)
> >  {
> >         fdt32_t *en;
> >
> > -       FDT_SW_CHECK_HEADER(fdt);
> > +       FDT_SW_PROBE_STRUCT(fdt);
> >
> >         en = fdt_grab_space_(fdt, FDT_TAGSIZE);
> >         if (! en)
> > @@ -197,19 +246,13 @@ int fdt_end_node(void *fdt)
> >         return 0;
> >  }
> >
> > -static int fdt_find_add_string_(void *fdt, const char *s)
> > +static int fdt_add_string_(void *fdt, const char *s)
> >  {
> >         char *strtab = (char *)fdt + fdt_totalsize(fdt);
> > -       const char *p;
> >         int strtabsize = fdt_size_dt_strings(fdt);
> >         int len = strlen(s) + 1;
> >         int struct_top, offset;
> >
> > -       p = fdt_find_string_(strtab - strtabsize, strtabsize, s);
> > -       if (p)
> > -               return p - strtab;
> > -
> > -       /* Add it */
> >         offset = -strtabsize - len;
> >         struct_top = fdt_off_dt_struct(fdt) + fdt_size_dt_struct(fdt);
> >         if (fdt_totalsize(fdt) + offset < struct_top)
> > @@ -220,20 +263,56 @@ static int fdt_find_add_string_(void *fdt, const char *s)
> >         return offset;
> >  }
> >
> > +/* Must only be used to roll back in case of error */
> > +static void fdt_del_last_string_(void *fdt, const char *s)
> > +{
> > +       int strtabsize = fdt_size_dt_strings(fdt);
> > +       int len = strlen(s) + 1;
> > +
> > +       fdt_set_size_dt_strings(fdt, strtabsize - len);
> > +}
> > +
> > +static int fdt_find_add_string_(void *fdt, const char *s, int *allocated)
> > +{
> > +       char *strtab = (char *)fdt + fdt_totalsize(fdt);
> > +       int strtabsize = fdt_size_dt_strings(fdt);
> > +       const char *p;
> > +
> > +       *allocated = 0;
> > +
> > +       p = fdt_find_string_(strtab - strtabsize, strtabsize, s);
> > +       if (p)
> > +               return p - strtab;
> > +
> > +       *allocated = 1;
> > +
> > +       return fdt_add_string_(fdt, s);
> > +}
> > +
> >  int fdt_property_placeholder(void *fdt, const char *name, int len, void **valp)
> >  {
> >         struct fdt_property *prop;
> >         int nameoff;
> > +       int allocated;
> >
> > -       FDT_SW_CHECK_HEADER(fdt);
> > +       FDT_SW_PROBE_STRUCT(fdt);
> >
> > -       nameoff = fdt_find_add_string_(fdt, name);
> > +       /* String de-duplication can be slow, _NO_NAME_DEDUP skips it */
> > +       if (sw_flags(fdt) & FDT_CREATE_FLAG_NO_NAME_DEDUP) {
> > +               allocated = 1;
> > +               nameoff = fdt_add_string_(fdt, name);
> > +       } else {
> > +               nameoff = fdt_find_add_string_(fdt, name, &allocated);
> > +       }
> >         if (nameoff == 0)
> >                 return -FDT_ERR_NOSPACE;
> >
> >         prop = fdt_grab_space_(fdt, sizeof(*prop) + FDT_TAGALIGN(len));
> > -       if (! prop)
> > +       if (! prop) {
> > +               if (allocated)
> > +                       fdt_del_last_string_(fdt, name);
> >                 return -FDT_ERR_NOSPACE;
> > +       }
> >
> >         prop->tag = cpu_to_fdt32(FDT_PROP);
> >         prop->nameoff = cpu_to_fdt32(nameoff);
> > @@ -262,7 +341,7 @@ int fdt_finish(void *fdt)
> >         uint32_t tag;
> >         int offset, nextoffset;
> >
> > -       FDT_SW_CHECK_HEADER(fdt);
> > +       FDT_SW_PROBE_STRUCT(fdt);
> >
> >         /* Add terminator */
> >         end = fdt_grab_space_(fdt, sizeof(*end));
> > @@ -295,6 +374,10 @@ int fdt_finish(void *fdt)
> >
> >         /* Finally, adjust the header */
> >         fdt_set_totalsize(fdt, newstroffset + fdt_size_dt_strings(fdt));
> > +
> > +       /* And fix up fields that were keeping intermediate state. */
> > +       fdt_set_last_comp_version(fdt, FDT_FIRST_SUPPORTED_VERSION);
> >         fdt_set_magic(fdt, FDT_MAGIC);
> > +
> >         return 0;
> >  }
> > diff --git a/scripts/dtc/libfdt/fdt_wip.c b/scripts/dtc/libfdt/fdt_wip.c
> > index 534c1cbbb2..f64139e0b3 100644
> > --- a/scripts/dtc/libfdt/fdt_wip.c
> > +++ b/scripts/dtc/libfdt/fdt_wip.c
> > @@ -1,52 +1,7 @@
> > +// SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-2-Clause)
> >  /*
> >   * libfdt - Flat Device Tree manipulation
> >   * Copyright (C) 2006 David Gibson, IBM Corporation.
> > - *
> > - * libfdt is dual licensed: you can use it either under the terms of
> > - * the GPL, or the BSD license, at your option.
> > - *
> > - *  a) This library is free software; you can redistribute it and/or
> > - *     modify it under the terms of the GNU General Public License as
> > - *     published by the Free Software Foundation; either version 2 of the
> > - *     License, or (at your option) any later version.
> > - *
> > - *     This library is distributed in the hope that it will be useful,
> > - *     but WITHOUT ANY WARRANTY; without even the implied warranty of
> > - *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> > - *     GNU General Public License for more details.
> > - *
> > - *     You should have received a copy of the GNU General Public
> > - *     License along with this library; if not, write to the Free
> > - *     Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
> > - *     MA 02110-1301 USA
> > - *
> > - * Alternatively,
> > - *
> > - *  b) Redistribution and use in source and binary forms, with or
> > - *     without modification, are permitted provided that the following
> > - *     conditions are met:
> > - *
> > - *     1. Redistributions of source code must retain the above
> > - *        copyright notice, this list of conditions and the following
> > - *        disclaimer.
> > - *     2. Redistributions in binary form must reproduce the above
> > - *        copyright notice, this list of conditions and the following
> > - *        disclaimer in the documentation and/or other materials
> > - *        provided with the distribution.
> > - *
> > - *     THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
> > - *     CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
> > - *     INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
> > - *     MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
> > - *     DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
> > - *     CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
> > - *     SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
> > - *     NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
> > - *     LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
> > - *     HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
> > - *     CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
> > - *     OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
> > - *     EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
> >   */
> >  #include "libfdt_env.h"
> >
> > diff --git a/scripts/dtc/libfdt/libfdt.h b/scripts/dtc/libfdt/libfdt.h
> > index c400f2f5d5..36fadcdea5 100644
> > --- a/scripts/dtc/libfdt/libfdt.h
> > +++ b/scripts/dtc/libfdt/libfdt.h
> > @@ -1,54 +1,9 @@
> > +/* SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-2-Clause) */
> >  #ifndef LIBFDT_H
> >  #define LIBFDT_H
> >  /*
> >   * libfdt - Flat Device Tree manipulation
> >   * Copyright (C) 2006 David Gibson, IBM Corporation.
> > - *
> > - * libfdt is dual licensed: you can use it either under the terms of
> > - * the GPL, or the BSD license, at your option.
> > - *
> > - *  a) This library is free software; you can redistribute it and/or
> > - *     modify it under the terms of the GNU General Public License as
> > - *     published by the Free Software Foundation; either version 2 of the
> > - *     License, or (at your option) any later version.
> > - *
> > - *     This library is distributed in the hope that it will be useful,
> > - *     but WITHOUT ANY WARRANTY; without even the implied warranty of
> > - *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> > - *     GNU General Public License for more details.
> > - *
> > - *     You should have received a copy of the GNU General Public
> > - *     License along with this library; if not, write to the Free
> > - *     Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
> > - *     MA 02110-1301 USA
> > - *
> > - * Alternatively,
> > - *
> > - *  b) Redistribution and use in source and binary forms, with or
> > - *     without modification, are permitted provided that the following
> > - *     conditions are met:
> > - *
> > - *     1. Redistributions of source code must retain the above
> > - *        copyright notice, this list of conditions and the following
> > - *        disclaimer.
> > - *     2. Redistributions in binary form must reproduce the above
> > - *        copyright notice, this list of conditions and the following
> > - *        disclaimer in the documentation and/or other materials
> > - *        provided with the distribution.
> > - *
> > - *     THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
> > - *     CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
> > - *     INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
> > - *     MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
> > - *     DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
> > - *     CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
> > - *     SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
> > - *     NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
> > - *     LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
> > - *     HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
> > - *     CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
> > - *     OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
> > - *     EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
> >   */
> >
> >  #include "libfdt_env.h"
> > @@ -90,8 +45,9 @@
> >
> >  /* Error codes: codes for bad device tree blobs */
> >  #define FDT_ERR_TRUNCATED      8
> > -       /* FDT_ERR_TRUNCATED: Structure block of the given device tree
> > -        * ends without an FDT_END tag. */
> > +       /* FDT_ERR_TRUNCATED: FDT or a sub-block is improperly
> > +        * terminated (overflows, goes outside allowed bounds, or
> > +        * isn't properly terminated).  */
> >  #define FDT_ERR_BADMAGIC       9
> >         /* FDT_ERR_BADMAGIC: Given "device tree" appears not to be a
> >          * device tree at all - it is missing the flattened device
> > @@ -137,7 +93,11 @@
> >         /* FDT_ERR_NOPHANDLES: The device tree doesn't have any
> >          * phandle available anymore without causing an overflow */
> >
> > -#define FDT_ERR_MAX            17
> > +#define FDT_ERR_BADFLAGS       18
> > +       /* FDT_ERR_BADFLAGS: The function was passed a flags field that
> > +        * contains invalid flags or an invalid combination of flags. */
> > +
> > +#define FDT_ERR_MAX            18
> >
> >  /* constants */
> >  #define FDT_MAX_PHANDLE 0xfffffffe
> > @@ -157,6 +117,61 @@ static inline void *fdt_offset_ptr_w(void *fdt, int offset, int checklen)
> >
> >  uint32_t fdt_next_tag(const void *fdt, int offset, int *nextoffset);
> >
> > +/*
> > + * Alignment helpers:
> > + *     These helpers access words from a device tree blob.  They're
> > + *     built to work even with unaligned pointers on platforms (ike
> > + *     ARM) that don't like unaligned loads and stores
> > + */
> > +
> > +static inline uint32_t fdt32_ld(const fdt32_t *p)
> > +{
> > +       const uint8_t *bp = (const uint8_t *)p;
> > +
> > +       return ((uint32_t)bp[0] << 24)
> > +               | ((uint32_t)bp[1] << 16)
> > +               | ((uint32_t)bp[2] << 8)
> > +               | bp[3];
> > +}
> > +
> > +static inline void fdt32_st(void *property, uint32_t value)
> > +{
> > +       uint8_t *bp = (uint8_t *)property;
> > +
> > +       bp[0] = value >> 24;
> > +       bp[1] = (value >> 16) & 0xff;
> > +       bp[2] = (value >> 8) & 0xff;
> > +       bp[3] = value & 0xff;
> > +}
> > +
> > +static inline uint64_t fdt64_ld(const fdt64_t *p)
> > +{
> > +       const uint8_t *bp = (const uint8_t *)p;
> > +
> > +       return ((uint64_t)bp[0] << 56)
> > +               | ((uint64_t)bp[1] << 48)
> > +               | ((uint64_t)bp[2] << 40)
> > +               | ((uint64_t)bp[3] << 32)
> > +               | ((uint64_t)bp[4] << 24)
> > +               | ((uint64_t)bp[5] << 16)
> > +               | ((uint64_t)bp[6] << 8)
> > +               | bp[7];
> > +}
> > +
> > +static inline void fdt64_st(void *property, uint64_t value)
> > +{
> > +       uint8_t *bp = (uint8_t *)property;
> > +
> > +       bp[0] = value >> 56;
> > +       bp[1] = (value >> 48) & 0xff;
> > +       bp[2] = (value >> 40) & 0xff;
> > +       bp[3] = (value >> 32) & 0xff;
> > +       bp[4] = (value >> 24) & 0xff;
> > +       bp[5] = (value >> 16) & 0xff;
> > +       bp[6] = (value >> 8) & 0xff;
> > +       bp[7] = value & 0xff;
> > +}
> > +
> >  /**********************************************************************/
> >  /* Traversal functions                                                */
> >  /**********************************************************************/
> > @@ -199,7 +214,7 @@ int fdt_next_subnode(const void *fdt, int offset);
> >   *             ...
> >   *     }
> >   *
> > - *     if ((node < 0) && (node != -FDT_ERR_NOT_FOUND)) {
> > + *     if ((node < 0) && (node != -FDT_ERR_NOTFOUND)) {
> >   *             Error handling
> >   *     }
> >   *
> > @@ -217,7 +232,7 @@ int fdt_next_subnode(const void *fdt, int offset);
> >  /* General functions                                                  */
> >  /**********************************************************************/
> >  #define fdt_get_header(fdt, field) \
> > -       (fdt32_to_cpu(((const struct fdt_header *)(fdt))->field))
> > +       (fdt32_ld(&((const struct fdt_header *)(fdt))->field))
> >  #define fdt_magic(fdt)                 (fdt_get_header(fdt, magic))
> >  #define fdt_totalsize(fdt)             (fdt_get_header(fdt, totalsize))
> >  #define fdt_off_dt_struct(fdt)         (fdt_get_header(fdt, off_dt_struct))
> > @@ -248,18 +263,32 @@ fdt_set_hdr_(size_dt_struct);
> >  #undef fdt_set_hdr_
> >
> >  /**
> > - * fdt_check_header - sanity check a device tree or possible device tree
> > + * fdt_header_size - return the size of the tree's header
> > + * @fdt: pointer to a flattened device tree
> > + */
> > +size_t fdt_header_size(const void *fdt);
> > +
> > +/**
> > + * fdt_header_size_ - internal function which takes a version number
> > + */
> > +size_t fdt_header_size_(uint32_t version);
> > +
> > +/**
> > + * fdt_check_header - sanity check a device tree header
> > +
> >   * @fdt: pointer to data which might be a flattened device tree
> >   *
> >   * fdt_check_header() checks that the given buffer contains what
> > - * appears to be a flattened device tree with sane information in its
> > - * header.
> > + * appears to be a flattened device tree, and that the header contains
> > + * valid information (to the extent that can be determined from the
> > + * header alone).
> >   *
> >   * returns:
> >   *     0, if the buffer appears to contain a valid device tree
> >   *     -FDT_ERR_BADMAGIC,
> >   *     -FDT_ERR_BADVERSION,
> > - *     -FDT_ERR_BADSTATE, standard meanings, as above
> > + *     -FDT_ERR_BADSTATE,
> > + *     -FDT_ERR_TRUNCATED, standard meanings, as above
> >   */
> >  int fdt_check_header(const void *fdt);
> >
> > @@ -288,6 +317,24 @@ int fdt_move(const void *fdt, void *buf, int bufsize);
> >  /* Read-only functions                                                */
> >  /**********************************************************************/
> >
> > +int fdt_check_full(const void *fdt, size_t bufsize);
> > +
> > +/**
> > + * fdt_get_string - retrieve a string from the strings block of a device tree
> > + * @fdt: pointer to the device tree blob
> > + * @stroffset: offset of the string within the strings block (native endian)
> > + * @lenp: optional pointer to return the string's length
> > + *
> > + * fdt_get_string() retrieves a pointer to a single string from the
> > + * strings block of the device tree blob at fdt, and optionally also
> > + * returns the string's length in *lenp.
> > + *
> > + * returns:
> > + *     a pointer to the string, on success
> > + *     NULL, if stroffset is out of bounds, or doesn't point to a valid string
> > + */
> > +const char *fdt_get_string(const void *fdt, int stroffset, int *lenp);
> > +
> >  /**
> >   * fdt_string - retrieve a string from the strings block of a device tree
> >   * @fdt: pointer to the device tree blob
> > @@ -298,10 +345,24 @@ int fdt_move(const void *fdt, void *buf, int bufsize);
> >   *
> >   * returns:
> >   *     a pointer to the string, on success
> > - *     NULL, if stroffset is out of bounds
> > + *     NULL, if stroffset is out of bounds, or doesn't point to a valid string
> >   */
> >  const char *fdt_string(const void *fdt, int stroffset);
> >
> > +/**
> > + * fdt_find_max_phandle - find and return the highest phandle in a tree
> > + * @fdt: pointer to the device tree blob
> > + * @phandle: return location for the highest phandle value found in the tree
> > + *
> > + * fdt_find_max_phandle() finds the highest phandle value in the given device
> > + * tree. The value returned in @phandle is only valid if the function returns
> > + * success.
> > + *
> > + * returns:
> > + *     0 on success or a negative error code on failure
> > + */
> > +int fdt_find_max_phandle(const void *fdt, uint32_t *phandle);
> > +
> >  /**
> >   * fdt_get_max_phandle - retrieves the highest phandle in a tree
> >   * @fdt: pointer to the device tree blob
> > @@ -310,12 +371,24 @@ const char *fdt_string(const void *fdt, int stroffset);
> >   * device tree. This will ignore badly formatted phandles, or phandles
> >   * with a value of 0 or -1.
> >   *
> > + * This function is deprecated in favour of fdt_find_max_phandle().
> > + *
> >   * returns:
> >   *      the highest phandle on success
> >   *      0, if no phandle was found in the device tree
> >   *      -1, if an error occurred
> >   */
> > -uint32_t fdt_get_max_phandle(const void *fdt);
> > +static inline uint32_t fdt_get_max_phandle(const void *fdt)
> > +{
> > +       uint32_t phandle;
> > +       int err;
> > +
> > +       err = fdt_find_max_phandle(fdt, &phandle);
> > +       if (err < 0)
> > +               return (uint32_t)-1;
> > +
> > +       return phandle;
> > +}
> >
> >  /**
> >   * fdt_generate_phandle - return a new, unused phandle for a device tree blob
> > @@ -522,7 +595,7 @@ int fdt_next_property_offset(const void *fdt, int offset);
> >   *             ...
> >   *     }
> >   *
> > - *     if ((property < 0) && (property != -FDT_ERR_NOT_FOUND)) {
> > + *     if ((property < 0) && (property != -FDT_ERR_NOTFOUND)) {
> >   *             Error handling
> >   *     }
> >   *
> > @@ -625,7 +698,7 @@ static inline struct fdt_property *fdt_get_property_w(void *fdt, int nodeoffset,
> >  /**
> >   * fdt_getprop_by_offset - retrieve the value of a property at a given offset
> >   * @fdt: pointer to the device tree blob
> > - * @ffset: offset of the property to read
> > + * @offset: offset of the property to read
> >   * @namep: pointer to a string variable (will be overwritten) or NULL
> >   * @lenp: pointer to an integer variable (will be overwritten) or NULL
> >   *
> > @@ -734,7 +807,7 @@ uint32_t fdt_get_phandle(const void *fdt, int nodeoffset);
> >  /**
> >   * fdt_get_alias_namelen - get alias based on substring
> >   * @fdt: pointer to the device tree blob
> > - * @name: name of the alias to look up
> > + * @name: name of the alias th look up
> >   * @namelen: number of characters of name to consider
> >   *
> >   * Identical to fdt_get_alias(), but only examine the first namelen
> > @@ -1316,7 +1389,45 @@ int fdt_nop_node(void *fdt, int nodeoffset);
> >  /* Sequential write functions                                         */
> >  /**********************************************************************/
> >
> > +/* fdt_create_with_flags flags */
> > +#define FDT_CREATE_FLAG_NO_NAME_DEDUP 0x1
> > +       /* FDT_CREATE_FLAG_NO_NAME_DEDUP: Do not try to de-duplicate property
> > +        * names in the fdt. This can result in faster creation times, but
> > +        * a larger fdt. */
> > +
> > +#define FDT_CREATE_FLAGS_ALL   (FDT_CREATE_FLAG_NO_NAME_DEDUP)
> > +
> > +/**
> > + * fdt_create_with_flags - begin creation of a new fdt
> > + * @fdt: pointer to memory allocated where fdt will be created
> > + * @bufsize: size of the memory space at fdt
> > + * @flags: a valid combination of FDT_CREATE_FLAG_ flags, or 0.
> > + *
> > + * fdt_create_with_flags() begins the process of creating a new fdt with
> > + * the sequential write interface.
> > + *
> > + * fdt creation process must end with fdt_finished() to produce a valid fdt.
> > + *
> > + * returns:
> > + *     0, on success
> > + *     -FDT_ERR_NOSPACE, bufsize is insufficient for a minimal fdt
> > + *     -FDT_ERR_BADFLAGS, flags is not valid
> > + */
> > +int fdt_create_with_flags(void *buf, int bufsize, uint32_t flags);
> > +
> > +/**
> > + * fdt_create - begin creation of a new fdt
> > + * @fdt: pointer to memory allocated where fdt will be created
> > + * @bufsize: size of the memory space at fdt
> > + *
> > + * fdt_create() is equivalent to fdt_create_with_flags() with flags=0.
> > + *
> > + * returns:
> > + *     0, on success
> > + *     -FDT_ERR_NOSPACE, bufsize is insufficient for a minimal fdt
> > + */
> >  int fdt_create(void *buf, int bufsize);
> > +
> >  int fdt_resize(void *fdt, void *buf, int bufsize);
> >  int fdt_add_reservemap_entry(void *fdt, uint64_t addr, uint64_t size);
> >  int fdt_finish_reservemap(void *fdt);
> > @@ -1787,6 +1898,43 @@ static inline int fdt_appendprop_cell(void *fdt, int nodeoffset,
> >  #define fdt_appendprop_string(fdt, nodeoffset, name, str) \
> >         fdt_appendprop((fdt), (nodeoffset), (name), (str), strlen(str)+1)
> >
> > +/**
> > + * fdt_appendprop_addrrange - append a address range property
> > + * @fdt: pointer to the device tree blob
> > + * @parent: offset of the parent node
> > + * @nodeoffset: offset of the node to add a property at
> > + * @name: name of property
> > + * @addr: start address of a given range
> > + * @size: size of a given range
> > + *
> > + * fdt_appendprop_addrrange() appends an address range value (start
> > + * address and size) to the value of the named property in the given
> > + * node, or creates a new property with that value if it does not
> > + * already exist.
> > + * If "name" is not specified, a default "reg" is used.
> > + * Cell sizes are determined by parent's #address-cells and #size-cells.
> > + *
> > + * This function may insert data into the blob, and will therefore
> > + * change the offsets of some existing nodes.
> > + *
> > + * returns:
> > + *     0, on success
> > + *     -FDT_ERR_BADLAYOUT,
> > + *     -FDT_ERR_BADMAGIC,
> > + *     -FDT_ERR_BADNCELLS, if the node has a badly formatted or invalid
> > + *             #address-cells property
> > + *     -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag
> > + *     -FDT_ERR_BADSTATE,
> > + *     -FDT_ERR_BADSTRUCTURE,
> > + *     -FDT_ERR_BADVERSION,
> > + *     -FDT_ERR_BADVALUE, addr or size doesn't fit to respective cells size
> > + *     -FDT_ERR_NOSPACE, there is insufficient free space in the blob to
> > + *             contain a new property
> > + *     -FDT_ERR_TRUNCATED, standard meanings
> > + */
> > +int fdt_appendprop_addrrange(void *fdt, int parent, int nodeoffset,
> > +                            const char *name, uint64_t addr, uint64_t size);
> > +
> >  /**
> >   * fdt_delprop - delete a property
> >   * @fdt: pointer to the device tree blob
> > diff --git a/scripts/dtc/libfdt/libfdt_env.h b/scripts/dtc/libfdt/libfdt_env.h
> > index 3ff9e28630..73b6d40450 100644
> > --- a/scripts/dtc/libfdt/libfdt_env.h
> > +++ b/scripts/dtc/libfdt/libfdt_env.h
> > @@ -1,55 +1,10 @@
> > +/* SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-2-Clause) */
> >  #ifndef LIBFDT_ENV_H
> >  #define LIBFDT_ENV_H
> >  /*
> >   * libfdt - Flat Device Tree manipulation
> >   * Copyright (C) 2006 David Gibson, IBM Corporation.
> >   * Copyright 2012 Kim Phillips, Freescale Semiconductor.
> > - *
> > - * libfdt is dual licensed: you can use it either under the terms of
> > - * the GPL, or the BSD license, at your option.
> > - *
> > - *  a) This library is free software; you can redistribute it and/or
> > - *     modify it under the terms of the GNU General Public License as
> > - *     published by the Free Software Foundation; either version 2 of the
> > - *     License, or (at your option) any later version.
> > - *
> > - *     This library is distributed in the hope that it will be useful,
> > - *     but WITHOUT ANY WARRANTY; without even the implied warranty of
> > - *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> > - *     GNU General Public License for more details.
> > - *
> > - *     You should have received a copy of the GNU General Public
> > - *     License along with this library; if not, write to the Free
> > - *     Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
> > - *     MA 02110-1301 USA
> > - *
> > - * Alternatively,
> > - *
> > - *  b) Redistribution and use in source and binary forms, with or
> > - *     without modification, are permitted provided that the following
> > - *     conditions are met:
> > - *
> > - *     1. Redistributions of source code must retain the above
> > - *        copyright notice, this list of conditions and the following
> > - *        disclaimer.
> > - *     2. Redistributions in binary form must reproduce the above
> > - *        copyright notice, this list of conditions and the following
> > - *        disclaimer in the documentation and/or other materials
> > - *        provided with the distribution.
> > - *
> > - *     THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
> > - *     CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
> > - *     INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
> > - *     MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
> > - *     DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
> > - *     CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
> > - *     SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
> > - *     NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
> > - *     LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
> > - *     HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
> > - *     CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
> > - *     OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
> > - *     EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
> >   */
> >
> >  #include <stdbool.h>
> > @@ -57,6 +12,7 @@
> >  #include <stdint.h>
> >  #include <stdlib.h>
> >  #include <string.h>
> > +#include <limits.h>
> >
> >  #ifdef __CHECKER__
> >  #define FDT_FORCE __attribute__((force))
> > diff --git a/scripts/dtc/libfdt/libfdt_internal.h b/scripts/dtc/libfdt/libfdt_internal.h
> > index 7681e19229..5436e2ceea 100644
> > --- a/scripts/dtc/libfdt/libfdt_internal.h
> > +++ b/scripts/dtc/libfdt/libfdt_internal.h
> > @@ -1,65 +1,24 @@
> > +/* SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-2-Clause) */
> >  #ifndef LIBFDT_INTERNAL_H
> >  #define LIBFDT_INTERNAL_H
> >  /*
> >   * libfdt - Flat Device Tree manipulation
> >   * Copyright (C) 2006 David Gibson, IBM Corporation.
> > - *
> > - * libfdt is dual licensed: you can use it either under the terms of
> > - * the GPL, or the BSD license, at your option.
> > - *
> > - *  a) This library is free software; you can redistribute it and/or
> > - *     modify it under the terms of the GNU General Public License as
> > - *     published by the Free Software Foundation; either version 2 of the
> > - *     License, or (at your option) any later version.
> > - *
> > - *     This library is distributed in the hope that it will be useful,
> > - *     but WITHOUT ANY WARRANTY; without even the implied warranty of
> > - *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> > - *     GNU General Public License for more details.
> > - *
> > - *     You should have received a copy of the GNU General Public
> > - *     License along with this library; if not, write to the Free
> > - *     Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
> > - *     MA 02110-1301 USA
> > - *
> > - * Alternatively,
> > - *
> > - *  b) Redistribution and use in source and binary forms, with or
> > - *     without modification, are permitted provided that the following
> > - *     conditions are met:
> > - *
> > - *     1. Redistributions of source code must retain the above
> > - *        copyright notice, this list of conditions and the following
> > - *        disclaimer.
> > - *     2. Redistributions in binary form must reproduce the above
> > - *        copyright notice, this list of conditions and the following
> > - *        disclaimer in the documentation and/or other materials
> > - *        provided with the distribution.
> > - *
> > - *     THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
> > - *     CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
> > - *     INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
> > - *     MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
> > - *     DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
> > - *     CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
> > - *     SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
> > - *     NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
> > - *     LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
> > - *     HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
> > - *     CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
> > - *     OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
> > - *     EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
> >   */
> >  #include <fdt.h>
> >
> >  #define FDT_ALIGN(x, a)                (((x) + (a) - 1) & ~((a) - 1))
> >  #define FDT_TAGALIGN(x)                (FDT_ALIGN((x), FDT_TAGSIZE))
> >
> > -#define FDT_CHECK_HEADER(fdt) \
> > -       { \
> > -               int err_; \
> > -               if ((err_ = fdt_check_header(fdt)) != 0) \
> > -                       return err_; \
> > +int fdt_ro_probe_(const void *fdt);
> > +#define FDT_RO_PROBE(fdt)                                      \
> > +       {                                                       \
> > +               int totalsize_;                                 \
> > +               if (fdt_chk_basic()) {                          \
> > +                       totalsize_ = fdt_ro_probe_(fdt);        \
> > +                       if (totalsize_ < 0)                     \
> > +                               return totalsize_;              \
> > +               }                                               \
> >         }
> >
> >  int fdt_check_node_offset_(const void *fdt, int offset);
> > @@ -92,4 +51,87 @@ static inline struct fdt_reserve_entry *fdt_mem_rsv_w_(void *fdt, int n)
> >
> >  #define FDT_SW_MAGIC           (~FDT_MAGIC)
> >
> > +/**********************************************************************/
> > +/* Checking controls                                                  */
> > +/**********************************************************************/
> > +
> > +#ifndef FDT_ASSUME_MASK
> > +#define FDT_ASSUME_MASK 0
> > +#endif
> > +
> > +/*
> > + * Defines assumptions which can be enabled. Each of these can be enabled
> > + * individually. For maximum saftey, don't enable any assumptions!
> > + *
> > + * For minimal code size and no safety, use FDT_ASSUME_PERFECT at your own risk.
> > + * You should have another method of validating the device tree, such as a
> > + * signature or hash check before using libfdt.
> > + *
> > + * For situations where security is not a concern it may be safe to enable
> > + * FDT_ASSUME_FRIENDLY.
> > + */
> > +enum {
> > +       /*
> > +        * This does essentially no checks. Only the latest device-tree
> > +        * version is correctly handled. Incosistencies or errors in the device
> > +        * tree may cause undefined behaviour or crashes.
> > +        *
> > +        * If an error occurs when modifying the tree it may leave the tree in
> > +        * an intermediate (but valid) state. As an example, adding a property
> > +        * where there is insufficient space may result in the property name
> > +        * being added to the string table even though the property itself is
> > +        * not added to the struct section.
> > +        *
> > +        * Only use this if you have a fully validated device tree with
> > +        * the latest supported version and wish to minimise code size.
> > +        */
> > +       FDT_ASSUME_PERFECT      = 0xff,
> > +
> > +       /*
> > +        * This assumes that the device tree is sane. i.e. header metadata
> > +        * and basic hierarchy are correct.
> > +        *
> > +        * These checks will be sufficient if you have a valid device tree with
> > +        * no internal inconsistencies. With this assumption, libfdt will
> > +        * generally not return -FDT_ERR_INTERNAL, -FDT_ERR_BADLAYOUT, etc.
> > +        */
> > +       FDT_ASSUME_SANE         = 1 << 0,
> > +
> > +       /*
> > +        * This disables checks for device-tree version and removes all code
> > +        * which handles older versions.
> > +        *
> > +        * Only enable this if you know you have a device tree with the latest
> > +        * version.
> > +        */
> > +       FDT_ASSUME_LATEST       = 1 << 1,
> > +
> > +       /*
> > +        * This disables any extensive checking of parameters and the device
> > +        * tree, making various assumptions about correctness. Normal device
> > +        * trees produced by libfdt and the compiler should be handled safely.
> > +        * Malicious device trees and complete garbage may cause libfdt to
> > +        * behave badly or crash.
> > +        */
> > +       FDT_ASSUME_FRIENDLY     = 1 << 2,
> > +};
> > +
> > +/** fdt_chk_basic() - see if basic checking of params and DT data is enabled */
> > +static inline bool fdt_chk_basic(void)
> > +{
> > +       return !(FDT_ASSUME_MASK & FDT_ASSUME_SANE);
> > +}
> > +
> > +/** fdt_chk_version() - see if we need to handle old versions of the DT */
> > +static inline bool fdt_chk_version(void)
> > +{
> > +       return !(FDT_ASSUME_MASK & FDT_ASSUME_LATEST);
> > +}
> > +
> > +/** fdt_chk_extra() - see if extra checking is enabled */
> > +static inline bool fdt_chk_extra(void)
> > +{
> > +       return !(FDT_ASSUME_MASK & FDT_ASSUME_FRIENDLY);
> > +}
> > +
> >  #endif /* LIBFDT_INTERNAL_H */
> > diff --git a/tools/libfdt/fdt_rw.c b/tools/libfdt/fdt_rw.c
> > index 68fc7c8c88..7189f01429 100644
> > --- a/tools/libfdt/fdt_rw.c
> > +++ b/tools/libfdt/fdt_rw.c
> > @@ -11,6 +11,7 @@ int fdt_remove_unused_strings(const void *old, void *new)
> >         const char *str;
> >         int ret;
> >         int tag = FDT_PROP;
> > +       int allocated;
> >
> >         /* Make a copy and remove the strings */
> >         memcpy(new, old, size);
> > @@ -25,7 +26,7 @@ int fdt_remove_unused_strings(const void *old, void *new)
> >                 new_prop = (struct fdt_property *)(unsigned long)
> >                         fdt_get_property_by_offset(new, offset, NULL);
> >                 str = fdt_string(old, fdt32_to_cpu(old_prop->nameoff));
> > -               ret = fdt_find_add_string_(new, str);
> > +               ret = fdt_find_add_string_(new, str, &allocated);
> >                 if (ret < 0)
> >                         return ret;
> >                 new_prop->nameoff = cpu_to_fdt32(ret);
> > --
> > 2.24.0.rc0.303.g954a862665-goog
> >
> > _______________________________________________
> > U-Boot mailing list
> > U-Boot at lists.denx.de
> > https://lists.denx.de/listinfo/u-boot

^ permalink raw reply	[flat|nested] 18+ messages in thread

end of thread, other threads:[~2020-01-08 13:56 UTC | newest]

Thread overview: 18+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-10-27 15:47 [U-Boot] [PATCH 0/4] fdt: Switch to the latest libfdt, sort-of Simon Glass
2019-10-27 15:47 ` [U-Boot] [PATCH 1/4] fdt: Add INT32_MAX to kernel.h for libfdt Simon Glass
2019-10-30 17:01   ` Tom Rini
2019-11-05 12:06   ` sjg at google.com
2019-10-27 15:47 ` [U-Boot] [PATCH 2/4] fdt: Add Kconfig options to control code size Simon Glass
2019-10-27 18:06   ` Heinrich Schuchardt
2019-10-27 18:49     ` Simon Glass
2019-10-28 14:01       ` Tom Rini
2019-10-30 17:02   ` Tom Rini
2019-11-05 12:06   ` sjg at google.com
2019-10-27 15:47 ` [U-Boot] [PATCH 3/4] mx6: tbs2910: Minimise libfdt " Simon Glass
2019-10-27 15:47 ` [U-Boot] [PATCH 4/4] fdt: Sync up to the latest libfdt Simon Glass
2020-01-07 11:43   ` Adam Ford
2020-01-08 13:56     ` Adam Ford
2019-10-28 14:04 ` [U-Boot] [PATCH 0/4] fdt: Switch to the latest libfdt, sort-of Tom Rini
2019-10-29  3:37   ` Simon Glass
2019-11-05 12:06 ` [U-Boot] [PATCH 4/4] fdt: Sync up to the latest libfdt sjg at google.com
2019-11-05 12:06 ` [U-Boot] [PATCH 3/4] mx6: tbs2910: Minimise libfdt code size sjg at google.com

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.