[REGRESSION] scripts/dtc: Update to upstream version v1.7.2-35-g52f07dcca47c

Anshul Dalal anshuld at ti.com
Thu Jan 8 14:51:10 CET 2026


CC+: TI folks

On Thu Jan 8, 2026 at 7:15 PM IST, Anshul Dalal wrote:
> Hi all,
>
> On Wed Dec 3, 2025 at 1:02 AM IST, Marek Vasut wrote:
>> Synchronize local copy of DTC with Linux 6.17 . This includes the
>> following picked and squashed commits from Linux kernel. The squash
>> was necessary, since the DTC here contains changes which were also
>> part of DTC in Linux alraedy, and the squash helped resolve those
>> without going back and forth with the changes.
>>
>> The following commits from Linux are picked:
>>
>> 8f324cd712df7 # scripts/dtc: consolidate include path options in Makefile
>> b5b3d9b63b0ee # scripts/dtc: Add yamltree.c to dtc sources
>> 7d97a76f226d6 # scripts/dtc: Update to upstream version v1.4.7-14-gc86da84d30e4
>> ea6f243be74e5 # scripts/dtc: Update to upstream version v1.4.7-57-gf267e674d145
>> 02d435d4eccd8 # scripts/dtc: Update to upstream version v1.5.0-23-g87963ee20693
>> 6e321b7637396 # scripts/dtc: Update to upstream version v1.5.0-30-g702c1b6c0e73
>> 9f19ec91a7a35 # scripts/dtc: dtx_diff - add color output support
>> 8287d642f38d1 # scripts/dtc: Update to upstream version v1.5.1-22-gc40aeb60b47a
>> 4c52deef9225d # scripts/dtc: Revert "yamltree: Ensure consistent bracketing of properties with phandles"
>> 5d3827e1452ed # scripts/dtc: Remove unused makefile fragments
>> 40dd266887654 # scripts/dtc: Update to upstream version v1.6.0-2-g87a656ae5ff9
>> 8d4cf6b6acb59 # scripts/dtc: use pkg-config to include <yaml.h> in non-standard path
>> b9bf9ace5ae90 # scripts/dtc: Update to upstream version v1.6.0-11-g9d7888cbf19c
>> 69a883b6f5ac0 # scripts/dtc: dtx_diff - make help text formatting consistent
>> 8f829108b8aed # scripts/dtc: only append to HOST_EXTRACFLAGS instead of overwriting
>> b39b4342ac495 # scripts/dtc: Update to upstream version v1.6.0-31-gcbca977ea121
>> 93c6424c486b3 # scripts: dtc: Fetch fdtoverlay.c from external DTC project
>> 0dd574a1d75c3 # scripts/dtc: Update to upstream version v1.6.0-51-g183df9e9c2b9
>> ec38b5df8a231 # scripts: dtc: Build fdtoverlay tool
>> a0c8c431411f5 # scripts: dtc: Remove the unused fdtdump.c file
>> e7dc653d4e890 # scripts/dtc: Add missing fdtoverlay to gitignore
>> d2bf5d2e3f09c # scripts/dtc: Update to upstream version v1.6.1-19-g0a3a9d3449c8
>> a60878f5532d0 # scripts/dtc: dtx_diff: remove broken example from help text
>> 8b739d8658a9b # scripts/dtc: Call pkg-config POSIXly correct
>> b6eeafa67df00 # scripts/dtc: Update to upstream version v1.6.1-63-g55778a03df61
>> f96cc4c787588 # scripts/dtc: Update to upstream version v1.6.1-66-gabbd523bae6e
>> 09ab9c092ef2b # scripts/dtc: Update to upstream version v1.7.0-93-g1df7b047fe43
>> ded8a5a498f2d # scripts/dtc: Update to upstream version v1.7.0-95-gbcd02b523429
>> ee6ff6fca7e71 # scripts/dtc: Update to upstream version v1.7.2-35-g52f07dcca47c
>>
>> This also includes forward port of U-Boot commit
>> e8c2d25845c7 ("libfdt: Revert 6dcb8ba4 from upstream libfdt")
>> to avoid binary size growth.
>>
>> Signed-off-by: Marek Vasut <marek.vasut+renesas at mailbox.org>
>> ---
>> Cc: Adriano Cordova <adrianox at gmail.com>
>> Cc: Andrew Goodbody <andrew.goodbody at linaro.org>
>> Cc: Christian Marangi <ansuelsmth at gmail.com>
>> Cc: Heinrich Schuchardt <xypron.glpk at gmx.de>
>> Cc: Ilias Apalodimas <ilias.apalodimas at linaro.org>
>> Cc: Patrice Chotard <patrice.chotard at foss.st.com>
>> Cc: Sam Edwards <cfsworks at gmail.com>
>> Cc: Simon Glass <sjg at chromium.org>
>> Cc: Tom Rini <trini at konsulko.com>
>> Cc: u-boot at lists.denx.de
>
> We observed several boot failures on K3 platforms since the addition of
> this patch at the R5 SPL stage, the issue seems to be the newly added
> check for alignment in fdt_check_header in scripts/dtc/libfdt/fdt.c:95
> but the binaries generated don't have 8-byte aligned FDTs.
>
> I have been able to reproduce the issue on AM62p EVM with a clean
> working directory (this is important since any minor change to the
> SPL binary size such as by the added "-dirty" tag could make the address
> aligned) and GCC 13.3[1].
>
> Are we ensuring the fdt present in the SPL binary is properly aligned?
>
> [1]: https://armkeil.blob.core.windows.net/developer/Files/downloads/gnu/13.3.rel1/binrel/arm-gnu-toolchain-13.3.rel1-x86_64-arm-none-eabi.tar.xz
>
> Regards,
> Anshul
>
>> ---
>> V2: - Fix off-by-one in fdt_remove_unused_strings()
>>     - Restore e8c2d25845c7 ("libfdt: Revert 6dcb8ba4 from upstream libfdt")
>> ---
>>  scripts/Makefile.lib                 |   4 +-
>>  scripts/dtc/.gitignore               |   1 +
>>  scripts/dtc/Makefile                 |  23 +-
>>  scripts/dtc/Makefile.dtc             |  18 -
>>  scripts/dtc/checks.c                 | 686 +++++++++++++++++++++------
>>  scripts/dtc/data.c                   |  74 ++-
>>  scripts/dtc/dtc-lexer.l              |  38 +-
>>  scripts/dtc/dtc-parser.y             | 109 +++--
>>  scripts/dtc/dtc.c                    |  58 ++-
>>  scripts/dtc/dtc.h                    | 137 ++++--
>>  scripts/dtc/fdtoverlay.c             | 214 +++++++++
>>  scripts/dtc/flattree.c               |  70 ++-
>>  scripts/dtc/fstree.c                 |  26 +-
>>  scripts/dtc/libfdt/fdt.c             |  84 ++--
>>  scripts/dtc/libfdt/fdt.h             |   4 +-
>>  scripts/dtc/libfdt/fdt_addresses.c   |   2 +-
>>  scripts/dtc/libfdt/fdt_overlay.c     | 386 +++++++++++----
>>  scripts/dtc/libfdt/fdt_ro.c          | 100 ++--
>>  scripts/dtc/libfdt/fdt_rw.c          | 101 ++--
>>  scripts/dtc/libfdt/fdt_strerror.c    |   1 +
>>  scripts/dtc/libfdt/fdt_sw.c          |  26 +-
>>  scripts/dtc/libfdt/libfdt.h          | 414 +++++++++++++---
>>  scripts/dtc/libfdt/libfdt_internal.h | 141 ++++--
>>  scripts/dtc/livetree.c               | 156 +++---
>>  scripts/dtc/srcpos.c                 | 190 ++++++--
>>  scripts/dtc/srcpos.h                 |  31 +-
>>  scripts/dtc/treesource.c             | 319 ++++++++-----
>>  scripts/dtc/update-dtc-source.sh     |   7 +-
>>  scripts/dtc/util.c                   | 122 ++---
>>  scripts/dtc/util.h                   |  61 +--
>>  scripts/dtc/version_gen.h            |   2 +-
>>  scripts/dtc/yamltree.c               | 235 +++++++++
>>  tools/libfdt/fdt_rw.c                |   2 +-
>>  33 files changed, 2830 insertions(+), 1012 deletions(-)
>>  delete mode 100644 scripts/dtc/Makefile.dtc
>>  create mode 100644 scripts/dtc/fdtoverlay.c
>>  create mode 100644 scripts/dtc/yamltree.c
>>
>> diff --git a/scripts/Makefile.lib b/scripts/Makefile.lib
>> index 791eb1cb327..b062db7e87f 100644
>> --- a/scripts/Makefile.lib
>> +++ b/scripts/Makefile.lib
>> @@ -319,6 +319,7 @@ quiet_cmd_gzip = GZIP    $@
>>  # DTC
>>  # ---------------------------------------------------------------------------
>>  DTC ?= $(objtree)/scripts/dtc/dtc
>> +DTC_FLAGS += -Wno-interrupt_provider
>>  
>>  # Disable noisy checks by default
>>  ifeq ($(findstring 1,$(KBUILD_ENABLE_EXTRA_GCC_CHECKS)),)
>> @@ -338,7 +339,8 @@ endif
>>  
>>  ifneq ($(findstring 2,$(KBUILD_ENABLE_EXTRA_GCC_CHECKS)),)
>>  DTC_FLAGS += -Wnode_name_chars_strict \
>> -	-Wproperty_name_chars_strict
>> +	-Wproperty_name_chars_strict \
>> +	-Winterrupt_provider
>>  endif
>>  
>>  DTC_FLAGS += $(DTC_FLAGS_$(basetarget))
>> diff --git a/scripts/dtc/.gitignore b/scripts/dtc/.gitignore
>> index 689b9be0f93..60984f72e27 100644
>> --- a/scripts/dtc/.gitignore
>> +++ b/scripts/dtc/.gitignore
>> @@ -1 +1,2 @@
>>  /dtc
>> +/fdtoverlay
>> diff --git a/scripts/dtc/Makefile b/scripts/dtc/Makefile
>> index faa72d95e28..73081b17d18 100644
>> --- a/scripts/dtc/Makefile
>> +++ b/scripts/dtc/Makefile
>> @@ -1,15 +1,32 @@
>>  # SPDX-License-Identifier: GPL-2.0
>>  # scripts/dtc makefile
>>  
>> -hostprogs-y	:= dtc
>> -always		:= $(hostprogs-y)
>> +# *** Also keep .gitignore in sync when changing ***
>> +hostprogs-y	+= dtc fdtoverlay
>> +always		+= dtc
>>  
>>  dtc-objs	:= dtc.o flattree.o fstree.o data.o livetree.o treesource.o \
>>  		   srcpos.o checks.o util.o
>>  dtc-objs	+= dtc-lexer.lex.o dtc-parser.tab.o
>>  
>> +# The upstream project builds libfdt as a separate library.  We are choosing to
>> +# instead directly link the libfdt object files into fdtoverlay.
>> +libfdt-objs	:= fdt.o fdt_ro.o fdt_wip.o fdt_sw.o fdt_rw.o fdt_strerror.o fdt_empty_tree.o fdt_addresses.o fdt_overlay.o
>> +libfdt		= $(addprefix libfdt/,$(libfdt-objs))
>> +fdtoverlay-objs	:= $(libfdt) fdtoverlay.o util.o
>> +
>>  # Source files need to get at the userspace version of libfdt_env.h to compile
>> -HOST_EXTRACFLAGS := -I$(src)/libfdt
>> +HOST_EXTRACFLAGS += -I$(src)/libfdt
>> +
>> +ifeq ($(wildcard /usr/include/yaml.h),)
>> +HOST_EXTRACFLAGS += -DNO_YAML
>> +else
>> +dtc-objs	+= yamltree.o
>> +# To include <yaml.h> installed in a non-default path
>> +HOSTCFLAGS_yamltree.o := $(shell pkg-config --cflags yaml-0.1)
>> +# To link libyaml installed in a non-default path
>> +HOSTLDLIBS_dtc	:= $(shell pkg-config --libs yaml-0.1)
>> +endif
>>  
>>  # Generated files need one more search path to include headers in source tree
>>  HOSTCFLAGS_dtc-lexer.lex.o := -I$(src)
>> diff --git a/scripts/dtc/Makefile.dtc b/scripts/dtc/Makefile.dtc
>> deleted file mode 100644
>> index bece49b3553..00000000000
>> --- a/scripts/dtc/Makefile.dtc
>> +++ /dev/null
>> @@ -1,18 +0,0 @@
>> -# Makefile.dtc
>> -#
>> -# This is not a complete Makefile of itself.  Instead, it is designed to
>> -# be easily embeddable into other systems of Makefiles.
>> -#
>> -DTC_SRCS = \
>> -	checks.c \
>> -	data.c \
>> -	dtc.c \
>> -	flattree.c \
>> -	fstree.c \
>> -	livetree.c \
>> -	srcpos.c \
>> -	treesource.c \
>> -	util.c
>> -
>> -DTC_GEN_SRCS = dtc-lexer.lex.c dtc-parser.tab.c
>> -DTC_OBJS = $(DTC_SRCS:%.c=%.o) $(DTC_GEN_SRCS:%.c=%.o)
>> diff --git a/scripts/dtc/checks.c b/scripts/dtc/checks.c
>> index 2feec44a0f7..d10c49eeb2a 100644
>> --- a/scripts/dtc/checks.c
>> +++ b/scripts/dtc/checks.c
>> @@ -1,24 +1,10 @@
>> +// SPDX-License-Identifier: GPL-2.0-or-later
>>  /*
>>   * (C) Copyright David Gibson <dwg at au1.ibm.com>, IBM Corporation.  2007.
>> - *
>> - *
>> - * This program 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 program 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 program; if not, write to the Free Software
>> - *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307
>> - *                                                                   USA
>>   */
>>  
>>  #include "dtc.h"
>> +#include "srcpos.h"
>>  
>>  #ifdef TRACE_CHECKS
>>  #define TRACE(c, ...) \
>> @@ -45,7 +31,7 @@ typedef void (*check_fn)(struct check *c, struct dt_info *dti, struct node *node
>>  struct check {
>>  	const char *name;
>>  	check_fn fn;
>> -	void *data;
>> +	const void *data;
>>  	bool warn, error;
>>  	enum checkstatus status;
>>  	bool inprogress;
>> @@ -78,23 +64,57 @@ static inline void  PRINTF(5, 6) check_msg(struct check *c, struct dt_info *dti,
>>  					   const char *fmt, ...)
>>  {
>>  	va_list ap;
>> -	va_start(ap, fmt);
>> +	char *str = NULL;
>> +	struct srcpos *pos = NULL;
>> +	char *file_str;
>> +
>> +	if (!(c->warn && (quiet < 1)) && !(c->error && (quiet < 2)))
>> +		return;
>>  
>> -	if ((c->warn && (quiet < 1))
>> -	    || (c->error && (quiet < 2))) {
>> -		fprintf(stderr, "%s: %s (%s): ",
>> -			strcmp(dti->outname, "-") ? dti->outname : "<stdout>",
>> +	if (prop && prop->srcpos)
>> +		pos = prop->srcpos;
>> +	else if (node && node->srcpos)
>> +		pos = node->srcpos;
>> +
>> +	if (pos) {
>> +		file_str = srcpos_string(pos);
>> +		xasprintf(&str, "%s", file_str);
>> +		free(file_str);
>> +	} else if (streq(dti->outname, "-")) {
>> +		xasprintf(&str, "<stdout>");
>> +	} else {
>> +		xasprintf(&str, "%s", dti->outname);
>> +	}
>> +
>> +	xasprintf_append(&str, ": %s (%s): ",
>>  			(c->error) ? "ERROR" : "Warning", c->name);
>> -		if (node) {
>> -			fprintf(stderr, "%s", node->fullpath);
>> -			if (prop)
>> -				fprintf(stderr, ":%s", prop->name);
>> -			fputs(": ", stderr);
>> -		}
>> -		vfprintf(stderr, fmt, ap);
>> -		fprintf(stderr, "\n");
>> +
>> +	if (node) {
>> +		if (prop)
>> +			xasprintf_append(&str, "%s:%s: ", node->fullpath, prop->name);
>> +		else
>> +			xasprintf_append(&str, "%s: ", node->fullpath);
>>  	}
>> +
>> +	va_start(ap, fmt);
>> +	xavsprintf_append(&str, fmt, ap);
>>  	va_end(ap);
>> +
>> +	xasprintf_append(&str, "\n");
>> +
>> +	if (!prop && pos) {
>> +		pos = node->srcpos;
>> +		while (pos->next) {
>> +			pos = pos->next;
>> +
>> +			file_str = srcpos_string(pos);
>> +			xasprintf_append(&str, "  also defined at %s\n", file_str);
>> +			free(file_str);
>> +		}
>> +	}
>> +
>> +	fputs(str, stderr);
>> +	free(str);
>>  }
>>  
>>  #define FAIL(c, dti, node, ...)						\
>> @@ -123,6 +143,14 @@ static void check_nodes_props(struct check *c, struct dt_info *dti, struct node
>>  		check_nodes_props(c, dti, child);
>>  }
>>  
>> +static bool is_multiple_of(int multiple, int divisor)
>> +{
>> +	if (divisor == 0)
>> +		return multiple == 0;
>> +	else
>> +		return (multiple % divisor) == 0;
>> +}
>> +
>>  static bool run_check(struct check *c, struct dt_info *dti)
>>  {
>>  	struct node *dt = dti->dt;
>> @@ -179,7 +207,7 @@ static void check_is_string(struct check *c, struct dt_info *dti,
>>  			    struct node *node)
>>  {
>>  	struct property *prop;
>> -	char *propname = c->data;
>> +	const char *propname = c->data;
>>  
>>  	prop = get_property(node, propname);
>>  	if (!prop)
>> @@ -198,7 +226,7 @@ static void check_is_string_list(struct check *c, struct dt_info *dti,
>>  {
>>  	int rem, l;
>>  	struct property *prop;
>> -	char *propname = c->data;
>> +	const char *propname = c->data;
>>  	char *str;
>>  
>>  	prop = get_property(node, propname);
>> @@ -226,7 +254,7 @@ static void check_is_cell(struct check *c, struct dt_info *dti,
>>  			  struct node *node)
>>  {
>>  	struct property *prop;
>> -	char *propname = c->data;
>> +	const char *propname = c->data;
>>  
>>  	prop = get_property(node, propname);
>>  	if (!prop)
>> @@ -277,19 +305,20 @@ ERROR(duplicate_property_names, check_duplicate_property_names, NULL);
>>  #define LOWERCASE	"abcdefghijklmnopqrstuvwxyz"
>>  #define UPPERCASE	"ABCDEFGHIJKLMNOPQRSTUVWXYZ"
>>  #define DIGITS		"0123456789"
>> -#define PROPNODECHARS	LOWERCASE UPPERCASE DIGITS ",._+*#?-"
>> +#define NODECHARS	LOWERCASE UPPERCASE DIGITS ",._+-@"
>> +#define PROPCHARS	LOWERCASE UPPERCASE DIGITS ",._+*#?-"
>>  #define PROPNODECHARSSTRICT	LOWERCASE UPPERCASE DIGITS ",-"
>>  
>>  static void check_node_name_chars(struct check *c, struct dt_info *dti,
>>  				  struct node *node)
>>  {
>> -	int n = strspn(node->name, c->data);
>> +	size_t n = strspn(node->name, c->data);
>>  
>>  	if (n < strlen(node->name))
>>  		FAIL(c, dti, node, "Bad character '%c' in node name",
>>  		     node->name[n]);
>>  }
>> -ERROR(node_name_chars, check_node_name_chars, PROPNODECHARS "@");
>> +ERROR(node_name_chars, check_node_name_chars, NODECHARS);
>>  
>>  static void check_node_name_chars_strict(struct check *c, struct dt_info *dti,
>>  					 struct node *node)
>> @@ -310,6 +339,20 @@ static void check_node_name_format(struct check *c, struct dt_info *dti,
>>  }
>>  ERROR(node_name_format, check_node_name_format, NULL, &node_name_chars);
>>  
>> +static void check_node_name_vs_property_name(struct check *c,
>> +					     struct dt_info *dti,
>> +					     struct node *node)
>> +{
>> +	if (!node->parent)
>> +		return;
>> +
>> +	if (get_property(node->parent, node->name)) {
>> +		FAIL(c, dti, node, "node name and property name conflict");
>> +	}
>> +}
>> +WARNING(node_name_vs_property_name, check_node_name_vs_property_name,
>> +	NULL, &node_name_chars);
>> +
>>  static void check_unit_address_vs_reg(struct check *c, struct dt_info *dti,
>>  				      struct node *node)
>>  {
>> @@ -332,7 +375,7 @@ static void check_unit_address_vs_reg(struct check *c, struct dt_info *dti,
>>  			FAIL(c, dti, node, "node has a reg or ranges property, but no unit name");
>>  	} else {
>>  		if (unitname[0])
>> -			FAIL(c, dti, node, "node has a unit name, but no reg property");
>> +			FAIL(c, dti, node, "node has a unit name, but no reg or ranges property");
>>  	}
>>  }
>>  WARNING(unit_address_vs_reg, check_unit_address_vs_reg, NULL);
>> @@ -343,14 +386,14 @@ static void check_property_name_chars(struct check *c, struct dt_info *dti,
>>  	struct property *prop;
>>  
>>  	for_each_property(node, prop) {
>> -		int n = strspn(prop->name, c->data);
>> +		size_t n = strspn(prop->name, c->data);
>>  
>>  		if (n < strlen(prop->name))
>>  			FAIL_PROP(c, dti, node, prop, "Bad character '%c' in property name",
>>  				  prop->name[n]);
>>  	}
>>  }
>> -ERROR(property_name_chars, check_property_name_chars, PROPNODECHARS);
>> +ERROR(property_name_chars, check_property_name_chars, PROPCHARS);
>>  
>>  static void check_property_name_chars_strict(struct check *c,
>>  					     struct dt_info *dti,
>> @@ -360,7 +403,7 @@ static void check_property_name_chars_strict(struct check *c,
>>  
>>  	for_each_property(node, prop) {
>>  		const char *name = prop->name;
>> -		int n = strspn(name, c->data);
>> +		size_t n = strspn(name, c->data);
>>  
>>  		if (n == strlen(prop->name))
>>  			continue;
>> @@ -477,7 +520,7 @@ static cell_t check_phandle_prop(struct check *c, struct dt_info *dti,
>>  
>>  	phandle = propval_cell(prop);
>>  
>> -	if ((phandle == 0) || (phandle == -1)) {
>> +	if (!phandle_is_valid(phandle)) {
>>  		FAIL_PROP(c, dti, node, prop, "bad value (0x%x) in %s property",
>>  		     phandle, prop->name);
>>  		return 0;
>> @@ -536,7 +579,7 @@ static void check_name_properties(struct check *c, struct dt_info *dti,
>>  	if (!prop)
>>  		return; /* No name property, that's fine */
>>  
>> -	if ((prop->val.len != node->basenamelen+1)
>> +	if ((prop->val.len != node->basenamelen + 1U)
>>  	    || (memcmp(prop->val.val, node->name, node->basenamelen) != 0)) {
>>  		FAIL(c, dti, node, "\"name\" property is incorrect (\"%s\" instead"
>>  		     " of base node name)", prop->val.val);
>> @@ -625,6 +668,8 @@ ERROR(path_references, fixup_path_references, NULL, &duplicate_node_names);
>>  static void fixup_omit_unused_nodes(struct check *c, struct dt_info *dti,
>>  				    struct node *node)
>>  {
>> +	if (generate_symbols && node->labels)
>> +		return;
>>  	if (node->omit_if_unused && !node->is_referenced)
>>  		delete_node(node);
>>  }
>> @@ -635,7 +680,6 @@ ERROR(omit_unused_nodes, fixup_omit_unused_nodes, NULL, &phandle_references, &pa
>>   */
>>  WARNING_IF_NOT_CELL(address_cells_is_cell, "#address-cells");
>>  WARNING_IF_NOT_CELL(size_cells_is_cell, "#size-cells");
>> -WARNING_IF_NOT_CELL(interrupt_cells_is_cell, "#interrupt-cells");
>>  
>>  WARNING_IF_NOT_STRING(device_type_is_string, "device_type");
>>  WARNING_IF_NOT_STRING(model_is_string, "model");
>> @@ -650,8 +694,7 @@ static void check_names_is_string_list(struct check *c, struct dt_info *dti,
>>  	struct property *prop;
>>  
>>  	for_each_property(node, prop) {
>> -		const char *s = strrchr(prop->name, '-');
>> -		if (!s || !streq(s, "-names"))
>> +		if (!strends(prop->name, "-names"))
>>  			continue;
>>  
>>  		c->data = prop->name;
>> @@ -669,6 +712,11 @@ static void check_alias_paths(struct check *c, struct dt_info *dti,
>>  		return;
>>  
>>  	for_each_property(node, prop) {
>> +		if (streq(prop->name, "phandle")
>> +		    || streq(prop->name, "linux,phandle")) {
>> +			continue;
>> +		}
>> +
>>  		if (!prop->val.val || !get_node_by_path(dti->dt, prop->val.val)) {
>>  			FAIL_PROP(c, dti, node, prop, "aliases property is not a valid node (%s)",
>>  				  prop->val.val);
>> @@ -726,7 +774,7 @@ static void check_reg_format(struct check *c, struct dt_info *dti,
>>  	size_cells = node_size_cells(node->parent);
>>  	entrylen = (addr_cells + size_cells) * sizeof(cell_t);
>>  
>> -	if (!entrylen || (prop->val.len % entrylen) != 0)
>> +	if (!is_multiple_of(prop->val.len, entrylen))
>>  		FAIL_PROP(c, dti, node, prop, "property has invalid length (%d bytes) "
>>  			  "(#address-cells == %d, #size-cells == %d)",
>>  			  prop->val.len, addr_cells, size_cells);
>> @@ -738,13 +786,15 @@ static void check_ranges_format(struct check *c, struct dt_info *dti,
>>  {
>>  	struct property *prop;
>>  	int c_addr_cells, p_addr_cells, c_size_cells, p_size_cells, entrylen;
>> +	const char *ranges = c->data;
>>  
>> -	prop = get_property(node, "ranges");
>> +	prop = get_property(node, ranges);
>>  	if (!prop)
>>  		return;
>>  
>>  	if (!node->parent) {
>> -		FAIL_PROP(c, dti, node, prop, "Root node has a \"ranges\" property");
>> +		FAIL_PROP(c, dti, node, prop, "Root node has a \"%s\" property",
>> +			  ranges);
>>  		return;
>>  	}
>>  
>> @@ -756,23 +806,24 @@ static void check_ranges_format(struct check *c, struct dt_info *dti,
>>  
>>  	if (prop->val.len == 0) {
>>  		if (p_addr_cells != c_addr_cells)
>> -			FAIL_PROP(c, dti, node, prop, "empty \"ranges\" property but its "
>> +			FAIL_PROP(c, dti, node, prop, "empty \"%s\" property but its "
>>  				  "#address-cells (%d) differs from %s (%d)",
>> -				  c_addr_cells, node->parent->fullpath,
>> +				  ranges, c_addr_cells, node->parent->fullpath,
>>  				  p_addr_cells);
>>  		if (p_size_cells != c_size_cells)
>> -			FAIL_PROP(c, dti, node, prop, "empty \"ranges\" property but its "
>> +			FAIL_PROP(c, dti, node, prop, "empty \"%s\" property but its "
>>  				  "#size-cells (%d) differs from %s (%d)",
>> -				  c_size_cells, node->parent->fullpath,
>> +				  ranges, c_size_cells, node->parent->fullpath,
>>  				  p_size_cells);
>> -	} else if ((prop->val.len % entrylen) != 0) {
>> -		FAIL_PROP(c, dti, node, prop, "\"ranges\" property has invalid length (%d bytes) "
>> +	} else if (!is_multiple_of(prop->val.len, entrylen)) {
>> +		FAIL_PROP(c, dti, node, prop, "\"%s\" property has invalid length (%d bytes) "
>>  			  "(parent #address-cells == %d, child #address-cells == %d, "
>> -			  "#size-cells == %d)", prop->val.len,
>> +			  "#size-cells == %d)", ranges, prop->val.len,
>>  			  p_addr_cells, c_addr_cells, c_size_cells);
>>  	}
>>  }
>> -WARNING(ranges_format, check_ranges_format, NULL, &addr_size_cells);
>> +WARNING(ranges_format, check_ranges_format, "ranges", &addr_size_cells);
>> +WARNING(dma_ranges_format, check_ranges_format, "dma-ranges", &addr_size_cells);
>>  
>>  static const struct bus_type pci_bus = {
>>  	.name = "PCI",
>> @@ -842,7 +893,7 @@ static void check_pci_device_bus_num(struct check *c, struct dt_info *dti, struc
>>  	} else {
>>  		cells = (cell_t *)prop->val.val;
>>  		min_bus = fdt32_to_cpu(cells[0]);
>> -		max_bus = fdt32_to_cpu(cells[0]);
>> +		max_bus = fdt32_to_cpu(cells[1]);
>>  	}
>>  	if ((bus_num < min_bus) || (bus_num > max_bus))
>>  		FAIL_PROP(c, dti, node, prop, "PCI bus number %d out of range, expected (%d - %d)",
>> @@ -862,10 +913,8 @@ static void check_pci_device_reg(struct check *c, struct dt_info *dti, struct no
>>  		return;
>>  
>>  	prop = get_property(node, "reg");
>> -	if (!prop) {
>> -		FAIL(c, dti, node, "missing PCI reg property");
>> +	if (!prop)
>>  		return;
>> -	}
>>  
>>  	cells = (cell_t *)prop->val.val;
>>  	if (cells[1] || cells[2])
>> @@ -910,7 +959,7 @@ static bool node_is_compatible(struct node *node, const char *compat)
>>  
>>  	for (str = prop->val.val, end = str + prop->val.len; str < end;
>>  	     str += strnlen(str, end - str) + 1) {
>> -		if (strprefixeq(str, end - str, compat))
>> +		if (streq(str, compat))
>>  			return true;
>>  	}
>>  	return false;
>> @@ -921,7 +970,8 @@ static void check_simple_bus_bridge(struct check *c, struct dt_info *dti, struct
>>  	if (node_is_compatible(node, "simple-bus"))
>>  		node->bus = &simple_bus;
>>  }
>> -WARNING(simple_bus_bridge, check_simple_bus_bridge, NULL, &addr_size_cells);
>> +WARNING(simple_bus_bridge, check_simple_bus_bridge, NULL,
>> +	&addr_size_cells, &compatible_is_string_list);
>>  
>>  static void check_simple_bus_reg(struct check *c, struct dt_info *dti, struct node *node)
>>  {
>> @@ -962,6 +1012,160 @@ static void check_simple_bus_reg(struct check *c, struct dt_info *dti, struct no
>>  }
>>  WARNING(simple_bus_reg, check_simple_bus_reg, NULL, &reg_format, &simple_bus_bridge);
>>  
>> +static const struct bus_type i2c_bus = {
>> +	.name = "i2c-bus",
>> +};
>> +
>> +static void check_i2c_bus_bridge(struct check *c, struct dt_info *dti, struct node *node)
>> +{
>> +	if (strprefixeq(node->name, node->basenamelen, "i2c-bus") ||
>> +	    strprefixeq(node->name, node->basenamelen, "i2c-arb")) {
>> +		node->bus = &i2c_bus;
>> +	} else if (strprefixeq(node->name, node->basenamelen, "i2c")) {
>> +		struct node *child;
>> +		for_each_child(node, child) {
>> +			if (strprefixeq(child->name, child->basenamelen, "i2c-bus"))
>> +				return;
>> +		}
>> +		node->bus = &i2c_bus;
>> +	} else
>> +		return;
>> +
>> +	if (!node->children)
>> +		return;
>> +
>> +	if (node_addr_cells(node) != 1)
>> +		FAIL(c, dti, node, "incorrect #address-cells for I2C bus");
>> +	if (node_size_cells(node) != 0)
>> +		FAIL(c, dti, node, "incorrect #size-cells for I2C bus");
>> +
>> +}
>> +WARNING(i2c_bus_bridge, check_i2c_bus_bridge, NULL, &addr_size_cells);
>> +
>> +#define I2C_OWN_SLAVE_ADDRESS	(1U << 30)
>> +#define I2C_TEN_BIT_ADDRESS	(1U << 31)
>> +
>> +static void check_i2c_bus_reg(struct check *c, struct dt_info *dti, struct node *node)
>> +{
>> +	struct property *prop;
>> +	const char *unitname = get_unitname(node);
>> +	char unit_addr[17];
>> +	uint32_t reg = 0;
>> +	int len;
>> +	cell_t *cells = NULL;
>> +
>> +	if (!node->parent || (node->parent->bus != &i2c_bus))
>> +		return;
>> +
>> +	prop = get_property(node, "reg");
>> +	if (prop)
>> +		cells = (cell_t *)prop->val.val;
>> +
>> +	if (!cells) {
>> +		FAIL(c, dti, node, "missing or empty reg property");
>> +		return;
>> +	}
>> +
>> +	reg = fdt32_to_cpu(*cells);
>> +	/* Ignore I2C_OWN_SLAVE_ADDRESS */
>> +	reg &= ~I2C_OWN_SLAVE_ADDRESS;
>> +	snprintf(unit_addr, sizeof(unit_addr), "%x", reg);
>> +	if (!streq(unitname, unit_addr))
>> +		FAIL(c, dti, node, "I2C bus unit address format error, expected \"%s\"",
>> +		     unit_addr);
>> +
>> +	for (len = prop->val.len; len > 0; len -= 4) {
>> +		reg = fdt32_to_cpu(*(cells++));
>> +		/* Ignore I2C_OWN_SLAVE_ADDRESS */
>> +		reg &= ~I2C_OWN_SLAVE_ADDRESS;
>> +
>> +		if (reg & I2C_TEN_BIT_ADDRESS) {
>> +			if ((reg & ~I2C_TEN_BIT_ADDRESS) > 0x3ff)
>> +				FAIL_PROP(c, dti, node, prop, "I2C address must be less than 10-bits, got \"0x%x\"",
>> +				  reg);
>> +		} else if (reg > 0x7f)
>> +			FAIL_PROP(c, dti, node, prop, "I2C address must be less than 7-bits, got \"0x%x\". Set I2C_TEN_BIT_ADDRESS for 10 bit addresses or fix the property",
>> +				  reg);
>> +	}
>> +}
>> +WARNING(i2c_bus_reg, check_i2c_bus_reg, NULL, &reg_format, &i2c_bus_bridge);
>> +
>> +static const struct bus_type spi_bus = {
>> +	.name = "spi-bus",
>> +};
>> +
>> +static void check_spi_bus_bridge(struct check *c, struct dt_info *dti, struct node *node)
>> +{
>> +	int spi_addr_cells = 1;
>> +
>> +	if (strprefixeq(node->name, node->basenamelen, "spi")) {
>> +		node->bus = &spi_bus;
>> +	} else {
>> +		/* Try to detect SPI buses which don't have proper node name */
>> +		struct node *child;
>> +
>> +		if (node_addr_cells(node) != 1 || node_size_cells(node) != 0)
>> +			return;
>> +
>> +		for_each_child(node, child) {
>> +			struct property *prop;
>> +			for_each_property(child, prop) {
>> +				if (strstarts(prop->name, "spi-")) {
>> +					node->bus = &spi_bus;
>> +					break;
>> +				}
>> +			}
>> +			if (node->bus == &spi_bus)
>> +				break;
>> +		}
>> +
>> +		if (node->bus == &spi_bus && get_property(node, "reg"))
>> +			FAIL(c, dti, node, "node name for SPI buses should be 'spi'");
>> +	}
>> +	if (node->bus != &spi_bus || !node->children)
>> +		return;
>> +
>> +	if (get_property(node, "spi-slave"))
>> +		spi_addr_cells = 0;
>> +	if (node_addr_cells(node) != spi_addr_cells)
>> +		FAIL(c, dti, node, "incorrect #address-cells for SPI bus");
>> +	if (node_size_cells(node) != 0)
>> +		FAIL(c, dti, node, "incorrect #size-cells for SPI bus");
>> +
>> +}
>> +WARNING(spi_bus_bridge, check_spi_bus_bridge, NULL, &addr_size_cells);
>> +
>> +static void check_spi_bus_reg(struct check *c, struct dt_info *dti, struct node *node)
>> +{
>> +	struct property *prop;
>> +	const char *unitname = get_unitname(node);
>> +	char unit_addr[9];
>> +	uint32_t reg = 0;
>> +	cell_t *cells = NULL;
>> +
>> +	if (!node->parent || (node->parent->bus != &spi_bus))
>> +		return;
>> +
>> +	if (get_property(node->parent, "spi-slave"))
>> +		return;
>> +
>> +	prop = get_property(node, "reg");
>> +	if (prop)
>> +		cells = (cell_t *)prop->val.val;
>> +
>> +	if (!cells) {
>> +		FAIL(c, dti, node, "missing or empty reg property");
>> +		return;
>> +	}
>> +
>> +	reg = fdt32_to_cpu(*cells);
>> +	snprintf(unit_addr, sizeof(unit_addr), "%x", reg);
>> +	if (!streq(unitname, unit_addr))
>> +		FAIL(c, dti, node, "SPI bus unit address format error, expected \"%s\"",
>> +		     unit_addr);
>> +}
>> +WARNING(spi_bus_reg, check_spi_bus_reg, NULL, &reg_format, &spi_bus_bridge);
>> +
>>  static void check_unit_address_format(struct check *c, struct dt_info *dti,
>>  				      struct node *node)
>>  {
>> @@ -978,7 +1182,7 @@ static void check_unit_address_format(struct check *c, struct dt_info *dti,
>>  		/* skip over 0x for next test */
>>  		unitname += 2;
>>  	}
>> -	if (unitname[0] == '0' && isxdigit(unitname[1]))
>> +	if (unitname[0] == '0' && isxdigit((unsigned char)unitname[1]))
>>  		FAIL(c, dti, node, "unit name should not have leading 0s");
>>  }
>>  WARNING(unit_address_format, check_unit_address_format, NULL,
>> @@ -1013,29 +1217,48 @@ WARNING(avoid_default_addr_size, check_avoid_default_addr_size, NULL,
>>  static void check_avoid_unnecessary_addr_size(struct check *c, struct dt_info *dti,
>>  					      struct node *node)
>>  {
>> -	struct property *prop;
>>  	struct node *child;
>> -	bool has_reg = false;
>>  
>>  	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) {
>> -		prop = get_property(child, "reg");
>> -		if (prop)
>> -			has_reg = true;
>> +		/*
>> +		 * Even if the child devices' address space is not mapped into
>> +		 * the parent bus (no 'ranges' property on node), children can
>> +		 * still have registers on a local bus, or map local addresses
>> +		 * to another subordinate address space. The properties on the
>> +		 * child nodes then make #address-cells/#size-cells necessary:
>> +		 */
>> +		if (get_property(child, "reg") || get_property(child, "ranges"))
>> +			return;
>>  	}
>>  
>> -	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\" or \"ranges\" property");
>>  }
>>  WARNING(avoid_unnecessary_addr_size, check_avoid_unnecessary_addr_size, NULL, &avoid_default_addr_size);
>>  
>> -static void check_unique_unit_address(struct check *c, struct dt_info *dti,
>> -					      struct node *node)
>> +static bool node_is_disabled(struct node *node)
>> +{
>> +	struct property *prop;
>> +
>> +	prop = get_property(node, "status");
>> +	if (prop) {
>> +		char *str = prop->val.val;
>> +		if (streq("disabled", str))
>> +			return true;
>> +	}
>> +
>> +	return false;
>> +}
>> +
>> +static void check_unique_unit_address_common(struct check *c,
>> +						struct dt_info *dti,
>> +						struct node *node,
>> +						bool disable_check)
>>  {
>>  	struct node *childa;
>>  
>> @@ -1052,18 +1275,38 @@ static void check_unique_unit_address(struct check *c, struct dt_info *dti,
>>  		if (!strlen(addr_a))
>>  			continue;
>>  
>> +		if (disable_check && node_is_disabled(childa))
>> +			continue;
>> +
>>  		for_each_child(node, childb) {
>>  			const char *addr_b = get_unitname(childb);
>>  			if (childa == childb)
>>  				break;
>>  
>> +			if (disable_check && node_is_disabled(childb))
>> +				continue;
>> +
>>  			if (streq(addr_a, addr_b))
>>  				FAIL(c, dti, childb, "duplicate unit-address (also used in node %s)", childa->fullpath);
>>  		}
>>  	}
>>  }
>> +
>> +static void check_unique_unit_address(struct check *c, struct dt_info *dti,
>> +					      struct node *node)
>> +{
>> +	check_unique_unit_address_common(c, dti, node, false);
>> +}
>>  WARNING(unique_unit_address, check_unique_unit_address, NULL, &avoid_default_addr_size);
>>  
>> +static void check_unique_unit_address_if_enabled(struct check *c, struct dt_info *dti,
>> +					      struct node *node)
>> +{
>> +	check_unique_unit_address_common(c, dti, node, true);
>> +}
>> +CHECK_ENTRY(unique_unit_address_if_enabled, check_unique_unit_address_if_enabled,
>> +	    NULL, false, false, &avoid_default_addr_size);
>> +
>>  static void check_obsolete_chosen_interrupt_controller(struct check *c,
>>  						       struct dt_info *dti,
>>  						       struct node *node)
>> @@ -1143,15 +1386,15 @@ struct provider {
>>  };
>>  
>>  static void check_property_phandle_args(struct check *c,
>> -					  struct dt_info *dti,
>> -				          struct node *node,
>> -				          struct property *prop,
>> -				          const struct provider *provider)
>> +					struct dt_info *dti,
>> +					struct node *node,
>> +					struct property *prop,
>> +					const struct provider *provider)
>>  {
>>  	struct node *root = dti->dt;
>> -	int cell, cellsize = 0;
>> +	unsigned int cell, cellsize = 0;
>>  
>> -	if (prop->val.len % sizeof(cell_t)) {
>> +	if (!is_multiple_of(prop->val.len, sizeof(cell_t))) {
>>  		FAIL_PROP(c, dti, node, prop,
>>  			  "property size (%d) is invalid, expected multiple of %zu",
>>  			  prop->val.len, sizeof(cell_t));
>> @@ -1161,14 +1404,15 @@ static void check_property_phandle_args(struct check *c,
>>  	for (cell = 0; cell < prop->val.len / sizeof(cell_t); cell += cellsize + 1) {
>>  		struct node *provider_node;
>>  		struct property *cellprop;
>> -		int phandle;
>> +		cell_t phandle;
>> +		unsigned int expected;
>>  
>>  		phandle = propval_cell_n(prop, cell);
>>  		/*
>>  		 * Some bindings use a cell value 0 or -1 to skip over optional
>>  		 * entries when each index position has a specific definition.
>>  		 */
>> -		if (phandle == 0 || phandle == -1) {
>> +		if (!phandle_is_valid(phandle)) {
>>  			/* Give up if this is an overlay with external references */
>>  			if (dti->dtsflags & DTSF_PLUGIN)
>>  				break;
>> @@ -1211,10 +1455,12 @@ static void check_property_phandle_args(struct check *c,
>>  			break;
>>  		}
>>  
>> -		if (prop->val.len < ((cell + cellsize + 1) * sizeof(cell_t))) {
>> +		expected = (cell + cellsize + 1) * sizeof(cell_t);
>> +		if ((expected <= cell) || prop->val.len < expected) {
>>  			FAIL_PROP(c, dti, node, prop,
>> -				  "property size (%d) too small for cell size %d",
>> +				  "property size (%d) too small for cell size %u",
>>  				  prop->val.len, cellsize);
>> +			break;
>>  		}
>>  	}
>>  }
>> @@ -1223,7 +1469,7 @@ static void check_provider_cells_property(struct check *c,
>>  					  struct dt_info *dti,
>>  				          struct node *node)
>>  {
>> -	struct provider *provider = c->data;
>> +	const struct provider *provider = c->data;
>>  	struct property *prop;
>>  
>>  	prop = get_property(node, provider->prop_name);
>> @@ -1234,7 +1480,8 @@ static void check_provider_cells_property(struct check *c,
>>  }
>>  #define WARNING_PROPERTY_PHANDLE_CELLS(nm, propname, cells_name, ...) \
>>  	static struct provider nm##_provider = { (propname), (cells_name), __VA_ARGS__ }; \
>> -	WARNING(nm##_property, check_provider_cells_property, &nm##_provider, &phandle_references);
>> +	WARNING_IF_NOT_CELL(nm##_is_cell, cells_name); \
>> +	WARNING(nm##_property, check_provider_cells_property, &nm##_provider, &nm##_is_cell, &phandle_references);
>>  
>>  WARNING_PROPERTY_PHANDLE_CELLS(clocks, "clocks", "#clock-cells");
>>  WARNING_PROPERTY_PHANDLE_CELLS(cooling_device, "cooling-device", "#cooling-cells");
>> @@ -1255,24 +1502,17 @@ WARNING_PROPERTY_PHANDLE_CELLS(thermal_sensors, "thermal-sensors", "#thermal-sen
>>  
>>  static bool prop_is_gpio(struct property *prop)
>>  {
>> -	char *str;
>> -
>>  	/*
>>  	 * *-gpios and *-gpio can appear in property names,
>>  	 * so skip over any false matches (only one known ATM)
>>  	 */
>> -	if (strstr(prop->name, "nr-gpio"))
>> +	if (strends(prop->name, ",nr-gpios"))
>>  		return false;
>>  
>> -	str = strrchr(prop->name, '-');
>> -	if (str)
>> -		str++;
>> -	else
>> -		str = prop->name;
>> -	if (!(streq(str, "gpios") || streq(str, "gpio")))
>> -		return false;
>> -
>> -	return true;
>> +	return strends(prop->name, "-gpios") ||
>> +		streq(prop->name, "gpios") ||
>> +		strends(prop->name, "-gpio") ||
>> +		streq(prop->name, "gpio");
>>  }
>>  
>>  static void check_gpios_property(struct check *c,
>> @@ -1307,13 +1547,10 @@ static void check_deprecated_gpio_property(struct check *c,
>>  	struct property *prop;
>>  
>>  	for_each_property(node, prop) {
>> -		char *str;
>> -
>>  		if (!prop_is_gpio(prop))
>>  			continue;
>>  
>> -		str = strstr(prop->name, "gpio");
>> -		if (!streq(str, "gpio"))
>> +		if (!strends(prop->name, "gpio"))
>>  			continue;
>>  
>>  		FAIL_PROP(c, dti, node, prop,
>> @@ -1337,6 +1574,121 @@ static bool node_is_interrupt_provider(struct node *node)
>>  
>>  	return false;
>>  }
>> +
>> +static void check_interrupt_provider(struct check *c,
>> +				     struct dt_info *dti,
>> +				     struct node *node)
>> +{
>> +	struct property *prop;
>> +	bool irq_provider = node_is_interrupt_provider(node);
>> +
>> +	prop = get_property(node, "#interrupt-cells");
>> +	if (irq_provider && !prop) {
>> +		FAIL(c, dti, node,
>> +		     "Missing '#interrupt-cells' in interrupt provider");
>> +		return;
>> +	}
>> +
>> +	if (!irq_provider && prop) {
>> +		FAIL(c, dti, node,
>> +		     "'#interrupt-cells' found, but node is not an interrupt provider");
>> +		return;
>> +	}
>> +}
>> +WARNING(interrupt_provider, check_interrupt_provider, NULL, &interrupts_extended_is_cell);
>> +
>> +static void check_interrupt_map(struct check *c,
>> +				struct dt_info *dti,
>> +				struct node *node)
>> +{
>> +	struct node *root = dti->dt;
>> +	struct property *prop, *irq_map_prop;
>> +	size_t cellsize, cell, map_cells;
>> +
>> +	irq_map_prop = get_property(node, "interrupt-map");
>> +	if (!irq_map_prop)
>> +		return;
>> +
>> +	if (node->addr_cells < 0) {
>> +		FAIL(c, dti, node,
>> +		     "Missing '#address-cells' in interrupt-map provider");
>> +		return;
>> +	}
>> +	cellsize = node_addr_cells(node);
>> +	cellsize += propval_cell(get_property(node, "#interrupt-cells"));
>> +
>> +	prop = get_property(node, "interrupt-map-mask");
>> +	if (prop && (prop->val.len != (cellsize * sizeof(cell_t))))
>> +		FAIL_PROP(c, dti, node, prop,
>> +			  "property size (%d) is invalid, expected %zu",
>> +			  prop->val.len, cellsize * sizeof(cell_t));
>> +
>> +	if (!is_multiple_of(irq_map_prop->val.len, sizeof(cell_t))) {
>> +		FAIL_PROP(c, dti, node, irq_map_prop,
>> +			  "property size (%d) is invalid, expected multiple of %zu",
>> +			  irq_map_prop->val.len, sizeof(cell_t));
>> +		return;
>> +	}
>> +
>> +	map_cells = irq_map_prop->val.len / sizeof(cell_t);
>> +	for (cell = 0; cell < map_cells; ) {
>> +		struct node *provider_node;
>> +		struct property *cellprop;
>> +		int phandle;
>> +		size_t parent_cellsize;
>> +
>> +		if ((cell + cellsize) >= map_cells) {
>> +			FAIL_PROP(c, dti, node, irq_map_prop,
>> +				  "property size (%d) too small, expected > %zu",
>> +				  irq_map_prop->val.len, (cell + cellsize) * sizeof(cell_t));
>> +			break;
>> +		}
>> +		cell += cellsize;
>> +
>> +		phandle = propval_cell_n(irq_map_prop, cell);
>> +		if (!phandle_is_valid(phandle)) {
>> +			/* Give up if this is an overlay with external references */
>> +			if (!(dti->dtsflags & DTSF_PLUGIN))
>> +				FAIL_PROP(c, dti, node, irq_map_prop,
>> +					  "Cell %zu is not a phandle(%d)",
>> +					  cell, phandle);
>> +			break;
>> +		}
>> +
>> +		provider_node = get_node_by_phandle(root, phandle);
>> +		if (!provider_node) {
>> +			FAIL_PROP(c, dti, node, irq_map_prop,
>> +				  "Could not get phandle(%d) node for (cell %zu)",
>> +				  phandle, cell);
>> +			break;
>> +		}
>> +
>> +		cellprop = get_property(provider_node, "#interrupt-cells");
>> +		if (cellprop) {
>> +			parent_cellsize = propval_cell(cellprop);
>> +		} else {
>> +			FAIL(c, dti, node, "Missing property '#interrupt-cells' in node %s or bad phandle (referred from interrupt-map[%zu])",
>> +			     provider_node->fullpath, cell);
>> +			break;
>> +		}
>> +
>> +		cellprop = get_property(provider_node, "#address-cells");
>> +		if (cellprop)
>> +			parent_cellsize += propval_cell(cellprop);
>> +		else
>> +			FAIL_PROP(c, dti, node, irq_map_prop,
>> +				"Missing property '#address-cells' in node %s, using 0 as fallback",
>> +				provider_node->fullpath);
>> +
>> +		cell += 1 + parent_cellsize;
>> +		if (cell > map_cells)
>> +			FAIL_PROP(c, dti, node, irq_map_prop,
>> +				"property size (%d) mismatch, expected %zu",
>> +				irq_map_prop->val.len, cell * sizeof(cell_t));
>> +	}
>> +}
>> +WARNING(interrupt_map, check_interrupt_map, NULL, &phandle_references, &addr_size_cells, &interrupt_provider);
>> +
>>  static void check_interrupts_property(struct check *c,
>>  				      struct dt_info *dti,
>>  				      struct node *node)
>> @@ -1344,13 +1696,13 @@ static void check_interrupts_property(struct check *c,
>>  	struct node *root = dti->dt;
>>  	struct node *irq_node = NULL, *parent = node;
>>  	struct property *irq_prop, *prop = NULL;
>> -	int irq_cells, phandle;
>> +	cell_t irq_cells, phandle;
>>  
>>  	irq_prop = get_property(node, "interrupts");
>>  	if (!irq_prop)
>>  		return;
>>  
>> -	if (irq_prop->val.len % sizeof(cell_t))
>> +	if (!is_multiple_of(irq_prop->val.len, sizeof(cell_t)))
>>  		FAIL_PROP(c, dti, node, irq_prop, "size (%d) is invalid, expected multiple of %zu",
>>  		     irq_prop->val.len, sizeof(cell_t));
>>  
>> @@ -1363,10 +1715,14 @@ static void check_interrupts_property(struct check *c,
>>  		prop = get_property(parent, "interrupt-parent");
>>  		if (prop) {
>>  			phandle = propval_cell(prop);
>> -			/* Give up if this is an overlay with external references */
>> -			if ((phandle == 0 || phandle == -1) &&
>> -			    (dti->dtsflags & DTSF_PLUGIN))
>> +			if (!phandle_is_valid(phandle)) {
>> +				/* Give up if this is an overlay with
>> +				 * external references */
>> +				if (dti->dtsflags & DTSF_PLUGIN)
>>  					return;
>> +				FAIL_PROP(c, dti, parent, prop, "Invalid phandle");
>> +				continue;
>> +			}
>>  
>>  			irq_node = get_node_by_phandle(root, phandle);
>>  			if (!irq_node) {
>> @@ -1390,12 +1746,12 @@ static void check_interrupts_property(struct check *c,
>>  
>>  	prop = get_property(irq_node, "#interrupt-cells");
>>  	if (!prop) {
>> -		FAIL(c, dti, irq_node, "Missing #interrupt-cells in interrupt-parent");
>> +		/* We warn about that already in another test. */
>>  		return;
>>  	}
>>  
>>  	irq_cells = propval_cell(prop);
>> -	if (irq_prop->val.len % (irq_cells * sizeof(cell_t))) {
>> +	if (!is_multiple_of(irq_prop->val.len, irq_cells * sizeof(cell_t))) {
>>  		FAIL_PROP(c, dti, node, prop,
>>  			  "size is (%d), expected multiple of %d",
>>  			  irq_prop->val.len, (int)(irq_cells * sizeof(cell_t)));
>> @@ -1421,6 +1777,11 @@ static void check_graph_nodes(struct check *c, struct dt_info *dti,
>>  		      get_property(child, "remote-endpoint")))
>>  			continue;
>>  
>> +                /* The root node cannot be a port */
>> +		if (!node->parent) {
>> +			FAIL(c, dti, node, "root node contains endpoint node '%s', potentially misplaced remote-endpoint property", child->name);
>> +			continue;
>> +		}
>>  		node->bus = &graph_port_bus;
>>  
>>  		/* The parent of 'port' nodes can be either 'ports' or a device */
>> @@ -1434,31 +1795,6 @@ static void check_graph_nodes(struct check *c, struct dt_info *dti,
>>  }
>>  WARNING(graph_nodes, check_graph_nodes, NULL);
>>  
>> -static void check_graph_child_address(struct check *c, struct dt_info *dti,
>> -				      struct node *node)
>> -{
>> -	int cnt = 0;
>> -	struct node *child;
>> -
>> -	if (node->bus != &graph_ports_bus && node->bus != &graph_port_bus)
>> -		return;
>> -
>> -	for_each_child(node, child) {
>> -		struct property *prop = get_property(child, "reg");
>> -
>> -		/* No error if we have any non-zero unit address */
>> -		if (prop && propval_cell(prop) != 0)
>> -			return;
>> -
>> -		cnt++;
>> -	}
>> -
>> -	if (cnt == 1 && node->addr_cells != -1)
>> -		FAIL(c, dti, node, "graph node has single child node '%s', #address-cells/#size-cells are not necessary",
>> -		     node->children->name);
>> -}
>> -WARNING(graph_child_address, check_graph_child_address, NULL, &graph_nodes);
>> -
>>  static void check_graph_reg(struct check *c, struct dt_info *dti,
>>  			    struct node *node)
>>  {
>> @@ -1496,17 +1832,21 @@ static void check_graph_port(struct check *c, struct dt_info *dti,
>>  	if (node->bus != &graph_port_bus)
>>  		return;
>>  
>> +	check_graph_reg(c, dti, node);
>> +
>> +	/* skip checks below for overlays */
>> +	if (dti->dtsflags & DTSF_PLUGIN)
>> +		return;
>> +
>>  	if (!strprefixeq(node->name, node->basenamelen, "port"))
>>  		FAIL(c, dti, node, "graph port node name should be 'port'");
>> -
>> -	check_graph_reg(c, dti, node);
>>  }
>>  WARNING(graph_port, check_graph_port, NULL, &graph_nodes);
>>  
>>  static struct node *get_remote_endpoint(struct check *c, struct dt_info *dti,
>>  					struct node *endpoint)
>>  {
>> -	int phandle;
>> +	cell_t phandle;
>>  	struct node *node;
>>  	struct property *prop;
>>  
>> @@ -1516,7 +1856,7 @@ static struct node *get_remote_endpoint(struct check *c, struct dt_info *dti,
>>  
>>  	phandle = propval_cell(prop);
>>  	/* Give up if this is an overlay with external references */
>> -	if (phandle == 0 || phandle == -1)
>> +	if (!phandle_is_valid(phandle))
>>  		return NULL;
>>  
>>  	node = get_node_by_phandle(dti->dt, phandle);
>> @@ -1534,11 +1874,15 @@ static void check_graph_endpoint(struct check *c, struct dt_info *dti,
>>  	if (!node->parent || node->parent->bus != &graph_port_bus)
>>  		return;
>>  
>> -	if (!strprefixeq(node->name, node->basenamelen, "endpoint"))
>> -		FAIL(c, dti, node, "graph endpont node name should be 'endpoint'");
>> -
>>  	check_graph_reg(c, dti, node);
>>  
>> +	/* skip checks below for overlays */
>> +	if (dti->dtsflags & DTSF_PLUGIN)
>> +		return;
>> +
>> +	if (!strprefixeq(node->name, node->basenamelen, "endpoint"))
>> +		FAIL(c, dti, node, "graph endpoint node name should be 'endpoint'");
>> +
>>  	remote_node = get_remote_endpoint(c, dti, node);
>>  	if (!remote_node)
>>  		return;
>> @@ -1549,10 +1893,35 @@ static void check_graph_endpoint(struct check *c, struct dt_info *dti,
>>  }
>>  WARNING(graph_endpoint, check_graph_endpoint, NULL, &graph_nodes);
>>  
>> +static void check_graph_child_address(struct check *c, struct dt_info *dti,
>> +				      struct node *node)
>> +{
>> +	int cnt = 0;
>> +	struct node *child;
>> +
>> +	if (node->bus != &graph_ports_bus && node->bus != &graph_port_bus)
>> +		return;
>> +
>> +	for_each_child(node, child) {
>> +		struct property *prop = get_property(child, "reg");
>> +
>> +		/* No error if we have any non-zero unit address */
>> +                if (prop && propval_cell(prop) != 0 )
>> +			return;
>> +
>> +		cnt++;
>> +	}
>> +
>> +	if (cnt == 1 && node->addr_cells != -1)
>> +		FAIL(c, dti, node, "graph node has single child node '%s', #address-cells/#size-cells are not necessary",
>> +		     node->children->name);
>> +}
>> +WARNING(graph_child_address, check_graph_child_address, NULL, &graph_nodes, &graph_port, &graph_endpoint);
>> +
>>  static struct check *check_table[] = {
>>  	&duplicate_node_names, &duplicate_property_names,
>>  	&node_name_chars, &node_name_format, &property_name_chars,
>> -	&name_is_string, &name_properties,
>> +	&name_is_string, &name_properties, &node_name_vs_property_name,
>>  
>>  	&duplicate_label,
>>  
>> @@ -1560,7 +1929,7 @@ static struct check *check_table[] = {
>>  	&phandle_references, &path_references,
>>  	&omit_unused_nodes,
>>  
>> -	&address_cells_is_cell, &size_cells_is_cell, &interrupt_cells_is_cell,
>> +	&address_cells_is_cell, &size_cells_is_cell,
>>  	&device_type_is_string, &model_is_string, &status_is_string,
>>  	&label_is_string,
>>  
>> @@ -1569,7 +1938,7 @@ static struct check *check_table[] = {
>>  	&property_name_chars_strict,
>>  	&node_name_chars_strict,
>>  
>> -	&addr_size_cells, &reg_format, &ranges_format,
>> +	&addr_size_cells, &reg_format, &ranges_format, &dma_ranges_format,
>>  
>>  	&unit_address_vs_reg,
>>  	&unit_address_format,
>> @@ -1581,32 +1950,57 @@ static struct check *check_table[] = {
>>  	&simple_bus_bridge,
>>  	&simple_bus_reg,
>>  
>> +	&i2c_bus_bridge,
>> +	&i2c_bus_reg,
>> +
>> +	&spi_bus_bridge,
>> +	&spi_bus_reg,
>> +
>>  	&avoid_default_addr_size,
>>  	&avoid_unnecessary_addr_size,
>>  	&unique_unit_address,
>> +	&unique_unit_address_if_enabled,
>>  	&obsolete_chosen_interrupt_controller,
>>  	&chosen_node_is_root, &chosen_node_bootargs, &chosen_node_stdout_path,
>>  
>>  	&clocks_property,
>> +	&clocks_is_cell,
>>  	&cooling_device_property,
>> +	&cooling_device_is_cell,
>>  	&dmas_property,
>> +	&dmas_is_cell,
>>  	&hwlocks_property,
>> +	&hwlocks_is_cell,
>>  	&interrupts_extended_property,
>> +	&interrupts_extended_is_cell,
>>  	&io_channels_property,
>> +	&io_channels_is_cell,
>>  	&iommus_property,
>> +	&iommus_is_cell,
>>  	&mboxes_property,
>> +	&mboxes_is_cell,
>>  	&msi_parent_property,
>> +	&msi_parent_is_cell,
>>  	&mux_controls_property,
>> +	&mux_controls_is_cell,
>>  	&phys_property,
>> +	&phys_is_cell,
>>  	&power_domains_property,
>> +	&power_domains_is_cell,
>>  	&pwms_property,
>> +	&pwms_is_cell,
>>  	&resets_property,
>> +	&resets_is_cell,
>>  	&sound_dai_property,
>> +	&sound_dai_is_cell,
>>  	&thermal_sensors_property,
>> +	&thermal_sensors_is_cell,
>>  
>>  	&deprecated_gpio_property,
>>  	&gpios_property,
>>  	&interrupts_property,
>> +	&interrupt_provider,
>> +	&interrupt_map,
>>  
>>  	&alias_paths,
>>  
>> @@ -1630,7 +2024,7 @@ static void enable_warning_error(struct check *c, bool warn, bool error)
>>  
>>  static void disable_warning_error(struct check *c, bool warn, bool error)
>>  {
>> -	int i;
>> +	unsigned int i;
>>  
>>  	/* Lowering level, also lower it for things this is the prereq
>>  	 * for */
>> @@ -1651,7 +2045,7 @@ static void disable_warning_error(struct check *c, bool warn, bool error)
>>  
>>  void parse_checks_option(bool warn, bool error, const char *arg)
>>  {
>> -	int i;
>> +	unsigned int i;
>>  	const char *name = arg;
>>  	bool enable = true;
>>  
>> @@ -1678,7 +2072,7 @@ void parse_checks_option(bool warn, bool error, const char *arg)
>>  
>>  void process_checks(bool force, struct dt_info *dti)
>>  {
>> -	int i;
>> +	unsigned int i;
>>  	int error = 0;
>>  
>>  	for (i = 0; i < ARRAY_SIZE(check_table); i++) {
>> diff --git a/scripts/dtc/data.c b/scripts/dtc/data.c
>> index aa37a16c889..5b25aa06041 100644
>> --- a/scripts/dtc/data.c
>> +++ b/scripts/dtc/data.c
>> @@ -1,21 +1,6 @@
>> +// SPDX-License-Identifier: GPL-2.0-or-later
>>  /*
>>   * (C) Copyright David Gibson <dwg at au1.ibm.com>, IBM Corporation.  2005.
>> - *
>> - *
>> - * This program 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 program 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 program; if not, write to the Free Software
>> - *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307
>> - *                                                                   USA
>>   */
>>  
>>  #include "dtc.h"
>> @@ -36,10 +21,10 @@ void data_free(struct data d)
>>  		free(d.val);
>>  }
>>  
>> -struct data data_grow_for(struct data d, int xlen)
>> +struct data data_grow_for(struct data d, unsigned int xlen)
>>  {
>>  	struct data nd;
>> -	int newsize;
>> +	unsigned int newsize;
>>  
>>  	if (xlen == 0)
>>  		return d;
>> @@ -74,7 +59,8 @@ struct data data_copy_escape_string(const char *s, int len)
>>  	struct data d;
>>  	char *q;
>>  
>> -	d = data_grow_for(empty_data, len + 1);
>> +	d = data_add_marker(empty_data, TYPE_STRING, NULL);
>> +	d = data_grow_for(d, len + 1);
>>  
>>  	q = d.val;
>>  	while (i < len) {
>> @@ -94,10 +80,11 @@ struct data data_copy_file(FILE *f, size_t maxlen)
>>  {
>>  	struct data d = empty_data;
>>  
>> +	d = data_add_marker(d, TYPE_NONE, NULL);
>>  	while (!feof(f) && (d.len < maxlen)) {
>>  		size_t chunksize, ret;
>>  
>> -		if (maxlen == -1)
>> +		if (maxlen == (size_t)-1)
>>  			chunksize = 4096;
>>  		else
>>  			chunksize = maxlen - d.len;
>> @@ -241,11 +228,7 @@ struct data data_add_marker(struct data d, enum markertype type, char *ref)
>>  {
>>  	struct marker *m;
>>  
>> -	m = xmalloc(sizeof(*m));
>> -	m->offset = d.len;
>> -	m->type = type;
>> -	m->ref = ref;
>> -	m->next = NULL;
>> +	m = alloc_marker(d.len, type, ref);
>>  
>>  	return data_append_markers(d, m);
>>  }
>> @@ -267,3 +250,44 @@ bool data_is_one_string(struct data d)
>>  
>>  	return true;
>>  }
>> +
>> +struct data data_insert_data(struct data d, struct marker *m, struct data old)
>> +{
>> +	unsigned int offset = m->offset;
>> +	struct marker *next = m->next;
>> +	struct marker *marker;
>> +	struct data new_data;
>> +	char *ref;
>> +
>> +	new_data = data_insert_at_marker(d, m, old.val, old.len);
>> +
>> +	/* Copy all markers from old value */
>> +	marker = old.markers;
>> +	for_each_marker(marker) {
>> +		ref = NULL;
>> +
>> +		if (marker->ref)
>> +			ref = xstrdup(marker->ref);
>> +
>> +		m->next = alloc_marker(marker->offset + offset, marker->type,
>> +				       ref);
>> +		m = m->next;
>> +	}
>> +	m->next = next;
>> +
>> +	return new_data;
>> +}
>> +
>> +struct marker *alloc_marker(unsigned int offset, enum markertype type,
>> +			    char *ref)
>> +{
>> +	struct marker *m;
>> +
>> +	m = xmalloc(sizeof(*m));
>> +	m->offset = offset;
>> +	m->type = type;
>> +	m->ref = ref;
>> +	m->next = NULL;
>> +
>> +	return m;
>> +}
>> diff --git a/scripts/dtc/dtc-lexer.l b/scripts/dtc/dtc-lexer.l
>> index d34e1b04220..15d585c8079 100644
>> --- a/scripts/dtc/dtc-lexer.l
>> +++ b/scripts/dtc/dtc-lexer.l
>> @@ -1,21 +1,6 @@
>> +/* SPDX-License-Identifier: GPL-2.0-or-later */
>>  /*
>>   * (C) Copyright David Gibson <dwg at au1.ibm.com>, IBM Corporation.  2005.
>> - *
>> - *
>> - * This program 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 program 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 program; if not, write to the Free Software
>> - *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307
>> - *                                                                   USA
>>   */
>>  
>>  %option noyywrap nounput noinput never-interactive
>> @@ -72,7 +57,7 @@ static void PRINTF(1, 2) lexical_error(const char *fmt, ...);
>>  			push_input_file(name);
>>  		}
>>  
>> -<*>^"#"(line)?[ \t]+[0-9]+[ \t]+{STRING}([ \t]+[0-9]+)? {
>> +<*>^"#"(line)?[ \t]+[0-9]+[ \t]+{STRING}([ \t]+[0-9]+)* {
>>  			char *line, *fnstart, *fnend;
>>  			struct data fn;
>>  			/* skip text before line # */
>> @@ -166,6 +151,21 @@ static void PRINTF(1, 2) lexical_error(const char *fmt, ...);
>>  			return DT_LABEL;
>>  		}
>>  
>> +<V1>{LABEL} 	{
>> +			/* Missed includes or macro definitions while
>> +			 * preprocessing can lead to unexpected identifiers in
>> +			 * the input. Report a slightly more informative error
>> +			 * in this case */
>> +
>> +			lexical_error("Unexpected '%s'", yytext);
>> +
>> +			/* Treat it as a literal which often generates further
>> +			 * useful error messages */
>> +
>> +			yylval.integer = 0;
>> +			return DT_LITERAL;
>> +		}
>> +
>>  <V1>([0-9]+|0[xX][0-9a-fA-F]+)(U|L|UL|LL|ULL)? {
>>  			char *e;
>>  			DPRINT("Integer Literal: '%s'\n", yytext);
>> @@ -212,14 +212,14 @@ static void PRINTF(1, 2) lexical_error(const char *fmt, ...);
>>  <*>\&{LABEL}	{	/* label reference */
>>  			DPRINT("Ref: %s\n", yytext+1);
>>  			yylval.labelref = xstrdup(yytext+1);
>> -			return DT_REF;
>> +			return DT_LABEL_REF;
>>  		}
>>  
>>  <*>"&{"{PATHCHAR}*\}	{	/* new-style path reference */
>>  			yytext[yyleng-1] = '\0';
>>  			DPRINT("Ref: %s\n", yytext+2);
>>  			yylval.labelref = xstrdup(yytext+2);
>> -			return DT_REF;
>> +			return DT_PATH_REF;
>>  		}
>>  
>>  <BYTESTRING>[0-9a-fA-F]{2} {
>> diff --git a/scripts/dtc/dtc-parser.y b/scripts/dtc/dtc-parser.y
>> index b3b9c83873d..4d5eece5262 100644
>> --- a/scripts/dtc/dtc-parser.y
>> +++ b/scripts/dtc/dtc-parser.y
>> @@ -1,22 +1,9 @@
>> +// SPDX-License-Identifier: GPL-2.0-or-later
>>  /*
>>   * (C) Copyright David Gibson <dwg at au1.ibm.com>, IBM Corporation.  2005.
>> - *
>> - *
>> - * This program 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 program 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 program; if not, write to the Free Software
>> - *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307
>> - *                                                                   USA
>>   */
>> +%locations
>> +
>>  %{
>>  #include <stdio.h>
>>  #include <inttypes.h>
>> @@ -32,6 +19,8 @@ extern void yyerror(char const *s);
>>  		treesource_error = true; \
>>  	} while (0)
>>  
>> +#define YYERROR_CALL(msg) yyerror(msg)
>> +
>>  extern struct dt_info *parser_output;
>>  extern bool treesource_error;
>>  
>> @@ -76,7 +65,8 @@ static bool is_ref_relative(const char *ref)
>>  %token <byte> DT_BYTE
>>  %token <data> DT_STRING
>>  %token <labelref> DT_LABEL
>> -%token <labelref> DT_REF
>> +%token <labelref> DT_LABEL_REF
>> +%token <labelref> DT_PATH_REF
>>  %token DT_INCBIN
>>  
>>  %type <data> propdata
>> @@ -89,6 +79,7 @@ static bool is_ref_relative(const char *ref)
>>  %type <data> bytestring
>>  %type <prop> propdef
>>  %type <proplist> proplist
>> +%type <labelref> dt_ref
>>  
>>  %type <node> devicetree
>>  %type <node> nodedef
>> @@ -164,6 +155,8 @@ memreserve:
>>  		}
>>  	;
>>  
>> +dt_ref: DT_LABEL_REF | DT_PATH_REF;
>> +
>>  devicetree:
>>  	  '/' nodedef
>>  		{
>> @@ -173,7 +166,7 @@ devicetree:
>>  		{
>>  			$$ = merge_nodes($1, $3);
>>  		}
>> -	| DT_REF nodedef
>> +	| dt_ref nodedef
>>  		{
>>  			/*
>>  			 * We rely on the rule being always:
>> @@ -184,9 +177,12 @@ devicetree:
>>  				ERROR(&@2, "Label or path %s not found", $1);
>>  			else if (is_ref_relative($1))
>>  				ERROR(&@2, "Label-relative reference %s not supported in plugin", $1);
>> -			$$ = add_orphan_node(name_node(build_node(NULL, NULL), ""), $2, $1);
>> +			$$ = add_orphan_node(
>> +					name_node(build_node(NULL, NULL, NULL),
>> +						  ""),
>> +					$2, $1);
>>  		}
>> -	| devicetree DT_LABEL DT_REF nodedef
>> +	| devicetree DT_LABEL dt_ref nodedef
>>  		{
>>  			struct node *target = get_node_by_ref($1, $3);
>>  
>> @@ -200,7 +196,7 @@ devicetree:
>>  				ERROR(&@3, "Label or path %s not found", $3);
>>  			$$ = $1;
>>  		}
>> -	| devicetree DT_REF nodedef
>> +	| devicetree DT_PATH_REF nodedef
>>  		{
>>  			/*
>>  			 * We rely on the rule being always:
>> @@ -221,7 +217,26 @@ devicetree:
>>  			}
>>  			$$ = $1;
>>  		}
>> -	| devicetree DT_DEL_NODE DT_REF ';'
>> +	| devicetree DT_LABEL_REF nodedef
>> +		{
>> +			struct node *target = get_node_by_ref($1, $2);
>> +
>> +			if (target) {
>> +				merge_nodes(target, $3);
>> +			} else {
>> +				/*
>> +				 * We rely on the rule being always:
>> +				 *   versioninfo plugindecl memreserves devicetree
>> +				 * so $-1 is what we want (plugindecl)
>> +				 */
>> +				if ($<flags>-1 & DTSF_PLUGIN)
>> +					add_orphan_node($1, $3, $2);
>> +				else
>> +					ERROR(&@2, "Label or path %s not found", $2);
>> +			}
>> +			$$ = $1;
>> +		}
>> +	| devicetree DT_DEL_NODE dt_ref ';'
>>  		{
>>  			struct node *target = get_node_by_ref($1, $3);
>>  
>> @@ -233,7 +248,7 @@ devicetree:
>>  
>>  			$$ = $1;
>>  		}
>> -	| devicetree DT_OMIT_NO_REF DT_REF ';'
>> +	| devicetree DT_OMIT_NO_REF dt_ref ';'
>>  		{
>>  			struct node *target = get_node_by_ref($1, $3);
>>  
>> @@ -250,7 +265,7 @@ devicetree:
>>  nodedef:
>>  	  '{' proplist subnodes '}' ';'
>>  		{
>> -			$$ = build_node($2, $3);
>> +			$$ = build_node($2, $3, &@$);
>>  		}
>>  	;
>>  
>> @@ -268,15 +283,18 @@ proplist:
>>  propdef:
>>  	  DT_PROPNODENAME '=' propdata ';'
>>  		{
>> -			$$ = build_property($1, $3);
>> +			$$ = build_property($1, $3, &@$);
>> +			free($1);
>>  		}
>>  	| DT_PROPNODENAME ';'
>>  		{
>> -			$$ = build_property($1, empty_data);
>> +			$$ = build_property($1, empty_data, &@$);
>> +			free($1);
>>  		}
>>  	| DT_DEL_PROP DT_PROPNODENAME ';'
>>  		{
>>  			$$ = build_property_delete($2);
>> +			free($2);
>>  		}
>>  	| DT_LABEL propdef
>>  		{
>> @@ -298,8 +316,9 @@ propdata:
>>  		{
>>  			$$ = data_merge($1, $3);
>>  		}
>> -	| propdataprefix DT_REF
>> +	| propdataprefix dt_ref
>>  		{
>> +			$1 = data_add_marker($1, TYPE_STRING, $2);
>>  			$$ = data_add_marker($1, REF_PATH, $2);
>>  		}
>>  	| propdataprefix DT_INCBIN '(' DT_STRING ',' integer_prim ',' integer_prim ')'
>> @@ -353,22 +372,27 @@ arrayprefix:
>>  	DT_BITS DT_LITERAL '<'
>>  		{
>>  			unsigned long long bits;
>> +			enum markertype type = TYPE_UINT32;
>>  
>>  			bits = $2;
>>  
>> -			if ((bits !=  8) && (bits != 16) &&
>> -			    (bits != 32) && (bits != 64)) {
>> +			switch (bits) {
>> +			case 8: type = TYPE_UINT8; break;
>> +			case 16: type = TYPE_UINT16; break;
>> +			case 32: type = TYPE_UINT32; break;
>> +			case 64: type = TYPE_UINT64; break;
>> +			default:
>>  				ERROR(&@2, "Array elements must be"
>>  				      " 8, 16, 32 or 64-bits");
>>  				bits = 32;
>>  			}
>>  
>> -			$$.data = empty_data;
>> +			$$.data = data_add_marker(empty_data, type, NULL);
>>  			$$.bits = bits;
>>  		}
>>  	| '<'
>>  		{
>> -			$$.data = empty_data;
>> +			$$.data = data_add_marker(empty_data, TYPE_UINT32, NULL);
>>  			$$.bits = 32;
>>  		}
>>  	| arrayprefix integer_prim
>> @@ -383,14 +407,19 @@ arrayprefix:
>>  				 * 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);
>>  		}
>> -	| arrayprefix DT_REF
>> +	| arrayprefix dt_ref
>>  		{
>>  			uint64_t val = ~0ULL >> (64 - $1.bits);
>>  
>> @@ -468,8 +497,8 @@ integer_rela:
>>  	;
>>  
>>  integer_shift:
>> -	  integer_shift DT_LSHIFT integer_add { $$ = $1 << $3; }
>> -	| integer_shift DT_RSHIFT integer_add { $$ = $1 >> $3; }
>> +	  integer_shift DT_LSHIFT integer_add { $$ = ($3 < 64) ? ($1 << $3) : 0; }
>> +	| integer_shift DT_RSHIFT integer_add { $$ = ($3 < 64) ? ($1 >> $3) : 0; }
>>  	| integer_add
>>  	;
>>  
>> @@ -512,7 +541,7 @@ integer_unary:
>>  bytestring:
>>  	  /* empty */
>>  		{
>> -			$$ = empty_data;
>> +			$$ = data_add_marker(empty_data, TYPE_UINT8, NULL);
>>  		}
>>  	| bytestring DT_BYTE
>>  		{
>> @@ -544,10 +573,12 @@ subnode:
>>  	  DT_PROPNODENAME nodedef
>>  		{
>>  			$$ = name_node($2, $1);
>> +			free($1);
>>  		}
>>  	| DT_DEL_NODE DT_PROPNODENAME ';'
>>  		{
>> -			$$ = name_node(build_node_delete(), $2);
>> +			$$ = name_node(build_node_delete(&@$), $2);
>> +			free($2);
>>  		}
>>  	| DT_OMIT_NO_REF subnode
>>  		{
>> diff --git a/scripts/dtc/dtc.c b/scripts/dtc/dtc.c
>> index c36994e6eac..b3445b7d647 100644
>> --- a/scripts/dtc/dtc.c
>> +++ b/scripts/dtc/dtc.c
>> @@ -1,21 +1,6 @@
>> +// SPDX-License-Identifier: GPL-2.0-or-later
>>  /*
>>   * (C) Copyright David Gibson <dwg at au1.ibm.com>, IBM Corporation.  2005.
>> - *
>> - *
>> - * This program 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 program 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 program; if not, write to the Free Software
>> - *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307
>> - *                                                                   USA
>>   */
>>  
>>  #include <sys/stat.h>
>> @@ -27,14 +12,16 @@
>>   * Command line options
>>   */
>>  int quiet;		/* Level of quietness */
>> -int reservenum;		/* Number of memory reservation slots */
>> +unsigned int reservenum;/* Number of memory reservation slots */
>>  int minsize;		/* Minimum blob size */
>>  int padsize;		/* Additional padding to blob */
>> -int alignsize;		/* Additional padding to blob accroding to the alignsize */
>> +int alignsize;		/* Additional padding to blob according to the alignsize */
>>  int phandle_format = PHANDLE_EPAPR;	/* Use linux,phandle or phandle properties */
>>  int generate_symbols;	/* enable symbols & fixup support */
>>  int generate_fixups;		/* suppress generation of fixups on symbol support */
>>  int auto_label_aliases;		/* auto generate labels -> aliases */
>> +int annotate;		/* Level of annotation: 1 for input source location
>> +			   >1 for full input source location. */
>>  
>>  static int is_power_of_2(int x)
>>  {
>> @@ -60,7 +47,7 @@ static void fill_fullpaths(struct node *tree, const char *prefix)
>>  
>>  /* Usage related data. */
>>  static const char usage_synopsis[] = "dtc [options] <input file>";
>> -static const char usage_short_opts[] = "qI:O:o:V:d:R:S:p:a:fb:i:H:sW:E:@Ahv";
>> +static const char usage_short_opts[] = "qI:O:o:V:d:R:S:p:a:fb:i:H:sW:E:@LAThv";
>>  static struct option const usage_long_opts[] = {
>>  	{"quiet",            no_argument, NULL, 'q'},
>>  	{"in-format",         a_argument, NULL, 'I'},
>> @@ -80,7 +67,9 @@ static struct option const usage_long_opts[] = {
>>  	{"warning",           a_argument, NULL, 'W'},
>>  	{"error",             a_argument, NULL, 'E'},
>>  	{"symbols",	     no_argument, NULL, '@'},
>> +	{"local-fixups",     no_argument, NULL, 'L'},
>>  	{"auto-alias",       no_argument, NULL, 'A'},
>> +	{"annotate",         no_argument, NULL, 'T'},
>>  	{"help",             no_argument, NULL, 'h'},
>>  	{"version",          no_argument, NULL, 'v'},
>>  	{NULL,               no_argument, NULL, 0x0},
>> @@ -95,6 +84,9 @@ static const char * const usage_opts_help[] = {
>>  	"\n\tOutput formats are:\n"
>>  	 "\t\tdts - device tree source text\n"
>>  	 "\t\tdtb - device tree blob\n"
>> +#ifndef NO_YAML
>> +	 "\t\tyaml - device tree encoded as YAML\n"
>> +#endif
>>  	 "\t\tasm - assembler source",
>>  	"\n\tBlob version to produce, defaults to "stringify(DEFAULT_FDT_VERSION)" (for dtb and asm output)",
>>  	"\n\tOutput dependency file",
>> @@ -113,7 +105,9 @@ static const char * const usage_opts_help[] = {
>>  	"\n\tEnable/disable warnings (prefix with \"no-\")",
>>  	"\n\tEnable/disable errors (prefix with \"no-\")",
>>  	"\n\tEnable generation of symbols",
>> +	"\n\tPossibly generates a __local_fixups__ and a __fixups__ node at the root node",
>>  	"\n\tEnable auto-alias of labels",
>> +	"\n\tAnnotate output .dts with input source file and line (-T -T for more details)",
>>  	"\n\tPrint this help and exit",
>>  	"\n\tPrint version and exit",
>>  	NULL,
>> @@ -128,6 +122,10 @@ static const char *guess_type_by_name(const char *fname, const char *fallback)
>>  		return fallback;
>>  	if (!strcasecmp(s, ".dts"))
>>  		return "dts";
>> +	if (!strcasecmp(s, ".yaml"))
>> +		return "yaml";
>> +	if (!strcasecmp(s, ".dtbo"))
>> +		return "dtb";
>>  	if (!strcasecmp(s, ".dtb"))
>>  		return "dtb";
>>  	return fallback;
>> @@ -201,7 +199,7 @@ int main(int argc, char *argv[])
>>  			depname = optarg;
>>  			break;
>>  		case 'R':
>> -			reservenum = strtol(optarg, NULL, 0);
>> +			reservenum = strtoul(optarg, NULL, 0);
>>  			break;
>>  		case 'S':
>>  			minsize = strtol(optarg, NULL, 0);
>> @@ -256,9 +254,17 @@ int main(int argc, char *argv[])
>>  		case '@':
>>  			generate_symbols = 1;
>>  			break;
>> +
>> +		case 'L':
>> +			generate_fixups = 1;
>> +			break;
>> +
>>  		case 'A':
>>  			auto_label_aliases = 1;
>>  			break;
>> +		case 'T':
>> +			annotate++;
>> +			break;
>>  
>>  		case 'h':
>>  			usage(NULL);
>> @@ -283,7 +289,9 @@ int main(int argc, char *argv[])
>>  		if (!depfile)
>>  			die("Couldn't open dependency file %s: %s\n", depname,
>>  			    strerror(errno));
>> -		fprintf(depfile, "%s:", outname);
>> +
>> +		fprint_path_escaped(depfile, outname);
>> +		fputc(':', depfile);
>>  	}
>>  
>>  	if (inform == NULL)
>> @@ -297,6 +305,8 @@ int main(int argc, char *argv[])
>>  				outform = "dts";
>>  		}
>>  	}
>> +	if (annotate && (!streq(inform, "dts") || !streq(outform, "dts")))
>> +		die("--annotate requires -I dts -O dts\n");
>>  	if (streq(inform, "dts"))
>>  		dti = dt_from_source(arg);
>>  	else if (streq(inform, "fs"))
>> @@ -350,6 +360,12 @@ int main(int argc, char *argv[])
>>  
>>  	if (streq(outform, "dts")) {
>>  		dt_to_source(outf, dti);
>> +#ifndef NO_YAML
>> +	} else if (streq(outform, "yaml")) {
>> +		if (!streq(inform, "dts"))
>> +			die("YAML output format requires dts input format\n");
>> +		dt_to_yaml(outf, dti);
>> +#endif
>>  	} else if (streq(outform, "dtb")) {
>>  		dt_to_blob(outf, dti, outversion);
>>  	} else if (streq(outform, "asm")) {
>> diff --git a/scripts/dtc/dtc.h b/scripts/dtc/dtc.h
>> index 39c50a2c4fc..fcc97bbc70e 100644
>> --- a/scripts/dtc/dtc.h
>> +++ b/scripts/dtc/dtc.h
>> @@ -1,24 +1,9 @@
>> +/* SPDX-License-Identifier: GPL-2.0-or-later */
>>  #ifndef DTC_H
>>  #define DTC_H
>>  
>>  /*
>>   * (C) Copyright David Gibson <dwg at au1.ibm.com>, IBM Corporation.  2005.
>> - *
>> - *
>> - * This program 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 program 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 program; if not, write to the Free Software
>> - *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307
>> - *                                                                   USA
>>   */
>>  
>>  #include <stdio.h>
>> @@ -50,14 +35,15 @@
>>   * Command line options
>>   */
>>  extern int quiet;		/* Level of quietness */
>> -extern int reservenum;		/* Number of memory reservation slots */
>> +extern unsigned int reservenum;	/* Number of memory reservation slots */
>>  extern int minsize;		/* Minimum blob size */
>>  extern int padsize;		/* Additional padding to blob */
>> -extern int alignsize;		/* Additional padding to blob accroding to the alignsize */
>> +extern int alignsize;		/* Additional padding to blob according to the alignsize */
>>  extern int phandle_format;	/* Use linux,phandle or phandle properties */
>>  extern int generate_symbols;	/* generate symbols for nodes with labels */
>>  extern int generate_fixups;	/* generate fixups */
>>  extern int auto_label_aliases;	/* auto generate labels -> aliases */
>> +extern int annotate;		/* annotate .dts with input source location */
>>  
>>  #define PHANDLE_LEGACY	0x1
>>  #define PHANDLE_EPAPR	0x2
>> @@ -65,28 +51,88 @@ extern int auto_label_aliases;	/* auto generate labels -> aliases */
>>  
>>  typedef uint32_t cell_t;
>>  
>> +static inline bool phandle_is_valid(cell_t phandle)
>> +{
>> +	return phandle != 0 && phandle != ~0U;
>> +}
>> +
>> +static inline uint16_t dtb_ld16(const void *p)
>> +{
>> +	const uint8_t *bp = (const uint8_t *)p;
>> +
>> +	return ((uint16_t)bp[0] << 8)
>> +		| bp[1];
>> +}
>> +
>> +static inline uint32_t dtb_ld32(const void *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 uint64_t dtb_ld64(const void *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];
>> +}
>> +
>>  #define streq(a, b)	(strcmp((a), (b)) == 0)
>>  #define strstarts(s, prefix)	(strncmp((s), (prefix), strlen(prefix)) == 0)
>>  #define strprefixeq(a, n, b)	(strlen(b) == (n) && (memcmp(a, b, n) == 0))
>> +static inline bool strends(const char *str, const char *suffix)
>> +{
>> +	unsigned int len, suffix_len;
>> +
>> +	len = strlen(str);
>> +	suffix_len = strlen(suffix);
>> +	if (len < suffix_len)
>> +		return false;
>> +	return streq(str + len - suffix_len, suffix);
>> +}
>>  
>>  #define ALIGN(x, a)	(((x) + (a) - 1) & ~((a) - 1))
>>  
>>  /* Data blobs */
>>  enum markertype {
>> +	TYPE_NONE,
>>  	REF_PHANDLE,
>>  	REF_PATH,
>>  	LABEL,
>> +	TYPE_UINT8,
>> +	TYPE_UINT16,
>> +	TYPE_UINT32,
>> +	TYPE_UINT64,
>> +	TYPE_STRING,
>>  };
>>  
>> +static inline bool is_type_marker(enum markertype type)
>> +{
>> +	return type >= TYPE_UINT8;
>> +}
>> +
>> +extern const char *markername(enum markertype markertype);
>> +
>>  struct  marker {
>>  	enum markertype type;
>> -	int offset;
>> +	unsigned int offset;
>>  	char *ref;
>>  	struct marker *next;
>>  };
>>  
>>  struct data {
>> -	int len;
>> +	unsigned int len;
>>  	char *val;
>>  	struct marker *markers;
>>  };
>> @@ -99,9 +145,26 @@ struct data {
>>  	for_each_marker(m) \
>>  		if ((m)->type == (t))
>>  
>> +static inline struct marker *next_type_marker(struct marker *m)
>> +{
>> +	for_each_marker(m)
>> +		if (is_type_marker(m->type))
>> +			break;
>> +	return m;
>> +}
>> +
>> +static inline size_t type_marker_length(struct marker *m)
>> +{
>> +	struct marker *next = next_type_marker(m->next);
>> +
>> +	if (next)
>> +		return next->offset - m->offset;
>> +	return 0;
>> +}
>> +
>>  void data_free(struct data d);
>>  
>> -struct data data_grow_for(struct data d, int xlen);
>> +struct data data_grow_for(struct data d, unsigned int xlen);
>>  
>>  struct data data_copy_mem(const char *mem, int len);
>>  struct data data_copy_escape_string(const char *s, int len);
>> @@ -118,7 +181,10 @@ struct data data_append_addr(struct data d, uint64_t addr);
>>  struct data data_append_byte(struct data d, uint8_t byte);
>>  struct data data_append_zeroes(struct data d, int len);
>>  struct data data_append_align(struct data d, int align);
>> +struct data data_insert_data(struct data d, struct marker *m, struct data old);
>>  
>> +struct marker *alloc_marker(unsigned int offset, enum markertype type,
>> +			    char *ref);
>>  struct data data_add_marker(struct data d, enum markertype type, char *ref);
>>  
>>  bool data_is_one_string(struct data d);
>> @@ -147,6 +213,7 @@ struct property {
>>  	struct property *next;
>>  
>>  	struct label *labels;
>> +	struct srcpos *srcpos;
>>  };
>>  
>>  struct node {
>> @@ -166,6 +233,7 @@ struct node {
>>  
>>  	struct label *labels;
>>  	const struct bus_type *bus;
>> +	struct srcpos *srcpos;
>>  
>>  	bool omit_if_unused, is_referenced;
>>  };
>> @@ -194,14 +262,16 @@ struct node {
>>  void add_label(struct label **labels, char *label);
>>  void delete_labels(struct label **labels);
>>  
>> -struct property *build_property(char *name, struct data val);
>> -struct property *build_property_delete(char *name);
>> +struct property *build_property(const char *name, struct data val,
>> +				struct srcpos *srcpos);
>> +struct property *build_property_delete(const char *name);
>>  struct property *chain_property(struct property *first, struct property *list);
>>  struct property *reverse_properties(struct property *first);
>>  
>> -struct node *build_node(struct property *proplist, struct node *children);
>> -struct node *build_node_delete(void);
>> -struct node *name_node(struct node *node, char *name);
>> +struct node *build_node(struct property *proplist, struct node *children,
>> +			struct srcpos *srcpos);
>> +struct node *build_node_delete(struct srcpos *srcpos);
>> +struct node *name_node(struct node *node, const char *name);
>>  struct node *omit_node_if_unused(struct node *node);
>>  struct node *reference_node(struct node *node);
>>  struct node *chain_node(struct node *first, struct node *list);
>> @@ -215,12 +285,13 @@ void add_child(struct node *parent, struct node *child);
>>  void delete_node_by_name(struct node *parent, char *name);
>>  void delete_node(struct node *node);
>>  void append_to_property(struct node *node,
>> -			char *name, const void *data, int len);
>> +			char *name, const void *data, int len,
>> +			enum markertype type);
>>  
>>  const char *get_unitname(struct node *node);
>>  struct property *get_property(struct node *node, const char *propname);
>>  cell_t propval_cell(struct property *prop);
>> -cell_t propval_cell_n(struct property *prop, int n);
>> +cell_t propval_cell_n(struct property *prop, unsigned int n);
>>  struct property *get_property_by_label(struct node *tree, const char *label,
>>  				       struct node **node);
>>  struct marker *get_marker_label(struct node *tree, const char *label,
>> @@ -266,9 +337,9 @@ struct dt_info *build_dt_info(unsigned int dtsflags,
>>  			      struct reserve_info *reservelist,
>>  			      struct node *tree, uint32_t boot_cpuid_phys);
>>  void sort_tree(struct dt_info *dti);
>> -void generate_label_tree(struct dt_info *dti, char *name, bool allocph);
>> -void generate_fixups_tree(struct dt_info *dti, char *name);
>> -void generate_local_fixups_tree(struct dt_info *dti, char *name);
>> +void generate_label_tree(struct dt_info *dti, const char *name, bool allocph);
>> +void generate_fixups_tree(struct dt_info *dti, const char *name);
>> +void generate_local_fixups_tree(struct dt_info *dti, const char *name);
>>  
>>  /* Checks */
>>  
>> @@ -287,6 +358,10 @@ struct dt_info *dt_from_blob(const char *fname);
>>  void dt_to_source(FILE *f, struct dt_info *dti);
>>  struct dt_info *dt_from_source(const char *f);
>>  
>> +/* YAML source */
>> +
>> +void dt_to_yaml(FILE *f, struct dt_info *dti);
>> +
>>  /* FS trees */
>>  
>>  struct dt_info *dt_from_fs(const char *dirname);
>> diff --git a/scripts/dtc/fdtoverlay.c b/scripts/dtc/fdtoverlay.c
>> new file mode 100644
>> index 00000000000..ee1eb8f3ad2
>> --- /dev/null
>> +++ b/scripts/dtc/fdtoverlay.c
>> @@ -0,0 +1,214 @@
>> +// SPDX-License-Identifier: GPL-2.0-or-later
>> +/*
>> + * Copyright (c) 2017 Konsulko Group Inc. All rights reserved.
>> + *
>> + * Author:
>> + *	 Pantelis Antoniou <pantelis.antoniou at konsulko.com>
>> + */
>> +
>> +#include <assert.h>
>> +#include <ctype.h>
>> +#include <getopt.h>
>> +#include <stdio.h>
>> +#include <stdlib.h>
>> +#include <string.h>
>> +#include <inttypes.h>
>> +
>> +#include <libfdt.h>
>> +
>> +#include "util.h"
>> +
>> +#define BUF_INCREMENT	65536
>> +
>> +/* Usage related data. */
>> +static const char usage_synopsis[] =
>> +	"apply a number of overlays to a base blob\n"
>> +	"	fdtoverlay <options> [<overlay.dtbo> [<overlay.dtbo>]]";
>> +static const char usage_short_opts[] = "i:o:v" USAGE_COMMON_SHORT_OPTS;
>> +static struct option const usage_long_opts[] = {
>> +	{"input",            required_argument, NULL, 'i'},
>> +	{"output",	     required_argument, NULL, 'o'},
>> +	{"verbose",	           no_argument, NULL, 'v'},
>> +	USAGE_COMMON_LONG_OPTS,
>> +};
>> +static const char * const usage_opts_help[] = {
>> +	"Input base DT blob",
>> +	"Output DT blob",
>> +	"Verbose messages",
>> +	USAGE_COMMON_OPTS_HELP
>> +};
>> +
>> +int verbose = 0;
>> +
>> +static void *apply_one(char *base, const char *overlay, size_t *buf_len,
>> +		       const char *name)
>> +{
>> +	char *tmp = NULL;
>> +	char *tmpo;
>> +	int ret;
>> +	bool has_symbols;
>> +
>> +	/*
>> +	 * We take copies first, because a failed apply can trash
>> +	 * both the base blob and the overlay
>> +	 */
>> +	tmpo = xmalloc(fdt_totalsize(overlay));
>> +
>> +	do {
>> +		tmp = xrealloc(tmp, *buf_len);
>> +		ret = fdt_open_into(base, tmp, *buf_len);
>> +		if (ret) {
>> +			fprintf(stderr,
>> +				"\nFailed to make temporary copy: %s\n",
>> +				fdt_strerror(ret));
>> +			goto fail;
>> +		}
>> +		ret = fdt_path_offset(tmp, "/__symbols__");
>> +		has_symbols = ret >= 0;
>> +
>> +		memcpy(tmpo, overlay, fdt_totalsize(overlay));
>> +
>> +		ret = fdt_overlay_apply(tmp, tmpo);
>> +		if (ret == -FDT_ERR_NOSPACE) {
>> +			*buf_len += BUF_INCREMENT;
>> +		}
>> +	} while (ret == -FDT_ERR_NOSPACE);
>> +
>> +	if (ret) {
>> +		fprintf(stderr, "\nFailed to apply '%s': %s\n",
>> +			name, fdt_strerror(ret));
>> +		if (!has_symbols) {
>> +			fprintf(stderr,
>> +				"base blob does not have a '/__symbols__' node, "
>> +				"make sure you have compiled the base blob with '-@' option\n");
>> +		}
>> +		goto fail;
>> +	}
>> +
>> +	free(base);
>> +	free(tmpo);
>> +	return tmp;
>> +
>> +fail:
>> +	free(tmpo);
>> +	if (tmp)
>> +		free(tmp);
>> +
>> +	return NULL;
>> +}
>> +static int do_fdtoverlay(const char *input_filename,
>> +			 const char *output_filename,
>> +			 int argc, char *argv[])
>> +{
>> +	char *blob = NULL;
>> +	char **ovblob = NULL;
>> +	size_t buf_len;
>> +	int i, ret = -1;
>> +
>> +	blob = utilfdt_read(input_filename, &buf_len);
>> +	if (!blob) {
>> +		fprintf(stderr, "\nFailed to read '%s'\n", input_filename);
>> +		goto out_err;
>> +	}
>> +	if (fdt_totalsize(blob) > buf_len) {
>> +		fprintf(stderr,
>> + "\nBase blob is incomplete (%lu / %" PRIu32 " bytes read)\n",
>> +			(unsigned long)buf_len, fdt_totalsize(blob));
>> +		goto out_err;
>> +	}
>> +
>> +	/* allocate blob pointer array */
>> +	ovblob = xmalloc(sizeof(*ovblob) * argc);
>> +	memset(ovblob, 0, sizeof(*ovblob) * argc);
>> +
>> +	/* read and keep track of the overlay blobs */
>> +	for (i = 0; i < argc; i++) {
>> +		size_t ov_len;
>> +		ovblob[i] = utilfdt_read(argv[i], &ov_len);
>> +		if (!ovblob[i]) {
>> +			fprintf(stderr, "\nFailed to read '%s'\n", argv[i]);
>> +			goto out_err;
>> +		}
>> +		if (fdt_totalsize(ovblob[i]) > ov_len) {
>> +			fprintf(stderr,
>> +"\nOverlay '%s' is incomplete (%lu / %" PRIu32 " bytes read)\n",
>> +				argv[i], (unsigned long)ov_len,
>> +				fdt_totalsize(ovblob[i]));
>> +			goto out_err;
>> +		}
>> +	}
>> +
>> +	buf_len = fdt_totalsize(blob);
>> +
>> +	/* apply the overlays in sequence */
>> +	for (i = 0; i < argc; i++) {
>> +		blob = apply_one(blob, ovblob[i], &buf_len, argv[i]);
>> +		if (!blob)
>> +			goto out_err;
>> +	}
>> +
>> +	fdt_pack(blob);
>> +	ret = utilfdt_write(output_filename, blob);
>> +	if (ret)
>> +		fprintf(stderr, "\nFailed to write '%s'\n",
>> +			output_filename);
>> +
>> +out_err:
>> +	if (ovblob) {
>> +		for (i = 0; i < argc; i++) {
>> +			if (ovblob[i])
>> +				free(ovblob[i]);
>> +		}
>> +		free(ovblob);
>> +	}
>> +	free(blob);
>> +
>> +	return ret;
>> +}
>> +
>> +int main(int argc, char *argv[])
>> +{
>> +	int opt, i;
>> +	char *input_filename = NULL;
>> +	char *output_filename = NULL;
>> +
>> +	while ((opt = util_getopt_long()) != EOF) {
>> +		switch (opt) {
>> +		case_USAGE_COMMON_FLAGS
>> +
>> +		case 'i':
>> +			input_filename = optarg;
>> +			break;
>> +		case 'o':
>> +			output_filename = optarg;
>> +			break;
>> +		case 'v':
>> +			verbose = 1;
>> +			break;
>> +		}
>> +	}
>> +
>> +	if (!input_filename)
>> +		usage("missing input file");
>> +
>> +	if (!output_filename)
>> +		usage("missing output file");
>> +
>> +	argv += optind;
>> +	argc -= optind;
>> +
>> +	if (argc <= 0)
>> +		usage("missing overlay file(s)");
>> +
>> +	if (verbose) {
>> +		printf("input  = %s\n", input_filename);
>> +		printf("output = %s\n", output_filename);
>> +		for (i = 0; i < argc; i++)
>> +			printf("overlay[%d] = %s\n", i, argv[i]);
>> +	}
>> +
>> +	if (do_fdtoverlay(input_filename, output_filename, argc, argv))
>> +		return 1;
>> +
>> +	return 0;
>> +}
>> diff --git a/scripts/dtc/flattree.c b/scripts/dtc/flattree.c
>> index 086c5abf10f..ae3f9dec82f 100644
>> --- a/scripts/dtc/flattree.c
>> +++ b/scripts/dtc/flattree.c
>> @@ -1,21 +1,6 @@
>> +// SPDX-License-Identifier: GPL-2.0-or-later
>>  /*
>>   * (C) Copyright David Gibson <dwg at au1.ibm.com>, IBM Corporation.  2005.
>> - *
>> - *
>> - * This program 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 program 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 program; if not, write to the Free Software
>> - *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307
>> - *                                                                   USA
>>   */
>>  
>>  #include "dtc.h"
>> @@ -139,7 +124,8 @@ static void asm_emit_cell(void *e, cell_t val)
>>  {
>>  	FILE *f = e;
>>  
>> -	fprintf(f, "\t.byte 0x%02x; .byte 0x%02x; .byte 0x%02x; .byte 0x%02x\n",
>> +	fprintf(f, "\t.byte\t0x%02x\n" "\t.byte\t0x%02x\n"
>> +		"\t.byte\t0x%02x\n" "\t.byte\t0x%02x\n",
>>  		(val >> 24) & 0xff, (val >> 16) & 0xff,
>>  		(val >> 8) & 0xff, val & 0xff);
>>  }
>> @@ -149,9 +135,9 @@ static void asm_emit_string(void *e, const char *str, int len)
>>  	FILE *f = e;
>>  
>>  	if (len != 0)
>> -		fprintf(f, "\t.string\t\"%.*s\"\n", len, str);
>> +		fprintf(f, "\t.asciz\t\"%.*s\"\n", len, str);
>>  	else
>> -		fprintf(f, "\t.string\t\"%s\"\n", str);
>> +		fprintf(f, "\t.asciz\t\"%s\"\n", str);
>>  }
>>  
>>  static void asm_emit_align(void *e, int a)
>> @@ -164,14 +150,14 @@ static void asm_emit_align(void *e, int a)
>>  static void asm_emit_data(void *e, struct data d)
>>  {
>>  	FILE *f = e;
>> -	int off = 0;
>> +	unsigned int off = 0;
>>  	struct marker *m = d.markers;
>>  
>>  	for_each_marker_of_type(m, LABEL)
>>  		emit_offset_label(f, m->ref, m->offset);
>>  
>>  	while ((d.len - off) >= sizeof(uint32_t)) {
>> -		asm_emit_cell(e, fdt32_to_cpu(*((fdt32_t *)(d.val+off))));
>> +		asm_emit_cell(e, dtb_ld32(d.val + off));
>>  		off += sizeof(uint32_t);
>>  	}
>>  
>> @@ -234,7 +220,7 @@ static struct emitter asm_emitter = {
>>  
>>  static int stringtable_insert(struct data *d, const char *str)
>>  {
>> -	int i;
>> +	unsigned int i;
>>  
>>  	/* FIXME: do this more efficiently? */
>>  
>> @@ -310,7 +296,7 @@ static struct data flatten_reserve_list(struct reserve_info *reservelist,
>>  {
>>  	struct reserve_info *re;
>>  	struct data d = empty_data;
>> -	int    j;
>> +	unsigned int j;
>>  
>>  	for (re = reservelist; re; re = re->next) {
>>  		d = data_append_re(d, re->address, re->size);
>> @@ -360,7 +346,7 @@ static void make_fdt_header(struct fdt_header *fdt,
>>  void dt_to_blob(FILE *f, struct dt_info *dti, int version)
>>  {
>>  	struct version_info *vi = NULL;
>> -	int i;
>> +	unsigned int i;
>>  	struct data blob       = empty_data;
>>  	struct data reservebuf = empty_data;
>>  	struct data dtbuf      = empty_data;
>> @@ -393,7 +379,7 @@ void dt_to_blob(FILE *f, struct dt_info *dti, int version)
>>  			padlen = 0;
>>  			if (quiet < 1)
>>  				fprintf(stderr,
>> -					"Warning: blob size %d >= minimum size %d\n",
>> +					"Warning: blob size %"PRIu32" >= minimum size %d\n",
>>  					fdt32_to_cpu(fdt.totalsize), minsize);
>>  		}
>>  	}
>> @@ -453,7 +439,7 @@ static void dump_stringtable_asm(FILE *f, struct data strbuf)
>>  
>>  	while (p < (strbuf.val + strbuf.len)) {
>>  		len = strlen(p);
>> -		fprintf(f, "\t.string \"%s\"\n", p);
>> +		fprintf(f, "\t.asciz \"%s\"\n", p);
>>  		p += len+1;
>>  	}
>>  }
>> @@ -461,7 +447,7 @@ static void dump_stringtable_asm(FILE *f, struct data strbuf)
>>  void dt_to_asm(FILE *f, struct dt_info *dti, int version)
>>  {
>>  	struct version_info *vi = NULL;
>> -	int i;
>> +	unsigned int i;
>>  	struct data strbuf = empty_data;
>>  	struct reserve_info *re;
>>  	const char *symprefix = "dt";
>> @@ -517,7 +503,7 @@ void dt_to_asm(FILE *f, struct dt_info *dti, int version)
>>  	 * Reserve map entries.
>>  	 * Align the reserve map to a doubleword boundary.
>>  	 * Each entry is an (address, size) pair of u64 values.
>> -	 * Always supply a zero-sized temination entry.
>> +	 * Always supply a zero-sized termination entry.
>>  	 */
>>  	asm_emit_align(f, 8);
>>  	emit_label(f, symprefix, "reserve_map");
>> @@ -525,7 +511,7 @@ void dt_to_asm(FILE *f, struct dt_info *dti, int version)
>>  	fprintf(f, "/* Memory reserve map from source file */\n");
>>  
>>  	/*
>> -	 * Use .long on high and low halfs of u64s to avoid .quad
>> +	 * Use .long on high and low halves of u64s to avoid .quad
>>  	 * as it appears .quad isn't available in some assemblers.
>>  	 */
>>  	for (re = dti->reservelist; re; re = re->next) {
>> @@ -618,11 +604,11 @@ static void flat_realign(struct inbuf *inb, int align)
>>  		die("Premature end of data parsing flat device tree\n");
>>  }
>>  
>> -static char *flat_read_string(struct inbuf *inb)
>> +static const char *flat_read_string(struct inbuf *inb)
>>  {
>>  	int len = 0;
>>  	const char *p = inb->ptr;
>> -	char *str;
>> +	const char *str;
>>  
>>  	do {
>>  		if (p >= inb->limit)
>> @@ -630,7 +616,7 @@ static char *flat_read_string(struct inbuf *inb)
>>  		len++;
>>  	} while ((*p++) != '\0');
>>  
>> -	str = xstrdup(inb->ptr);
>> +	str = inb->ptr;
>>  
>>  	inb->ptr += len;
>>  
>> @@ -692,7 +678,7 @@ static struct property *flat_read_property(struct inbuf *dtbuf,
>>  
>>  	val = flat_read_data(dtbuf, proplen);
>>  
>> -	return build_property(name, val);
>> +	return build_property(name, val, NULL);
>>  }
>>  
>>  static struct reserve_info *flat_read_mem_reserve(struct inbuf *inb)
>> @@ -723,7 +709,8 @@ static struct reserve_info *flat_read_mem_reserve(struct inbuf *inb)
>>  	return reservelist;
>>  }
>>  
>> -static char *nodename_from_path(const char *ppath, const char *cpath)
>> +
>> +static const char *nodename_from_path(const char *ppath, const char *cpath)
>>  {
>>  	int plen;
>>  
>> @@ -737,7 +724,7 @@ static char *nodename_from_path(const char *ppath, const char *cpath)
>>  	if (!streq(ppath, "/"))
>>  		plen++;
>>  
>> -	return xstrdup(cpath + plen);
>> +	return cpath + plen;
>>  }
>>  
>>  static struct node *unflatten_tree(struct inbuf *dtbuf,
>> @@ -745,17 +732,18 @@ static struct node *unflatten_tree(struct inbuf *dtbuf,
>>  				   const char *parent_flatname, int flags)
>>  {
>>  	struct node *node;
>> -	char *flatname;
>> +	const char *flatname;
>>  	uint32_t val;
>>  
>> -	node = build_node(NULL, NULL);
>> +	node = build_node(NULL, NULL, NULL);
>>  
>>  	flatname = flat_read_string(dtbuf);
>>  
>>  	if (flags & FTF_FULLPATH)
>> -		node->name = nodename_from_path(parent_flatname, flatname);
>> +		node->name = xstrdup(nodename_from_path(parent_flatname,
>> +							flatname));
>>  	else
>> -		node->name = flatname;
>> +		node->name = xstrdup(flatname);
>>  
>>  	do {
>>  		struct property *prop;
>> @@ -797,10 +785,6 @@ static struct node *unflatten_tree(struct inbuf *dtbuf,
>>  		}
>>  	} while (val != FDT_END_NODE);
>>  
>> -	if (node->name != flatname) {
>> -		free(flatname);
>> -	}
>> -
>>  	return node;
>>  }
>>  
>> diff --git a/scripts/dtc/fstree.c b/scripts/dtc/fstree.c
>> index ae7d06c3c49..0f9a534bacd 100644
>> --- a/scripts/dtc/fstree.c
>> +++ b/scripts/dtc/fstree.c
>> @@ -1,21 +1,6 @@
>> +// SPDX-License-Identifier: GPL-2.0-or-later
>>  /*
>>   * (C) Copyright David Gibson <dwg at au1.ibm.com>, IBM Corporation.  2005.
>> - *
>> - *
>> - * This program 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 program 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 program; if not, write to the Free Software
>> - *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307
>> - *                                                                   USA
>>   */
>>  
>>  #include "dtc.h"
>> @@ -34,7 +19,7 @@ static struct node *read_fstree(const char *dirname)
>>  	if (!d)
>>  		die("Couldn't opendir() \"%s\": %s\n", dirname, strerror(errno));
>>  
>> -	tree = build_node(NULL, NULL);
>> +	tree = build_node(NULL, NULL, NULL);
>>  
>>  	while ((de = readdir(d)) != NULL) {
>>  		char *tmpname;
>> @@ -45,7 +30,7 @@ static struct node *read_fstree(const char *dirname)
>>  
>>  		tmpname = join_path(dirname, de->d_name);
>>  
>> -		if (lstat(tmpname, &st) < 0)
>> +		if (stat(tmpname, &st) < 0)
>>  			die("stat(%s): %s\n", tmpname, strerror(errno));
>>  
>>  		if (S_ISREG(st.st_mode)) {
>> @@ -58,9 +43,10 @@ static struct node *read_fstree(const char *dirname)
>>  					"WARNING: Cannot open %s: %s\n",
>>  					tmpname, strerror(errno));
>>  			} else {
>> -				prop = build_property(xstrdup(de->d_name),
>> +				prop = build_property(de->d_name,
>>  						      data_copy_file(pfile,
>> -								     st.st_size));
>> +								     st.st_size),
>> +						      NULL);
>>  				add_property(tree, prop);
>>  				fclose(pfile);
>>  			}
>> diff --git a/scripts/dtc/libfdt/fdt.c b/scripts/dtc/libfdt/fdt.c
>> index 28f4e1a5f15..95f644c31f9 100644
>> --- a/scripts/dtc/libfdt/fdt.c
>> +++ b/scripts/dtc/libfdt/fdt.c
>> @@ -19,9 +19,16 @@ int32_t fdt_ro_probe_(const void *fdt)
>>  {
>>  	uint32_t totalsize = fdt_totalsize(fdt);
>>  
>> +	if (can_assume(VALID_DTB))
>> +		return totalsize;
>> +
>> +	/* The device tree must be at an 8-byte aligned address */
>> +	if ((uintptr_t)fdt & 7)
>> +		return -FDT_ERR_ALIGNMENT;
>> +
>>  	if (fdt_magic(fdt) == FDT_MAGIC) {
>>  		/* Complete tree */
>> -		if (fdt_chk_version()) {
>> +		if (!can_assume(LATEST)) {
>>  			if (fdt_version(fdt) < FDT_FIRST_SUPPORTED_VERSION)
>>  				return -FDT_ERR_BADVERSION;
>>  			if (fdt_last_comp_version(fdt) >
>> @@ -30,7 +37,7 @@ int32_t fdt_ro_probe_(const void *fdt)
>>  		}
>>  	} else if (fdt_magic(fdt) == FDT_SW_MAGIC) {
>>  		/* Unfinished sequential-write blob */
>> -		if (fdt_size_dt_struct(fdt) == 0)
>> +		if (!can_assume(VALID_INPUT) && fdt_size_dt_struct(fdt) == 0)
>>  			return -FDT_ERR_BADSTATE;
>>  	} else {
>>  		return -FDT_ERR_BADMAGIC;
>> @@ -75,17 +82,21 @@ size_t fdt_header_size_(uint32_t version)
>>  
>>  size_t fdt_header_size(const void *fdt)
>>  {
>> -	return fdt_chk_version() ? fdt_header_size_(fdt_version(fdt)) :
>> -		FDT_V17_SIZE;
>> +	return can_assume(LATEST) ? FDT_V17_SIZE :
>> +		fdt_header_size_(fdt_version(fdt));
>>  }
>>  
>>  int fdt_check_header(const void *fdt)
>>  {
>>  	size_t hdrsize;
>>  
>> +	/* The device tree must be at an 8-byte aligned address */
>> +	if ((uintptr_t)fdt & 7)
>> +		return -FDT_ERR_ALIGNMENT;
>> +
>>  	if (fdt_magic(fdt) != FDT_MAGIC)
>>  		return -FDT_ERR_BADMAGIC;
>> -	if (fdt_chk_version()) {
>> +	if (!can_assume(LATEST)) {
>>  		if ((fdt_version(fdt) < FDT_FIRST_SUPPORTED_VERSION)
>>  		    || (fdt_last_comp_version(fdt) >
>>  			FDT_LAST_SUPPORTED_VERSION))
>> @@ -94,8 +105,7 @@ int fdt_check_header(const void *fdt)
>>  			return -FDT_ERR_BADVERSION;
>>  	}
>>  	hdrsize = fdt_header_size(fdt);
>> -	if (fdt_chk_basic()) {
>> -
>> +	if (!can_assume(VALID_DTB)) {
>>  		if ((fdt_totalsize(fdt) < hdrsize)
>>  		    || (fdt_totalsize(fdt) > INT_MAX))
>>  			return -FDT_ERR_TRUNCATED;
>> @@ -104,11 +114,9 @@ int fdt_check_header(const void *fdt)
>>  		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 (!can_assume(LATEST) && fdt_version(fdt) < 17) {
>>  			if (!check_off_(hdrsize, fdt_totalsize(fdt),
>>  					fdt_off_dt_struct(fdt)))
>>  				return -FDT_ERR_TRUNCATED;
>> @@ -137,13 +145,13 @@ const void *fdt_offset_ptr(const void *fdt, int offset, unsigned int len)
>>  	if (offset < 0)
>>  		return NULL;
>>  
>> -	if (fdt_chk_basic())
>> +	if (!can_assume(VALID_INPUT))
>>  		if ((absoffset < uoffset)
>>  		    || ((absoffset + len) < absoffset)
>>  		    || (absoffset + len) > fdt_totalsize(fdt))
>>  			return NULL;
>>  
>> -	if (!fdt_chk_version() || fdt_version(fdt) >= 0x11)
>> +	if (can_assume(LATEST) || fdt_version(fdt) >= 0x11)
>>  		if (((uoffset + len) < uoffset)
>>  		    || ((offset + len) > fdt_size_dt_struct(fdt)))
>>  			return NULL;
>> @@ -154,13 +162,13 @@ const void *fdt_offset_ptr(const void *fdt, int offset, unsigned int len)
>>  uint32_t fdt_next_tag(const void *fdt, int startoffset, int *nextoffset)
>>  {
>>  	const fdt32_t *tagp, *lenp;
>> -	uint32_t tag;
>> +	uint32_t tag, len, sum;
>>  	int offset = startoffset;
>>  	const char *p;
>>  
>>  	*nextoffset = -FDT_ERR_TRUNCATED;
>>  	tagp = fdt_offset_ptr(fdt, offset, FDT_TAGSIZE);
>> -	if (fdt_chk_basic() && !tagp)
>> +	if (!can_assume(VALID_DTB) && !tagp)
>>  		return FDT_END; /* premature end */
>>  	tag = fdt32_to_cpu(*tagp);
>>  	offset += FDT_TAGSIZE;
>> @@ -172,20 +180,27 @@ 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 (fdt_chk_basic() && !p)
>> +		if (!can_assume(VALID_DTB) && !p)
>>  			return FDT_END; /* premature end */
>>  		break;
>>  
>>  	case FDT_PROP:
>>  		lenp = fdt_offset_ptr(fdt, offset, sizeof(*lenp));
>> -		if (fdt_chk_basic() && !lenp)
>> +		if (!can_assume(VALID_DTB) && !lenp)
>>  			return FDT_END; /* premature end */
>> +
>> +		len = fdt32_to_cpu(*lenp);
>> +		sum = len + offset;
>> +		if (!can_assume(VALID_DTB) &&
>> +		    (INT_MAX <= sum || sum < (uint32_t) offset))
>> +			return FDT_END; /* premature end */
>> +
>>  		/* skip-name offset, length and value */
>> -		offset += sizeof(struct fdt_property) - FDT_TAGSIZE
>> -			+ fdt32_to_cpu(*lenp);
>> -		if (fdt_chk_version() &&
>> -		    fdt_version(fdt) < 0x10 && fdt32_to_cpu(*lenp) >= 8 &&
>> -		    ((offset - fdt32_to_cpu(*lenp)) % 8) != 0)
>> +		offset += sizeof(struct fdt_property) - FDT_TAGSIZE + len;
>> +
>> +		if (!can_assume(LATEST) &&
>> +		    fdt_version(fdt) < 0x10 && len >= 8 &&
>> +		    ((offset - len) % 8) != 0)
>>  			offset += 4;
>>  		break;
>>  
>> @@ -198,8 +213,7 @@ uint32_t fdt_next_tag(const void *fdt, int startoffset, int *nextoffset)
>>  		return FDT_END;
>>  	}
>>  
>> -	if (fdt_chk_basic() &&
>> -	    !fdt_offset_ptr(fdt, startoffset, offset - startoffset))
>> +	if (!fdt_offset_ptr(fdt, startoffset, offset - startoffset))
>>  		return FDT_END; /* premature end */
>>  
>>  	*nextoffset = FDT_TAGALIGN(offset);
>> @@ -208,8 +222,11 @@ uint32_t fdt_next_tag(const void *fdt, int startoffset, int *nextoffset)
>>  
>>  int fdt_check_node_offset_(const void *fdt, int offset)
>>  {
>> -	if ((offset < 0) || (offset % FDT_TAGSIZE)
>> -	    || (fdt_next_tag(fdt, offset, &offset) != FDT_BEGIN_NODE))
>> +	if (!can_assume(VALID_INPUT)
>> +	    && ((offset < 0) || (offset % FDT_TAGSIZE)))
>> +		return -FDT_ERR_BADOFFSET;
>> +
>> +	if (fdt_next_tag(fdt, offset, &offset) != FDT_BEGIN_NODE)
>>  		return -FDT_ERR_BADOFFSET;
>>  
>>  	return offset;
>> @@ -217,8 +234,11 @@ int fdt_check_node_offset_(const void *fdt, int offset)
>>  
>>  int fdt_check_prop_offset_(const void *fdt, int offset)
>>  {
>> -	if ((offset < 0) || (offset % FDT_TAGSIZE)
>> -	    || (fdt_next_tag(fdt, offset, &offset) != FDT_PROP))
>> +	if (!can_assume(VALID_INPUT)
>> +	    && ((offset < 0) || (offset % FDT_TAGSIZE)))
>> +		return -FDT_ERR_BADOFFSET;
>> +
>> +	if (fdt_next_tag(fdt, offset, &offset) != FDT_PROP)
>>  		return -FDT_ERR_BADOFFSET;
>>  
>>  	return offset;
>> @@ -292,21 +312,21 @@ int fdt_next_subnode(const void *fdt, int offset)
>>  	return offset;
>>  }
>>  
>> -const char *fdt_find_string_(const char *strtab, int tabsize, const char *s)
>> +const char *fdt_find_string_len_(const char *strtab, int tabsize, const char *s,
>> +				 int slen)
>>  {
>> -	int len = strlen(s) + 1;
>> -	const char *last = strtab + tabsize - len;
>> +	const char *last = strtab + tabsize - (slen + 1);
>>  	const char *p;
>>  
>>  	for (p = strtab; p <= last; p++)
>> -		if (memcmp(p, s, len) == 0)
>> +		if (memcmp(p, s, slen) == 0 && p[slen] == '\0')
>>  			return p;
>>  	return NULL;
>>  }
>>  
>>  int fdt_move(const void *fdt, void *buf, int bufsize)
>>  {
>> -	if (fdt_chk_basic() && bufsize < 0)
>> +	if (!can_assume(VALID_INPUT) && bufsize < 0)
>>  		return -FDT_ERR_NOSPACE;
>>  
>>  	FDT_RO_PROBE(fdt);
>> diff --git a/scripts/dtc/libfdt/fdt.h b/scripts/dtc/libfdt/fdt.h
>> index f2e68807f27..c6e4d7838dc 100644
>> --- a/scripts/dtc/libfdt/fdt.h
>> +++ b/scripts/dtc/libfdt/fdt.h
>> @@ -7,7 +7,7 @@
>>   * Copyright 2012 Kim Phillips, Freescale Semiconductor.
>>   */
>>  
>> -#ifndef __ASSEMBLY__
>> +#ifndef __ASSEMBLER__
>>  
>>  struct fdt_header {
>>  	fdt32_t magic;			 /* magic word FDT_MAGIC */
>> @@ -45,7 +45,7 @@ struct fdt_property {
>>  	char data[0];
>>  };
>>  
>> -#endif /* !__ASSEMBLY */
>> +#endif /* !__ASSEMBLER__ */
>>  
>>  #define FDT_MAGIC	0xd00dfeed	/* 4: version, 4: total size */
>>  #define FDT_TAGSIZE	sizeof(fdt32_t)
>> diff --git a/scripts/dtc/libfdt/fdt_addresses.c b/scripts/dtc/libfdt/fdt_addresses.c
>> index 9a82cd0ba2f..c40ba094f1f 100644
>> --- a/scripts/dtc/libfdt/fdt_addresses.c
>> +++ b/scripts/dtc/libfdt/fdt_addresses.c
>> @@ -73,7 +73,7 @@ int fdt_appendprop_addrrange(void *fdt, int parent, int nodeoffset,
>>  	/* check validity of address */
>>  	prop = data;
>>  	if (addr_cells == 1) {
>> -		if ((addr > UINT32_MAX) || ((UINT32_MAX + 1 - addr) < size))
>> +		if ((addr > UINT32_MAX) || (((uint64_t) UINT32_MAX + 1 - addr) < size))
>>  			return -FDT_ERR_BADVALUE;
>>  
>>  		fdt32_st(prop, (uint32_t)addr);
>> diff --git a/scripts/dtc/libfdt/fdt_overlay.c b/scripts/dtc/libfdt/fdt_overlay.c
>> index 7a65c35af6f..ee64f0b8110 100644
>> --- a/scripts/dtc/libfdt/fdt_overlay.c
>> +++ b/scripts/dtc/libfdt/fdt_overlay.c
>> @@ -40,37 +40,22 @@ static uint32_t overlay_get_target_phandle(const void *fdto, int fragment)
>>  	return fdt32_to_cpu(*val);
>>  }
>>  
>> -/**
>> - * overlay_get_target - retrieves the offset of a fragment's target
>> - * @fdt: Base device tree blob
>> - * @fdto: Device tree overlay blob
>> - * @fragment: node offset of the fragment in the overlay
>> - * @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 targeting is
>> - * done (through a phandle or a path)
>> - *
>> - * returns:
>> - *      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,
>> -			      int fragment, char const **pathp)
>> +int fdt_overlay_target_offset(const void *fdt, const void *fdto,
>> +			      int fragment_offset, char const **pathp)
>>  {
>>  	uint32_t phandle;
>>  	const char *path = NULL;
>>  	int path_len = 0, ret;
>>  
>>  	/* Try first to do a phandle based lookup */
>> -	phandle = overlay_get_target_phandle(fdto, fragment);
>> +	phandle = overlay_get_target_phandle(fdto, fragment_offset);
>>  	if (phandle == (uint32_t)-1)
>>  		return -FDT_ERR_BADPHANDLE;
>>  
>>  	/* no phandle, try path */
>>  	if (!phandle) {
>>  		/* And then a path based lookup */
>> -		path = fdt_getprop(fdto, fragment, "target-path", &path_len);
>> +		path = fdt_getprop(fdto, fragment_offset, "target-path", &path_len);
>>  		if (path)
>>  			ret = fdt_path_offset(fdt, path);
>>  		else
>> @@ -116,26 +101,22 @@ static int overlay_get_target(const void *fdt, const void *fdto,
>>  static int overlay_phandle_add_offset(void *fdt, int node,
>>  				      const char *name, uint32_t delta)
>>  {
>> -	const fdt32_t *val;
>> -	uint32_t adj_val;
>> +	fdt32_t *valp, val;
>>  	int len;
>>  
>> -	val = fdt_getprop(fdt, node, name, &len);
>> -	if (!val)
>> +	valp = fdt_getprop_w(fdt, node, name, &len);
>> +	if (!valp)
>>  		return len;
>>  
>> -	if (len != sizeof(*val))
>> +	if (len != sizeof(val))
>>  		return -FDT_ERR_BADPHANDLE;
>>  
>> -	adj_val = fdt32_to_cpu(*val);
>> -	if ((adj_val + delta) < adj_val)
>> +	val = fdt32_ld(valp);
>> +	if (val + delta < val || val + delta == (uint32_t)-1)
>>  		return -FDT_ERR_NOPHANDLES;
>>  
>> -	adj_val += delta;
>> -	if (adj_val == (uint32_t)-1)
>> -		return -FDT_ERR_NOPHANDLES;
>> -
>> -	return fdt_setprop_inplace_u32(fdt, node, name, adj_val);
>> +	fdt32_st(valp, val + delta);
>> +	return 0;
>>  }
>>  
>>  /**
>> @@ -228,8 +209,8 @@ static int overlay_update_local_node_references(void *fdto,
>>  
>>  	fdt_for_each_property_offset(fixup_prop, fdto, fixup_node) {
>>  		const fdt32_t *fixup_val;
>> -		const char *tree_val;
>>  		const char *name;
>> +		char *tree_val;
>>  		int fixup_len;
>>  		int tree_len;
>>  		int i;
>> @@ -243,7 +224,7 @@ static int overlay_update_local_node_references(void *fdto,
>>  			return -FDT_ERR_BADOVERLAY;
>>  		fixup_len /= sizeof(uint32_t);
>>  
>> -		tree_val = fdt_getprop(fdto, tree_node, name, &tree_len);
>> +		tree_val = fdt_getprop_w(fdto, tree_node, name, &tree_len);
>>  		if (!tree_val) {
>>  			if (tree_len == -FDT_ERR_NOTFOUND)
>>  				return -FDT_ERR_BADOVERLAY;
>> @@ -252,33 +233,15 @@ static int overlay_update_local_node_references(void *fdto,
>>  		}
>>  
>>  		for (i = 0; i < fixup_len; i++) {
>> -			fdt32_t adj_val;
>> -			uint32_t poffset;
>> +			fdt32_t *refp;
>>  
>> -			poffset = fdt32_to_cpu(fixup_val[i]);
>> +			refp = (fdt32_t *)(tree_val + fdt32_ld_(fixup_val + i));
>>  
>>  			/*
>> -			 * phandles to fixup can be unaligned.
>> -			 *
>> -			 * Use a memcpy for the architectures that do
>> -			 * not support unaligned accesses.
>> +			 * phandles to fixup can be unaligned, so use
>> +			 * fdt32_{ld,st}() to read/write them.
>>  			 */
>> -			memcpy(&adj_val, tree_val + poffset, sizeof(adj_val));
>> -
>> -			adj_val = cpu_to_fdt32(fdt32_to_cpu(adj_val) + delta);
>> -
>> -			ret = fdt_setprop_inplace_namelen_partial(fdto,
>> -								  tree_node,
>> -								  name,
>> -								  strlen(name),
>> -								  poffset,
>> -								  &adj_val,
>> -								  sizeof(adj_val));
>> -			if (ret == -FDT_ERR_NOSPACE)
>> -				return -FDT_ERR_BADOVERLAY;
>> -
>> -			if (ret)
>> -				return ret;
>> +			fdt32_st(refp, fdt32_ld(refp) + delta);
>>  		}
>>  	}
>>  
>> @@ -344,7 +307,6 @@ static int overlay_update_local_references(void *fdto, uint32_t delta)
>>  
>>  /**
>>   * overlay_fixup_one_phandle - Set an overlay phandle to the base one
>> - * @fdt: Base Device Tree blob
>>   * @fdto: Device tree overlay blob
>>   * @symbols_off: Node offset of the symbols node in the base device tree
>>   * @path: Path to a node holding a phandle in the overlay
>> @@ -352,7 +314,7 @@ static int overlay_update_local_references(void *fdto, uint32_t delta)
>>   * @name: Name of the property holding the phandle reference in the overlay
>>   * @name_len: number of name characters to consider
>>   * @poffset: Offset within the overlay property where the phandle is stored
>> - * @label: Label of the node referenced by the phandle
>> + * @phandle: Phandle referencing the node
>>   *
>>   * overlay_fixup_one_phandle() resolves an overlay phandle pointing to
>>   * a node in the base device tree.
>> @@ -365,34 +327,17 @@ static int overlay_update_local_references(void *fdto, uint32_t delta)
>>   *      0 on success
>>   *      Negative error code on failure
>>   */
>> -static int overlay_fixup_one_phandle(void *fdt, void *fdto,
>> -				     int symbols_off,
>> +static int overlay_fixup_one_phandle(void *fdto, int symbols_off,
>>  				     const char *path, uint32_t path_len,
>>  				     const char *name, uint32_t name_len,
>> -				     int poffset, const char *label)
>> +				     int poffset, uint32_t phandle)
>>  {
>> -	const char *symbol_path;
>> -	uint32_t phandle;
>>  	fdt32_t phandle_prop;
>> -	int symbol_off, fixup_off;
>> -	int prop_len;
>> +	int fixup_off;
>>  
>>  	if (symbols_off < 0)
>>  		return symbols_off;
>>  
>> -	symbol_path = fdt_getprop(fdt, symbols_off, label,
>> -				  &prop_len);
>> -	if (!symbol_path)
>> -		return prop_len;
>> -
>> -	symbol_off = fdt_path_offset(fdt, symbol_path);
>> -	if (symbol_off < 0)
>> -		return symbol_off;
>> -
>> -	phandle = fdt_get_phandle(fdt, symbol_off);
>> -	if (!phandle)
>> -		return -FDT_ERR_NOTFOUND;
>> -
>>  	fixup_off = fdt_path_offset_namelen(fdto, path, path_len);
>>  	if (fixup_off == -FDT_ERR_NOTFOUND)
>>  		return -FDT_ERR_BADOVERLAY;
>> @@ -404,7 +349,7 @@ static int overlay_fixup_one_phandle(void *fdt, void *fdto,
>>  						   name, name_len, poffset,
>>  						   &phandle_prop,
>>  						   sizeof(phandle_prop));
>> -};
>> +}
>>  
>>  /**
>>   * overlay_fixup_phandle - Set an overlay phandle to the base one
>> @@ -431,6 +376,10 @@ static int overlay_fixup_phandle(void *fdt, void *fdto, int symbols_off,
>>  	const char *value;
>>  	const char *label;
>>  	int len;
>> +	const char *symbol_path;
>> +	int prop_len;
>> +	int symbol_off;
>> +	uint32_t phandle;
>>  
>>  	value = fdt_getprop_by_offset(fdto, property,
>>  				      &label, &len);
>> @@ -441,6 +390,18 @@ static int overlay_fixup_phandle(void *fdt, void *fdto, int symbols_off,
>>  		return len;
>>  	}
>>  
>> +	symbol_path = fdt_getprop(fdt, symbols_off, label, &prop_len);
>> +	if (!symbol_path)
>> +		return prop_len;
>> +
>> +	symbol_off = fdt_path_offset(fdt, symbol_path);
>> +	if (symbol_off < 0)
>> +		return symbol_off;
>> +
>> +	phandle = fdt_get_phandle(fdt, symbol_off);
>> +	if (!phandle)
>> +		return -FDT_ERR_NOTFOUND;
>> +
>>  	do {
>>  		const char *path, *name, *fixup_end;
>>  		const char *fixup_str = value;
>> @@ -480,9 +441,9 @@ static int overlay_fixup_phandle(void *fdt, void *fdto, int symbols_off,
>>  		if ((*endptr != '\0') || (endptr <= (sep + 1)))
>>  			return -FDT_ERR_BADOVERLAY;
>>  
>> -		ret = overlay_fixup_one_phandle(fdt, fdto, symbols_off,
>> +		ret = overlay_fixup_one_phandle(fdto, symbols_off,
>>  						path, path_len, name, name_len,
>> -						poffset, label);
>> +						poffset, phandle);
>>  		if (ret)
>>  			return ret;
>>  	} while (len > 0);
>> @@ -535,6 +496,255 @@ static int overlay_fixup_phandles(void *fdt, void *fdto)
>>  	return 0;
>>  }
>>  
>> +/**
>> + * overlay_adjust_local_conflicting_phandle: Changes a phandle value
>> + * @fdto: Device tree overlay
>> + * @node: The node the phandle is set for
>> + * @fdt_phandle: The new value for the phandle
>> + *
>> + * returns:
>> + *      0 on success
>> + *      Negative error code on failure
>> + */
>> +static int overlay_adjust_local_conflicting_phandle(void *fdto, int node,
>> +						    uint32_t fdt_phandle)
>> +{
>> +	const fdt32_t *php;
>> +	int len, ret;
>> +
>> +	php = fdt_getprop(fdto, node, "phandle", &len);
>> +	if (php && len == sizeof(*php)) {
>> +		ret = fdt_setprop_inplace_u32(fdto, node, "phandle", fdt_phandle);
>> +		if (ret)
>> +			return ret;
>> +	}
>> +
>> +	php = fdt_getprop(fdto, node, "linux,phandle", &len);
>> +	if (php && len == sizeof(*php)) {
>> +		ret = fdt_setprop_inplace_u32(fdto, node, "linux,phandle", fdt_phandle);
>> +		if (ret)
>> +			return ret;
>> +	}
>> +
>> +	return 0;
>> +}
>> +
>> +/**
>> + * overlay_update_node_conflicting_references - Recursively replace phandle values
>> + * @fdto: Device tree overlay blob
>> + * @tree_node: Node to recurse into
>> + * @fixup_node: Node offset of the matching local fixups node
>> + * @fdt_phandle: Value to replace phandles with
>> + * @fdto_phandle: Value to be replaced
>> + *
>> + * Replaces all phandles with value @fdto_phandle by @fdt_phandle.
>> + *
>> + * returns:
>> + *      0 on success
>> + *      Negative error code on failure
>> + */
>> +static int overlay_update_node_conflicting_references(void *fdto, int tree_node,
>> +						      int fixup_node,
>> +						      uint32_t fdt_phandle,
>> +						      uint32_t fdto_phandle)
>> +{
>> +	int fixup_prop;
>> +	int fixup_child;
>> +	int ret;
>> +
>> +	fdt_for_each_property_offset(fixup_prop, fdto, fixup_node) {
>> +		const fdt32_t *fixup_val;
>> +		const char *name;
>> +		char *tree_val;
>> +		int fixup_len;
>> +		int tree_len;
>> +		int i;
>> +
>> +		fixup_val = fdt_getprop_by_offset(fdto, fixup_prop,
>> +						  &name, &fixup_len);
>> +		if (!fixup_val)
>> +			return fixup_len;
>> +
>> +		if (fixup_len % sizeof(uint32_t))
>> +			return -FDT_ERR_BADOVERLAY;
>> +		fixup_len /= sizeof(uint32_t);
>> +
>> +		tree_val = fdt_getprop_w(fdto, tree_node, name, &tree_len);
>> +		if (!tree_val) {
>> +			if (tree_len == -FDT_ERR_NOTFOUND)
>> +				return -FDT_ERR_BADOVERLAY;
>> +
>> +			return tree_len;
>> +		}
>> +
>> +		for (i = 0; i < fixup_len; i++) {
>> +			fdt32_t *refp;
>> +			uint32_t valp;
>> +
>> +			refp = (fdt32_t *)(tree_val + fdt32_ld_(fixup_val + i));
>> +			valp = fdt32_ld(refp);
>> +
>> +			if (valp == fdto_phandle)
>> +				fdt32_st(refp, fdt_phandle);
>> +		}
>> +	}
>> +
>> +	fdt_for_each_subnode(fixup_child, fdto, fixup_node) {
>> +		const char *fixup_child_name = fdt_get_name(fdto, fixup_child, NULL);
>> +		int tree_child;
>> +
>> +		tree_child = fdt_subnode_offset(fdto, tree_node, fixup_child_name);
>> +
>> +		if (tree_child == -FDT_ERR_NOTFOUND)
>> +			return -FDT_ERR_BADOVERLAY;
>> +		if (tree_child < 0)
>> +			return tree_child;
>> +
>> +		ret = overlay_update_node_conflicting_references(fdto, tree_child,
>> +								 fixup_child,
>> +								 fdt_phandle,
>> +								 fdto_phandle);
>> +		if (ret)
>> +			return ret;
>> +	}
>> +
>> +	return 0;
>> +}
>> +
>> +/**
>> + * overlay_update_local_conflicting_references - Recursively replace phandle values
>> + * @fdto: Device tree overlay blob
>> + * @fdt_phandle: Value to replace phandles with
>> + * @fdto_phandle: Value to be replaced
>> + *
>> + * Replaces all phandles with value @fdto_phandle by @fdt_phandle.
>> + *
>> + * returns:
>> + *      0 on success
>> + *      Negative error code on failure
>> + */
>> +static int overlay_update_local_conflicting_references(void *fdto,
>> +						       uint32_t fdt_phandle,
>> +						       uint32_t fdto_phandle)
>> +{
>> +	int fixups;
>> +
>> +	fixups = fdt_path_offset(fdto, "/__local_fixups__");
>> +	if (fixups == -FDT_ERR_NOTFOUND)
>> +		return 0;
>> +	if (fixups < 0)
>> +		return fixups;
>> +
>> +	return overlay_update_node_conflicting_references(fdto, 0, fixups,
>> +							  fdt_phandle,
>> +							  fdto_phandle);
>> +}
>> +
>> +/**
>> + * overlay_prevent_phandle_overwrite_node - Helper function for overlay_prevent_phandle_overwrite
>> + * @fdt: Base Device tree blob
>> + * @fdtnode: Node in fdt that is checked for an overwrite
>> + * @fdto: Device tree overlay blob
>> + * @fdtonode: Node in fdto matching @fdtnode
>> + *
>> + * returns:
>> + *      0 on success
>> + *      Negative error code on failure
>> + */
>> +static int overlay_prevent_phandle_overwrite_node(void *fdt, int fdtnode,
>> +						  void *fdto, int fdtonode)
>> +{
>> +	uint32_t fdt_phandle, fdto_phandle;
>> +	int fdtochild;
>> +
>> +	fdt_phandle = fdt_get_phandle(fdt, fdtnode);
>> +	fdto_phandle = fdt_get_phandle(fdto, fdtonode);
>> +
>> +	if (fdt_phandle && fdto_phandle) {
>> +		int ret;
>> +
>> +		ret = overlay_adjust_local_conflicting_phandle(fdto, fdtonode,
>> +							       fdt_phandle);
>> +		if (ret)
>> +			return ret;
>> +
>> +		ret = overlay_update_local_conflicting_references(fdto,
>> +								  fdt_phandle,
>> +								  fdto_phandle);
>> +		if (ret)
>> +			return ret;
>> +	}
>> +
>> +	fdt_for_each_subnode(fdtochild, fdto, fdtonode) {
>> +		const char *name = fdt_get_name(fdto, fdtochild, NULL);
>> +		int fdtchild;
>> +		int ret;
>> +
>> +		fdtchild = fdt_subnode_offset(fdt, fdtnode, name);
>> +		if (fdtchild == -FDT_ERR_NOTFOUND)
>> +			/*
>> +			 * no further overwrites possible here as this node is
>> +			 * new
>> +			 */
>> +			continue;
>> +
>> +		ret = overlay_prevent_phandle_overwrite_node(fdt, fdtchild,
>> +							     fdto, fdtochild);
>> +		if (ret)
>> +			return ret;
>> +	}
>> +
>> +	return 0;
>> +}
>> +
>> +/**
>> + * overlay_prevent_phandle_overwrite - Fixes overlay phandles to not overwrite base phandles
>> + * @fdt: Base Device Tree blob
>> + * @fdto: Device tree overlay blob
>> + *
>> + * Checks recursively if applying fdto overwrites phandle values in the base
>> + * dtb. When such a phandle is found, the fdto is changed to use the fdt's
>> + * phandle value to not break references in the base.
>> + *
>> + * returns:
>> + *      0 on success
>> + *      Negative error code on failure
>> + */
>> +static int overlay_prevent_phandle_overwrite(void *fdt, void *fdto)
>> +{
>> +	int fragment;
>> +
>> +	fdt_for_each_subnode(fragment, fdto, 0) {
>> +		int overlay;
>> +		int target;
>> +		int ret;
>> +
>> +		overlay = fdt_subnode_offset(fdto, fragment, "__overlay__");
>> +		if (overlay == -FDT_ERR_NOTFOUND)
>> +			continue;
>> +
>> +		if (overlay < 0)
>> +			return overlay;
>> +
>> +		target = fdt_overlay_target_offset(fdt, fdto, fragment, NULL);
>> +		if (target == -FDT_ERR_NOTFOUND)
>> +			/*
>> +			 * The subtree doesn't exist in the base, so nothing
>> +			 * will be overwritten.
>> +			 */
>> +			continue;
>> +		else if (target < 0)
>> +			return target;
>> +
>> +		ret = overlay_prevent_phandle_overwrite_node(fdt, target,
>> +							     fdto, overlay);
>> +		if (ret)
>> +			return ret;
>> +	}
>> +
>> +	return 0;
>> +}
>> +
>>  /**
>>   * overlay_apply_node - Merges a node into the base device tree
>>   * @fdt: Base Device Tree blob
>> @@ -636,7 +846,7 @@ static int overlay_merge(void *fdt, void *fdto)
>>  		if (overlay < 0)
>>  			return overlay;
>>  
>> -		target = overlay_get_target(fdt, fdto, fragment, NULL);
>> +		target = fdt_overlay_target_offset(fdt, fdto, fragment, NULL);
>>  		if (target < 0)
>>  			return target;
>>  
>> @@ -779,7 +989,7 @@ static int overlay_symbol_update(void *fdt, void *fdto)
>>  			return -FDT_ERR_BADOVERLAY;
>>  
>>  		/* get the target of the fragment */
>> -		ret = overlay_get_target(fdt, fdto, fragment, &target_path);
>> +		ret = fdt_overlay_target_offset(fdt, fdto, fragment, &target_path);
>>  		if (ret < 0)
>>  			return ret;
>>  		target = ret;
>> @@ -801,7 +1011,7 @@ static int overlay_symbol_update(void *fdt, void *fdto)
>>  
>>  		if (!target_path) {
>>  			/* again in case setprop_placeholder changed it */
>> -			ret = overlay_get_target(fdt, fdto, fragment, &target_path);
>> +			ret = fdt_overlay_target_offset(fdt, fdto, fragment, &target_path);
>>  			if (ret < 0)
>>  				return ret;
>>  			target = ret;
>> @@ -838,18 +1048,26 @@ int fdt_overlay_apply(void *fdt, void *fdto)
>>  	if (ret)
>>  		goto err;
>>  
>> +	/* Increase all phandles in the fdto by delta */
>>  	ret = overlay_adjust_local_phandles(fdto, delta);
>>  	if (ret)
>>  		goto err;
>>  
>> +	/* Adapt the phandle values in fdto to the above increase */
>>  	ret = overlay_update_local_references(fdto, delta);
>>  	if (ret)
>>  		goto err;
>>  
>> +	/* Update fdto's phandles using symbols from fdt */
>>  	ret = overlay_fixup_phandles(fdt, fdto);
>>  	if (ret)
>>  		goto err;
>>  
>> +	/* Don't overwrite phandles in fdt */
>> +	ret = overlay_prevent_phandle_overwrite(fdt, fdto);
>> +	if (ret)
>> +		goto err;
>> +
>>  	ret = overlay_merge(fdt, fdto);
>>  	if (ret)
>>  		goto err;
>> diff --git a/scripts/dtc/libfdt/fdt_ro.c b/scripts/dtc/libfdt/fdt_ro.c
>> index d65656aaa8b..3e7e26b4398 100644
>> --- a/scripts/dtc/libfdt/fdt_ro.c
>> +++ b/scripts/dtc/libfdt/fdt_ro.c
>> @@ -16,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 || (fdt_chk_extra() && olen < len))
>> +	if (!p || olen < len)
>>  		/* short match */
>>  		return 0;
>>  
>> @@ -39,7 +39,7 @@ const char *fdt_get_string(const void *fdt, int stroffset, int *lenp)
>>  	int err;
>>  	const char *s, *n;
>>  
>> -	if (!fdt_chk_extra()) {
>> +	if (can_assume(VALID_INPUT)) {
>>  		s = (const char *)fdt + fdt_off_dt_strings(fdt) + stroffset;
>>  
>>  		if (lenp)
>> @@ -60,7 +60,7 @@ const char *fdt_get_string(const void *fdt, int stroffset, int *lenp)
>>  	if (fdt_magic(fdt) == FDT_MAGIC) {
>>  		if (stroffset < 0)
>>  			goto fail;
>> -		if (!fdt_chk_version() || fdt_version(fdt) >= 17) {
>> +		if (can_assume(LATEST) || fdt_version(fdt) >= 17) {
>>  			if ((unsigned)stroffset >= fdt_size_dt_strings(fdt))
>>  				goto fail;
>>  			if ((fdt_size_dt_strings(fdt) - stroffset) < len)
>> @@ -72,7 +72,7 @@ const char *fdt_get_string(const void *fdt, int stroffset, int *lenp)
>>  		if ((stroffset >= 0) ||
>>  		    (sw_stroffset > fdt_size_dt_strings(fdt)))
>>  			goto fail;
>> -		if ((sw_stroffset) < len)
>> +		if (sw_stroffset < len)
>>  			len = sw_stroffset;
>>  	} else {
>>  		err = -FDT_ERR_INTERNAL;
>> @@ -162,7 +162,7 @@ static const struct fdt_reserve_entry *fdt_mem_rsv(const void *fdt, int n)
>>  	unsigned int offset = n * sizeof(struct fdt_reserve_entry);
>>  	unsigned int absoffset = fdt_off_mem_rsvmap(fdt) + offset;
>>  
>> -	if (fdt_chk_extra()) {
>> +	if (!can_assume(VALID_INPUT)) {
>>  		if (absoffset < fdt_off_mem_rsvmap(fdt))
>>  			return NULL;
>>  		if (absoffset > fdt_totalsize(fdt) -
>> @@ -178,11 +178,11 @@ int fdt_get_mem_rsv(const void *fdt, int n, uint64_t *address, uint64_t *size)
>>  
>>  	FDT_RO_PROBE(fdt);
>>  	re = fdt_mem_rsv(fdt, n);
>> -	if (fdt_chk_extra() && !re)
>> +	if (!can_assume(VALID_INPUT) && !re)
>>  		return -FDT_ERR_BADOFFSET;
>>  
>> -	*address = fdt64_to_cpu(re->address);
>> -	*size = fdt64_to_cpu(re->size);
>> +	*address = fdt64_ld_(&re->address);
>> +	*size = fdt64_ld_(&re->size);
>>  	return 0;
>>  }
>>  
>> @@ -192,7 +192,7 @@ int fdt_num_mem_rsv(const void *fdt)
>>  	const struct fdt_reserve_entry *re;
>>  
>>  	for (i = 0; (re = fdt_mem_rsv(fdt, i)) != NULL; i++) {
>> -		if (fdt64_to_cpu(re->size) == 0)
>> +		if (fdt64_ld_(&re->size) == 0)
>>  			return i;
>>  	}
>>  	return -FDT_ERR_TRUNCATED;
>> @@ -255,6 +255,9 @@ int fdt_path_offset_namelen(const void *fdt, const char *path, int namelen)
>>  
>>  	FDT_RO_PROBE(fdt);
>>  
>> +	if (!can_assume(VALID_INPUT) && namelen <= 0)
>> +		return -FDT_ERR_BADPATH;
>> +
>>  	/* see if we have an alias */
>>  	if (*path != '/') {
>>  		const char *q = memchr(path, '/', end - p);
>> @@ -303,14 +306,13 @@ const char *fdt_get_name(const void *fdt, int nodeoffset, int *len)
>>  	const char *nameptr;
>>  	int err;
>>  
>> -	if (fdt_chk_extra() &&
>> -	    (((err = fdt_ro_probe_(fdt)) < 0)
>> -	     || ((err = fdt_check_node_offset_(fdt, nodeoffset)) < 0)))
>> -		goto fail;
>> +	if (((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) {
>> +	if (!can_assume(LATEST) && fdt_version(fdt) < 0x10) {
>>  		/*
>>  		 * For old FDT versions, match the naming conventions of V16:
>>  		 * give only the leaf name (after all /). The actual tree
>> @@ -361,7 +363,8 @@ static const struct fdt_property *fdt_get_property_by_offset_(const void *fdt,
>>  	int err;
>>  	const struct fdt_property *prop;
>>  
>> -	if (fdt_chk_basic() && (err = fdt_check_prop_offset_(fdt, offset)) < 0) {
>> +	if (!can_assume(VALID_INPUT) &&
>> +	    (err = fdt_check_prop_offset_(fdt, offset)) < 0) {
>>  		if (lenp)
>>  			*lenp = err;
>>  		return NULL;
>> @@ -370,7 +373,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;
>>  }
>> @@ -382,7 +385,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_chk_version() && fdt_version(fdt) < 0x10) {
>> +	if (!can_assume(LATEST) && fdt_version(fdt) < 0x10) {
>>  		if (lenp)
>>  			*lenp = -FDT_ERR_BADVERSION;
>>  		return NULL;
>> @@ -404,11 +407,11 @@ static const struct fdt_property *fdt_get_property_namelen_(const void *fdt,
>>  		const struct fdt_property *prop;
>>  
>>  		prop = fdt_get_property_by_offset_(fdt, offset, lenp);
>> -		if (fdt_chk_extra() && !prop) {
>> +		if (!can_assume(LIBFDT_FLAWLESS) && !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;
>> @@ -428,7 +431,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_chk_version() && fdt_version(fdt) < 0x10) {
>> +	if (!can_assume(LATEST) && fdt_version(fdt) < 0x10) {
>>  		if (lenp)
>>  			*lenp = -FDT_ERR_BADVERSION;
>>  		return NULL;
>> @@ -458,8 +461,8 @@ const void *fdt_getprop_namelen(const void *fdt, int nodeoffset,
>>  		return NULL;
>>  
>>  	/* Handle realignment */
>> -	if (fdt_chk_version() && fdt_version(fdt) < 0x10 &&
>> -	    (poffset + sizeof(*prop)) % 8 && fdt32_to_cpu(prop->len) >= 8)
>> +	if (!can_assume(LATEST) && fdt_version(fdt) < 0x10 &&
>> +	    (poffset + sizeof(*prop)) % 8 && fdt32_ld_(&prop->len) >= 8)
>>  		return prop->data + 4;
>>  	return prop->data;
>>  }
>> @@ -476,23 +479,23 @@ const void *fdt_getprop_by_offset(const void *fdt, int offset,
>>  		const char *name;
>>  		int namelen;
>>  
>> -		if (fdt_chk_extra()) {
>> -			name = fdt_get_string(fdt, fdt32_to_cpu(prop->nameoff),
>> +		if (!can_assume(VALID_INPUT)) {
>> +			name = fdt_get_string(fdt, fdt32_ld_(&prop->nameoff),
>>  					      &namelen);
>> +			*namep = name;
>>  			if (!name) {
>>  				if (lenp)
>>  					*lenp = namelen;
>>  				return NULL;
>>  			}
>> -			*namep = name;
>>  		} else {
>> -			*namep = fdt_string(fdt, fdt32_to_cpu(prop->nameoff));
>> +			*namep = fdt_string(fdt, fdt32_ld_(&prop->nameoff));
>>  		}
>>  	}
>>  
>>  	/* Handle realignment */
>> -	if (fdt_chk_version() && fdt_version(fdt) < 0x10 &&
>> -	    (offset + sizeof(*prop)) % 8 && fdt32_to_cpu(prop->len) >= 8)
>> +	if (!can_assume(LATEST) && fdt_version(fdt) < 0x10 &&
>> +	    (offset + sizeof(*prop)) % 8 && fdt32_ld_(&prop->len) >= 8)
>>  		return prop->data + 4;
>>  	return prop->data;
>>  }
>> @@ -517,19 +520,34 @@ uint32_t fdt_get_phandle(const void *fdt, int nodeoffset)
>>  			return 0;
>>  	}
>>  
>> -	return fdt32_to_cpu(*php);
>> +	return fdt32_ld_(php);
>> +}
>> +
>> +static const void *fdt_path_getprop_namelen(const void *fdt, const char *path,
>> +					    const char *propname, int propnamelen,
>> +					    int *lenp)
>> +{
>> +	int offset = fdt_path_offset(fdt, path);
>> +
>> +	if (offset < 0)
>> +		return NULL;
>> +
>> +	return fdt_getprop_namelen(fdt, offset, propname, propnamelen, lenp);
>>  }
>>  
>>  const char *fdt_get_alias_namelen(const void *fdt,
>>  				  const char *name, int namelen)
>>  {
>> -	int aliasoffset;
>> +	int len;
>> +	const char *alias;
>> +
>> +	alias = fdt_path_getprop_namelen(fdt, "/aliases", name, namelen, &len);
>>  
>> -	aliasoffset = fdt_path_offset(fdt, "/aliases");
>> -	if (aliasoffset < 0)
>> +	if (!can_assume(VALID_DTB) &&
>> +	    !(alias && len > 0 && alias[len - 1] == '\0' && *alias == '/'))
>>  		return NULL;
>>  
>> -	return fdt_getprop_namelen(fdt, aliasoffset, name, namelen, NULL);
>> +	return alias;
>>  }
>>  
>>  const char *fdt_get_alias(const void *fdt, const char *name)
>> @@ -537,6 +555,17 @@ const char *fdt_get_alias(const void *fdt, const char *name)
>>  	return fdt_get_alias_namelen(fdt, name, strlen(name));
>>  }
>>  
>> +const char *fdt_get_symbol_namelen(const void *fdt,
>> +				   const char *name, int namelen)
>> +{
>> +	return fdt_path_getprop_namelen(fdt, "/__symbols__", name, namelen, NULL);
>> +}
>> +
>> +const char *fdt_get_symbol(const void *fdt, const char *name)
>> +{
>> +	return fdt_get_symbol_namelen(fdt, name, strlen(name));
>> +}
>> +
>>  int fdt_get_path(const void *fdt, int nodeoffset, char *buf, int buflen)
>>  {
>>  	int pdepth = 0, p = 0;
>> @@ -617,7 +646,7 @@ int fdt_supernode_atdepth_offset(const void *fdt, int nodeoffset,
>>  		}
>>  	}
>>  
>> -	if (fdt_chk_extra()) {
>> +	if (!can_assume(VALID_INPUT)) {
>>  		if ((offset == -FDT_ERR_NOTFOUND) || (offset >= 0))
>>  			return -FDT_ERR_BADOFFSET;
>>  		else if (offset == -FDT_ERR_BADOFFSET)
>> @@ -634,7 +663,8 @@ int fdt_node_depth(const void *fdt, int nodeoffset)
>>  
>>  	err = fdt_supernode_atdepth_offset(fdt, nodeoffset, 0, &nodedepth);
>>  	if (err)
>> -		return (!fdt_chk_extra() || err < 0) ? err : -FDT_ERR_INTERNAL;
>> +		return (can_assume(LIBFDT_FLAWLESS) || err < 0) ? err :
>> +			-FDT_ERR_INTERNAL;
>>  	return nodedepth;
>>  }
>>  
>> diff --git a/scripts/dtc/libfdt/fdt_rw.c b/scripts/dtc/libfdt/fdt_rw.c
>> index 2eb2b38703b..7475cafce07 100644
>> --- a/scripts/dtc/libfdt/fdt_rw.c
>> +++ b/scripts/dtc/libfdt/fdt_rw.c
>> @@ -13,8 +13,6 @@
>>  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))
>> @@ -26,16 +24,16 @@ static int fdt_blocks_misordered_(const void *fdt,
>>  
>>  static int fdt_rw_probe_(void *fdt)
>>  {
>> -	if (!fdt_chk_basic())
>> +	if (can_assume(VALID_DTB))
>>  		return 0;
>>  	FDT_RO_PROBE(fdt);
>>  
>> -	if (fdt_chk_version() && fdt_version(fdt) < 17)
>> +	if (!can_assume(LATEST) && fdt_version(fdt) < 17)
>>  		return -FDT_ERR_BADVERSION;
>>  	if (fdt_blocks_misordered_(fdt, sizeof(struct fdt_reserve_entry),
>>  				   fdt_size_dt_struct(fdt)))
>>  		return -FDT_ERR_BADLAYOUT;
>> -	if (fdt_chk_version() && fdt_version(fdt) > 17)
>> +	if (!can_assume(LATEST) && fdt_version(fdt) > 17)
>>  		fdt_set_version(fdt, 17);
>>  
>>  	return 0;
>> @@ -44,11 +42,11 @@ static int fdt_rw_probe_(void *fdt)
>>  #define FDT_RW_PROBE(fdt) \
>>  	{ \
>>  		int err_; \
>> -		if (fdt_chk_extra() && (err_ = fdt_rw_probe_(fdt)) != 0) \
>> +		if ((err_ = fdt_rw_probe_(fdt)) != 0) \
>>  			return err_; \
>>  	}
>>  
>> -static inline int fdt_data_size_(void *fdt)
>> +static inline unsigned int fdt_data_size_(void *fdt)
>>  {
>>  	return fdt_off_dt_strings(fdt) + fdt_size_dt_strings(fdt);
>>  }
>> @@ -56,15 +54,16 @@ static inline int fdt_data_size_(void *fdt)
>>  static int fdt_splice_(void *fdt, void *splicepoint, int oldlen, int newlen)
>>  {
>>  	char *p = splicepoint;
>> -	char *end = (char *)fdt + fdt_data_size_(fdt);
>> +	unsigned int dsize = fdt_data_size_(fdt);
>> +	size_t soff = p - (char *)fdt;
>>  
>> -	if (((p + oldlen) < p) || ((p + oldlen) > end))
>> +	if ((oldlen < 0) || (soff + oldlen < soff) || (soff + oldlen > dsize))
>>  		return -FDT_ERR_BADOFFSET;
>> -	if ((p < (char *)fdt) || ((end - oldlen + newlen) < (char *)fdt))
>> +	if ((p < (char *)fdt) || (dsize + newlen < (unsigned)oldlen))
>>  		return -FDT_ERR_BADOFFSET;
>> -	if ((end - oldlen + newlen) > ((char *)fdt + fdt_totalsize(fdt)))
>> +	if (dsize - oldlen + newlen > fdt_totalsize(fdt))
>>  		return -FDT_ERR_NOSPACE;
>> -	memmove(p + newlen, p + oldlen, end - p - oldlen);
>> +	memmove(p + newlen, p + oldlen, ((char *)fdt + dsize) - (p + oldlen));
>>  	return 0;
>>  }
>>  
>> @@ -122,34 +121,36 @@ static int fdt_splice_string_(void *fdt, int newlen)
>>   * @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)
>> + *	allocated. Ignored if can_assume(NO_ROLLBACK)
>> + * @return offset of string in the string table (whether found or added)
>>   */
>> -static int fdt_find_add_string_(void *fdt, const char *s, int *allocated)
>> +static int fdt_find_add_string_(void *fdt, const char *s, int slen,
>> +				int *allocated)
>>  {
>>  	char *strtab = (char *)fdt + fdt_off_dt_strings(fdt);
>>  	const char *p;
>>  	char *new;
>> -	int len = strlen(s) + 1;
>>  	int err;
>>  
>> -	if (fdt_chk_basic())
>> +	if (!can_assume(NO_ROLLBACK))
>>  		*allocated = 0;
>>  
>> -	p = fdt_find_string_(strtab, fdt_size_dt_strings(fdt), s);
>> +	p = fdt_find_string_len_(strtab, fdt_size_dt_strings(fdt), s, slen);
>>  	if (p)
>>  		/* found it */
>>  		return (p - strtab);
>>  
>>  	new = strtab + fdt_size_dt_strings(fdt);
>> -	err = fdt_splice_string_(fdt, len);
>> +	err = fdt_splice_string_(fdt, slen + 1);
>>  	if (err)
>>  		return err;
>>  
>> -	if (fdt_chk_basic())
>> +	if (!can_assume(NO_ROLLBACK))
>>  		*allocated = 1;
>>  
>> -	memcpy(new, s, len);
>> +	memcpy(new, s, slen);
>> +	new[slen] = '\0';
>> +
>>  	return (new - strtab);
>>  }
>>  
>> @@ -182,13 +183,15 @@ int fdt_del_mem_rsv(void *fdt, int n)
>>  	return fdt_splice_mem_rsv_(fdt, re, 1, 0);
>>  }
>>  
>> -static int fdt_resize_property_(void *fdt, int nodeoffset, const char *name,
>> +static int fdt_resize_property_(void *fdt, int nodeoffset,
>> +				const char *name, int namelen,
>>  				int len, struct fdt_property **prop)
>>  {
>>  	int oldlen;
>>  	int err;
>>  
>> -	*prop = fdt_get_property_w(fdt, nodeoffset, name, &oldlen);
>> +	*prop = fdt_get_property_namelen_w(fdt, nodeoffset, name, namelen,
>> +					   &oldlen);
>>  	if (!*prop)
>>  		return oldlen;
>>  
>> @@ -201,7 +204,7 @@ static int fdt_resize_property_(void *fdt, int nodeoffset, const char *name,
>>  }
>>  
>>  static int fdt_add_property_(void *fdt, int nodeoffset, const char *name,
>> -			     int len, struct fdt_property **prop)
>> +			     int namelen, int len, struct fdt_property **prop)
>>  {
>>  	int proplen;
>>  	int nextoffset;
>> @@ -212,7 +215,7 @@ static int fdt_add_property_(void *fdt, int nodeoffset, const char *name,
>>  	if ((nextoffset = fdt_check_node_offset_(fdt, nodeoffset)) < 0)
>>  		return nextoffset;
>>  
>> -	namestroff = fdt_find_add_string_(fdt, name, &allocated);
>> +	namestroff = fdt_find_add_string_(fdt, name, namelen, &allocated);
>>  	if (namestroff < 0)
>>  		return namestroff;
>>  
>> @@ -222,7 +225,7 @@ static int fdt_add_property_(void *fdt, int nodeoffset, const char *name,
>>  	err = fdt_splice_struct_(fdt, *prop, 0, proplen);
>>  	if (err) {
>>  		/* Delete the string if we failed to add it */
>> -		if (fdt_chk_basic() && allocated)
>> +		if (!can_assume(NO_ROLLBACK) && allocated)
>>  			fdt_del_last_string_(fdt, name);
>>  		return err;
>>  	}
>> @@ -256,17 +259,18 @@ int fdt_set_name(void *fdt, int nodeoffset, const char *name)
>>  	return 0;
>>  }
>>  
>> -int fdt_setprop_placeholder(void *fdt, int nodeoffset, const char *name,
>> -			    int len, void **prop_data)
>> +int fdt_setprop_placeholder_namelen(void *fdt, int nodeoffset, const char *name,
>> +				    int namelen, int len, void **prop_data)
>>  {
>>  	struct fdt_property *prop;
>>  	int err;
>>  
>>  	FDT_RW_PROBE(fdt);
>>  
>> -	err = fdt_resize_property_(fdt, nodeoffset, name, len, &prop);
>> +	err = fdt_resize_property_(fdt, nodeoffset, name, namelen, len, &prop);
>>  	if (err == -FDT_ERR_NOTFOUND)
>> -		err = fdt_add_property_(fdt, nodeoffset, name, len, &prop);
>> +		err = fdt_add_property_(fdt, nodeoffset, name, namelen, len,
>> +					&prop);
>>  	if (err)
>>  		return err;
>>  
>> @@ -274,13 +278,14 @@ int fdt_setprop_placeholder(void *fdt, int nodeoffset, const char *name,
>>  	return 0;
>>  }
>>  
>> -int fdt_setprop(void *fdt, int nodeoffset, const char *name,
>> -		const void *val, int len)
>> +int fdt_setprop_namelen(void *fdt, int nodeoffset, const char *name,
>> +			int namelen, const void *val, int len)
>>  {
>>  	void *prop_data;
>>  	int err;
>>  
>> -	err = fdt_setprop_placeholder(fdt, nodeoffset, name, len, &prop_data);
>> +	err = fdt_setprop_placeholder_namelen(fdt, nodeoffset, name, namelen,
>> +					      len, &prop_data);
>>  	if (err)
>>  		return err;
>>  
>> @@ -308,7 +313,8 @@ int fdt_appendprop(void *fdt, int nodeoffset, const char *name,
>>  		prop->len = cpu_to_fdt32(newlen);
>>  		memcpy(prop->data + oldlen, val, len);
>>  	} else {
>> -		err = fdt_add_property_(fdt, nodeoffset, name, len, &prop);
>> +		err = fdt_add_property_(fdt, nodeoffset, name, strlen(name),
>> +					len, &prop);
>>  		if (err)
>>  			return err;
>>  		memcpy(prop->data, val, len);
>> @@ -350,7 +356,10 @@ int fdt_add_subnode_namelen(void *fdt, int parentoffset,
>>  		return offset;
>>  
>>  	/* Try to place the new node after the parent's properties */
>> -	fdt_next_tag(fdt, parentoffset, &nextoffset); /* skip the BEGIN_NODE */
>> +	tag = fdt_next_tag(fdt, parentoffset, &nextoffset);
>> +	/* the fdt_subnode_offset_namelen() should ensure this never hits */
>> +	if (!can_assume(LIBFDT_FLAWLESS) && (tag != FDT_BEGIN_NODE))
>> +		return -FDT_ERR_INTERNAL;
>>  	do {
>>  		offset = nextoffset;
>>  		tag = fdt_next_tag(fdt, offset, &nextoffset);
>> @@ -392,7 +401,9 @@ int fdt_del_node(void *fdt, int nodeoffset)
>>  }
>>  
>>  static void fdt_packblocks_(const char *old, char *new,
>> -			    int mem_rsv_size, int struct_size)
>> +			    int mem_rsv_size,
>> +			    int struct_size,
>> +			    int strings_size)
>>  {
>>  	int mem_rsv_off, struct_off, strings_off;
>>  
>> @@ -407,8 +418,7 @@ static void fdt_packblocks_(const char *old, char *new,
>>  	fdt_set_off_dt_struct(new, struct_off);
>>  	fdt_set_size_dt_struct(new, struct_size);
>>  
>> -	memmove(new + strings_off, old + fdt_off_dt_strings(old),
>> -		fdt_size_dt_strings(old));
>> +	memmove(new + strings_off, old + fdt_off_dt_strings(old), strings_size);
>>  	fdt_set_off_dt_strings(new, strings_off);
>>  	fdt_set_size_dt_strings(new, fdt_size_dt_strings(old));
>>  }
>> @@ -427,17 +437,20 @@ int fdt_open_into(const void *fdt, void *buf, int bufsize)
>>  	mem_rsv_size = (fdt_num_mem_rsv(fdt)+1)
>>  		* sizeof(struct fdt_reserve_entry);
>>  
>> -	if (!fdt_chk_version() || fdt_version(fdt) >= 17) {
>> +	if (can_assume(LATEST) || fdt_version(fdt) >= 17) {
>>  		struct_size = fdt_size_dt_struct(fdt);
>> -	} else {
>> +	} else if (fdt_version(fdt) == 16) {
>>  		struct_size = 0;
>>  		while (fdt_next_tag(fdt, struct_size, &struct_size) != FDT_END)
>>  			;
>>  		if (struct_size < 0)
>>  			return struct_size;
>> +	} else {
>> +		return -FDT_ERR_BADVERSION;
>>  	}
>>  
>> -	if (!fdt_blocks_misordered_(fdt, mem_rsv_size, struct_size)) {
>> +	if (can_assume(LIBFDT_ORDER) ||
>> +	    !fdt_blocks_misordered_(fdt, mem_rsv_size, struct_size)) {
>>  		/* no further work necessary */
>>  		err = fdt_move(fdt, buf, bufsize);
>>  		if (err)
>> @@ -465,7 +478,8 @@ int fdt_open_into(const void *fdt, void *buf, int bufsize)
>>  			return -FDT_ERR_NOSPACE;
>>  	}
>>  
>> -	fdt_packblocks_(fdt, tmp, mem_rsv_size, struct_size);
>> +	fdt_packblocks_(fdt, tmp, mem_rsv_size, struct_size,
>> +			fdt_size_dt_strings(fdt));
>>  	memmove(buf, tmp, newsize);
>>  
>>  	fdt_set_magic(buf, FDT_MAGIC);
>> @@ -485,7 +499,8 @@ int fdt_pack(void *fdt)
>>  
>>  	mem_rsv_size = (fdt_num_mem_rsv(fdt)+1)
>>  		* sizeof(struct fdt_reserve_entry);
>> -	fdt_packblocks_(fdt, fdt, mem_rsv_size, fdt_size_dt_struct(fdt));
>> +	fdt_packblocks_(fdt, fdt, mem_rsv_size, fdt_size_dt_struct(fdt),
>> +			fdt_size_dt_strings(fdt));
>>  	fdt_set_totalsize(fdt, fdt_data_size_(fdt));
>>  
>>  	return 0;
>> diff --git a/scripts/dtc/libfdt/fdt_strerror.c b/scripts/dtc/libfdt/fdt_strerror.c
>> index b4356931b06..d852b77e81e 100644
>> --- a/scripts/dtc/libfdt/fdt_strerror.c
>> +++ b/scripts/dtc/libfdt/fdt_strerror.c
>> @@ -39,6 +39,7 @@ static struct fdt_errtabent fdt_errtable[] = {
>>  	FDT_ERRTABENT(FDT_ERR_BADOVERLAY),
>>  	FDT_ERRTABENT(FDT_ERR_NOPHANDLES),
>>  	FDT_ERRTABENT(FDT_ERR_BADFLAGS),
>> +	FDT_ERRTABENT(FDT_ERR_ALIGNMENT),
>>  };
>>  #define FDT_ERRTABSIZE	((int)(sizeof(fdt_errtable) / sizeof(fdt_errtable[0])))
>>  
>> diff --git a/scripts/dtc/libfdt/fdt_sw.c b/scripts/dtc/libfdt/fdt_sw.c
>> index d9e67fa2a61..4c569ee7eb0 100644
>> --- a/scripts/dtc/libfdt/fdt_sw.c
>> +++ b/scripts/dtc/libfdt/fdt_sw.c
>> @@ -12,7 +12,7 @@
>>  
>>  static int fdt_sw_probe_(void *fdt)
>>  {
>> -	if (fdt_chk_basic()) {
>> +	if (!can_assume(VALID_INPUT)) {
>>  		if (fdt_magic(fdt) == FDT_MAGIC)
>>  			return -FDT_ERR_BADSTATE;
>>  		else if (fdt_magic(fdt) != FDT_SW_MAGIC)
>> @@ -25,14 +25,14 @@ static int fdt_sw_probe_(void *fdt)
>>  #define FDT_SW_PROBE(fdt) \
>>  	{ \
>>  		int err; \
>> -		if (fdt_chk_basic() && (err = fdt_sw_probe_(fdt)) != 0) \
>> +		if ((err = fdt_sw_probe_(fdt)) != 0) \
>>  			return err; \
>>  	}
>>  
>>  /* 'memrsv' state:	Initial state after fdt_create()
>>   *
>>   * Allowed functions:
>> - *	fdt_add_reservmap_entry()
>> + *	fdt_add_reservemap_entry()
>>   *	fdt_finish_reservemap()		[moves to 'struct' state]
>>   */
>>  static int fdt_sw_probe_memrsv_(void *fdt)
>> @@ -41,7 +41,7 @@ static int fdt_sw_probe_memrsv_(void *fdt)
>>  	if (err)
>>  		return err;
>>  
>> -	if (fdt_chk_extra() && fdt_off_dt_strings(fdt) != 0)
>> +	if (!can_assume(VALID_INPUT) && fdt_off_dt_strings(fdt) != 0)
>>  		return -FDT_ERR_BADSTATE;
>>  	return 0;
>>  }
>> @@ -49,7 +49,7 @@ static int fdt_sw_probe_memrsv_(void *fdt)
>>  #define FDT_SW_PROBE_MEMRSV(fdt) \
>>  	{ \
>>  		int err; \
>> -		if (fdt_chk_extra() && (err = fdt_sw_probe_memrsv_(fdt)) != 0) \
>> +		if ((err = fdt_sw_probe_memrsv_(fdt)) != 0) \
>>  			return err; \
>>  	}
>>  
>> @@ -63,15 +63,12 @@ static int fdt_sw_probe_memrsv_(void *fdt)
>>   */
>>  static int fdt_sw_probe_struct_(void *fdt)
>>  {
>> -	int err;
>> -
>> -	if (!fdt_chk_extra())
>> -		return 0;
>> -	err = fdt_sw_probe_(fdt);
>> +	int err = fdt_sw_probe_(fdt);
>>  	if (err)
>>  		return err;
>>  
>> -	if (fdt_off_dt_strings(fdt) != fdt_totalsize(fdt))
>> +	if (!can_assume(VALID_INPUT) &&
>> +	    fdt_off_dt_strings(fdt) != fdt_totalsize(fdt))
>>  		return -FDT_ERR_BADSTATE;
>>  	return 0;
>>  }
>> @@ -79,7 +76,7 @@ static int fdt_sw_probe_struct_(void *fdt)
>>  #define FDT_SW_PROBE_STRUCT(fdt) \
>>  	{ \
>>  		int err; \
>> -		if (fdt_chk_extra() && (err = fdt_sw_probe_struct_(fdt)) != 0) \
>> +		if ((err = fdt_sw_probe_struct_(fdt)) != 0) \
>>  			return err; \
>>  	}
>>  
>> @@ -161,7 +158,8 @@ int fdt_resize(void *fdt, void *buf, int bufsize)
>>  	headsize = fdt_off_dt_struct(fdt) + fdt_size_dt_struct(fdt);
>>  	tailsize = fdt_size_dt_strings(fdt);
>>  
>> -	if (fdt_chk_extra() && (headsize + tailsize) > fdt_totalsize(fdt))
>> +	if (!can_assume(VALID_DTB) &&
>> +	    headsize + tailsize > fdt_totalsize(fdt))
>>  		return -FDT_ERR_INTERNAL;
>>  
>>  	if ((headsize + tailsize) > (unsigned)bufsize)
>> @@ -379,7 +377,7 @@ int fdt_finish(void *fdt)
>>  	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_last_comp_version(fdt, FDT_LAST_COMPATIBLE_VERSION);
>>  	fdt_set_magic(fdt, FDT_MAGIC);
>>  
>>  	return 0;
>> diff --git a/scripts/dtc/libfdt/libfdt.h b/scripts/dtc/libfdt/libfdt.h
>> index 16ec53e78b8..7f8bb05c545 100644
>> --- a/scripts/dtc/libfdt/libfdt.h
>> +++ b/scripts/dtc/libfdt/libfdt.h
>> @@ -9,7 +9,12 @@
>>  #include "libfdt_env.h"
>>  #include "fdt.h"
>>  
>> +#ifdef __cplusplus
>> +extern "C" {
>> +#endif
>> +
>>  #define FDT_FIRST_SUPPORTED_VERSION	0x02
>> +#define FDT_LAST_COMPATIBLE_VERSION	0x10
>>  #define FDT_LAST_SUPPORTED_VERSION	0x11
>>  
>>  /* Error codes: informative error codes */
>> @@ -97,7 +102,11 @@
>>  	/* 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
>> +#define FDT_ERR_ALIGNMENT	19
>> +	/* FDT_ERR_ALIGNMENT: The device tree base address is not 8-byte
>> +	 * aligned. */
>> +
>> +#define FDT_ERR_MAX		19
>>  
>>  /* constants */
>>  #define FDT_MAX_PHANDLE 0xfffffffe
>> @@ -117,6 +126,23 @@ 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);
>>  
>> +/*
>> + * External helpers to access words from a device tree blob. They're built
>> + * to work even with unaligned pointers on platforms (such as ARMv5) that don't
>> + * like unaligned loads and stores.
>> + */
>> +static inline uint16_t fdt16_ld(const fdt16_t *p)
>> +{
>> +	const uint8_t *bp = (const uint8_t *)p;
>> +
>> +	return ((uint16_t)bp[0] << 8) | bp[1];
>> +}
>> +
>> +static inline uint32_t fdt32_ld(const fdt32_t *p)
>> +{
>> +	return fdt32_to_cpu(*p);
>> +}
>> +
>>  static inline void fdt32_st(void *property, uint32_t value)
>>  {
>>  	uint8_t *bp = (uint8_t *)property;
>> @@ -127,6 +153,11 @@ static inline void fdt32_st(void *property, uint32_t value)
>>  	bp[3] = value & 0xff;
>>  }
>>  
>> +static inline uint64_t fdt64_ld(const fdt64_t *p)
>> +{
>> +	return fdt64_to_cpu(*p);
>> +}
>> +
>>  static inline void fdt64_st(void *property, uint64_t value)
>>  {
>>  	uint8_t *bp = (uint8_t *)property;
>> @@ -149,23 +180,23 @@ int fdt_next_node(const void *fdt, int offset, int *depth);
>>  
>>  /**
>>   * fdt_first_subnode() - get offset of first direct subnode
>> - *
>>   * @fdt:	FDT blob
>>   * @offset:	Offset of node to check
>> + *
>>   * Return: offset of first subnode, or -FDT_ERR_NOTFOUND if there is none
>>   */
>>  int fdt_first_subnode(const void *fdt, int offset);
>>  
>>  /**
>>   * fdt_next_subnode() - get offset of next direct subnode
>> + * @fdt:	FDT blob
>> + * @offset:	Offset of previous subnode
>>   *
>>   * After first calling fdt_first_subnode(), call this function repeatedly to
>>   * get direct subnodes of a parent node.
>>   *
>> - * @fdt:	FDT blob
>> - * @offset:	Offset of previous subnode
>>   * Return: offset of next subnode, or -FDT_ERR_NOTFOUND if there are no more
>> - * subnodes
>> + *         subnodes
>>   */
>>  int fdt_next_subnode(const void *fdt, int offset);
>>  
>> @@ -190,7 +221,6 @@ int fdt_next_subnode(const void *fdt, int offset);
>>   * Note that this is implemented as a macro and @node is used as
>>   * iterator in the loop. The parent variable be constant or even a
>>   * literal.
>> - *
>>   */
>>  #define fdt_for_each_subnode(node, fdt, parent)		\
>>  	for (node = fdt_first_subnode(fdt, parent);	\
>> @@ -201,7 +231,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))
>> @@ -219,32 +249,36 @@ int fdt_next_subnode(const void *fdt, int offset);
>>  		struct fdt_header *fdth = (struct fdt_header *)fdt; \
>>  		fdth->name = cpu_to_fdt32(val); \
>>  	}
>> -fdt_set_hdr_(magic);
>> -fdt_set_hdr_(totalsize);
>> -fdt_set_hdr_(off_dt_struct);
>> -fdt_set_hdr_(off_dt_strings);
>> -fdt_set_hdr_(off_mem_rsvmap);
>> -fdt_set_hdr_(version);
>> -fdt_set_hdr_(last_comp_version);
>> -fdt_set_hdr_(boot_cpuid_phys);
>> -fdt_set_hdr_(size_dt_strings);
>> -fdt_set_hdr_(size_dt_struct);
>> +fdt_set_hdr_(magic)
>> +fdt_set_hdr_(totalsize)
>> +fdt_set_hdr_(off_dt_struct)
>> +fdt_set_hdr_(off_dt_strings)
>> +fdt_set_hdr_(off_mem_rsvmap)
>> +fdt_set_hdr_(version)
>> +fdt_set_hdr_(last_comp_version)
>> +fdt_set_hdr_(boot_cpuid_phys)
>> +fdt_set_hdr_(size_dt_strings)
>> +fdt_set_hdr_(size_dt_struct)
>>  #undef fdt_set_hdr_
>>  
>>  /**
>>   * fdt_header_size - return the size of the tree's header
>>   * @fdt: pointer to a flattened device tree
>> + *
>> + * Return: size of DTB header in bytes
>>   */
>>  size_t fdt_header_size(const void *fdt);
>>  
>>  /**
>> - * fdt_header_size_ - internal function which takes a version number
>> + * fdt_header_size_ - internal function to get header size from a version number
>> + * @version: device tree version number
>> + *
>> + * Return: size of DTB header in bytes
>>   */
>>  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
>> @@ -369,8 +403,7 @@ static inline uint32_t fdt_get_max_phandle(const void *fdt)
>>   * highest phandle value in the device tree blob) will be returned in the
>>   * @phandle parameter.
>>   *
>> - * Returns:
>> - *   0 on success or a negative error-code on failure
>> + * Return: 0 on success or a negative error-code on failure
>>   */
>>  int fdt_generate_phandle(const void *fdt, uint32_t *phandle);
>>  
>> @@ -390,9 +423,11 @@ int fdt_num_mem_rsv(const void *fdt);
>>  /**
>>   * fdt_get_mem_rsv - retrieve one memory reserve map entry
>>   * @fdt: pointer to the device tree blob
>> - * @address, @size: pointers to 64-bit variables
>> + * @n: index of reserve map entry
>> + * @address: pointer to 64-bit variable to hold the start address
>> + * @size: pointer to 64-bit variable to hold the size of the entry
>>   *
>> - * On success, *address and *size will contain the address and size of
>> + * On success, @address and @size will contain the address and size of
>>   * the n-th reserve map entry from the device tree blob, in
>>   * native-endian format.
>>   *
>> @@ -415,6 +450,8 @@ int fdt_get_mem_rsv(const void *fdt, int n, uint64_t *address, uint64_t *size);
>>   * namelen characters of name for matching the subnode name.  This is
>>   * useful for finding subnodes based on a portion of a larger string,
>>   * such as a full path.
>> + *
>> + * Return: offset of the subnode or -FDT_ERR_NOTFOUND if name not found.
>>   */
>>  #ifndef SWIG /* Not available in Python */
>>  int fdt_subnode_offset_namelen(const void *fdt, int parentoffset,
>> @@ -454,6 +491,8 @@ int fdt_subnode_offset(const void *fdt, int parentoffset, const char *name);
>>   *
>>   * Identical to fdt_path_offset(), but only consider the first namelen
>>   * characters of path as the path name.
>> + *
>> + * Return: offset of the node or negative libfdt error value otherwise
>>   */
>>  #ifndef SWIG /* Not available in Python */
>>  int fdt_path_offset_namelen(const void *fdt, const char *path, int namelen);
>> @@ -471,12 +510,37 @@ int fdt_path_offset_namelen(const void *fdt, const char *path, int namelen);
>>   * level matching the given component, differentiated only by unit
>>   * address).
>>   *
>> + * If the path is not absolute (i.e. does not begin with '/'), the
>> + * first component is treated as an alias.  That is, the property by
>> + * that name is looked up in the /aliases node, and the value of that
>> + * property used in place of that first component.
>> + *
>> + * For example, for this small fragment
>> + *
>> + * / {
>> + *     aliases {
>> + *         i2c2 = &foo; // RHS compiles to "/soc at 0/i2c at 30a40000/eeprom at 52"
>> + *     };
>> + *     soc at 0 {
>> + *         foo: i2c at 30a40000 {
>> + *             bar: eeprom at 52 {
>> + *             };
>> + *         };
>> + *     };
>> + * };
>> + *
>> + * these would be equivalent:
>> + *
>> + *   /soc at 0/i2c at 30a40000/eeprom at 52
>> + *   i2c2/eeprom at 52
>> + *
>>   * returns:
>>   *	structure block offset of the node with the requested path (>=0), on
>>   *		success
>> - *	-FDT_ERR_BADPATH, given path does not begin with '/' or is invalid
>> + *	-FDT_ERR_BADPATH, given path does not begin with '/' and the first
>> + *		component is not a valid alias
>>   *	-FDT_ERR_NOTFOUND, if the requested node does not exist
>> - *      -FDT_ERR_BADMAGIC,
>> + *	-FDT_ERR_BADMAGIC,
>>   *	-FDT_ERR_BADVERSION,
>>   *	-FDT_ERR_BADSTATE,
>>   *	-FDT_ERR_BADSTRUCTURE,
>> @@ -521,7 +585,7 @@ const char *fdt_get_name(const void *fdt, int nodeoffset, int *lenp);
>>   *	structure block offset of the property (>=0), on success
>>   *	-FDT_ERR_NOTFOUND, if the requested node has no properties
>>   *	-FDT_ERR_BADOFFSET, if nodeoffset did not point to an FDT_BEGIN_NODE tag
>> - *      -FDT_ERR_BADMAGIC,
>> + *	-FDT_ERR_BADMAGIC,
>>   *	-FDT_ERR_BADVERSION,
>>   *	-FDT_ERR_BADSTATE,
>>   *	-FDT_ERR_BADSTRUCTURE,
>> @@ -542,7 +606,7 @@ int fdt_first_property_offset(const void *fdt, int nodeoffset);
>>   *	structure block offset of the next property (>=0), on success
>>   *	-FDT_ERR_NOTFOUND, if the given property is the last in its node
>>   *	-FDT_ERR_BADOFFSET, if nodeoffset did not point to an FDT_PROP tag
>> - *      -FDT_ERR_BADMAGIC,
>> + *	-FDT_ERR_BADMAGIC,
>>   *	-FDT_ERR_BADVERSION,
>>   *	-FDT_ERR_BADSTATE,
>>   *	-FDT_ERR_BADSTRUCTURE,
>> @@ -553,9 +617,9 @@ int fdt_next_property_offset(const void *fdt, int offset);
>>  /**
>>   * fdt_for_each_property_offset - iterate over all properties of a node
>>   *
>> - * @property_offset:	property offset (int, lvalue)
>> - * @fdt:		FDT blob (const void *)
>> - * @node:		node offset (int)
>> + * @property:	property offset (int, lvalue)
>> + * @fdt:	FDT blob (const void *)
>> + * @node:	node offset (int)
>>   *
>>   * This is actually a wrapper around a for loop and would be used like so:
>>   *
>> @@ -607,6 +671,13 @@ int fdt_next_property_offset(const void *fdt, int offset);
>>  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
>> @@ -618,12 +689,22 @@ const struct fdt_property *fdt_get_property_by_offset(const void *fdt,
>>   *
>>   * Identical to fdt_get_property(), but only examine the first namelen
>>   * characters of name for matching the property name.
>> + *
>> + * Return: pointer to the structure representing the property, or NULL
>> + *         if not found
>>   */
>>  #ifndef SWIG /* Not available in Python */
>>  const struct fdt_property *fdt_get_property_namelen(const void *fdt,
>>  						    int nodeoffset,
>>  						    const char *name,
>>  						    int namelen, int *lenp);
>> +static inline struct fdt_property *
>> +fdt_get_property_namelen_w(void *fdt, int nodeoffset, const char *name,
>> +			   int namelen, int *lenp)
>> +{
>> +	return (struct fdt_property *)(uintptr_t)fdt_get_property_namelen(
>> +		fdt, nodeoffset, name, namelen, lenp);
>> +}
>>  #endif
>>  
>>  /**
>> @@ -676,7 +757,7 @@ static inline struct fdt_property *fdt_get_property_w(void *fdt, int nodeoffset,
>>   * to within the device blob itself, not a copy of the value).  If
>>   * lenp is non-NULL, the length of the property value is also
>>   * returned, in the integer pointed to by lenp.  If namep is non-NULL,
>> - * the property's namne will also be returned in the char * pointed to
>> + * the property's name will also be returned in the char * pointed to
>>   * by namep (this will be a pointer to within the device tree's string
>>   * block, not a new copy of the name).
>>   *
>> @@ -684,7 +765,7 @@ static inline struct fdt_property *fdt_get_property_w(void *fdt, int nodeoffset,
>>   *	pointer to the property's value
>>   *		if lenp is non-NULL, *lenp contains the length of the property
>>   *		value (>=0)
>> - *		if namep is non-NULL *namep contiains a pointer to the property
>> + *		if namep is non-NULL *namep contains a pointer to the property
>>   *		name.
>>   *	NULL, on error
>>   *		if lenp is non-NULL, *lenp contains an error code (<0):
>> @@ -710,6 +791,8 @@ const void *fdt_getprop_by_offset(const void *fdt, int offset,
>>   *
>>   * Identical to fdt_getprop(), but only examine the first namelen
>>   * characters of name for matching the property name.
>> + *
>> + * Return: pointer to the property's value or NULL on error
>>   */
>>  #ifndef SWIG /* Not available in Python */
>>  const void *fdt_getprop_namelen(const void *fdt, int nodeoffset,
>> @@ -731,10 +814,10 @@ static inline void *fdt_getprop_namelen_w(void *fdt, int nodeoffset,
>>   * @lenp: pointer to an integer variable (will be overwritten) or NULL
>>   *
>>   * fdt_getprop() retrieves a pointer to the value of the property
>> - * named 'name' of the node at offset nodeoffset (this will be a
>> + * named @name of the node at offset @nodeoffset (this will be a
>>   * pointer to within the device blob itself, not a copy of the value).
>> - * If lenp is non-NULL, the length of the property value is also
>> - * returned, in the integer pointed to by lenp.
>> + * If @lenp is non-NULL, the length of the property value is also
>> + * returned, in the integer pointed to by @lenp.
>>   *
>>   * returns:
>>   *	pointer to the property's value
>> @@ -776,11 +859,14 @@ 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 th look up
>> + * @name: name of the alias to look up
>>   * @namelen: number of characters of name to consider
>>   *
>> - * Identical to fdt_get_alias(), but only examine the first namelen
>> - * characters of name for matching the alias name.
>> + * Identical to fdt_get_alias(), but only examine the first @namelen
>> + * characters of @name for matching the alias name.
>> + *
>> + * Return: a pointer to the expansion of the alias named @name, if it exists,
>> + *	   NULL otherwise
>>   */
>>  #ifndef SWIG /* Not available in Python */
>>  const char *fdt_get_alias_namelen(const void *fdt,
>> @@ -790,10 +876,10 @@ const char *fdt_get_alias_namelen(const void *fdt,
>>  /**
>>   * fdt_get_alias - retrieve the path referenced by a given alias
>>   * @fdt: pointer to the device tree blob
>> - * @name: name of the alias th look up
>> + * @name: name of the alias to look up
>>   *
>>   * fdt_get_alias() retrieves the value of a given alias.  That is, the
>> - * value of the property named 'name' in the node /aliases.
>> + * value of the property named @name in the node /aliases.
>>   *
>>   * returns:
>>   *	a pointer to the expansion of the alias named 'name', if it exists
>> @@ -801,6 +887,42 @@ const char *fdt_get_alias_namelen(const void *fdt,
>>   */
>>  const char *fdt_get_alias(const void *fdt, const char *name);
>>  
>> +/**
>> + * fdt_get_symbol_namelen - get symbol based on substring
>> + * @fdt: pointer to the device tree blob
>> + * @name: name of the symbol to look up
>> + * @namelen: number of characters of name to consider
>> + *
>> + * Identical to fdt_get_symbol(), but only examine the first @namelen
>> + * characters of @name for matching the symbol name.
>> + *
>> + * Return: a pointer to the expansion of the symbol named @name, if it exists,
>> + *	   NULL otherwise
>> + */
>> +#ifndef SWIG /* Not available in Python */
>> +const char *fdt_get_symbol_namelen(const void *fdt,
>> +				   const char *name, int namelen);
>> +#endif
>> +
>> +/**
>> + * fdt_get_symbol - retrieve the path referenced by a given symbol
>> + * @fdt: pointer to the device tree blob
>> + * @name: name of the symbol to look up
>> + *
>> + * fdt_get_symbol() retrieves the value of a given symbol.  That is,
>> + * the value of the property named @name in the node
>> + * /__symbols__. Such a node exists only for a device tree blob that
>> + * has been compiled with the -@ dtc option. Each property corresponds
>> + * to a label appearing in the device tree source, with the name of
>> + * the property being the label and the value being the full path of
>> + * the node it is attached to.
>> + *
>> + * returns:
>> + *	a pointer to the expansion of the symbol named 'name', if it exists
>> + *	NULL, if the given symbol or the /__symbols__ node does not exist
>> + */
>> +const char *fdt_get_symbol(const void *fdt, const char *name);
>> +
>>  /**
>>   * fdt_get_path - determine the full path of a node
>>   * @fdt: pointer to the device tree blob
>> @@ -969,14 +1091,13 @@ int fdt_node_offset_by_prop_value(const void *fdt, int startoffset,
>>  int fdt_node_offset_by_phandle(const void *fdt, uint32_t phandle);
>>  
>>  /**
>> - * fdt_node_check_compatible: check a node's compatible property
>> + * fdt_node_check_compatible - check a node's compatible property
>>   * @fdt: pointer to the device tree blob
>>   * @nodeoffset: offset of a tree node
>>   * @compatible: string to match against
>>   *
>> - *
>>   * fdt_node_check_compatible() returns 0 if the given node contains a
>> - * 'compatible' property with the given string as one of its elements,
>> + * @compatible property with the given string as one of its elements,
>>   * it returns non-zero otherwise, or on error.
>>   *
>>   * returns:
>> @@ -1040,7 +1161,7 @@ int fdt_node_offset_by_compatible(const void *fdt, int startoffset,
>>   * one or more strings, each terminated by \0, as is found in a device tree
>>   * "compatible" property.
>>   *
>> - * @return: 1 if the string is found in the list, 0 not found, or invalid list
>> + * Return: 1 if the string is found in the list, 0 not found, or invalid list
>>   */
>>  int fdt_stringlist_contains(const char *strlist, int listlen, const char *str);
>>  
>> @@ -1049,7 +1170,8 @@ int fdt_stringlist_contains(const char *strlist, int listlen, const char *str);
>>   * @fdt: pointer to the device tree blob
>>   * @nodeoffset: offset of a tree node
>>   * @property: name of the property containing the string list
>> - * @return:
>> + *
>> + * Return:
>>   *   the number of strings in the given property
>>   *   -FDT_ERR_BADVALUE if the property value is not NUL-terminated
>>   *   -FDT_ERR_NOTFOUND if the property does not exist
>> @@ -1069,7 +1191,7 @@ int fdt_stringlist_count(const void *fdt, int nodeoffset, const char *property);
>>   * small-valued cell properties, such as #address-cells, when searching for
>>   * the empty string.
>>   *
>> - * @return:
>> + * return:
>>   *   the index of the string in the list of strings
>>   *   -FDT_ERR_BADVALUE if the property value is not NUL-terminated
>>   *   -FDT_ERR_NOTFOUND if the property does not exist or does not contain
>> @@ -1093,7 +1215,7 @@ int fdt_stringlist_search(const void *fdt, int nodeoffset, const char *property,
>>   * If non-NULL, the length of the string (on success) or a negative error-code
>>   * (on failure) will be stored in the integer pointer to by lenp.
>>   *
>> - * @return:
>> + * Return:
>>   *   A pointer to the string at the given index in the string list or NULL on
>>   *   failure. On success the length of the string will be stored in the memory
>>   *   location pointed to by the lenp parameter, if non-NULL. On failure one of
>> @@ -1130,8 +1252,8 @@ const char *fdt_stringlist_get(const void *fdt, int nodeoffset,
>>   *
>>   * returns:
>>   *	0 <= n < FDT_MAX_NCELLS, on success
>> - *      2, if the node has no #address-cells property
>> - *      -FDT_ERR_BADNCELLS, if the node has a badly formatted or invalid
>> + *	2, if the node has no #address-cells property
>> + *	-FDT_ERR_BADNCELLS, if the node has a badly formatted or invalid
>>   *		#address-cells property
>>   *	-FDT_ERR_BADMAGIC,
>>   *	-FDT_ERR_BADVERSION,
>> @@ -1151,8 +1273,8 @@ int fdt_address_cells(const void *fdt, int nodeoffset);
>>   *
>>   * returns:
>>   *	0 <= n < FDT_MAX_NCELLS, on success
>> - *      1, if the node has no #size-cells property
>> - *      -FDT_ERR_BADNCELLS, if the node has a badly formatted or invalid
>> + *	1, if the node has no #size-cells property
>> + *	-FDT_ERR_BADNCELLS, if the node has a badly formatted or invalid
>>   *		#size-cells property
>>   *	-FDT_ERR_BADMAGIC,
>>   *	-FDT_ERR_BADVERSION,
>> @@ -1181,6 +1303,8 @@ int fdt_size_cells(const void *fdt, int nodeoffset);
>>   * starting from the given index, and using only the first characters
>>   * of the name. It is useful when you want to manipulate only one value of
>>   * an array and you have a string that doesn't end with \0.
>> + *
>> + * Return: 0 on success, negative libfdt error value otherwise
>>   */
>>  #ifndef SWIG /* Not available in Python */
>>  int fdt_setprop_inplace_namelen_partial(void *fdt, int nodeoffset,
>> @@ -1294,8 +1418,13 @@ static inline int fdt_setprop_inplace_u64(void *fdt, int nodeoffset,
>>  
>>  /**
>>   * fdt_setprop_inplace_cell - change the value of a single-cell property
>> + * @fdt: pointer to the device tree blob
>> + * @nodeoffset: offset of the node containing the property
>> + * @name: name of the property to change the value of
>> + * @val: new value of the 32-bit cell
>>   *
>>   * This is an alternative name for fdt_setprop_inplace_u32()
>> + * Return: 0 on success, negative libfdt error number otherwise.
>>   */
>>  static inline int fdt_setprop_inplace_cell(void *fdt, int nodeoffset,
>>  					   const char *name, uint32_t val)
>> @@ -1367,14 +1496,14 @@ int fdt_nop_node(void *fdt, int nodeoffset);
>>  
>>  /**
>>   * fdt_create_with_flags - begin creation of a new fdt
>> - * @fdt: pointer to memory allocated where fdt will be created
>> + * @buf: 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.
>> + * fdt creation process must end with fdt_finish() to produce a valid fdt.
>>   *
>>   * returns:
>>   *	0, on success
>> @@ -1385,7 +1514,7 @@ 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
>> + * @buf: 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.
>> @@ -1425,7 +1554,7 @@ static inline int fdt_property_cell(void *fdt, const char *name, uint32_t val)
>>   * @fdt: pointer to the device tree blob
>>   * @name: name of property to add
>>   * @len: length of property value in bytes
>> - * @valp: returns a pointer to where where the value should be placed
>> + * @valp: returns a pointer to where the value should be placed
>>   *
>>   * returns:
>>   *	0, on success
>> @@ -1450,7 +1579,8 @@ int fdt_pack(void *fdt);
>>  /**
>>   * fdt_add_mem_rsv - add one memory reserve map entry
>>   * @fdt: pointer to the device tree blob
>> - * @address, @size: 64-bit values (native endian)
>> + * @address: 64-bit start address of the reserve map entry
>> + * @size: 64-bit size of the reserved region
>>   *
>>   * Adds a reserve map entry to the given blob reserving a region at
>>   * address address of length size.
>> @@ -1521,6 +1651,38 @@ int fdt_del_mem_rsv(void *fdt, int n);
>>   */
>>  int fdt_set_name(void *fdt, int nodeoffset, const char *name);
>>  
>> +/**
>> + * fdt_setprop_namelen - create or change a property
>> + * @fdt: pointer to the device tree blob
>> + * @nodeoffset: offset of the node whose property to change
>> + * @name: name of the property to change
>> + * @namelen: length of the name
>> + * @val: pointer to data to set the property value to
>> + * @len: length of the property value
>> + *
>> + * fdt_setprop_namelen() sets the value of the named property in the given
>> + * node to the given value and length, creating the property if it
>> + * does not already exist.
>> + *
>> + * This function may insert or delete data from the blob, and will
>> + * therefore change the offsets of some existing nodes.
>> + *
>> + * returns:
>> + *	0, on success
>> + *	-FDT_ERR_NOSPACE, there is insufficient free space in the blob to
>> + *		contain the new property value
>> + *	-FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag
>> + *	-FDT_ERR_BADLAYOUT,
>> + *	-FDT_ERR_BADMAGIC,
>> + *	-FDT_ERR_BADVERSION,
>> + *	-FDT_ERR_BADSTATE,
>> + *	-FDT_ERR_BADSTRUCTURE,
>> + *	-FDT_ERR_BADLAYOUT,
>> + *	-FDT_ERR_TRUNCATED, standard meanings
>> + */
>> +int fdt_setprop_namelen(void *fdt, int nodeoffset, const char *name,
>> +			int namelen, const void *val, int len);
>> +
>>  /**
>>   * fdt_setprop - create or change a property
>>   * @fdt: pointer to the device tree blob
>> @@ -1549,8 +1711,44 @@ int fdt_set_name(void *fdt, int nodeoffset, const char *name);
>>   *	-FDT_ERR_BADLAYOUT,
>>   *	-FDT_ERR_TRUNCATED, standard meanings
>>   */
>> -int fdt_setprop(void *fdt, int nodeoffset, const char *name,
>> -		const void *val, int len);
>> +static inline int fdt_setprop(void *fdt, int nodeoffset, const char *name,
>> +			      const void *val, int len)
>> +{
>> +	return fdt_setprop_namelen(fdt, nodeoffset, name, strlen(name), val,
>> +				   len);
>> +}
>> +
>> +/**
>> + * fdt_setprop_placeholder_namelen - allocate space for a property
>> + * @fdt: pointer to the device tree blob
>> + * @nodeoffset: offset of the node whose property to change
>> + * @name: name of the property to change
>> + * @namelen: length of the name
>> + * @len: length of the property value
>> + * @prop_data: return pointer to property data
>> + *
>> + * fdt_setprop_placeholder_namelen() allocates the named property in the given node.
>> + * If the property exists it is resized. In either case a pointer to the
>> + * property data is returned.
>> + *
>> + * This function may insert or delete data from the blob, and will
>> + * therefore change the offsets of some existing nodes.
>> + *
>> + * returns:
>> + *	0, on success
>> + *	-FDT_ERR_NOSPACE, there is insufficient free space in the blob to
>> + *		contain the new property value
>> + *	-FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag
>> + *	-FDT_ERR_BADLAYOUT,
>> + *	-FDT_ERR_BADMAGIC,
>> + *	-FDT_ERR_BADVERSION,
>> + *	-FDT_ERR_BADSTATE,
>> + *	-FDT_ERR_BADSTRUCTURE,
>> + *	-FDT_ERR_BADLAYOUT,
>> + *	-FDT_ERR_TRUNCATED, standard meanings
>> + */
>> +int fdt_setprop_placeholder_namelen(void *fdt, int nodeoffset, const char *name,
>> +				    int namelen, int len, void **prop_data);
>>  
>>  /**
>>   * fdt_setprop_placeholder - allocate space for a property
>> @@ -1560,7 +1758,7 @@ int fdt_setprop(void *fdt, int nodeoffset, const char *name,
>>   * @len: length of the property value
>>   * @prop_data: return pointer to property data
>>   *
>> - * fdt_setprop_placeholer() allocates the named property in the given node.
>> + * fdt_setprop_placeholder() allocates the named property in the given node.
>>   * If the property exists it is resized. In either case a pointer to the
>>   * property data is returned.
>>   *
>> @@ -1580,8 +1778,13 @@ int fdt_setprop(void *fdt, int nodeoffset, const char *name,
>>   *	-FDT_ERR_BADLAYOUT,
>>   *	-FDT_ERR_TRUNCATED, standard meanings
>>   */
>> -int fdt_setprop_placeholder(void *fdt, int nodeoffset, const char *name,
>> -			    int len, void **prop_data);
>> +static inline int fdt_setprop_placeholder(void *fdt, int nodeoffset,
>> +					  const char *name, int len,
>> +					  void **prop_data)
>> +{
>> +	return fdt_setprop_placeholder_namelen(fdt, nodeoffset, name,
>> +					       strlen(name), len, prop_data);
>> +}
>>  
>>  /**
>>   * fdt_setprop_u32 - set a property to a 32-bit integer
>> @@ -1655,8 +1858,14 @@ static inline int fdt_setprop_u64(void *fdt, int nodeoffset, const char *name,
>>  
>>  /**
>>   * fdt_setprop_cell - set a property to a single cell value
>> + * @fdt: pointer to the device tree blob
>> + * @nodeoffset: offset of the node whose property to change
>> + * @name: name of the property to change
>> + * @val: 32-bit integer value for the property (native endian)
>>   *
>>   * This is an alternative name for fdt_setprop_u32()
>> + *
>> + * Return: 0 on success, negative libfdt error value otherwise.
>>   */
>>  static inline int fdt_setprop_cell(void *fdt, int nodeoffset, const char *name,
>>  				   uint32_t val)
>> @@ -1695,6 +1904,39 @@ static inline int fdt_setprop_cell(void *fdt, int nodeoffset, const char *name,
>>  #define fdt_setprop_string(fdt, nodeoffset, name, str) \
>>  	fdt_setprop((fdt), (nodeoffset), (name), (str), strlen(str)+1)
>>  
>> +/**
>> + * fdt_setprop_namelen_string - set a property to a string value
>> + * @fdt: pointer to the device tree blob
>> + * @nodeoffset: offset of the node whose property to change
>> + * @name: name of the property to change
>> + * @namelen: number of characters of name to consider
>> + * @str: string value for the property
>> + *
>> + * fdt_setprop_namelen_string() sets the value of the named property in the
>> + * given node to the given string value (using the length of the
>> + * string to determine the new length of the property), or creates a
>> + * new property with that value if it does not already exist.
>> + *
>> + * This function may insert or delete data from the blob, and will
>> + * therefore change the offsets of some existing nodes.
>> + *
>> + * returns:
>> + *	0, on success
>> + *	-FDT_ERR_NOSPACE, there is insufficient free space in the blob to
>> + *		contain the new property value
>> + *	-FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag
>> + *	-FDT_ERR_BADLAYOUT,
>> + *	-FDT_ERR_BADMAGIC,
>> + *	-FDT_ERR_BADVERSION,
>> + *	-FDT_ERR_BADSTATE,
>> + *	-FDT_ERR_BADSTRUCTURE,
>> + *	-FDT_ERR_BADLAYOUT,
>> + *	-FDT_ERR_TRUNCATED, standard meanings
>> + */
>> +#define fdt_setprop_namelen_string(fdt, nodeoffset, name, namelen, str)    \
>> +	fdt_setprop_namelen((fdt), (nodeoffset), (name), (namelen), (str), \
>> +			    strlen(str) + 1)
>> +
>>  /**
>>   * fdt_setprop_empty - set a property to an empty value
>>   * @fdt: pointer to the device tree blob
>> @@ -1826,8 +2068,14 @@ static inline int fdt_appendprop_u64(void *fdt, int nodeoffset,
>>  
>>  /**
>>   * fdt_appendprop_cell - append a single cell value to a property
>> + * @fdt: pointer to the device tree blob
>> + * @nodeoffset: offset of the node whose property to change
>> + * @name: name of the property to change
>> + * @val: 32-bit integer value to append to the property (native endian)
>>   *
>>   * This is an alternative name for fdt_appendprop_u32()
>> + *
>> + * Return: 0 on success, negative libfdt error value otherwise.
>>   */
>>  static inline int fdt_appendprop_cell(void *fdt, int nodeoffset,
>>  				      const char *name, uint32_t val)
>> @@ -1878,7 +2126,7 @@ static inline int fdt_appendprop_cell(void *fdt, int nodeoffset,
>>   * 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
>> @@ -1908,7 +2156,7 @@ int fdt_appendprop_addrrange(void *fdt, int parent, int nodeoffset,
>>   * @nodeoffset: offset of the node whose property to nop
>>   * @name: name of the property to nop
>>   *
>> - * fdt_del_property() will delete the given property.
>> + * fdt_delprop() will delete the given property.
>>   *
>>   * This function will delete data from the blob, and will therefore
>>   * change the offsets of some existing nodes.
>> @@ -1930,13 +2178,16 @@ int fdt_delprop(void *fdt, int nodeoffset, const char *name);
>>   * fdt_add_subnode_namelen - creates a new node based on substring
>>   * @fdt: pointer to the device tree blob
>>   * @parentoffset: structure block offset of a node
>> - * @name: name of the subnode to locate
>> + * @name: name of the subnode to create
>>   * @namelen: number of characters of name to consider
>>   *
>> - * Identical to fdt_add_subnode(), but use only the first namelen
>> - * characters of name as the name of the new node.  This is useful for
>> + * Identical to fdt_add_subnode(), but use only the first @namelen
>> + * characters of @name as the name of the new node.  This is useful for
>>   * creating subnodes based on a portion of a larger string, such as a
>>   * full path.
>> + *
>> + * Return: structure block offset of the created subnode (>=0),
>> + *	   negative libfdt error value otherwise
>>   */
>>  #ifndef SWIG /* Not available in Python */
>>  int fdt_add_subnode_namelen(void *fdt, int parentoffset,
>> @@ -1955,10 +2206,9 @@ int fdt_add_subnode_namelen(void *fdt, int parentoffset,
>>   *
>>   * This function will insert data into the blob, and will therefore
>>   * change the offsets of some existing nodes.
>> -
>> + *
>>   * returns:
>> - *	structure block offset of the created nodeequested subnode (>=0), on
>> - *		success
>> + *	structure block offset of the created subnode (>=0), on success
>>   *	-FDT_ERR_NOTFOUND, if the requested subnode does not exist
>>   *	-FDT_ERR_BADOFFSET, if parentoffset did not point to an FDT_BEGIN_NODE
>>   *		tag
>> @@ -1968,7 +2218,7 @@ int fdt_add_subnode_namelen(void *fdt, int parentoffset,
>>   *		blob to contain the new node
>>   *	-FDT_ERR_NOSPACE
>>   *	-FDT_ERR_BADLAYOUT
>> - *      -FDT_ERR_BADMAGIC,
>> + *	-FDT_ERR_BADMAGIC,
>>   *	-FDT_ERR_BADVERSION,
>>   *	-FDT_ERR_BADSTATE,
>>   *	-FDT_ERR_BADSTRUCTURE,
>> @@ -2013,7 +2263,7 @@ int fdt_del_node(void *fdt, int nodeoffset);
>>   * returns:
>>   *	0, on success
>>   *	-FDT_ERR_NOSPACE, there's not enough space in the base device tree
>> - *	-FDT_ERR_NOTFOUND, the overlay points to some inexistant nodes or
>> + *	-FDT_ERR_NOTFOUND, the overlay points to some nonexistent nodes or
>>   *		properties in the base DT
>>   *	-FDT_ERR_BADPHANDLE,
>>   *	-FDT_ERR_BADOVERLAY,
>> @@ -2030,6 +2280,24 @@ int fdt_del_node(void *fdt, int nodeoffset);
>>   */
>>  int fdt_overlay_apply(void *fdt, void *fdto);
>>  
>> +/**
>> + * fdt_overlay_target_offset - retrieves the offset of a fragment's target
>> + * @fdt: Base device tree blob
>> + * @fdto: Device tree overlay blob
>> + * @fragment_offset: node offset of the fragment in the overlay
>> + * @pathp: pointer which receives the path of the target (or NULL)
>> + *
>> + * fdt_overlay_target_offset() retrieves the target offset in the base
>> + * device tree of a fragment, no matter how the actual targeting is
>> + * done (through a phandle or a path)
>> + *
>> + * returns:
>> + *      the targeted node offset in the base device tree
>> + *      Negative error code on error
>> + */
>> +int fdt_overlay_target_offset(const void *fdt, const void *fdto,
>> +			      int fragment_offset, char const **pathp);
>> +
>>  /**
>>   * fdt_overlay_apply_node - Merges a node into the base device tree
>>   *
>> @@ -2043,4 +2311,8 @@ int fdt_overlay_apply_node(void *fdt, int target, void *fdto, int node);
>>  
>>  const char *fdt_strerror(int errval);
>>  
>> +#ifdef __cplusplus
>> +}
>> +#endif
>> +
>>  #endif /* LIBFDT_H */
>> diff --git a/scripts/dtc/libfdt/libfdt_internal.h b/scripts/dtc/libfdt/libfdt_internal.h
>> index 5436e2ceeac..b60b5456f59 100644
>> --- a/scripts/dtc/libfdt/libfdt_internal.h
>> +++ b/scripts/dtc/libfdt/libfdt_internal.h
>> @@ -10,20 +10,25 @@
>>  #define FDT_ALIGN(x, a)		(((x) + (a) - 1) & ~((a) - 1))
>>  #define FDT_TAGALIGN(x)		(FDT_ALIGN((x), FDT_TAGSIZE))
>>  
>> -int fdt_ro_probe_(const void *fdt);
>> +int32_t fdt_ro_probe_(const void *fdt);
>>  #define FDT_RO_PROBE(fdt)					\
>>  	{							\
>> -		int totalsize_;					\
>> -		if (fdt_chk_basic()) {				\
>> -			totalsize_ = fdt_ro_probe_(fdt);	\
>> -			if (totalsize_ < 0)			\
>> -				return totalsize_;		\
>> -		}						\
>> +		int32_t totalsize_;				\
>> +		if ((totalsize_ = fdt_ro_probe_(fdt)) < 0)	\
>> +			return totalsize_;			\
>>  	}
>>  
>>  int fdt_check_node_offset_(const void *fdt, int offset);
>>  int fdt_check_prop_offset_(const void *fdt, int offset);
>> -const char *fdt_find_string_(const char *strtab, int tabsize, const char *s);
>> +
>> +const char *fdt_find_string_len_(const char *strtab, int tabsize, const char *s,
>> +				 int s_len);
>> +static inline const char *fdt_find_string_(const char *strtab, int tabsize,
>> +					   const char *s)
>> +{
>> +	return fdt_find_string_len_(strtab, tabsize, s, strlen(s));
>> +}
>> +
>>  int fdt_node_end_offset_(void *fdt, int nodeoffset);
>>  
>>  static inline const void *fdt_offset_ptr_(const void *fdt, int offset)
>> @@ -49,6 +54,25 @@ static inline struct fdt_reserve_entry *fdt_mem_rsv_w_(void *fdt, int n)
>>  	return (void *)(uintptr_t)fdt_mem_rsv_(fdt, n);
>>  }
>>  
>> +/*
>> + * Internal helpers to access structural elements of the device tree
>> + * blob (rather than for example reading integers from within property
>> + * values).  We assume that we are either given a naturally aligned
>> + * address for the platform or if we are not, we are on a platform
>> + * where unaligned memory reads will be handled in a graceful manner.
>> + * If not the external helpers fdtXX_ld() from libfdt.h can be used
>> + * instead.
>> + */
>> +static inline uint32_t fdt32_ld_(const fdt32_t *p)
>> +{
>> +	return fdt32_to_cpu(*p);
>> +}
>> +
>> +static inline uint64_t fdt64_ld_(const fdt64_t *p)
>> +{
>> +	return fdt64_to_cpu(*p);
>> +}
>> +
>>  #define FDT_SW_MAGIC		(~FDT_MAGIC)
>>  
>>  /**********************************************************************/
>> @@ -61,20 +85,21 @@ static inline struct fdt_reserve_entry *fdt_mem_rsv_w_(void *fdt, int n)
>>  
>>  /*
>>   * Defines assumptions which can be enabled. Each of these can be enabled
>> - * individually. For maximum saftey, don't enable any assumptions!
>> + * individually. For maximum safety, don't enable any assumptions!
>>   *
>> - * For minimal code size and no safety, use FDT_ASSUME_PERFECT at your own risk.
>> + * For minimal code size and no safety, use ASSUME_PERFECT at your own risk.
>>   * You should have another method of validating the device tree, such as a
>>   * signature or hash check before using libfdt.
>>   *
>>   * For situations where security is not a concern it may be safe to enable
>> - * FDT_ASSUME_FRIENDLY.
>> + * ASSUME_SANE.
>>   */
>>  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.
>> +	 * version is correctly handled. Inconsistencies or errors in the device
>> +	 * tree may cause undefined behaviour or crashes. Invalid parameters
>> +	 * passed to libfdt may do the same.
>>  	 *
>>  	 * If an error occurs when modifying the tree it may leave the tree in
>>  	 * an intermediate (but valid) state. As an example, adding a property
>> @@ -85,17 +110,35 @@ enum {
>>  	 * 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,
>> +	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.
>> +	 * With this assumption enabled, normal device trees produced by libfdt
>> +	 * and the compiler should be handled safely. Malicious device trees and
>> +	 * complete garbage may cause libfdt to behave badly or crash. Truncated
>> +	 * device trees (e.g. those only partially loaded) can also cause
>> +	 * problems.
>> +	 *
>> +	 * Note: Only checks that relate exclusively to the device tree itself
>> +	 * (not the parameters passed to libfdt) are disabled by this
>> +	 * assumption. This includes checking headers, tags and the like.
>> +	 */
>> +	ASSUME_VALID_DTB	= 1 << 0,
>> +
>> +	/*
>> +	 * This builds on ASSUME_VALID_DTB and further assumes that libfdt
>> +	 * functions are called with valid parameters, i.e. not trigger
>> +	 * FDT_ERR_BADOFFSET or offsets that are out of bounds. It disables any
>> +	 * extensive checking of parameters and the device tree, making various
>> +	 * assumptions about correctness.
>> +	 *
>> +	 * It doesn't make sense to enable this assumption unless
>> +	 * ASSUME_VALID_DTB is also enabled.
>>  	 */
>> -	FDT_ASSUME_SANE		= 1 << 0,
>> +	ASSUME_VALID_INPUT	= 1 << 1,
>>  
>>  	/*
>>  	 * This disables checks for device-tree version and removes all code
>> @@ -104,34 +147,54 @@ enum {
>>  	 * Only enable this if you know you have a device tree with the latest
>>  	 * version.
>>  	 */
>> -	FDT_ASSUME_LATEST	= 1 << 1,
>> +	ASSUME_LATEST		= 1 << 2,
>>  
>>  	/*
>> -	 * 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.
>> +	 * This assumes that it is OK for a failed addition to the device tree,
>> +	 * due to lack of space or some other problem, to skip any rollback
>> +	 * steps (such as dropping the property name from the string table).
>> +	 * This is safe to enable in most circumstances, even though it may
>> +	 * leave the tree in a sub-optimal state.
>>  	 */
>> -	FDT_ASSUME_FRIENDLY	= 1 << 2,
>> -};
>> +	ASSUME_NO_ROLLBACK	= 1 << 3,
>>  
>> -/** 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);
>> -}
>> +	/*
>> +	 * This assumes that the device tree components appear in a 'convenient'
>> +	 * order, i.e. the memory reservation block first, then the structure
>> +	 * block and finally the string block.
>> +	 *
>> +	 * This order is not specified by the device-tree specification,
>> +	 * but is expected by libfdt. The device-tree compiler always created
>> +	 * device trees with this order.
>> +	 *
>> +	 * This assumption disables a check in fdt_open_into() and removes the
>> +	 * ability to fix the problem there. This is safe if you know that the
>> +	 * device tree is correctly ordered. See fdt_blocks_misordered_().
>> +	 */
>> +	ASSUME_LIBFDT_ORDER	= 1 << 4,
>>  
>> -/** 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);
>> -}
>> +	/*
>> +	 * This assumes that libfdt itself does not have any internal bugs. It
>> +	 * drops certain checks that should never be needed unless libfdt has an
>> +	 * undiscovered bug.
>> +	 *
>> +	 * This can generally be considered safe to enable.
>> +	 */
>> +	ASSUME_LIBFDT_FLAWLESS	= 1 << 5,
>> +};
>>  
>> -/** fdt_chk_extra() - see if extra checking is enabled */
>> -static inline bool fdt_chk_extra(void)
>> +/**
>> + * can_assume_() - check if a particular assumption is enabled
>> + *
>> + * @mask: Mask to check (ASSUME_...)
>> + * @return true if that assumption is enabled, else false
>> + */
>> +static inline bool can_assume_(int mask)
>>  {
>> -	return !(FDT_ASSUME_MASK & FDT_ASSUME_FRIENDLY);
>> +	return FDT_ASSUME_MASK & mask;
>>  }
>>  
>> +/** helper macros for checking assumptions */
>> +#define can_assume(_assume)	can_assume_(ASSUME_ ## _assume)
>> +
>>  #endif /* LIBFDT_INTERNAL_H */
>> diff --git a/scripts/dtc/livetree.c b/scripts/dtc/livetree.c
>> index 4cfc2adccdd..1e121d41a89 100644
>> --- a/scripts/dtc/livetree.c
>> +++ b/scripts/dtc/livetree.c
>> @@ -1,24 +1,10 @@
>> +// SPDX-License-Identifier: GPL-2.0-or-later
>>  /*
>>   * (C) Copyright David Gibson <dwg at au1.ibm.com>, IBM Corporation.  2005.
>> - *
>> - *
>> - * This program 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 program 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 program; if not, write to the Free Software
>> - *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307
>> - *                                                                   USA
>>   */
>>  
>>  #include "dtc.h"
>> +#include "srcpos.h"
>>  
>>  /*
>>   * Tree building functions
>> @@ -50,25 +36,27 @@ void delete_labels(struct label **labels)
>>  		label->deleted = 1;
>>  }
>>  
>> -struct property *build_property(char *name, struct data val)
>> +struct property *build_property(const char *name, struct data val,
>> +				struct srcpos *srcpos)
>>  {
>>  	struct property *new = xmalloc(sizeof(*new));
>>  
>>  	memset(new, 0, sizeof(*new));
>>  
>> -	new->name = name;
>> +	new->name = xstrdup(name);
>>  	new->val = val;
>> +	new->srcpos = srcpos_copy(srcpos);
>>  
>>  	return new;
>>  }
>>  
>> -struct property *build_property_delete(char *name)
>> +struct property *build_property_delete(const char *name)
>>  {
>>  	struct property *new = xmalloc(sizeof(*new));
>>  
>>  	memset(new, 0, sizeof(*new));
>>  
>> -	new->name = name;
>> +	new->name = xstrdup(name);
>>  	new->deleted = 1;
>>  
>>  	return new;
>> @@ -97,7 +85,8 @@ struct property *reverse_properties(struct property *first)
>>  	return head;
>>  }
>>  
>> -struct node *build_node(struct property *proplist, struct node *children)
>> +struct node *build_node(struct property *proplist, struct node *children,
>> +			struct srcpos *srcpos)
>>  {
>>  	struct node *new = xmalloc(sizeof(*new));
>>  	struct node *child;
>> @@ -106,6 +95,7 @@ struct node *build_node(struct property *proplist, struct node *children)
>>  
>>  	new->proplist = reverse_properties(proplist);
>>  	new->children = children;
>> +	new->srcpos = srcpos_copy(srcpos);
>>  
>>  	for_each_child(new, child) {
>>  		child->parent = new;
>> @@ -114,22 +104,23 @@ struct node *build_node(struct property *proplist, struct node *children)
>>  	return new;
>>  }
>>  
>> -struct node *build_node_delete(void)
>> +struct node *build_node_delete(struct srcpos *srcpos)
>>  {
>>  	struct node *new = xmalloc(sizeof(*new));
>>  
>>  	memset(new, 0, sizeof(*new));
>>  
>>  	new->deleted = 1;
>> +	new->srcpos = srcpos_copy(srcpos);
>>  
>>  	return new;
>>  }
>>  
>> -struct node *name_node(struct node *node, char *name)
>> +struct node *name_node(struct node *node, const char *name)
>>  {
>>  	assert(node->name == NULL);
>>  
>> -	node->name = name;
>> +	node->name = xstrdup(name);
>>  
>>  	return node;
>>  }
>> @@ -183,6 +174,8 @@ struct node *merge_nodes(struct node *old_node, struct node *new_node)
>>  
>>  				old_prop->val = new_prop->val;
>>  				old_prop->deleted = 0;
>> +				srcpos_free(old_prop->srcpos);
>> +				old_prop->srcpos = new_prop->srcpos;
>>  				free(new_prop);
>>  				new_prop = NULL;
>>  				break;
>> @@ -223,6 +216,8 @@ struct node *merge_nodes(struct node *old_node, struct node *new_node)
>>  			add_child(old_node, new_child);
>>  	}
>>  
>> +	old_node->srcpos = srcpos_extend(old_node->srcpos, new_node->srcpos);
>> +
>>  	/* The new node contents are now merged into the old node.  Free
>>  	 * the new node. */
>>  	free(new_node);
>> @@ -239,21 +234,23 @@ struct node * add_orphan_node(struct node *dt, struct node *new_node, char *ref)
>>  	char *name;
>>  
>>  	if (ref[0] == '/') {
>> +		d = data_add_marker(d, TYPE_STRING, ref);
>>  		d = data_append_data(d, ref, strlen(ref) + 1);
>>  
>> -		p = build_property("target-path", d);
>> +		p = build_property("target-path", d, NULL);
>>  	} else {
>>  		d = data_add_marker(d, REF_PHANDLE, ref);
>>  		d = data_append_integer(d, 0xffffffff, 32);
>>  
>> -		p = build_property("target", d);
>> +		p = build_property("target", d, NULL);
>>  	}
>>  
>>  	xasprintf(&name, "fragment@%u",
>>  			next_orphan_fragment++);
>>  	name_node(new_node, "__overlay__");
>> -	node = build_node(p, new_node);
>> +	node = build_node(p, new_node, NULL);
>>  	name_node(node, name);
>> +	free(name);
>>  
>>  	add_child(dt, node);
>>  	return dt;
>> @@ -340,18 +337,21 @@ void delete_node(struct node *node)
>>  }
>>  
>>  void append_to_property(struct node *node,
>> -				    char *name, const void *data, int len)
>> +			char *name, const void *data, int len,
>> +			enum markertype type)
>>  {
>>  	struct data d;
>>  	struct property *p;
>>  
>>  	p = get_property(node, name);
>>  	if (p) {
>> -		d = data_append_data(p->val, data, len);
>> +		d = data_add_marker(p->val, type, name);
>> +		d = data_append_data(d, data, len);
>>  		p->val = d;
>>  	} else {
>> -		d = data_append_data(empty_data, data, len);
>> -		p = build_property(name, d);
>> +		d = data_add_marker(empty_data, type, name);
>> +		d = data_append_data(d, data, len);
>> +		p = build_property(name, d, NULL);
>>  		add_property(node, p);
>>  	}
>>  }
>> @@ -439,9 +439,9 @@ cell_t propval_cell(struct property *prop)
>>  	return fdt32_to_cpu(*((fdt32_t *)prop->val.val));
>>  }
>>  
>> -cell_t propval_cell_n(struct property *prop, int n)
>> +cell_t propval_cell_n(struct property *prop, unsigned int n)
>>  {
>> -	assert(prop->val.len / sizeof(cell_t) >= n);
>> +	assert(prop->val.len / sizeof(cell_t) > n);
>>  	return fdt32_to_cpu(*((fdt32_t *)prop->val.val + n));
>>  }
>>  
>> @@ -504,7 +504,7 @@ struct node *get_subnode(struct node *node, const char *nodename)
>>  	struct node *child;
>>  
>>  	for_each_child(node, child)
>> -		if (streq(child->name, nodename))
>> +		if (streq(child->name, nodename) && !child->deleted)
>>  			return child;
>>  
>>  	return NULL;
>> @@ -527,8 +527,7 @@ struct node *get_node_by_path(struct node *tree, const char *path)
>>  	p = strchr(path, '/');
>>  
>>  	for_each_child(tree, child) {
>> -		if (p && (strlen(child->name) == p-path) &&
>> -		    strprefixeq(path, p - path, child->name))
>> +		if (p && strprefixeq(path, (size_t)(p - path), child->name))
>>  			return get_node_by_path(child, p+1);
>>  		else if (!p && streq(path, child->name))
>>  			return child;
>> @@ -561,7 +560,7 @@ struct node *get_node_by_phandle(struct node *tree, cell_t phandle)
>>  {
>>  	struct node *child, *node;
>>  
>> -	if ((phandle == 0) || (phandle == -1)) {
>> +	if (!phandle_is_valid(phandle)) {
>>  		assert(generate_fixups);
>>  		return NULL;
>>  	}
>> @@ -618,11 +617,27 @@ struct node *get_node_by_ref(struct node *tree, const char *ref)
>>  	return target;
>>  }
>>  
>> +static void add_phandle_property(struct node *node,
>> +				 const char *name, int format)
>> +{
>> +	struct data d;
>> +
>> +	if (!(phandle_format & format))
>> +		return;
>> +	if (get_property(node, name))
>> +		return;
>> +
>> +	d = data_add_marker(empty_data, TYPE_UINT32, NULL);
>> +	d = data_append_cell(d, node->phandle);
>> +
>> +	add_property(node, build_property(name, d, NULL));
>> +}
>> +
>>  cell_t get_node_phandle(struct node *root, struct node *node)
>>  {
>>  	static cell_t phandle = 1; /* FIXME: ick, static local */
>>  
>> -	if ((node->phandle != 0) && (node->phandle != -1))
>> +	if (phandle_is_valid(node->phandle))
>>  		return node->phandle;
>>  
>>  	while (get_node_by_phandle(root, phandle))
>> @@ -630,17 +645,8 @@ cell_t get_node_phandle(struct node *root, struct node *node)
>>  
>>  	node->phandle = phandle;
>>  
>> -	if (!get_property(node, "linux,phandle")
>> -	    && (phandle_format & PHANDLE_LEGACY))
>> -		add_property(node,
>> -			     build_property("linux,phandle",
>> -					    data_append_cell(empty_data, phandle)));
>> -
>> -	if (!get_property(node, "phandle")
>> -	    && (phandle_format & PHANDLE_EPAPR))
>> -		add_property(node,
>> -			     build_property("phandle",
>> -					    data_append_cell(empty_data, phandle)));
>> +	add_phandle_property(node, "linux,phandle", PHANDLE_LEGACY);
>> +	add_phandle_property(node, "phandle", PHANDLE_EPAPR);
>>  
>>  	/* If the node *does* have a phandle property, we must
>>  	 * be dealing with a self-referencing phandle, which will be
>> @@ -809,18 +815,18 @@ void sort_tree(struct dt_info *dti)
>>  }
>>  
>>  /* utility helper to avoid code duplication */
>> -static struct node *build_and_name_child_node(struct node *parent, char *name)
>> +static struct node *build_and_name_child_node(struct node *parent, const char *name)
>>  {
>>  	struct node *node;
>>  
>> -	node = build_node(NULL, NULL);
>> -	name_node(node, xstrdup(name));
>> +	node = build_node(NULL, NULL, NULL);
>> +	name_node(node, name);
>>  	add_child(parent, node);
>>  
>>  	return node;
>>  }
>>  
>> -static struct node *build_root_node(struct node *dt, char *name)
>> +static struct node *build_root_node(struct node *dt, const char *name)
>>  {
>>  	struct node *an;
>>  
>> @@ -874,8 +880,9 @@ static void generate_label_tree_internal(struct dt_info *dti,
>>  
>>  			/* insert it */
>>  			p = build_property(l->label,
>> -				data_copy_mem(node->fullpath,
>> -						strlen(node->fullpath) + 1));
>> +				data_copy_escape_string(node->fullpath,
>> +						strlen(node->fullpath)),
>> +				NULL);
>>  			add_property(an, p);
>>  		}
>>  
>> @@ -919,13 +926,19 @@ static void add_fixup_entry(struct dt_info *dti, struct node *fn,
>>  	/* 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");
>>  
>>  	xasprintf(&entry, "%s:%s:%u",
>>  			node->fullpath, prop->name, m->offset);
>> -	append_to_property(fn, m->ref, entry, strlen(entry) + 1);
>> +	append_to_property(fn, m->ref, entry, strlen(entry) + 1, TYPE_STRING);
>>  
>>  	free(entry);
>>  }
>> @@ -985,7 +998,7 @@ static void add_local_fixup_entry(struct dt_info *dti,
>>  	char **compp;
>>  	int i, depth;
>>  
>> -	/* walk back retreiving depth */
>> +	/* walk back retrieving depth */
>>  	depth = 0;
>>  	for (wn = node; wn; wn = wn->parent)
>>  		depth++;
>> @@ -1000,15 +1013,13 @@ static void add_local_fixup_entry(struct dt_info *dti,
>>  	/* walk the path components creating nodes if they don't exist */
>>  	for (wn = lfn, i = 1; i < depth; i++, wn = nwn) {
>>  		/* if no node exists, create it */
>> -		nwn = get_subnode(wn, compp[i]);
>> -		if (!nwn)
>> -			nwn = build_and_name_child_node(wn, compp[i]);
>> +		nwn = build_root_node(wn, compp[i]);
>>  	}
>>  
>>  	free(compp);
>>  
>>  	value_32 = cpu_to_fdt32(m->offset);
>> -	append_to_property(wn, prop->name, &value_32, sizeof(value_32));
>> +	append_to_property(wn, prop->name, &value_32, sizeof(value_32), TYPE_UINT32);
>>  }
>>  
>>  static void generate_local_fixups_tree_internal(struct dt_info *dti,
>> @@ -1034,7 +1045,7 @@ static void generate_local_fixups_tree_internal(struct dt_info *dti,
>>  		generate_local_fixups_tree_internal(dti, lfn, c);
>>  }
>>  
>> -void generate_label_tree(struct dt_info *dti, char *name, bool allocph)
>> +void generate_label_tree(struct dt_info *dti, const char *name, bool allocph)
>>  {
>>  	if (!any_label_tree(dti, dti->dt))
>>  		return;
>> @@ -1042,18 +1053,31 @@ void generate_label_tree(struct dt_info *dti, char *name, bool allocph)
>>  				     dti->dt, allocph);
>>  }
>>  
>> -void generate_fixups_tree(struct dt_info *dti, char *name)
>> +void generate_fixups_tree(struct dt_info *dti, const char *name)
>>  {
>> +	struct node *n = get_subnode(dti->dt, name);
>> +
>> +	/* Start with an empty __fixups__ node to not get duplicates */
>> +	if (n)
>> +		n->deleted = true;
>> +
>>  	if (!any_fixup_tree(dti, dti->dt))
>>  		return;
>> -	generate_fixups_tree_internal(dti, build_root_node(dti->dt, name),
>> +	generate_fixups_tree_internal(dti,
>> +				      build_and_name_child_node(dti->dt, name),
>>  				      dti->dt);
>>  }
>>  
>> -void generate_local_fixups_tree(struct dt_info *dti, char *name)
>> +void generate_local_fixups_tree(struct dt_info *dti, const char *name)
>>  {
>> +	struct node *n = get_subnode(dti->dt, name);
>> +
>> +	/* Start with an empty __local_fixups__ node to not get duplicates */
>> +	if (n)
>> +		n->deleted = true;
>>  	if (!any_local_fixup_tree(dti, dti->dt))
>>  		return;
>> -	generate_local_fixups_tree_internal(dti, build_root_node(dti->dt, name),
>> +	generate_local_fixups_tree_internal(dti,
>> +					    build_and_name_child_node(dti->dt, name),
>>  					    dti->dt);
>>  }
>> diff --git a/scripts/dtc/srcpos.c b/scripts/dtc/srcpos.c
>> index 0ad89e2af60..627a0760e6e 100644
>> --- a/scripts/dtc/srcpos.c
>> +++ b/scripts/dtc/srcpos.c
>> @@ -1,23 +1,11 @@
>> +// SPDX-License-Identifier: GPL-2.0-or-later
>>  /*
>>   * Copyright 2007 Jon Loeliger, Freescale Semiconductor, Inc.
>> - *
>> - * This program 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 program 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 program; if not, write to the Free Software
>> - *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307
>> - *                                                                   USA
>>   */
>>  
>> +#ifndef _GNU_SOURCE
>>  #define _GNU_SOURCE
>> +#endif
>>  
>>  #include <stdio.h>
>>  
>> @@ -33,6 +21,10 @@ struct search_path {
>>  /* This is the list of directories that we search for source files */
>>  static struct search_path *search_path_head, **search_path_tail;
>>  
>> +/* Detect infinite include recursion. */
>> +#define MAX_SRCFILE_DEPTH     (200)
>> +static int srcfile_depth; /* = 0 */
>> +
>>  static char *get_dirname(const char *path)
>>  {
>>  	const char *slash = strrchr(path, '/');
>> @@ -50,10 +42,51 @@ static char *get_dirname(const char *path)
>>  
>>  FILE *depfile; /* = NULL */
>>  struct srcfile_state *current_srcfile; /* = NULL */
>> +static char *initial_path; /* = NULL */
>> +static int initial_pathlen; /* = 0 */
>> +static bool initial_cpp = true;
>>  
>> -/* Detect infinite include recursion. */
>> -#define MAX_SRCFILE_DEPTH     (100)
>> -static int srcfile_depth; /* = 0 */
>> +static void set_initial_path(char *fname)
>> +{
>> +	int i, len = strlen(fname);
>> +
>> +	xasprintf(&initial_path, "%s", fname);
>> +	initial_pathlen = 0;
>> +	for (i = 0; i != len; i++)
>> +		if (initial_path[i] == '/')
>> +			initial_pathlen++;
>> +}
>> +
>> +static char *shorten_to_initial_path(char *fname)
>> +{
>> +	char *p1, *p2, *prevslash1 = NULL;
>> +	int slashes = 0;
>> +
>> +	for (p1 = fname, p2 = initial_path; *p1 && *p2; p1++, p2++) {
>> +		if (*p1 != *p2)
>> +			break;
>> +		if (*p1 == '/') {
>> +			prevslash1 = p1;
>> +			slashes++;
>> +		}
>> +	}
>> +	p1 = prevslash1 + 1;
>> +	if (prevslash1) {
>> +		int diff = initial_pathlen - slashes, i, j;
>> +		int restlen = strlen(fname) - (p1 - fname);
>> +		char *res;
>> +
>> +		res = xmalloc((3 * diff) + restlen + 1);
>> +		for (i = 0, j = 0; i != diff; i++) {
>> +			res[j++] = '.';
>> +			res[j++] = '.';
>> +			res[j++] = '/';
>> +		}
>> +		strcpy(res + j, p1);
>> +		return res;
>> +	}
>> +	return NULL;
>> +}
>>  
>>  /**
>>   * Try to open a file in a given directory.
>> @@ -127,8 +160,10 @@ FILE *srcfile_relative_open(const char *fname, char **fullnamep)
>>  			    strerror(errno));
>>  	}
>>  
>> -	if (depfile)
>> -		fprintf(depfile, " %s", fullname);
>> +	if (depfile) {
>> +		fputc(' ', depfile);
>> +		fprint_path_escaped(depfile, fullname);
>> +	}
>>  
>>  	if (fullnamep)
>>  		*fullnamep = fullname;
>> @@ -155,6 +190,9 @@ void srcfile_push(const char *fname)
>>  	srcfile->colno = 1;
>>  
>>  	current_srcfile = srcfile;
>> +
>> +	if (srcfile_depth == 1)
>> +		set_initial_path(srcfile->name);
>>  }
>>  
>>  bool srcfile_pop(void)
>> @@ -195,18 +233,6 @@ void srcfile_add_search_path(const char *dirname)
>>  	search_path_tail = &node->next;
>>  }
>>  
>> -/*
>> - * The empty source position.
>> - */
>> -
>> -struct srcpos srcpos_empty = {
>> -	.first_line = 0,
>> -	.first_column = 0,
>> -	.last_line = 0,
>> -	.last_column = 0,
>> -	.file = NULL,
>> -};
>> -
>>  void srcpos_update(struct srcpos *pos, const char *text, int len)
>>  {
>>  	int i;
>> @@ -232,13 +258,46 @@ struct srcpos *
>>  srcpos_copy(struct srcpos *pos)
>>  {
>>  	struct srcpos *pos_new;
>> +	struct srcfile_state *srcfile_state;
>> +
>> +	if (!pos)
>> +		return NULL;
>>  
>>  	pos_new = xmalloc(sizeof(struct srcpos));
>> +	assert(pos->next == NULL);
>>  	memcpy(pos_new, pos, sizeof(struct srcpos));
>>  
>> +	/* allocate without free */
>> +	srcfile_state = xmalloc(sizeof(struct srcfile_state));
>> +	memcpy(srcfile_state, pos->file, sizeof(struct srcfile_state));
>> +	pos_new->file = srcfile_state;
>> +
>>  	return pos_new;
>>  }
>>  
>> +struct srcpos *srcpos_extend(struct srcpos *pos, struct srcpos *newtail)
>> +{
>> +	struct srcpos *p;
>> +
>> +	if (!pos)
>> +		return newtail;
>> +
>> +	for (p = pos; p->next != NULL; p = p->next);
>> +	p->next = newtail;
>> +	return pos;
>> +}
>> +
>> +void srcpos_free(struct srcpos *pos)
>> +{
>> +	struct srcpos *p_next;
>> +
>> +	while (pos) {
>> +		p_next = pos->next;
>> +		free(pos);
>> +		pos = p_next;
>> +	}
>> +}
>> +
>>  char *
>>  srcpos_string(struct srcpos *pos)
>>  {
>> @@ -263,6 +322,68 @@ srcpos_string(struct srcpos *pos)
>>  	return pos_str;
>>  }
>>  
>> +static char *
>> +srcpos_string_comment(struct srcpos *pos, bool first_line, int level)
>> +{
>> +	char *pos_str, *fresh_fname = NULL, *first, *rest;
>> +	const char *fname;
>> +
>> +	if (!pos) {
>> +		if (level > 1) {
>> +			xasprintf(&pos_str, "<no-file>:<no-line>");
>> +			return pos_str;
>> +		} else {
>> +			return NULL;
>> +		}
>> +	}
>> +
>> +	if (!pos->file)
>> +		fname = "<no-file>";
>> +	else if (!pos->file->name)
>> +		fname = "<no-filename>";
>> +	else if (level > 1)
>> +		fname = pos->file->name;
>> +	else {
>> +		fresh_fname = shorten_to_initial_path(pos->file->name);
>> +		if (fresh_fname)
>> +			fname = fresh_fname;
>> +		else
>> +			fname = pos->file->name;
>> +	}
>> +
>> +	if (level > 1)
>> +		xasprintf(&first, "%s:%d:%d-%d:%d", fname,
>> +			  pos->first_line, pos->first_column,
>> +			  pos->last_line, pos->last_column);
>> +	else
>> +		xasprintf(&first, "%s:%d", fname,
>> +			  first_line ? pos->first_line : pos->last_line);
>> +
>> +	if (fresh_fname)
>> +		free(fresh_fname);
>> +
>> +	if (pos->next != NULL) {
>> +		rest = srcpos_string_comment(pos->next, first_line, level);
>> +		xasprintf(&pos_str, "%s, %s", first, rest);
>> +		free(first);
>> +		free(rest);
>> +	} else {
>> +		pos_str = first;
>> +	}
>> +
>> +	return pos_str;
>> +}
>> +
>> +char *srcpos_string_first(struct srcpos *pos, int level)
>> +{
>> +	return srcpos_string_comment(pos, true, level);
>> +}
>> +
>> +char *srcpos_string_last(struct srcpos *pos, int level)
>> +{
>> +	return srcpos_string_comment(pos, false, level);
>> +}
>> +
>>  void srcpos_verror(struct srcpos *pos, const char *prefix,
>>  		   const char *fmt, va_list va)
>>  {
>> @@ -291,4 +412,9 @@ void srcpos_set_line(char *f, int l)
>>  {
>>  	current_srcfile->name = f;
>>  	current_srcfile->lineno = l;
>> +
>> +	if (initial_cpp) {
>> +		initial_cpp = false;
>> +		set_initial_path(f);
>> +	}
>>  }
>> diff --git a/scripts/dtc/srcpos.h b/scripts/dtc/srcpos.h
>> index fcd9937a911..0b634f212eb 100644
>> --- a/scripts/dtc/srcpos.h
>> +++ b/scripts/dtc/srcpos.h
>> @@ -1,20 +1,6 @@
>> +/* SPDX-License-Identifier: GPL-2.0-or-later */
>>  /*
>>   * Copyright 2007 Jon Loeliger, Freescale Semiconductor, Inc.
>> - *
>> - * This program 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 program 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 program; if not, write to the Free Software
>> - *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307
>> - *                                                                   USA
>>   */
>>  
>>  #ifndef SRCPOS_H
>> @@ -74,6 +60,7 @@ struct srcpos {
>>      int last_line;
>>      int last_column;
>>      struct srcfile_state *file;
>> +    struct srcpos *next;
>>  };
>>  
>>  #define YYLTYPE struct srcpos
>> @@ -93,18 +80,18 @@ struct srcpos {
>>  				YYRHSLOC(Rhs, 0).last_column;			\
>>  			(Current).file = YYRHSLOC (Rhs, 0).file;		\
>>  		}								\
>> +		(Current).next = NULL;						\
>>  	} while (0)
>>  
>> -/*
>> - * Fictional source position used for IR nodes that are
>> - * created without otherwise knowing a true source position.
>> - * For example,constant definitions from the command line.
>> - */
>> -extern struct srcpos srcpos_empty;
>> -
>>  extern void srcpos_update(struct srcpos *pos, const char *text, int len);
>>  extern struct srcpos *srcpos_copy(struct srcpos *pos);
>> +extern struct srcpos *srcpos_extend(struct srcpos *new_srcpos,
>> +				    struct srcpos *old_srcpos);
>> +extern void srcpos_free(struct srcpos *pos);
>>  extern char *srcpos_string(struct srcpos *pos);
>> +extern char *srcpos_string_first(struct srcpos *pos, int level);
>> +extern char *srcpos_string_last(struct srcpos *pos, int level);
>> +
>>  
>>  extern void PRINTF(3, 0) srcpos_verror(struct srcpos *pos, const char *prefix,
>>  					const char *fmt, va_list va);
>> diff --git a/scripts/dtc/treesource.c b/scripts/dtc/treesource.c
>> index 8c8b914698d..d25f01fc693 100644
>> --- a/scripts/dtc/treesource.c
>> +++ b/scripts/dtc/treesource.c
>> @@ -1,21 +1,6 @@
>> +// SPDX-License-Identifier: GPL-2.0-or-later
>>  /*
>>   * (C) Copyright David Gibson <dwg at au1.ibm.com>, IBM Corporation.  2005.
>> - *
>> - *
>> - * This program 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 program 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 program; if not, write to the Free Software
>> - *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307
>> - *                                                                   USA
>>   */
>>  
>>  #include "dtc.h"
>> @@ -61,24 +46,18 @@ static bool isstring(char c)
>>  		|| strchr("\a\b\t\n\v\f\r", c));
>>  }
>>  
>> -static void write_propval_string(FILE *f, struct data val)
>> +static void write_propval_string(FILE *f, const char *s, size_t len)
>>  {
>> -	const char *str = val.val;
>> -	int i;
>> -	struct marker *m = val.markers;
>> -
>> -	assert(str[val.len-1] == '\0');
>> +	const char *end = s + len - 1;
>>  
>> -	while (m && (m->offset == 0)) {
>> -		if (m->type == LABEL)
>> -			fprintf(f, "%s: ", m->ref);
>> -		m = m->next;
>> -	}
>> -	fprintf(f, "\"");
>> +	if (!len)
>> +		return;
>>  
>> -	for (i = 0; i < (val.len-1); i++) {
>> -		char c = str[i];
>> +	assert(*end == '\0');
>>  
>> +	fprintf(f, "\"");
>> +	while (s < end) {
>> +		char c = *s++;
>>  		switch (c) {
>>  		case '\a':
>>  			fprintf(f, "\\a");
>> @@ -108,91 +87,103 @@ static void write_propval_string(FILE *f, struct data val)
>>  			fprintf(f, "\\\"");
>>  			break;
>>  		case '\0':
>> -			fprintf(f, "\", ");
>> -			while (m && (m->offset <= (i + 1))) {
>> -				if (m->type == LABEL) {
>> -					assert(m->offset == (i+1));
>> -					fprintf(f, "%s: ", m->ref);
>> -				}
>> -				m = m->next;
>> -			}
>> -			fprintf(f, "\"");
>> +			fprintf(f, "\\0");
>>  			break;
>>  		default:
>>  			if (isprint((unsigned char)c))
>>  				fprintf(f, "%c", c);
>>  			else
>> -				fprintf(f, "\\x%02hhx", c);
>> +				fprintf(f, "\\x%02"PRIx8, c);
>>  		}
>>  	}
>>  	fprintf(f, "\"");
>> -
>> -	/* Wrap up any labels at the end of the value */
>> -	for_each_marker_of_type(m, LABEL) {
>> -		assert (m->offset == val.len);
>> -		fprintf(f, " %s:", m->ref);
>> -	}
>>  }
>>  
>> -static void write_propval_cells(FILE *f, struct data val)
>> +static void write_propval_int(FILE *f, const char *p, size_t len, size_t width)
>>  {
>> -	void *propend = val.val + val.len;
>> -	fdt32_t *cp = (fdt32_t *)val.val;
>> -	struct marker *m = val.markers;
>> -
>> -	fprintf(f, "<");
>> -	for (;;) {
>> -		while (m && (m->offset <= ((char *)cp - val.val))) {
>> -			if (m->type == LABEL) {
>> -				assert(m->offset == ((char *)cp - val.val));
>> -				fprintf(f, "%s: ", m->ref);
>> -			}
>> -			m = m->next;
>> -		}
>> +	const char *end = p + len;
>> +	assert(len % width == 0);
>>  
>> -		fprintf(f, "0x%x", fdt32_to_cpu(*cp++));
>> -		if ((void *)cp >= propend)
>> +	for (; p < end; p += width) {
>> +		switch (width) {
>> +		case 1:
>> +			fprintf(f, "%02"PRIx8, *(const uint8_t*)p);
>>  			break;
>> -		fprintf(f, " ");
>> -	}
>> -
>> -	/* Wrap up any labels at the end of the value */
>> -	for_each_marker_of_type(m, LABEL) {
>> -		assert (m->offset == val.len);
>> -		fprintf(f, " %s:", m->ref);
>> +		case 2:
>> +			fprintf(f, "0x%02"PRIx16, dtb_ld16(p));
>> +			break;
>> +		case 4:
>> +			fprintf(f, "0x%02"PRIx32, dtb_ld32(p));
>> +			break;
>> +		case 8:
>> +			fprintf(f, "0x%02"PRIx64, dtb_ld64(p));
>> +			break;
>> +		}
>> +		if (p + width < end)
>> +			fputc(' ', f);
>>  	}
>> -	fprintf(f, ">");
>>  }
>>  
>> -static void write_propval_bytes(FILE *f, struct data val)
>> +static const char *delim_start[] = {
>> +	[TYPE_UINT8] = "[",
>> +	[TYPE_UINT16] = "/bits/ 16 <",
>> +	[TYPE_UINT32] = "<",
>> +	[TYPE_UINT64] = "/bits/ 64 <",
>> +	[TYPE_STRING] = "",
>> +};
>> +static const char *delim_end[] = {
>> +	[TYPE_UINT8] = "]",
>> +	[TYPE_UINT16] = ">",
>> +	[TYPE_UINT32] = ">",
>> +	[TYPE_UINT64] = ">",
>> +	[TYPE_STRING] = "",
>> +};
>> +
>> +/*
>> + * The invariants in the marker list are:
>> + *  - offsets are non-strictly monotonically increasing
>> + *  - for a single offset there is at most one type marker
>> + *  - for a single offset that has both a type marker and non-type markers, the
>> + *    type marker appears before the others.
>> + */
>> +static struct marker **add_marker(struct marker **mi,
>> +				  enum markertype type, unsigned int offset, char *ref)
>>  {
>> -	void *propend = val.val + val.len;
>> -	const char *bp = val.val;
>> -	struct marker *m = val.markers;
>> -
>> -	fprintf(f, "[");
>> -	for (;;) {
>> -		while (m && (m->offset == (bp-val.val))) {
>> -			if (m->type == LABEL)
>> -				fprintf(f, "%s: ", m->ref);
>> -			m = m->next;
>> -		}
>> +	struct marker *nm;
>>  
>> -		fprintf(f, "%02hhx", (unsigned char)(*bp++));
>> -		if ((const void *)bp >= propend)
>> -			break;
>> -		fprintf(f, " ");
>> -	}
>> +	while (*mi && (*mi)->offset < offset)
>> +		mi = &(*mi)->next;
>>  
>> -	/* Wrap up any labels at the end of the value */
>> -	for_each_marker_of_type(m, LABEL) {
>> -		assert (m->offset == val.len);
>> -		fprintf(f, " %s:", m->ref);
>> +	if (*mi && (*mi)->offset == offset && is_type_marker((*mi)->type)) {
>> +		if (is_type_marker(type))
>> +			return mi;
>> +		mi = &(*mi)->next;
>>  	}
>> -	fprintf(f, "]");
>> +
>> +	if (*mi && (*mi)->offset == offset && type == (*mi)->type)
>> +		return mi;
>> +
>> +	nm = xmalloc(sizeof(*nm));
>> +	nm->type = type;
>> +	nm->offset = offset;
>> +	nm->ref = ref;
>> +	nm->next = *mi;
>> +	*mi = nm;
>> +
>> +	return &nm->next;
>>  }
>>  
>> -static void write_propval(FILE *f, struct property *prop)
>> +static void add_string_markers(struct property *prop)
>> +{
>> +	int l, len = prop->val.len;
>> +	const char *p = prop->val.val;
>> +	struct marker **mi = &prop->val.markers;
>> +
>> +	for (l = strlen(p) + 1; l < len; l += strlen(p + l) + 1)
>> +		mi = add_marker(mi, TYPE_STRING, l, NULL);
>> +}
>> +
>> +static enum markertype guess_value_type(struct property *prop)
>>  {
>>  	int len = prop->val.len;
>>  	const char *p = prop->val.val;
>> @@ -201,11 +192,6 @@ static void write_propval(FILE *f, struct property *prop)
>>  	int nnotstringlbl = 0, nnotcelllbl = 0;
>>  	int i;
>>  
>> -	if (len == 0) {
>> -		fprintf(f, ";\n");
>> -		return;
>> -	}
>> -
>>  	for (i = 0; i < len; i++) {
>>  		if (! isstring(p[i]))
>>  			nnotstring++;
>> @@ -220,17 +206,116 @@ static void write_propval(FILE *f, struct property *prop)
>>  			nnotcelllbl++;
>>  	}
>>  
>> -	fprintf(f, " = ");
>> -	if ((p[len-1] == '\0') && (nnotstring == 0) && (nnul < (len-nnul))
>> +	if ((p[len-1] == '\0') && (nnotstring == 0) && (nnul <= (len-nnul))
>>  	    && (nnotstringlbl == 0)) {
>> -		write_propval_string(f, prop->val);
>> +		if (nnul > 1)
>> +			add_string_markers(prop);
>> +		return TYPE_STRING;
>>  	} else if (((len % sizeof(cell_t)) == 0) && (nnotcelllbl == 0)) {
>> -		write_propval_cells(f, prop->val);
>> -	} else {
>> -		write_propval_bytes(f, prop->val);
>> +		return TYPE_UINT32;
>>  	}
>>  
>> -	fprintf(f, ";\n");
>> +	return TYPE_UINT8;
>> +}
>> +
>> +static void write_propval(FILE *f, struct property *prop)
>> +{
>> +	size_t len = prop->val.len;
>> +	struct marker *m = prop->val.markers;
>> +	struct marker dummy_marker;
>> +	enum markertype emit_type = TYPE_NONE;
>> +	char *srcstr;
>> +
>> +	if (len == 0) {
>> +		fprintf(f, ";");
>> +		if (annotate) {
>> +			srcstr = srcpos_string_first(prop->srcpos, annotate);
>> +			if (srcstr) {
>> +				fprintf(f, " /* %s */", srcstr);
>> +				free(srcstr);
>> +			}
>> +		}
>> +		fprintf(f, "\n");
>> +		return;
>> +	}
>> +
>> +	fprintf(f, " =");
>> +
>> +	if (!next_type_marker(m)) {
>> +		/* data type information missing, need to guess */
>> +		dummy_marker.type = guess_value_type(prop);
>> +		dummy_marker.next = prop->val.markers;
>> +		dummy_marker.offset = 0;
>> +		dummy_marker.ref = NULL;
>> +		m = &dummy_marker;
>> +	}
>> +
>> +	for_each_marker(m) {
>> +		size_t chunk_len = (m->next ? m->next->offset : len) - m->offset;
>> +		size_t data_len = type_marker_length(m) ? : len - m->offset;
>> +		const char *p = &prop->val.val[m->offset];
>> +		struct marker *m_phandle;
>> +
>> +		if (is_type_marker(m->type)) {
>> +			emit_type = m->type;
>> +			fprintf(f, " %s", delim_start[emit_type]);
>> +		} else if (m->type == LABEL)
>> +			fprintf(f, " %s:", m->ref);
>> +
>> +		if (emit_type == TYPE_NONE || chunk_len == 0)
>> +			continue;
>> +
>> +		switch(emit_type) {
>> +		case TYPE_UINT16:
>> +			write_propval_int(f, p, chunk_len, 2);
>> +			break;
>> +		case TYPE_UINT32:
>> +			m_phandle = prop->val.markers;
>> +			for_each_marker_of_type(m_phandle, REF_PHANDLE)
>> +				if (m->offset == m_phandle->offset)
>> +					break;
>> +
>> +			if (m_phandle) {
>> +				if (m_phandle->ref[0] == '/')
>> +					fprintf(f, "&{%s}", m_phandle->ref);
>> +				else
>> +					fprintf(f, "&%s", m_phandle->ref);
>> +				if (chunk_len > 4) {
>> +					fputc(' ', f);
>> +					write_propval_int(f, p + 4, chunk_len - 4, 4);
>> +				}
>> +			} else {
>> +				write_propval_int(f, p, chunk_len, 4);
>> +			}
>> +			if (data_len > chunk_len)
>> +				fputc(' ', f);
>> +			break;
>> +		case TYPE_UINT64:
>> +			write_propval_int(f, p, chunk_len, 8);
>> +			break;
>> +		case TYPE_STRING:
>> +			write_propval_string(f, p, chunk_len);
>> +			break;
>> +		default:
>> +			write_propval_int(f, p, chunk_len, 1);
>> +		}
>> +
>> +		if (chunk_len == data_len) {
>> +			size_t pos = m->offset + chunk_len;
>> +			fprintf(f, pos == len ? "%s" : "%s,",
>> +			        delim_end[emit_type] ? : "");
>> +			emit_type = TYPE_NONE;
>> +		}
>> +	}
>> +	fprintf(f, ";");
>> +	if (annotate) {
>> +		srcstr = srcpos_string_first(prop->srcpos, annotate);
>> +		if (srcstr) {
>> +			fprintf(f, " /* %s */", srcstr);
>> +			free(srcstr);
>> +		}
>> +	}
>> +	fprintf(f, "\n");
>>  }
>>  
>>  static void write_tree_source_node(FILE *f, struct node *tree, int level)
>> @@ -238,14 +323,24 @@ static void write_tree_source_node(FILE *f, struct node *tree, int level)
>>  	struct property *prop;
>>  	struct node *child;
>>  	struct label *l;
>> +	char *srcstr;
>>  
>>  	write_prefix(f, level);
>>  	for_each_label(tree->labels, l)
>>  		fprintf(f, "%s: ", l->label);
>>  	if (tree->name && (*tree->name))
>> -		fprintf(f, "%s {\n", tree->name);
>> +		fprintf(f, "%s {", tree->name);
>>  	else
>> -		fprintf(f, "/ {\n");
>> +		fprintf(f, "/ {");
>> +
>> +	if (annotate) {
>> +		srcstr = srcpos_string_first(tree->srcpos, annotate);
>> +		if (srcstr) {
>> +			fprintf(f, " /* %s */", srcstr);
>> +			free(srcstr);
>> +		}
>> +	}
>> +	fprintf(f, "\n");
>>  
>>  	for_each_property(tree, prop) {
>>  		write_prefix(f, level+1);
>> @@ -259,7 +354,15 @@ static void write_tree_source_node(FILE *f, struct node *tree, int level)
>>  		write_tree_source_node(f, child, level+1);
>>  	}
>>  	write_prefix(f, level);
>> -	fprintf(f, "};\n");
>> +	fprintf(f, "};");
>> +	if (annotate) {
>> +		srcstr = srcpos_string_last(tree->srcpos, annotate);
>> +		if (srcstr) {
>> +			fprintf(f, " /* %s */", srcstr);
>> +			free(srcstr);
>> +		}
>> +	}
>> +	fprintf(f, "\n");
>>  }
>>  
>>  void dt_to_source(FILE *f, struct dt_info *dti)
>> diff --git a/scripts/dtc/update-dtc-source.sh b/scripts/dtc/update-dtc-source.sh
>> index 1a009fd195d..32ff17ffd08 100755
>> --- a/scripts/dtc/update-dtc-source.sh
>> +++ b/scripts/dtc/update-dtc-source.sh
>> @@ -32,11 +32,12 @@ DTC_UPSTREAM_PATH=`pwd`/../dtc
>>  DTC_LINUX_PATH=`pwd`/scripts/dtc
>>  
>>  DTC_SOURCE="checks.c data.c dtc.c dtc.h flattree.c fstree.c livetree.c srcpos.c \
>> -		srcpos.h treesource.c util.c util.h version_gen.h Makefile.dtc \
>> +		srcpos.h treesource.c util.c util.h version_gen.h yamltree.c \
>>  		dtc-lexer.l dtc-parser.y"
>> -LIBFDT_SOURCE="Makefile.libfdt fdt.c fdt.h fdt_addresses.c fdt_empty_tree.c \
>> +LIBFDT_SOURCE="fdt.c fdt.h fdt_addresses.c fdt_empty_tree.c \
>>  		fdt_overlay.c fdt_ro.c fdt_rw.c fdt_strerror.c fdt_sw.c \
>>  		fdt_wip.c libfdt.h libfdt_env.h libfdt_internal.h"
>> +FDTOVERLAY_SOURCE=fdtoverlay.c
>>  
>>  get_last_dtc_version() {
>>  	git log --oneline scripts/dtc/ | grep 'upstream' | head -1 | sed -e 's/^.* \(.*\)/\1/'
>> @@ -54,7 +55,7 @@ dtc_log=$(git log --oneline ${last_dtc_ver}..)
>>  
>>  # Copy the files into the Linux tree
>>  cd $DTC_LINUX_PATH
>> -for f in $DTC_SOURCE; do
>> +for f in $DTC_SOURCE $FDTOVERLAY_SOURCE; do
>>  	cp ${DTC_UPSTREAM_PATH}/${f} ${f}
>>  	git add ${f}
>>  done
>> diff --git a/scripts/dtc/util.c b/scripts/dtc/util.c
>> index 25d4db1e8c2..0e19a9f8acf 100644
>> --- a/scripts/dtc/util.c
>> +++ b/scripts/dtc/util.c
>> @@ -1,24 +1,10 @@
>> +// SPDX-License-Identifier: GPL-2.0-or-later
>>  /*
>>   * Copyright 2011 The Chromium Authors, All Rights Reserved.
>>   * Copyright 2008 Jon Loeliger, Freescale Semiconductor, Inc.
>>   *
>>   * util_is_printable_string contributed by
>>   *	Pantelis Antoniou <pantelis.antoniou AT gmail.com>
>> - *
>> - * This program 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 program 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 program; if not, write to the Free Software
>> - *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307
>> - *                                                                   USA
>>   */
>>  
>>  #include <ctype.h>
>> @@ -27,6 +13,7 @@
>>  #include <stdarg.h>
>>  #include <string.h>
>>  #include <assert.h>
>> +#include <inttypes.h>
>>  
>>  #include <errno.h>
>>  #include <fcntl.h>
>> @@ -36,6 +23,22 @@
>>  #include "util.h"
>>  #include "version_gen.h"
>>  
>> +void fprint_path_escaped(FILE *fp, const char *path)
>> +{
>> +	const char *p = path;
>> +
>> +	while (*p) {
>> +		if (*p == ' ') {
>> +			fputc('\\', fp);
>> +			fputc(' ', fp);
>> +		} else {
>> +			fputc(*p, fp);
>> +		}
>> +
>> +		p++;
>> +	}
>> +}
>> +
>>  char *xstrdup(const char *s)
>>  {
>>  	int len = strlen(s) + 1;
>> @@ -57,36 +60,54 @@ char *xstrndup(const char *s, size_t n)
>>  	return d;
>>  }
>>  
>> -/* based in part from (3) vsnprintf */
>> -int xasprintf(char **strp, const char *fmt, ...)
>> +int xavsprintf_append(char **strp, const char *fmt, va_list ap)
>>  {
>> -	int n, size = 128;	/* start with 128 bytes */
>> +	int n, size = 0;	/* start with 128 bytes */
>>  	char *p;
>> -	va_list ap;
>> +	va_list ap_copy;
>>  
>> -	/* initial pointer is NULL making the fist realloc to be malloc */
>> -	p = NULL;
>> -	while (1) {
>> -		p = xrealloc(p, size);
>> +	p = *strp;
>> +	if (p)
>> +		size = strlen(p);
>>  
>> -		/* Try to print in the allocated space. */
>> -		va_start(ap, fmt);
>> -		n = vsnprintf(p, size, fmt, ap);
>> -		va_end(ap);
>> +	va_copy(ap_copy, ap);
>> +	n = vsnprintf(NULL, 0, fmt, ap_copy) + 1;
>> +	va_end(ap_copy);
>> +
>> +	p = xrealloc(p, size + n);
>> +
>> +	n = vsnprintf(p + size, n, fmt, ap);
>>  
>> -		/* If that worked, return the string. */
>> -		if (n > -1 && n < size)
>> -			break;
>> -		/* Else try again with more space. */
>> -		if (n > -1)	/* glibc 2.1 */
>> -			size = n + 1; /* precisely what is needed */
>> -		else		/* glibc 2.0 */
>> -			size *= 2; /* twice the old size */
>> -	}
>>  	*strp = p;
>>  	return strlen(p);
>>  }
>>  
>> +int xasprintf_append(char **strp, const char *fmt, ...)
>> +{
>> +	int n;
>> +	va_list ap;
>> +
>> +	va_start(ap, fmt);
>> +	n = xavsprintf_append(strp, fmt, ap);
>> +	va_end(ap);
>> +
>> +	return n;
>> +}
>> +
>> +int xasprintf(char **strp, const char *fmt, ...)
>> +{
>> +	int n;
>> +	va_list ap;
>> +
>> +	*strp = NULL;
>> +
>> +	va_start(ap, fmt);
>> +	n = xavsprintf_append(strp, fmt, ap);
>> +	va_end(ap);
>> +
>> +	return n;
>> +}
>> +
>>  char *join_path(const char *path, const char *name)
>>  {
>>  	int lenp = strlen(path);
>> @@ -238,11 +259,11 @@ char get_escape_char(const char *s, int *i)
>>  	return val;
>>  }
>>  
>> -int utilfdt_read_err_len(const char *filename, char **buffp, off_t *len)
>> +int utilfdt_read_err(const char *filename, char **buffp, size_t *len)
>>  {
>>  	int fd = 0;	/* assume stdin */
>>  	char *buf = NULL;
>> -	off_t bufsize = 1024, offset = 0;
>> +	size_t bufsize = 1024, offset = 0;
>>  	int ret = 0;
>>  
>>  	*buffp = NULL;
>> @@ -275,20 +296,15 @@ int utilfdt_read_err_len(const char *filename, char **buffp, off_t *len)
>>  		free(buf);
>>  	else
>>  		*buffp = buf;
>> -	*len = bufsize;
>> +	if (len)
>> +		*len = bufsize;
>>  	return ret;
>>  }
>>  
>> -int utilfdt_read_err(const char *filename, char **buffp)
>> -{
>> -	off_t len;
>> -	return utilfdt_read_err_len(filename, buffp, &len);
>> -}
>> -
>> -char *utilfdt_read_len(const char *filename, off_t *len)
>> +char *utilfdt_read(const char *filename, size_t *len)
>>  {
>>  	char *buff;
>> -	int ret = utilfdt_read_err_len(filename, &buff, len);
>> +	int ret = utilfdt_read_err(filename, &buff, len);
>>  
>>  	if (ret) {
>>  		fprintf(stderr, "Couldn't open blob from '%s': %s\n", filename,
>> @@ -299,12 +315,6 @@ char *utilfdt_read_len(const char *filename, off_t *len)
>>  	return buff;
>>  }
>>  
>> -char *utilfdt_read(const char *filename)
>> -{
>> -	off_t len;
>> -	return utilfdt_read_len(filename, &len);
>> -}
>> -
>>  int utilfdt_write_err(const char *filename, const void *blob)
>>  {
>>  	int fd = 1;	/* assume stdout */
>> @@ -369,11 +379,11 @@ int utilfdt_decode_type(const char *fmt, int *type, int *size)
>>  	}
>>  
>>  	/* we should now have a type */
>> -	if ((*fmt == '\0') || !strchr("iuxs", *fmt))
>> +	if ((*fmt == '\0') || !strchr("iuxsr", *fmt))
>>  		return -1;
>>  
>>  	/* convert qualifier (bhL) to byte size */
>> -	if (*fmt != 's')
>> +	if (*fmt != 's' && *fmt != 'r')
>>  		*size = qualifier == 'b' ? 1 :
>>  				qualifier == 'h' ? 2 :
>>  				qualifier == 'l' ? 4 : -1;
>> @@ -410,7 +420,7 @@ void utilfdt_print_data(const char *data, int len)
>>  
>>  		printf(" = <");
>>  		for (i = 0, len /= 4; i < len; i++)
>> -			printf("0x%08x%s", fdt32_to_cpu(cell[i]),
>> +			printf("0x%08" PRIx32 "%s", fdt32_to_cpu(cell[i]),
>>  			       i < (len - 1) ? " " : "");
>>  		printf(">");
>>  	} else {
>> diff --git a/scripts/dtc/util.h b/scripts/dtc/util.h
>> index 23e32962385..2d63a9a9d8d 100644
>> --- a/scripts/dtc/util.h
>> +++ b/scripts/dtc/util.h
>> @@ -1,6 +1,8 @@
>> +/* SPDX-License-Identifier: GPL-2.0-or-later */
>>  #ifndef UTIL_H
>>  #define UTIL_H
>>  
>> +#include <stdlib.h>
>>  #include <stdarg.h>
>>  #include <stdbool.h>
>>  #include <getopt.h>
>> @@ -8,25 +10,16 @@
>>  /*
>>   * Copyright 2011 The Chromium Authors, All Rights Reserved.
>>   * Copyright 2008 Jon Loeliger, Freescale Semiconductor, Inc.
>> - *
>> - * This program 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 program 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 program; if not, write to the Free Software
>> - *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307
>> - *                                                                   USA
>>   */
>>  
>>  #ifdef __GNUC__
>> +#ifdef __MINGW_PRINTF_FORMAT
>> +#define PRINTF(i, j)	__attribute__((format (__MINGW_PRINTF_FORMAT, i, j)))
>> +#elif __GNUC__ >= 5 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 4)
>> +#define PRINTF(i, j)	__attribute__((format (gnu_printf, i, j)))
>> +#else
>>  #define PRINTF(i, j)	__attribute__((format (printf, i, j)))
>> +#endif
>>  #define NORETURN	__attribute__((noreturn))
>>  #else
>>  #define PRINTF(i, j)
>> @@ -49,6 +42,11 @@ static inline void NORETURN PRINTF(1, 2) die(const char *str, ...)
>>  	exit(1);
>>  }
>>  
>> +/**
>> + * Writes path to fp, escaping spaces with a backslash.
>> + */
>> +void fprint_path_escaped(FILE *fp, const char *path);
>> +
>>  static inline void *xmalloc(size_t len)
>>  {
>>  	void *new = malloc(len);
>> @@ -73,6 +71,8 @@ extern char *xstrdup(const char *s);
>>  extern char *xstrndup(const char *s, size_t len);
>>  
>>  extern int PRINTF(2, 3) xasprintf(char **strp, const char *fmt, ...);
>> +extern int PRINTF(2, 3) xasprintf_append(char **strp, const char *fmt, ...);
>> +extern int PRINTF(2, 0) xavsprintf_append(char **strp, const char *fmt, va_list ap);
>>  extern char *join_path(const char *path, const char *name);
>>  
>>  /**
>> @@ -99,16 +99,10 @@ char get_escape_char(const char *s, int *i);
>>   * stderr.
>>   *
>>   * @param filename	The filename to read, or - for stdin
>> - * Return: Pointer to allocated buffer containing fdt, or NULL on error
>> - */
>> -char *utilfdt_read(const char *filename);
>> -
>> -/**
>> - * Like utilfdt_read(), but also passes back the size of the file read.
>> - *
>>   * @param len		If non-NULL, the amount of data we managed to read
>> + * @return Pointer to allocated buffer containing fdt, or NULL on error
>>   */
>> -char *utilfdt_read_len(const char *filename, off_t *len);
>> +char *utilfdt_read(const char *filename, size_t *len);
>>  
>>  /**
>>   * Read a device tree file into a buffer. Does not report errors, but only
>> @@ -117,24 +111,18 @@ char *utilfdt_read_len(const char *filename, off_t *len);
>>   *
>>   * @param filename	The filename to read, or - for stdin
>>   * @param buffp		Returns pointer to buffer containing fdt
>> - * Return: 0 if ok, else an errno value representing the error
>> - */
>> -int utilfdt_read_err(const char *filename, char **buffp);
>> -
>> -/**
>> - * Like utilfdt_read_err(), but also passes back the size of the file read.
>> - *
>>   * @param len		If non-NULL, the amount of data we managed to read
>> + * @return 0 if ok, else an errno value representing the error
>>   */
>> -int utilfdt_read_err_len(const char *filename, char **buffp, off_t *len);
>> +int utilfdt_read_err(const char *filename, char **buffp, size_t *len);
>>  
>>  /**
>>   * Write a device tree buffer to a file. This will report any errors on
>>   * stderr.
>>   *
>>   * @param filename	The filename to write, or - for stdout
>> - * @param blob		Poiner to buffer containing fdt
>> - * Return: 0 if ok, -1 on error
>> + * @param blob		Pointer to buffer containing fdt
>> + * @return 0 if ok, -1 on error
>>   */
>>  int utilfdt_write(const char *filename, const void *blob);
>>  
>> @@ -144,8 +132,8 @@ int utilfdt_write(const char *filename, const void *blob);
>>   * an error message for the user.
>>   *
>>   * @param filename	The filename to write, or - for stdout
>> - * @param blob		Poiner to buffer containing fdt
>> - * Return: 0 if ok, else an errno value representing the error
>> + * @param blob		Pointer to buffer containing fdt
>> + * @return 0 if ok, else an errno value representing the error
>>   */
>>  int utilfdt_write_err(const char *filename, const void *blob);
>>  
>> @@ -163,6 +151,7 @@ int utilfdt_write_err(const char *filename, const void *blob);
>>   *		i	signed integer
>>   *		u	unsigned integer
>>   *		x	hex
>> + *		r	raw
>>   *
>>   * TODO: Implement ll modifier (8 bytes)
>>   * TODO: Implement o type (octal)
>> @@ -180,7 +169,7 @@ int utilfdt_decode_type(const char *fmt, int *type, int *size);
>>   */
>>  
>>  #define USAGE_TYPE_MSG \
>> -	"<type>\ts=string, i=int, u=unsigned, x=hex\n" \
>> +	"<type>\ts=string, i=int, u=unsigned, x=hex, r=raw\n" \
>>  	"\tOptional modifier prefix:\n" \
>>  	"\t\thh or b=byte, h=2 byte, l=4 byte (default)";
>>  
>> diff --git a/scripts/dtc/version_gen.h b/scripts/dtc/version_gen.h
>> index b00f14ff7a1..226c48bf75d 100644
>> --- a/scripts/dtc/version_gen.h
>> +++ b/scripts/dtc/version_gen.h
>> @@ -1 +1 @@
>> -#define DTC_VERSION "DTC 1.4.6-g84e414b0"
>> +#define DTC_VERSION "DTC 1.7.2-g52f07dcc"
>> diff --git a/scripts/dtc/yamltree.c b/scripts/dtc/yamltree.c
>> new file mode 100644
>> index 00000000000..55908c829c9
>> --- /dev/null
>> +++ b/scripts/dtc/yamltree.c
>> @@ -0,0 +1,235 @@
>> +// SPDX-License-Identifier: GPL-2.0-or-later
>> +/*
>> + * (C) Copyright Linaro, Ltd. 2018
>> + * (C) Copyright Arm Holdings.  2017
>> + * (C) Copyright David Gibson <dwg at au1.ibm.com>, IBM Corporation.  2005.
>> + */
>> +
>> +#include <stdlib.h>
>> +#include <yaml.h>
>> +#include "dtc.h"
>> +#include "srcpos.h"
>> +
>> +char *yaml_error_name[] = {
>> +	[YAML_NO_ERROR] = "no error",
>> +	[YAML_MEMORY_ERROR] = "memory error",
>> +	[YAML_READER_ERROR] = "reader error",
>> +	[YAML_SCANNER_ERROR] = "scanner error",
>> +	[YAML_PARSER_ERROR] = "parser error",
>> +	[YAML_COMPOSER_ERROR] = "composer error",
>> +	[YAML_WRITER_ERROR] = "writer error",
>> +	[YAML_EMITTER_ERROR] = "emitter error",
>> +};
>> +
>> +#define yaml_emitter_emit_or_die(emitter, event) (			\
>> +{									\
>> +	if (!yaml_emitter_emit(emitter, event))				\
>> +		die("yaml '%s': %s in %s, line %i\n",			\
>> +		    yaml_error_name[(emitter)->error], 			\
>> +		    (emitter)->problem, __func__, __LINE__);		\
>> +})
>> +
>> +static void yaml_propval_int(yaml_emitter_t *emitter, struct marker *markers,
>> +	char *data, unsigned int seq_offset, unsigned int len, int width)
>> +{
>> +	yaml_event_t event;
>> +	void *tag;
>> +	unsigned int off;
>> +
>> +	switch(width) {
>> +		case 1: tag = "!u8"; break;
>> +		case 2: tag = "!u16"; break;
>> +		case 4: tag = "!u32"; break;
>> +		case 8: tag = "!u64"; break;
>> +		default:
>> +			die("Invalid width %i", width);
>> +	}
>> +	assert(len % width == 0);
>> +
>> +	yaml_sequence_start_event_initialize(&event, NULL,
>> +		(yaml_char_t *)tag, width == 4, YAML_FLOW_SEQUENCE_STYLE);
>> +	yaml_emitter_emit_or_die(emitter, &event);
>> +
>> +	for (off = 0; off < len; off += width) {
>> +		char buf[32];
>> +		struct marker *m;
>> +		bool is_phandle = false;
>> +
>> +		switch(width) {
>> +		case 1:
>> +			sprintf(buf, "0x%"PRIx8, *(uint8_t*)(data + off));
>> +			break;
>> +		case 2:
>> +			sprintf(buf, "0x%"PRIx16, dtb_ld16(data + off));
>> +			break;
>> +		case 4:
>> +			sprintf(buf, "0x%"PRIx32, dtb_ld32(data + off));
>> +			m = markers;
>> +			is_phandle = false;
>> +			for_each_marker_of_type(m, REF_PHANDLE) {
>> +				if (m->offset == (seq_offset + off)) {
>> +					is_phandle = true;
>> +					break;
>> +				}
>> +			}
>> +			break;
>> +		case 8:
>> +			sprintf(buf, "0x%"PRIx64, dtb_ld64(data + off));
>> +			break;
>> +		}
>> +
>> +		if (is_phandle)
>> +			yaml_scalar_event_initialize(&event, NULL,
>> +				(yaml_char_t*)"!phandle", (yaml_char_t *)buf,
>> +				strlen(buf), 0, 0, YAML_PLAIN_SCALAR_STYLE);
>> +		else
>> +			yaml_scalar_event_initialize(&event, NULL,
>> +				(yaml_char_t*)YAML_INT_TAG, (yaml_char_t *)buf,
>> +				strlen(buf), 1, 1, YAML_PLAIN_SCALAR_STYLE);
>> +		yaml_emitter_emit_or_die(emitter, &event);
>> +	}
>> +
>> +	yaml_sequence_end_event_initialize(&event);
>> +	yaml_emitter_emit_or_die(emitter, &event);
>> +}
>> +
>> +static void yaml_propval_string(yaml_emitter_t *emitter, char *str, int len)
>> +{
>> +	yaml_event_t event;
>> +	int i;
>> +
>> +	assert(str[len-1] == '\0');
>> +
>> +	/* Make sure the entire string is in the lower 7-bit ascii range */
>> +	for (i = 0; i < len; i++)
>> +		assert(isascii(str[i]));
>> +
>> +	yaml_scalar_event_initialize(&event, NULL,
>> +		(yaml_char_t *)YAML_STR_TAG, (yaml_char_t*)str,
>> +		len-1, 0, 1, YAML_DOUBLE_QUOTED_SCALAR_STYLE);
>> +	yaml_emitter_emit_or_die(emitter, &event);
>> +}
>> +
>> +static void yaml_propval(yaml_emitter_t *emitter, struct property *prop)
>> +{
>> +	yaml_event_t event;
>> +	unsigned int len = prop->val.len;
>> +	struct marker *m = prop->val.markers;
>> +	struct marker *markers = prop->val.markers;
>> +
>> +	/* Emit the property name */
>> +	yaml_scalar_event_initialize(&event, NULL,
>> +		(yaml_char_t *)YAML_STR_TAG, (yaml_char_t*)prop->name,
>> +		strlen(prop->name), 1, 1, YAML_PLAIN_SCALAR_STYLE);
>> +	yaml_emitter_emit_or_die(emitter, &event);
>> +
>> +	/* Boolean properties are easiest to deal with. Length is zero, so just emit 'true' */
>> +	if (len == 0) {
>> +		yaml_scalar_event_initialize(&event, NULL,
>> +			(yaml_char_t *)YAML_BOOL_TAG,
>> +			(yaml_char_t*)"true",
>> +			strlen("true"), 1, 0, YAML_PLAIN_SCALAR_STYLE);
>> +		yaml_emitter_emit_or_die(emitter, &event);
>> +		return;
>> +	}
>> +
>> +	if (!m)
>> +		die("No markers present in property '%s' value\n", prop->name);
>> +
>> +	yaml_sequence_start_event_initialize(&event, NULL,
>> +		(yaml_char_t *)YAML_SEQ_TAG, 1, YAML_FLOW_SEQUENCE_STYLE);
>> +	yaml_emitter_emit_or_die(emitter, &event);
>> +
>> +	for_each_marker(m) {
>> +		int chunk_len;
>> +		char *data = &prop->val.val[m->offset];
>> +
>> +		if (m->type < TYPE_UINT8)
>> +			continue;
>> +
>> +		chunk_len = type_marker_length(m) ? : len;
>> +		assert(chunk_len > 0);
>> +		len -= chunk_len;
>> +
>> +		switch(m->type) {
>> +		case TYPE_UINT16:
>> +			yaml_propval_int(emitter, markers, data, m->offset, chunk_len, 2);
>> +			break;
>> +		case TYPE_UINT32:
>> +			yaml_propval_int(emitter, markers, data, m->offset, chunk_len, 4);
>> +			break;
>> +		case TYPE_UINT64:
>> +			yaml_propval_int(emitter, markers, data, m->offset, chunk_len, 8);
>> +			break;
>> +		case TYPE_STRING:
>> +			yaml_propval_string(emitter, data, chunk_len);
>> +			break;
>> +		default:
>> +			yaml_propval_int(emitter, markers, data, m->offset, chunk_len, 1);
>> +			break;
>> +		}
>> +	}
>> +
>> +	yaml_sequence_end_event_initialize(&event);
>> +	yaml_emitter_emit_or_die(emitter, &event);
>> +}
>> +
>> +
>> +static void yaml_tree(struct node *tree, yaml_emitter_t *emitter)
>> +{
>> +	struct property *prop;
>> +	struct node *child;
>> +	yaml_event_t event;
>> +
>> +	if (tree->deleted)
>> +		return;
>> +
>> +	yaml_mapping_start_event_initialize(&event, NULL,
>> +		(yaml_char_t *)YAML_MAP_TAG, 1, YAML_ANY_MAPPING_STYLE);
>> +	yaml_emitter_emit_or_die(emitter, &event);
>> +
>> +	for_each_property(tree, prop)
>> +		yaml_propval(emitter, prop);
>> +
>> +	/* Loop over all the children, emitting them into the map */
>> +	for_each_child(tree, child) {
>> +		yaml_scalar_event_initialize(&event, NULL,
>> +			(yaml_char_t *)YAML_STR_TAG, (yaml_char_t*)child->name,
>> +			strlen(child->name), 1, 0, YAML_PLAIN_SCALAR_STYLE);
>> +		yaml_emitter_emit_or_die(emitter, &event);
>> +		yaml_tree(child, emitter);
>> +	}
>> +
>> +	yaml_mapping_end_event_initialize(&event);
>> +	yaml_emitter_emit_or_die(emitter, &event);
>> +}
>> +
>> +void dt_to_yaml(FILE *f, struct dt_info *dti)
>> +{
>> +	yaml_emitter_t emitter;
>> +	yaml_event_t event;
>> +
>> +	yaml_emitter_initialize(&emitter);
>> +	yaml_emitter_set_output_file(&emitter, f);
>> +	yaml_stream_start_event_initialize(&event, YAML_UTF8_ENCODING);
>> +	yaml_emitter_emit_or_die(&emitter, &event);
>> +
>> +	yaml_document_start_event_initialize(&event, NULL, NULL, NULL, 0);
>> +	yaml_emitter_emit_or_die(&emitter, &event);
>> +
>> +	yaml_sequence_start_event_initialize(&event, NULL, (yaml_char_t *)YAML_SEQ_TAG, 1, YAML_ANY_SEQUENCE_STYLE);
>> +	yaml_emitter_emit_or_die(&emitter, &event);
>> +
>> +	yaml_tree(dti->dt, &emitter);
>> +
>> +	yaml_sequence_end_event_initialize(&event);
>> +	yaml_emitter_emit_or_die(&emitter, &event);
>> +
>> +	yaml_document_end_event_initialize(&event, 0);
>> +	yaml_emitter_emit_or_die(&emitter, &event);
>> +
>> +	yaml_stream_end_event_initialize(&event);
>> +	yaml_emitter_emit_or_die(&emitter, &event);
>> +
>> +	yaml_emitter_delete(&emitter);
>> +}
>> diff --git a/tools/libfdt/fdt_rw.c b/tools/libfdt/fdt_rw.c
>> index 7189f014295..95d47be2d8a 100644
>> --- a/tools/libfdt/fdt_rw.c
>> +++ b/tools/libfdt/fdt_rw.c
>> @@ -26,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, &allocated);
>> +		ret = fdt_find_add_string_(new, str, strlen(str), &allocated);
>>  		if (ret < 0)
>>  			return ret;
>>  		new_prop->nameoff = cpu_to_fdt32(ret);



More information about the U-Boot mailing list