Upgrade dtc to v1.7.0

This project was upgraded with external_updater.
Usage: tools/external_updater/updater.sh update external/dtc
For more info, check https://cs.android.com/android/platform/superproject/+/main:tools/external_updater/README.md

Test: TreeHugger
Change-Id: I7c3774a5f8fbc6ddf0926df9db3450c4dce54cf9
diff --git a/Documentation/manual.txt b/Documentation/manual.txt
index cf4b253..2087a4d 100644
--- a/Documentation/manual.txt
+++ b/Documentation/manual.txt
@@ -43,9 +43,8 @@
 
 1.1) Submitting Patches
 
-Patches should be sent to the maintainers:
+Patches should be sent to the maintainer:
 	David Gibson <david@gibson.dropbear.id.au>
-	Jon Loeliger <loeliger@gmail.com>
 and CCed to <devicetree-compiler@vger.kernel.org>.
 
 2) Description
diff --git a/MANIFEST.in b/MANIFEST.in
index 0eee931..c1c5e67 100644
--- a/MANIFEST.in
+++ b/MANIFEST.in
@@ -1,7 +1,7 @@
 # SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-2-Clause)
 
 global-exclude *
-include README
+include README.md
 include GPL
 include BSD-2-Clause
 include setup.py
diff --git a/METADATA b/METADATA
index a716954..8962629 100644
--- a/METADATA
+++ b/METADATA
@@ -1,19 +1,19 @@
 # This project was upgraded with external_updater.
-# Usage: tools/external_updater/updater.sh update dtc
-# For more info, check https://cs.android.com/android/platform/superproject/+/master:tools/external_updater/README.md
+# Usage: tools/external_updater/updater.sh update external/dtc
+# For more info, check https://cs.android.com/android/platform/superproject/+/main:tools/external_updater/README.md
 
 name: "dtc"
 description: "Device tree compiler tools (dtc) and libfdt."
 third_party {
-  url {
-    type: GIT
-    value: "https://git.kernel.org/pub/scm/utils/dtc/dtc.git"
-  }
-  version: "v1.6.1"
   license_type: RESTRICTED
   last_upgrade_date {
-    year: 2023
-    month: 1
-    day: 18
+    year: 2024
+    month: 3
+    day: 26
+  }
+  identifier {
+    type: "Git"
+    value: "https://git.kernel.org/pub/scm/utils/dtc/dtc.git"
+    version: "v1.7.0"
   }
 }
diff --git a/Makefile b/Makefile
index 7fe25f6..fa772cc 100644
--- a/Makefile
+++ b/Makefile
@@ -10,8 +10,8 @@
 # CONFIG_LOCALVERSION from some future config system.
 #
 VERSION = 1
-PATCHLEVEL = 6
-SUBLEVEL = 1
+PATCHLEVEL = 7
+SUBLEVEL = 0
 EXTRAVERSION =
 LOCAL_VERSION =
 CONFIG_LOCALVERSION =
@@ -384,7 +384,7 @@
 	@$(VECHO) LEX $@
 	$(LEX) -o$@ $<
 
-%.tab.c %.tab.h %.output: %.y
+%.tab.c %.tab.h: %.y
 	@$(VECHO) BISON $@
 	$(BISON) -b $(basename $(basename $@)) -d $<
 
@@ -393,3 +393,7 @@
 	ln -s $^ $@
 
 FORCE:
+
+ifeq ($(MAKE_RESTARTS),10)
+$(error "Make re-executed itself $(MAKE_RESTARTS) times. Infinite recursion?")
+endif
diff --git a/checks.c b/checks.c
index 9f31d26..69f2649 100644
--- a/checks.c
+++ b/checks.c
@@ -1222,7 +1222,7 @@
 	if (!node->parent || node->addr_cells < 0 || node->size_cells < 0)
 		return;
 
-	if (get_property(node, "ranges") || !node->children)
+	if (get_property(node, "ranges") || get_property(node, "dma-ranges") || !node->children)
 		return;
 
 	for_each_child(node, child) {
@@ -1232,7 +1232,7 @@
 	}
 
 	if (!has_reg)
-		FAIL(c, dti, node, "unnecessary #address-cells/#size-cells without \"ranges\" or child \"reg\" property");
+		FAIL(c, dti, node, "unnecessary #address-cells/#size-cells without \"ranges\", \"dma-ranges\" or child \"reg\" property");
 }
 WARNING(avoid_unnecessary_addr_size, check_avoid_unnecessary_addr_size, NULL, &avoid_default_addr_size);
 
diff --git a/dtc-parser.y b/dtc-parser.y
index b4acf7f..aeed79c 100644
--- a/dtc-parser.y
+++ b/dtc-parser.y
@@ -409,9 +409,14 @@
 				 * within the mask to one (i.e. | in the
 				 * mask), all bits are one.
 				 */
-				if (($2 > mask) && (($2 | mask) != -1ULL))
-					ERROR(&@2, "Value out of range for"
-					      " %d-bit array element", $1.bits);
+				if (($2 > mask) && (($2 | mask) != -1ULL)) {
+					char *loc = srcpos_string(&@2);
+					fprintf(stderr,
+						"WARNING: %s: Value 0x%016" PRIx64
+						" truncated to 0x%0*" PRIx64 "\n",
+						loc, $2, $1.bits / 4, ($2 & mask));
+					free(loc);
+				}
 			}
 
 			$$.data = data_append_integer($1.data, $2, $1.bits);
diff --git a/libfdt/fdt.c b/libfdt/fdt.c
index b8ffb33..dda342d 100644
--- a/libfdt/fdt.c
+++ b/libfdt/fdt.c
@@ -106,7 +106,6 @@
 	}
 	hdrsize = fdt_header_size(fdt);
 	if (!can_assume(VALID_DTB)) {
-
 		if ((fdt_totalsize(fdt) < hdrsize)
 		    || (fdt_totalsize(fdt) > INT_MAX))
 			return -FDT_ERR_TRUNCATED;
@@ -115,9 +114,7 @@
 		if (!check_off_(hdrsize, fdt_totalsize(fdt),
 				fdt_off_mem_rsvmap(fdt)))
 			return -FDT_ERR_TRUNCATED;
-	}
 
-	if (!can_assume(VALID_DTB)) {
 		/* Bounds check structure block */
 		if (!can_assume(LATEST) && fdt_version(fdt) < 17) {
 			if (!check_off_(hdrsize, fdt_totalsize(fdt),
diff --git a/libfdt/fdt.h b/libfdt/fdt.h
index f2e6880..0c91aa7 100644
--- a/libfdt/fdt.h
+++ b/libfdt/fdt.h
@@ -35,14 +35,14 @@
 
 struct fdt_node_header {
 	fdt32_t tag;
-	char name[0];
+	char name[];
 };
 
 struct fdt_property {
 	fdt32_t tag;
 	fdt32_t len;
 	fdt32_t nameoff;
-	char data[0];
+	char data[];
 };
 
 #endif /* !__ASSEMBLY */
diff --git a/libfdt/fdt_check.c b/libfdt/fdt_check.c
index 71390ee..a21ebbc 100644
--- a/libfdt/fdt_check.c
+++ b/libfdt/fdt_check.c
@@ -66,7 +66,10 @@
 				int len;
 
 				name = fdt_get_name(fdt, offset, &len);
-				if (!name || *name || len)
+				if (!name)
+					return len;
+
+				if (*name || len)
 					return -FDT_ERR_BADSTRUCTURE;
 			}
 			break;
diff --git a/libfdt/libfdt.h b/libfdt/libfdt.h
index a7f432c..d0a2ed2 100644
--- a/libfdt/libfdt.h
+++ b/libfdt/libfdt.h
@@ -660,6 +660,13 @@
 const struct fdt_property *fdt_get_property_by_offset(const void *fdt,
 						      int offset,
 						      int *lenp);
+static inline struct fdt_property *fdt_get_property_by_offset_w(void *fdt,
+								int offset,
+								int *lenp)
+{
+	return (struct fdt_property *)(uintptr_t)
+		fdt_get_property_by_offset(fdt, offset, lenp);
+}
 
 /**
  * fdt_get_property_namelen - find a property based on substring
diff --git a/livetree.c b/livetree.c
index 169462d..f46a098 100644
--- a/livetree.c
+++ b/livetree.c
@@ -919,6 +919,12 @@
 	/* m->ref can only be a REF_PHANDLE, but check anyway */
 	assert(m->type == REF_PHANDLE);
 
+	/* The format only permits fixups for references to label, not
+	 * references to path */
+	if (strchr(m->ref, '/'))
+		die("Can't generate fixup for reference to path &{%s}\n",
+		    m->ref);
+
 	/* there shouldn't be any ':' in the arguments */
 	if (strchr(node->fullpath, ':') || strchr(prop->name, ':'))
 		die("arguments should not contain ':'\n");
diff --git a/pylibfdt/libfdt.i b/pylibfdt/libfdt.i
index f9f7e7e..2361e22 100644
--- a/pylibfdt/libfdt.i
+++ b/pylibfdt/libfdt.i
@@ -443,11 +443,12 @@
         """
         return fdt_get_alias(self._fdt, name)
 
-    def get_path(self, nodeoffset, quiet=()):
+    def get_path(self, nodeoffset, size_hint=1024, quiet=()):
         """Get the full path of a node
 
         Args:
             nodeoffset: Node offset to check
+            size_hint: Hint for size of returned string
 
         Returns:
             Full path to the node
@@ -455,11 +456,10 @@
         Raises:
             FdtException if an error occurs
         """
-        size = 1024
         while True:
-            ret, path = fdt_get_path(self._fdt, nodeoffset, size)
+            ret, path = fdt_get_path(self._fdt, nodeoffset, size_hint)
             if ret == -NOSPACE:
-                size = size * 2
+                size_hint *= 2
                 continue
             err = check_err(ret, quiet)
             if err:
@@ -1036,6 +1036,9 @@
 
 %rename(fdt_property) fdt_property_func;
 
+%immutable fdt_property::data;
+%immutable fdt_node_header::name;
+
 /*
  * fdt32_t is a big-endian 32-bit value defined to uint32_t in libfdt_env.h
  * so use the same type here.
diff --git a/setup.py b/setup.py
index a8e54a3..e82a832 100755
--- a/setup.py
+++ b/setup.py
@@ -19,7 +19,7 @@
 
 srcdir = os.path.dirname(__file__)
 
-with open(os.path.join(srcdir, "README"), "r") as fh:
+with open(os.path.join(srcdir, "README.md"), "r") as fh:
     long_description = fh.read()
 
 def get_top_builddir():
diff --git a/tests/.gitignore b/tests/.gitignore
index 03bdde2..3376ed9 100644
--- a/tests/.gitignore
+++ b/tests/.gitignore
@@ -74,3 +74,4 @@
 /truncated_memrsv
 /utilfdt_test
 /value-labels
+/get_next_tag_invalid_prop_len
diff --git a/tests/Makefile.tests b/tests/Makefile.tests
index 2d36c5d..2c5b4c9 100644
--- a/tests/Makefile.tests
+++ b/tests/Makefile.tests
@@ -4,7 +4,7 @@
 	get_path supernode_atdepth_offset parent_offset \
 	node_offset_by_prop_value node_offset_by_phandle \
 	node_check_compatible node_offset_by_compatible \
-	get_alias \
+	get_alias get_next_tag_invalid_prop_len \
 	char_literal \
 	sized_cells \
 	notfound \
diff --git a/tests/cell-overflow-results.dts b/tests/cell-overflow-results.dts
new file mode 100644
index 0000000..e7f6dad
--- /dev/null
+++ b/tests/cell-overflow-results.dts
@@ -0,0 +1,7 @@
+/dts-v1/;
+
+/ {
+	prop1 = < 0 >;
+	prop2 = < 0xffffffff >;
+	prop3 = < 0 >;
+};
diff --git a/tests/cell-overflow.dts b/tests/cell-overflow.dts
new file mode 100644
index 0000000..2f940e8
--- /dev/null
+++ b/tests/cell-overflow.dts
@@ -0,0 +1,7 @@
+/dts-v1/;
+
+/ {
+	prop1 = < (-0xffffffff - 1) >;
+	prop2 = < (-0xffffffff - 2) >;
+	prop3 = < ((-0xffffffff - 1) * 2) >;
+};
diff --git a/tests/fixup-ref-to-path.dts b/tests/fixup-ref-to-path.dts
new file mode 100644
index 0000000..f6dcba0
--- /dev/null
+++ b/tests/fixup-ref-to-path.dts
@@ -0,0 +1,6 @@
+/dts-v1/;
+/plugin/;
+
+/ {
+	prop = < &{/path/to/node} >;
+};
diff --git a/tests/get_next_tag_invalid_prop_len.c b/tests/get_next_tag_invalid_prop_len.c
new file mode 100644
index 0000000..25d57c3
--- /dev/null
+++ b/tests/get_next_tag_invalid_prop_len.c
@@ -0,0 +1,100 @@
+// SPDX-License-Identifier: LGPL-2.1-or-later
+/*
+ * libfdt - Flat Device Tree manipulation
+ *	Testcase for fdt_next_tag()
+ */
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdint.h>
+
+#include <libfdt.h>
+#include "tests.h"
+#include "testdata.h"
+
+#define FDT_SIZE 65536
+#define CHECK_ERR(err) \
+({ if (err) \
+	FAIL("%s: %d: %s", __FILE__, __LINE__, fdt_strerror(err)); \
+})
+
+static void fdt_next_tag_test(bool fdt_finished)
+{
+	struct fdt_property *prp;
+	void *fdt;
+	int nextoff = 0, offset, err;
+	uint32_t tag;
+
+	fdt = malloc(FDT_SIZE);
+	if (!fdt)
+		FAIL("Can't allocate memory");
+	err = fdt_create(fdt, FDT_SIZE);
+	CHECK_ERR(err);
+	err = fdt_finish_reservemap(fdt);
+	CHECK_ERR(err);
+	/* Create a root node and add two properties */
+	err = fdt_begin_node(fdt, "");
+	CHECK_ERR(err);
+	err = fdt_property_u32(fdt, "prop-int-32", 0x1234);
+	CHECK_ERR(err);
+	err = fdt_property_u32(fdt, "prop2-int-32", 0x4321);
+	CHECK_ERR(err);
+	err = fdt_end_node(fdt);
+	CHECK_ERR(err);
+	if (fdt_finished) {
+		/* Call fdt_finish to set the correct fdt state. */
+		err = fdt_finish(fdt);
+		CHECK_ERR(err);
+	}
+
+	offset = fdt_first_property_offset(fdt, 0);
+	if (offset <= 0)
+		FAIL("Invalid offset %x, expected value greater than 0, finished=%d\n",
+		     offset, fdt_finished);
+
+	/* Normal case */
+	tag = fdt_next_tag(fdt, offset, &nextoff);
+	if (tag != FDT_PROP)
+		FAIL("Invalid tag %x, expected FDT_PROP, finished=%d\n",
+		     tag, fdt_finished);
+	if (nextoff <= 0)
+		FAIL("Invalid nextoff %d, expected value greater than 0, finished=%d",
+		     nextoff, fdt_finished);
+
+	/* Get a writable ptr to the first property and corrupt the length */
+	prp = fdt_get_property_by_offset_w(fdt, offset, NULL);
+	if (!prp)
+		FAIL("Bad property pointer, finished=%d", fdt_finished);
+
+	/* int overflow case */
+	prp->len = cpu_to_fdt32(0xFFFFFFFA);
+	tag = fdt_next_tag(fdt, offset, &nextoff);
+	if (tag != FDT_END)
+		FAIL("Invalid tag %x, expected premature FDT_END, finished=%d",
+		     tag, fdt_finished);
+	if (nextoff != -FDT_ERR_BADSTRUCTURE)
+		FAIL("Invalid nextoff, expected error -FDT_ERR_BADSTRUCTURE, finished=%d",
+		     fdt_finished);
+
+	/* negative offset case */
+	prp->len = cpu_to_fdt32(0x7FFFFFFA);
+	tag = fdt_next_tag(fdt, offset, &nextoff);
+	if (tag != FDT_END)
+		FAIL("Invalid tag %x, expected premature FDT_END, finished=%d",
+		     tag, fdt_finished);
+	if (nextoff != -FDT_ERR_BADSTRUCTURE)
+		FAIL("Invalid nextoff, expected -FDT_ERR_BADSTRUCTURE, finished=%d",
+		     fdt_finished);
+
+	free(fdt);
+}
+
+int main(int argc, char *argv[])
+{
+	test_init(argc, argv);
+
+	fdt_next_tag_test(false);
+	fdt_next_tag_test(true);
+
+	PASS();
+}
diff --git a/tests/meson.build b/tests/meson.build
index 4ac154a..29a42dd 100644
--- a/tests/meson.build
+++ b/tests/meson.build
@@ -47,6 +47,7 @@
   'get_path',
   'get_phandle',
   'get_prop_offset',
+  'get_next_tag_invalid_prop_len',
   'getprop',
   'incbin',
   'integer-expressions',
diff --git a/tests/pylibfdt_tests.py b/tests/pylibfdt_tests.py
index 68d6aaa..34c2764 100644
--- a/tests/pylibfdt_tests.py
+++ b/tests/pylibfdt_tests.py
@@ -354,6 +354,7 @@
         node2 = self.fdt.path_offset('/subnode@1/subsubnode')
         self.assertEqual("/subnode@1", self.fdt.get_path(node))
         self.assertEqual("/subnode@1/subsubnode", self.fdt.get_path(node2))
+        self.assertEqual("/subnode@1/subsubnode", self.fdt.get_path(node2, size_hint=1))
 
         with self.assertRaises(FdtException) as e:
             self.fdt.get_path(-1)
diff --git a/tests/run_tests.sh b/tests/run_tests.sh
index 0cabd13..91350ad 100755
--- a/tests/run_tests.sh
+++ b/tests/run_tests.sh
@@ -271,6 +271,7 @@
 	run_dtc_test -I dts -O dtb -o $tree.test.dtb "$SRCDIR/$tree.dts"
 	run_test overlay_bad_fixup overlay_base_no_symbols.test.dtb $tree.test.dtb
     done
+    run_sh_test "$SRCDIR/dtc-fatal.sh" -I dts -O dtb -o /dev/null fixup-ref-to-path.dts
 }
 
 # Tests to exercise dtc's overlay generation support
@@ -512,10 +513,16 @@
     run_dtc_test -I fs -O dts -o fs.test_tree1.test.dts $FSBASE/test_tree1
     run_dtc_test -I fs -O dtb -o fs.test_tree1.test.dtb $FSBASE/test_tree1
     run_test dtbs_equal_unordered -m fs.test_tree1.test.dtb test_tree1.dtb
+    run_test get_next_tag_invalid_prop_len
 
     ## https://github.com/dgibson/dtc/issues/64
     check_tests "$SRCDIR/phandle-args-overflow.dts" clocks_property
 
+    ## https://github.com/dgibson/dtc/issues/74
+    run_dtc_test -I dts -O dtb -o cell-overflow-results.test.dtb cell-overflow-results.dts
+    run_dtc_test -I dts -O dtb -o cell-overflow.test.dtb cell-overflow.dts
+    run_test dtbs_equal_ordered cell-overflow.test.dtb cell-overflow-results.test.dtb
+
     # check full tests
     for good in test_tree1.dtb; do
 	run_test check_full $good