[PATCH 1/2] scripts/dtc: Update to upstream version 1.4.6

Sascha Hauer s.hauer at pengutronix.de
Thu Jun 7 00:25:20 PDT 2018


On Tue, Jun 05, 2018 at 10:49:11PM +0000, Pascal Vizeli wrote:
> Signed-off-by: Pascal Vizeli <pvizeli at syshack.ch>
> ---

I still need some time to look at the overlay code, but for now applied
this one so we have this done already.

Sascha

>  scripts/dtc/.gitignore               |    1 -
>  scripts/dtc/Makefile                 |    8 +-
>  scripts/dtc/checks.c                 | 1194 +++++++++++++++++++++-----
>  scripts/dtc/data.c                   |   16 +-
>  scripts/dtc/dtc-lexer.l              |   63 +-
>  scripts/dtc/dtc-lexer.lex.c_shipped  |  894 +++++++++----------
>  scripts/dtc/dtc-parser.tab.c_shipped |  813 ++++++++++--------
>  scripts/dtc/dtc-parser.tab.h_shipped |   54 +-
>  scripts/dtc/dtc-parser.y             |   91 +-
>  scripts/dtc/dtc.c                    |  139 ++-
>  scripts/dtc/dtc.h                    |   62 +-
>  scripts/dtc/fdt.c                    |   24 +-
>  scripts/dtc/fdt.h                    |    6 +-
>  scripts/dtc/fdt_empty_tree.c         |    1 -
>  scripts/dtc/fdt_overlay.c            |  912 ++++++++++++++++++++
>  scripts/dtc/fdt_ro.c                 |  288 ++++++-
>  scripts/dtc/fdt_rw.c                 |  121 +--
>  scripts/dtc/fdt_strerror.c           |    6 +
>  scripts/dtc/fdt_sw.c                 |   40 +-
>  scripts/dtc/fdt_wip.c                |   43 +-
>  scripts/dtc/fdtdump.c                |  136 +--
>  scripts/dtc/fdtget.c                 |   60 +-
>  scripts/dtc/fdtput.c                 |  142 ++-
>  scripts/dtc/flattree.c               |  105 +--
>  scripts/dtc/fstree.c                 |    5 +-
>  scripts/dtc/libfdt.h                 |  429 +++++++--
>  scripts/dtc/libfdt_env.h             |   60 +-
>  scripts/dtc/libfdt_internal.h        |   32 +-
>  scripts/dtc/livetree.c               |  356 +++++++-
>  scripts/dtc/srcpos.c                 |   42 +-
>  scripts/dtc/srcpos.h                 |   18 +-
>  scripts/dtc/treesource.c             |   20 +-
>  scripts/dtc/update-dtc-source.sh     |   46 +-
>  scripts/dtc/util.c                   |   44 +-
>  scripts/dtc/util.h                   |   33 +-
>  scripts/dtc/version_gen.h            |    2 +-
>  36 files changed, 4578 insertions(+), 1728 deletions(-)
>  create mode 100644 scripts/dtc/fdt_overlay.c
> 
> diff --git a/scripts/dtc/.gitignore b/scripts/dtc/.gitignore
> index 80f6b50fd..cdabdc95a 100644
> --- a/scripts/dtc/.gitignore
> +++ b/scripts/dtc/.gitignore
> @@ -2,4 +2,3 @@ dtc
>  dtc-lexer.lex.c
>  dtc-parser.tab.c
>  dtc-parser.tab.h
> -fdtget
> diff --git a/scripts/dtc/Makefile b/scripts/dtc/Makefile
> index 05973b12a..06aaa8c55 100644
> --- a/scripts/dtc/Makefile
> +++ b/scripts/dtc/Makefile
> @@ -1,17 +1,15 @@
>  # scripts/dtc makefile
>  
> -hostprogs-y	:= dtc fdtget
> +hostprogs-y	:= dtc
>  always		:= $(hostprogs-y)
>  
>  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
>  
> -libfdt-objs	= fdt.o fdt_ro.o fdt_strerror.o fdt_wip.o
> +libfdt-objs	= fdt.o fdt_ro.o fdt_strerror.o fdt_wip.o fdt_overlay.o
>  libfdt-objs	+= fdt_empty_tree.o fdt_rw.o fdt_sw.o
>  
> -fdtget-objs	+= fdtget.o $(libfdt-objs) util.o
> -
>  # Source files need to get at the userspace version of libfdt_env.h to compile
>  
>  HOSTCFLAGS_DTC := -I$(src)
> @@ -33,7 +31,7 @@ HOSTCFLAGS_fdt_wip.o := $(HOSTCFLAGS_DTC)
>  HOSTCFLAGS_fdt_empty_tree.o := $(HOSTCFLAGS_DTC)
>  HOSTCFLAGS_fdt_rw.o := $(HOSTCFLAGS_DTC)
>  HOSTCFLAGS_fdt_sw.o := $(HOSTCFLAGS_DTC)
> -HOSTCFLAGS_fdtget.o := $(HOSTCFLAGS_DTC)
> +HOSTCFLAGS_fdt_overlay.o := $(HOSTCFLAGS_DTC)
>  
>  HOSTCFLAGS_dtc-lexer.lex.o := $(HOSTCFLAGS_DTC)
>  HOSTCFLAGS_dtc-parser.tab.o := $(HOSTCFLAGS_DTC)
> diff --git a/scripts/dtc/checks.c b/scripts/dtc/checks.c
> index 3bf0fa4a4..815eaf140 100644
> --- a/scripts/dtc/checks.c
> +++ b/scripts/dtc/checks.c
> @@ -40,16 +40,11 @@ enum checkstatus {
>  
>  struct check;
>  
> -typedef void (*tree_check_fn)(struct check *c, struct node *dt);
> -typedef void (*node_check_fn)(struct check *c, struct node *dt, struct node *node);
> -typedef void (*prop_check_fn)(struct check *c, struct node *dt,
> -			      struct node *node, struct property *prop);
> +typedef void (*check_fn)(struct check *c, struct dt_info *dti, struct node *node);
>  
>  struct check {
>  	const char *name;
> -	tree_check_fn tree_fn;
> -	node_check_fn node_fn;
> -	prop_check_fn prop_fn;
> +	check_fn fn;
>  	void *data;
>  	bool warn, error;
>  	enum checkstatus status;
> @@ -58,91 +53,80 @@ struct check {
>  	struct check **prereq;
>  };
>  
> -#define CHECK_ENTRY(nm, tfn, nfn, pfn, d, w, e, ...)	       \
> -	static struct check *nm##_prereqs[] = { __VA_ARGS__ }; \
> -	static struct check nm = { \
> -		.name = #nm, \
> -		.tree_fn = (tfn), \
> -		.node_fn = (nfn), \
> -		.prop_fn = (pfn), \
> -		.data = (d), \
> -		.warn = (w), \
> -		.error = (e), \
> +#define CHECK_ENTRY(nm_, fn_, d_, w_, e_, ...)	       \
> +	static struct check *nm_##_prereqs[] = { __VA_ARGS__ }; \
> +	static struct check nm_ = { \
> +		.name = #nm_, \
> +		.fn = (fn_), \
> +		.data = (d_), \
> +		.warn = (w_), \
> +		.error = (e_), \
>  		.status = UNCHECKED, \
> -		.num_prereqs = ARRAY_SIZE(nm##_prereqs), \
> -		.prereq = nm##_prereqs, \
> +		.num_prereqs = ARRAY_SIZE(nm_##_prereqs), \
> +		.prereq = nm_##_prereqs, \
>  	};
> -#define WARNING(nm, tfn, nfn, pfn, d, ...) \
> -	CHECK_ENTRY(nm, tfn, nfn, pfn, d, true, false, __VA_ARGS__)
> -#define ERROR(nm, tfn, nfn, pfn, d, ...) \
> -	CHECK_ENTRY(nm, tfn, nfn, pfn, d, false, true, __VA_ARGS__)
> -#define CHECK(nm, tfn, nfn, pfn, d, ...) \
> -	CHECK_ENTRY(nm, tfn, nfn, pfn, d, false, false, __VA_ARGS__)
> -
> -#define TREE_WARNING(nm, d, ...) \
> -	WARNING(nm, check_##nm, NULL, NULL, d, __VA_ARGS__)
> -#define TREE_ERROR(nm, d, ...) \
> -	ERROR(nm, check_##nm, NULL, NULL, d, __VA_ARGS__)
> -#define TREE_CHECK(nm, d, ...) \
> -	CHECK(nm, check_##nm, NULL, NULL, d, __VA_ARGS__)
> -#define NODE_WARNING(nm, d, ...) \
> -	WARNING(nm, NULL, check_##nm, NULL, d,  __VA_ARGS__)
> -#define NODE_ERROR(nm, d, ...) \
> -	ERROR(nm, NULL, check_##nm, NULL, d, __VA_ARGS__)
> -#define NODE_CHECK(nm, d, ...) \
> -	CHECK(nm, NULL, check_##nm, NULL, d, __VA_ARGS__)
> -#define PROP_WARNING(nm, d, ...) \
> -	WARNING(nm, NULL, NULL, check_##nm, d, __VA_ARGS__)
> -#define PROP_ERROR(nm, d, ...) \
> -	ERROR(nm, NULL, NULL, check_##nm, d, __VA_ARGS__)
> -#define PROP_CHECK(nm, d, ...) \
> -	CHECK(nm, NULL, NULL, check_##nm, d, __VA_ARGS__)
> -
> -#ifdef __GNUC__
> -static inline void check_msg(struct check *c, const char *fmt, ...) __attribute__((format (printf, 2, 3)));
> -#endif
> -static inline void check_msg(struct check *c, const char *fmt, ...)
> +#define WARNING(nm_, fn_, d_, ...) \
> +	CHECK_ENTRY(nm_, fn_, d_, true, false, __VA_ARGS__)
> +#define ERROR(nm_, fn_, d_, ...) \
> +	CHECK_ENTRY(nm_, fn_, d_, false, true, __VA_ARGS__)
> +#define CHECK(nm_, fn_, d_, ...) \
> +	CHECK_ENTRY(nm_, fn_, d_, false, false, __VA_ARGS__)
> +
> +static inline void  PRINTF(5, 6) check_msg(struct check *c, struct dt_info *dti,
> +					   struct node *node,
> +					   struct property *prop,
> +					   const char *fmt, ...)
>  {
>  	va_list ap;
>  	va_start(ap, fmt);
>  
>  	if ((c->warn && (quiet < 1))
>  	    || (c->error && (quiet < 2))) {
> -		fprintf(stderr, "%s (%s): ",
> +		fprintf(stderr, "%s: %s (%s): ",
> +			strcmp(dti->outname, "-") ? dti->outname : "<stdout>",
>  			(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");
>  	}
> +	va_end(ap);
>  }
>  
> -#define FAIL(c, ...) \
> -	do { \
> -		TRACE((c), "\t\tFAILED at %s:%d", __FILE__, __LINE__); \
> -		(c)->status = FAILED; \
> -		check_msg((c), __VA_ARGS__); \
> +#define FAIL(c, dti, node, ...)						\
> +	do {								\
> +		TRACE((c), "\t\tFAILED at %s:%d", __FILE__, __LINE__);	\
> +		(c)->status = FAILED;					\
> +		check_msg((c), dti, node, NULL, __VA_ARGS__);		\
>  	} while (0)
>  
> -static void check_nodes_props(struct check *c, struct node *dt, struct node *node)
> +#define FAIL_PROP(c, dti, node, prop, ...)				\
> +	do {								\
> +		TRACE((c), "\t\tFAILED at %s:%d", __FILE__, __LINE__);	\
> +		(c)->status = FAILED;					\
> +		check_msg((c), dti, node, prop, __VA_ARGS__);		\
> +	} while (0)
> +
> +
> +static void check_nodes_props(struct check *c, struct dt_info *dti, struct node *node)
>  {
>  	struct node *child;
> -	struct property *prop;
>  
>  	TRACE(c, "%s", node->fullpath);
> -	if (c->node_fn)
> -		c->node_fn(c, dt, node);
> -
> -	if (c->prop_fn)
> -		for_each_property(node, prop) {
> -			TRACE(c, "%s\t'%s'", node->fullpath, prop->name);
> -			c->prop_fn(c, dt, node, prop);
> -		}
> +	if (c->fn)
> +		c->fn(c, dti, node);
>  
>  	for_each_child(node, child)
> -		check_nodes_props(c, dt, child);
> +		check_nodes_props(c, dti, child);
>  }
>  
> -static bool run_check(struct check *c, struct node *dt)
> +static bool run_check(struct check *c, struct dt_info *dti)
>  {
> +	struct node *dt = dti->dt;
>  	bool error = false;
>  	int i;
>  
> @@ -155,10 +139,10 @@ static bool run_check(struct check *c, struct node *dt)
>  
>  	for (i = 0; i < c->num_prereqs; i++) {
>  		struct check *prq = c->prereq[i];
> -		error = error || run_check(prq, dt);
> +		error = error || run_check(prq, dti);
>  		if (prq->status != PASSED) {
>  			c->status = PREREQ;
> -			check_msg(c, "Failed prerequisite '%s'",
> +			check_msg(c, dti, NULL, NULL, "Failed prerequisite '%s'",
>  				  c->prereq[i]->name);
>  		}
>  	}
> @@ -166,11 +150,8 @@ static bool run_check(struct check *c, struct node *dt)
>  	if (c->status != UNCHECKED)
>  		goto out;
>  
> -	if (c->node_fn || c->prop_fn)
> -		check_nodes_props(c, dt, dt);
> +	check_nodes_props(c, dti, dt);
>  
> -	if (c->tree_fn)
> -		c->tree_fn(c, dt);
>  	if (c->status == UNCHECKED)
>  		c->status = PASSED;
>  
> @@ -188,13 +169,14 @@ out:
>   */
>  
>  /* A check which always fails, for testing purposes only */
> -static inline void check_always_fail(struct check *c, struct node *dt)
> +static inline void check_always_fail(struct check *c, struct dt_info *dti,
> +				     struct node *node)
>  {
> -	FAIL(c, "always_fail check");
> +	FAIL(c, dti, node, "always_fail check");
>  }
> -TREE_CHECK(always_fail, NULL);
> +CHECK(always_fail, check_always_fail, NULL);
>  
> -static void check_is_string(struct check *c, struct node *root,
> +static void check_is_string(struct check *c, struct dt_info *dti,
>  			    struct node *node)
>  {
>  	struct property *prop;
> @@ -205,15 +187,43 @@ static void check_is_string(struct check *c, struct node *root,
>  		return; /* Not present, assumed ok */
>  
>  	if (!data_is_one_string(prop->val))
> -		FAIL(c, "\"%s\" property in %s is not a string",
> -		     propname, node->fullpath);
> +		FAIL_PROP(c, dti, node, prop, "property is not a string");
>  }
>  #define WARNING_IF_NOT_STRING(nm, propname) \
> -	WARNING(nm, NULL, check_is_string, NULL, (propname))
> +	WARNING(nm, check_is_string, (propname))
>  #define ERROR_IF_NOT_STRING(nm, propname) \
> -	ERROR(nm, NULL, check_is_string, NULL, (propname))
> +	ERROR(nm, check_is_string, (propname))
> +
> +static void check_is_string_list(struct check *c, struct dt_info *dti,
> +				 struct node *node)
> +{
> +	int rem, l;
> +	struct property *prop;
> +	char *propname = c->data;
> +	char *str;
> +
> +	prop = get_property(node, propname);
> +	if (!prop)
> +		return; /* Not present, assumed ok */
> +
> +	str = prop->val.val;
> +	rem = prop->val.len;
> +	while (rem > 0) {
> +		l = strnlen(str, rem);
> +		if (l == rem) {
> +			FAIL_PROP(c, dti, node, prop, "property is not a string list");
> +			break;
> +		}
> +		rem -= l + 1;
> +		str += l + 1;
> +	}
> +}
> +#define WARNING_IF_NOT_STRING_LIST(nm, propname) \
> +	WARNING(nm, check_is_string_list, (propname))
> +#define ERROR_IF_NOT_STRING_LIST(nm, propname) \
> +	ERROR(nm, check_is_string_list, (propname))
>  
> -static void check_is_cell(struct check *c, struct node *root,
> +static void check_is_cell(struct check *c, struct dt_info *dti,
>  			  struct node *node)
>  {
>  	struct property *prop;
> @@ -224,19 +234,18 @@ static void check_is_cell(struct check *c, struct node *root,
>  		return; /* Not present, assumed ok */
>  
>  	if (prop->val.len != sizeof(cell_t))
> -		FAIL(c, "\"%s\" property in %s is not a single cell",
> -		     propname, node->fullpath);
> +		FAIL_PROP(c, dti, node, prop, "property is not a single cell");
>  }
>  #define WARNING_IF_NOT_CELL(nm, propname) \
> -	WARNING(nm, NULL, check_is_cell, NULL, (propname))
> +	WARNING(nm, check_is_cell, (propname))
>  #define ERROR_IF_NOT_CELL(nm, propname) \
> -	ERROR(nm, NULL, check_is_cell, NULL, (propname))
> +	ERROR(nm, check_is_cell, (propname))
>  
>  /*
>   * Structural check functions
>   */
>  
> -static void check_duplicate_node_names(struct check *c, struct node *dt,
> +static void check_duplicate_node_names(struct check *c, struct dt_info *dti,
>  				       struct node *node)
>  {
>  	struct node *child, *child2;
> @@ -246,12 +255,11 @@ static void check_duplicate_node_names(struct check *c, struct node *dt,
>  		     child2;
>  		     child2 = child2->next_sibling)
>  			if (streq(child->name, child2->name))
> -				FAIL(c, "Duplicate node name %s",
> -				     child->fullpath);
> +				FAIL(c, dti, node, "Duplicate node name");
>  }
> -NODE_ERROR(duplicate_node_names, NULL);
> +ERROR(duplicate_node_names, check_duplicate_node_names, NULL);
>  
> -static void check_duplicate_property_names(struct check *c, struct node *dt,
> +static void check_duplicate_property_names(struct check *c, struct dt_info *dti,
>  					   struct node *node)
>  {
>  	struct property *prop, *prop2;
> @@ -261,48 +269,116 @@ static void check_duplicate_property_names(struct check *c, struct node *dt,
>  			if (prop2->deleted)
>  				continue;
>  			if (streq(prop->name, prop2->name))
> -				FAIL(c, "Duplicate property name %s in %s",
> -				     prop->name, node->fullpath);
> +				FAIL_PROP(c, dti, node, prop, "Duplicate property name");
>  		}
>  	}
>  }
> -NODE_ERROR(duplicate_property_names, NULL);
> +ERROR(duplicate_property_names, check_duplicate_property_names, NULL);
>  
>  #define LOWERCASE	"abcdefghijklmnopqrstuvwxyz"
>  #define UPPERCASE	"ABCDEFGHIJKLMNOPQRSTUVWXYZ"
>  #define DIGITS		"0123456789"
>  #define PROPNODECHARS	LOWERCASE UPPERCASE DIGITS ",._+*#?-"
> +#define PROPNODECHARSSTRICT	LOWERCASE UPPERCASE DIGITS ",-"
>  
> -static void check_node_name_chars(struct check *c, struct node *dt,
> +static void check_node_name_chars(struct check *c, struct dt_info *dti,
>  				  struct node *node)
>  {
>  	int n = strspn(node->name, c->data);
>  
>  	if (n < strlen(node->name))
> -		FAIL(c, "Bad character '%c' in node %s",
> -		     node->name[n], node->fullpath);
> +		FAIL(c, dti, node, "Bad character '%c' in node name",
> +		     node->name[n]);
>  }
> -NODE_ERROR(node_name_chars, PROPNODECHARS "@");
> +ERROR(node_name_chars, check_node_name_chars, PROPNODECHARS "@");
>  
> -static void check_node_name_format(struct check *c, struct node *dt,
> +static void check_node_name_chars_strict(struct check *c, struct dt_info *dti,
> +					 struct node *node)
> +{
> +	int n = strspn(node->name, c->data);
> +
> +	if (n < node->basenamelen)
> +		FAIL(c, dti, node, "Character '%c' not recommended in node name",
> +		     node->name[n]);
> +}
> +CHECK(node_name_chars_strict, check_node_name_chars_strict, PROPNODECHARSSTRICT);
> +
> +static void check_node_name_format(struct check *c, struct dt_info *dti,
>  				   struct node *node)
>  {
>  	if (strchr(get_unitname(node), '@'))
> -		FAIL(c, "Node %s has multiple '@' characters in name",
> -		     node->fullpath);
> +		FAIL(c, dti, node, "multiple '@' characters in node name");
> +}
> +ERROR(node_name_format, check_node_name_format, NULL, &node_name_chars);
> +
> +static void check_unit_address_vs_reg(struct check *c, struct dt_info *dti,
> +				      struct node *node)
> +{
> +	const char *unitname = get_unitname(node);
> +	struct property *prop = get_property(node, "reg");
> +
> +	if (!prop) {
> +		prop = get_property(node, "ranges");
> +		if (prop && !prop->val.len)
> +			prop = NULL;
> +	}
> +
> +	if (prop) {
> +		if (!unitname[0])
> +			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");
> +	}
> +}
> +WARNING(unit_address_vs_reg, check_unit_address_vs_reg, NULL);
> +
> +static void check_property_name_chars(struct check *c, struct dt_info *dti,
> +				      struct node *node)
> +{
> +	struct property *prop;
> +
> +	for_each_property(node, prop) {
> +		int 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]);
> +	}
>  }
> -NODE_ERROR(node_name_format, NULL, &node_name_chars);
> +ERROR(property_name_chars, check_property_name_chars, PROPNODECHARS);
>  
> -static void check_property_name_chars(struct check *c, struct node *dt,
> -				      struct node *node, struct property *prop)
> +static void check_property_name_chars_strict(struct check *c,
> +					     struct dt_info *dti,
> +					     struct node *node)
>  {
> -	int n = strspn(prop->name, c->data);
> +	struct property *prop;
> +
> +	for_each_property(node, prop) {
> +		const char *name = prop->name;
> +		int n = strspn(name, c->data);
>  
> -	if (n < strlen(prop->name))
> -		FAIL(c, "Bad character '%c' in property name \"%s\", node %s",
> -		     prop->name[n], prop->name, node->fullpath);
> +		if (n == strlen(prop->name))
> +			continue;
> +
> +		/* Certain names are whitelisted */
> +		if (streq(name, "device_type"))
> +			continue;
> +
> +		/*
> +		 * # is only allowed at the beginning of property names not counting
> +		 * the vendor prefix.
> +		 */
> +		if (name[n] == '#' && ((n == 0) || (name[n-1] == ','))) {
> +			name += n + 1;
> +			n = strspn(name, c->data);
> +		}
> +		if (n < strlen(name))
> +			FAIL_PROP(c, dti, node, prop, "Character '%c' not recommended in property name",
> +				  name[n]);
> +	}
>  }
> -PROP_ERROR(property_name_chars, PROPNODECHARS);
> +CHECK(property_name_chars_strict, check_property_name_chars_strict, PROPNODECHARSSTRICT);
>  
>  #define DESCLABEL_FMT	"%s%s%s%s%s"
>  #define DESCLABEL_ARGS(node,prop,mark)		\
> @@ -311,10 +387,11 @@ PROP_ERROR(property_name_chars, PROPNODECHARS);
>  	((prop) ? (prop)->name : ""), \
>  	((prop) ? "' in " : ""), (node)->fullpath
>  
> -static void check_duplicate_label(struct check *c, struct node *dt,
> +static void check_duplicate_label(struct check *c, struct dt_info *dti,
>  				  const char *label, struct node *node,
>  				  struct property *prop, struct marker *mark)
>  {
> +	struct node *dt = dti->dt;
>  	struct node *othernode = NULL;
>  	struct property *otherprop = NULL;
>  	struct marker *othermark = NULL;
> @@ -331,50 +408,49 @@ static void check_duplicate_label(struct check *c, struct node *dt,
>  		return;
>  
>  	if ((othernode != node) || (otherprop != prop) || (othermark != mark))
> -		FAIL(c, "Duplicate label '%s' on " DESCLABEL_FMT
> +		FAIL(c, dti, node, "Duplicate label '%s' on " DESCLABEL_FMT
>  		     " and " DESCLABEL_FMT,
>  		     label, DESCLABEL_ARGS(node, prop, mark),
>  		     DESCLABEL_ARGS(othernode, otherprop, othermark));
>  }
>  
> -static void check_duplicate_label_node(struct check *c, struct node *dt,
> +static void check_duplicate_label_node(struct check *c, struct dt_info *dti,
>  				       struct node *node)
>  {
>  	struct label *l;
> +	struct property *prop;
>  
>  	for_each_label(node->labels, l)
> -		check_duplicate_label(c, dt, l->label, node, NULL, NULL);
> -}
> -static void check_duplicate_label_prop(struct check *c, struct node *dt,
> -				       struct node *node, struct property *prop)
> -{
> -	struct marker *m = prop->val.markers;
> -	struct label *l;
> +		check_duplicate_label(c, dti, l->label, node, NULL, NULL);
> +
> +	for_each_property(node, prop) {
> +		struct marker *m = prop->val.markers;
>  
> -	for_each_label(prop->labels, l)
> -		check_duplicate_label(c, dt, l->label, node, prop, NULL);
> +		for_each_label(prop->labels, l)
> +			check_duplicate_label(c, dti, l->label, node, prop, NULL);
>  
> -	for_each_marker_of_type(m, LABEL)
> -		check_duplicate_label(c, dt, m->ref, node, prop, m);
> +		for_each_marker_of_type(m, LABEL)
> +			check_duplicate_label(c, dti, m->ref, node, prop, m);
> +	}
>  }
> -ERROR(duplicate_label, NULL, check_duplicate_label_node,
> -      check_duplicate_label_prop, NULL);
> +ERROR(duplicate_label, check_duplicate_label_node, NULL);
>  
> -static void check_explicit_phandles(struct check *c, struct node *root,
> -				    struct node *node, struct property *prop)
> +static cell_t check_phandle_prop(struct check *c, struct dt_info *dti,
> +				 struct node *node, const char *propname)
>  {
> +	struct node *root = dti->dt;
> +	struct property *prop;
>  	struct marker *m;
> -	struct node *other;
>  	cell_t phandle;
>  
> -	if (!streq(prop->name, "phandle")
> -	    && !streq(prop->name, "linux,phandle"))
> -		return;
> +	prop = get_property(node, propname);
> +	if (!prop)
> +		return 0;
>  
>  	if (prop->val.len != sizeof(cell_t)) {
> -		FAIL(c, "%s has bad length (%d) %s property",
> -		     node->fullpath, prop->val.len, prop->name);
> -		return;
> +		FAIL_PROP(c, dti, node, prop, "bad length (%d) %s property",
> +			  prop->val.len, prop->name);
> +		return 0;
>  	}
>  
>  	m = prop->val.markers;
> @@ -384,42 +460,65 @@ static void check_explicit_phandles(struct check *c, struct node *root,
>  			/* "Set this node's phandle equal to some
>  			 * other node's phandle".  That's nonsensical
>  			 * by construction. */ {
> -			FAIL(c, "%s in %s is a reference to another node",
> -			     prop->name, node->fullpath);
> -			return;
> +			FAIL(c, dti, node, "%s is a reference to another node",
> +			     prop->name);
>  		}
>  		/* But setting this node's phandle equal to its own
>  		 * phandle is allowed - that means allocate a unique
>  		 * phandle for this node, even if it's not otherwise
>  		 * referenced.  The value will be filled in later, so
> -		 * no further checking for now. */
> -		return;
> +		 * we treat it as having no phandle data for now. */
> +		return 0;
>  	}
>  
>  	phandle = propval_cell(prop);
>  
>  	if ((phandle == 0) || (phandle == -1)) {
> -		FAIL(c, "%s has bad value (0x%x) in %s property",
> -		     node->fullpath, phandle, prop->name);
> -		return;
> +		FAIL_PROP(c, dti, node, prop, "bad value (0x%x) in %s property",
> +		     phandle, prop->name);
> +		return 0;
>  	}
>  
> -	if (node->phandle && (node->phandle != phandle))
> -		FAIL(c, "%s has %s property which replaces existing phandle information",
> -		     node->fullpath, prop->name);
> +	return phandle;
> +}
> +
> +static void check_explicit_phandles(struct check *c, struct dt_info *dti,
> +				    struct node *node)
> +{
> +	struct node *root = dti->dt;
> +	struct node *other;
> +	cell_t phandle, linux_phandle;
> +
> +	/* Nothing should have assigned phandles yet */
> +	assert(!node->phandle);
> +
> +	phandle = check_phandle_prop(c, dti, node, "phandle");
> +
> +	linux_phandle = check_phandle_prop(c, dti, node, "linux,phandle");
> +
> +	if (!phandle && !linux_phandle)
> +		/* No valid phandles; nothing further to check */
> +		return;
> +
> +	if (linux_phandle && phandle && (phandle != linux_phandle))
> +		FAIL(c, dti, node, "mismatching 'phandle' and 'linux,phandle'"
> +		     " properties");
> +
> +	if (linux_phandle && !phandle)
> +		phandle = linux_phandle;
>  
>  	other = get_node_by_phandle(root, phandle);
>  	if (other && (other != node)) {
> -		FAIL(c, "%s has duplicated phandle 0x%x (seen before at %s)",
> -		     node->fullpath, phandle, other->fullpath);
> +		FAIL(c, dti, node, "duplicated phandle 0x%x (seen before at %s)",
> +		     phandle, other->fullpath);
>  		return;
>  	}
>  
>  	node->phandle = phandle;
>  }
> -PROP_ERROR(explicit_phandles, NULL);
> +ERROR(explicit_phandles, check_explicit_phandles, NULL);
>  
> -static void check_name_properties(struct check *c, struct node *root,
> +static void check_name_properties(struct check *c, struct dt_info *dti,
>  				  struct node *node)
>  {
>  	struct property **pp, *prop = NULL;
> @@ -435,8 +534,8 @@ static void check_name_properties(struct check *c, struct node *root,
>  
>  	if ((prop->val.len != node->basenamelen+1)
>  	    || (memcmp(prop->val.val, node->name, node->basenamelen) != 0)) {
> -		FAIL(c, "\"name\" property in %s is incorrect (\"%s\" instead"
> -		     " of base node name)", node->fullpath, prop->val.val);
> +		FAIL(c, dti, node, "\"name\" property is incorrect (\"%s\" instead"
> +		     " of base node name)", prop->val.val);
>  	} else {
>  		/* The name property is correct, and therefore redundant.
>  		 * Delete it */
> @@ -447,60 +546,73 @@ static void check_name_properties(struct check *c, struct node *root,
>  	}
>  }
>  ERROR_IF_NOT_STRING(name_is_string, "name");
> -NODE_ERROR(name_properties, NULL, &name_is_string);
> +ERROR(name_properties, check_name_properties, NULL, &name_is_string);
>  
>  /*
>   * Reference fixup functions
>   */
>  
> -static void fixup_phandle_references(struct check *c, struct node *dt,
> -				     struct node *node, struct property *prop)
> +static void fixup_phandle_references(struct check *c, struct dt_info *dti,
> +				     struct node *node)
>  {
> -	struct marker *m = prop->val.markers;
> -	struct node *refnode;
> -	cell_t phandle;
> +	struct node *dt = dti->dt;
> +	struct property *prop;
>  
> -	for_each_marker_of_type(m, REF_PHANDLE) {
> -		assert(m->offset + sizeof(cell_t) <= prop->val.len);
> +	for_each_property(node, prop) {
> +		struct marker *m = prop->val.markers;
> +		struct node *refnode;
> +		cell_t phandle;
> +
> +		for_each_marker_of_type(m, REF_PHANDLE) {
> +			assert(m->offset + sizeof(cell_t) <= prop->val.len);
> +
> +			refnode = get_node_by_ref(dt, m->ref);
> +			if (! refnode) {
> +				if (!(dti->dtsflags & DTSF_PLUGIN))
> +					FAIL(c, dti, node, "Reference to non-existent node or "
> +							"label \"%s\"\n", m->ref);
> +				else /* mark the entry as unresolved */
> +					*((fdt32_t *)(prop->val.val + m->offset)) =
> +						cpu_to_fdt32(0xffffffff);
> +				continue;
> +			}
>  
> -		refnode = get_node_by_ref(dt, m->ref);
> -		if (! refnode) {
> -			FAIL(c, "Reference to non-existent node or label \"%s\"\n",
> -			     m->ref);
> -			continue;
> +			phandle = get_node_phandle(dt, refnode);
> +			*((fdt32_t *)(prop->val.val + m->offset)) = cpu_to_fdt32(phandle);
>  		}
> -
> -		phandle = get_node_phandle(dt, refnode);
> -		*((cell_t *)(prop->val.val + m->offset)) = cpu_to_fdt32(phandle);
>  	}
>  }
> -ERROR(phandle_references, NULL, NULL, fixup_phandle_references, NULL,
> +ERROR(phandle_references, fixup_phandle_references, NULL,
>        &duplicate_node_names, &explicit_phandles);
>  
> -static void fixup_path_references(struct check *c, struct node *dt,
> -				  struct node *node, struct property *prop)
> +static void fixup_path_references(struct check *c, struct dt_info *dti,
> +				  struct node *node)
>  {
> -	struct marker *m = prop->val.markers;
> -	struct node *refnode;
> -	char *path;
> +	struct node *dt = dti->dt;
> +	struct property *prop;
>  
> -	for_each_marker_of_type(m, REF_PATH) {
> -		assert(m->offset <= prop->val.len);
> +	for_each_property(node, prop) {
> +		struct marker *m = prop->val.markers;
> +		struct node *refnode;
> +		char *path;
>  
> -		refnode = get_node_by_ref(dt, m->ref);
> -		if (!refnode) {
> -			FAIL(c, "Reference to non-existent node or label \"%s\"\n",
> -			     m->ref);
> -			continue;
> -		}
> +		for_each_marker_of_type(m, REF_PATH) {
> +			assert(m->offset <= prop->val.len);
>  
> -		path = refnode->fullpath;
> -		prop->val = data_insert_at_marker(prop->val, m, path,
> -						  strlen(path) + 1);
> +			refnode = get_node_by_ref(dt, m->ref);
> +			if (!refnode) {
> +				FAIL(c, dti, node, "Reference to non-existent node or label \"%s\"\n",
> +				     m->ref);
> +				continue;
> +			}
> +
> +			path = refnode->fullpath;
> +			prop->val = data_insert_at_marker(prop->val, m, path,
> +							  strlen(path) + 1);
> +		}
>  	}
>  }
> -ERROR(path_references, NULL, NULL, fixup_path_references, NULL,
> -      &duplicate_node_names);
> +ERROR(path_references, fixup_path_references, NULL, &duplicate_node_names);
>  
>  /*
>   * Semantic checks
> @@ -512,8 +624,47 @@ 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");
>  WARNING_IF_NOT_STRING(status_is_string, "status");
> +WARNING_IF_NOT_STRING(label_is_string, "label");
> +
> +WARNING_IF_NOT_STRING_LIST(compatible_is_string_list, "compatible");
> +
> +static void check_names_is_string_list(struct check *c, struct dt_info *dti,
> +				       struct node *node)
> +{
> +	struct property *prop;
> +
> +	for_each_property(node, prop) {
> +		const char *s = strrchr(prop->name, '-');
> +		if (!s || !streq(s, "-names"))
> +			continue;
> +
> +		c->data = prop->name;
> +		check_is_string_list(c, dti, node);
> +	}
> +}
> +WARNING(names_is_string_list, check_names_is_string_list, NULL);
> +
> +static void check_alias_paths(struct check *c, struct dt_info *dti,
> +				    struct node *node)
> +{
> +	struct property *prop;
>  
> -static void fixup_addr_size_cells(struct check *c, struct node *dt,
> +	if (!streq(node->name, "aliases"))
> +		return;
> +
> +	for_each_property(node, prop) {
> +		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);
> +			continue;
> +		}
> +		if (strspn(prop->name, LOWERCASE DIGITS "-") != strlen(prop->name))
> +			FAIL(c, dti, node, "aliases property name must include only lowercase and '-'");
> +	}
> +}
> +WARNING(alias_paths, check_alias_paths, NULL);
> +
> +static void fixup_addr_size_cells(struct check *c, struct dt_info *dti,
>  				  struct node *node)
>  {
>  	struct property *prop;
> @@ -529,7 +680,7 @@ static void fixup_addr_size_cells(struct check *c, struct node *dt,
>  	if (prop)
>  		node->size_cells = propval_cell(prop);
>  }
> -WARNING(addr_size_cells, NULL, fixup_addr_size_cells, NULL, NULL,
> +WARNING(addr_size_cells, fixup_addr_size_cells, NULL,
>  	&address_cells_is_cell, &size_cells_is_cell);
>  
>  #define node_addr_cells(n) \
> @@ -537,7 +688,7 @@ WARNING(addr_size_cells, NULL, fixup_addr_size_cells, NULL, NULL,
>  #define node_size_cells(n) \
>  	(((n)->size_cells == -1) ? 1 : (n)->size_cells)
>  
> -static void check_reg_format(struct check *c, struct node *dt,
> +static void check_reg_format(struct check *c, struct dt_info *dti,
>  			     struct node *node)
>  {
>  	struct property *prop;
> @@ -548,25 +699,25 @@ static void check_reg_format(struct check *c, struct node *dt,
>  		return; /* No "reg", that's fine */
>  
>  	if (!node->parent) {
> -		FAIL(c, "Root node has a \"reg\" property");
> +		FAIL(c, dti, node, "Root node has a \"reg\" property");
>  		return;
>  	}
>  
>  	if (prop->val.len == 0)
> -		FAIL(c, "\"reg\" property in %s is empty", node->fullpath);
> +		FAIL_PROP(c, dti, node, prop, "property is empty");
>  
>  	addr_cells = node_addr_cells(node->parent);
>  	size_cells = node_size_cells(node->parent);
>  	entrylen = (addr_cells + size_cells) * sizeof(cell_t);
>  
> -	if ((prop->val.len % entrylen) != 0)
> -		FAIL(c, "\"reg\" property in %s has invalid length (%d bytes) "
> -		     "(#address-cells == %d, #size-cells == %d)",
> -		     node->fullpath, prop->val.len, addr_cells, size_cells);
> +	if (!entrylen || (prop->val.len % entrylen) != 0)
> +		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);
>  }
> -NODE_WARNING(reg_format, NULL, &addr_size_cells);
> +WARNING(reg_format, check_reg_format, NULL, &addr_size_cells);
>  
> -static void check_ranges_format(struct check *c, struct node *dt,
> +static void check_ranges_format(struct check *c, struct dt_info *dti,
>  				struct node *node)
>  {
>  	struct property *prop;
> @@ -577,7 +728,7 @@ static void check_ranges_format(struct check *c, struct node *dt,
>  		return;
>  
>  	if (!node->parent) {
> -		FAIL(c, "Root node has a \"ranges\" property");
> +		FAIL_PROP(c, dti, node, prop, "Root node has a \"ranges\" property");
>  		return;
>  	}
>  
> @@ -589,28 +740,237 @@ static void check_ranges_format(struct check *c, struct node *dt,
>  
>  	if (prop->val.len == 0) {
>  		if (p_addr_cells != c_addr_cells)
> -			FAIL(c, "%s has empty \"ranges\" property but its "
> -			     "#address-cells (%d) differs from %s (%d)",
> -			     node->fullpath, c_addr_cells, node->parent->fullpath,
> -			     p_addr_cells);
> +			FAIL_PROP(c, dti, node, prop, "empty \"ranges\" property but its "
> +				  "#address-cells (%d) differs from %s (%d)",
> +				  c_addr_cells, node->parent->fullpath,
> +				  p_addr_cells);
>  		if (p_size_cells != c_size_cells)
> -			FAIL(c, "%s has empty \"ranges\" property but its "
> -			     "#size-cells (%d) differs from %s (%d)",
> -			     node->fullpath, c_size_cells, node->parent->fullpath,
> -			     p_size_cells);
> +			FAIL_PROP(c, dti, node, prop, "empty \"ranges\" property but its "
> +				  "#size-cells (%d) differs from %s (%d)",
> +				  c_size_cells, node->parent->fullpath,
> +				  p_size_cells);
>  	} else if ((prop->val.len % entrylen) != 0) {
> -		FAIL(c, "\"ranges\" property in %s has invalid length (%d bytes) "
> -		     "(parent #address-cells == %d, child #address-cells == %d, "
> -		     "#size-cells == %d)", node->fullpath, prop->val.len,
> -		     p_addr_cells, c_addr_cells, c_size_cells);
> +		FAIL_PROP(c, dti, node, prop, "\"ranges\" property has invalid length (%d bytes) "
> +			  "(parent #address-cells == %d, child #address-cells == %d, "
> +			  "#size-cells == %d)", prop->val.len,
> +			  p_addr_cells, c_addr_cells, c_size_cells);
> +	}
> +}
> +WARNING(ranges_format, check_ranges_format, NULL, &addr_size_cells);
> +
> +static const struct bus_type pci_bus = {
> +	.name = "PCI",
> +};
> +
> +static void check_pci_bridge(struct check *c, struct dt_info *dti, struct node *node)
> +{
> +	struct property *prop;
> +	cell_t *cells;
> +
> +	prop = get_property(node, "device_type");
> +	if (!prop || !streq(prop->val.val, "pci"))
> +		return;
> +
> +	node->bus = &pci_bus;
> +
> +	if (!strprefixeq(node->name, node->basenamelen, "pci") &&
> +	    !strprefixeq(node->name, node->basenamelen, "pcie"))
> +		FAIL(c, dti, node, "node name is not \"pci\" or \"pcie\"");
> +
> +	prop = get_property(node, "ranges");
> +	if (!prop)
> +		FAIL(c, dti, node, "missing ranges for PCI bridge (or not a bridge)");
> +
> +	if (node_addr_cells(node) != 3)
> +		FAIL(c, dti, node, "incorrect #address-cells for PCI bridge");
> +	if (node_size_cells(node) != 2)
> +		FAIL(c, dti, node, "incorrect #size-cells for PCI bridge");
> +
> +	prop = get_property(node, "bus-range");
> +	if (!prop)
> +		return;
> +
> +	if (prop->val.len != (sizeof(cell_t) * 2)) {
> +		FAIL_PROP(c, dti, node, prop, "value must be 2 cells");
> +		return;
> +	}
> +	cells = (cell_t *)prop->val.val;
> +	if (fdt32_to_cpu(cells[0]) > fdt32_to_cpu(cells[1]))
> +		FAIL_PROP(c, dti, node, prop, "1st cell must be less than or equal to 2nd cell");
> +	if (fdt32_to_cpu(cells[1]) > 0xff)
> +		FAIL_PROP(c, dti, node, prop, "maximum bus number must be less than 256");
> +}
> +WARNING(pci_bridge, check_pci_bridge, NULL,
> +	&device_type_is_string, &addr_size_cells);
> +
> +static void check_pci_device_bus_num(struct check *c, struct dt_info *dti, struct node *node)
> +{
> +	struct property *prop;
> +	unsigned int bus_num, min_bus, max_bus;
> +	cell_t *cells;
> +
> +	if (!node->parent || (node->parent->bus != &pci_bus))
> +		return;
> +
> +	prop = get_property(node, "reg");
> +	if (!prop)
> +		return;
> +
> +	cells = (cell_t *)prop->val.val;
> +	bus_num = (fdt32_to_cpu(cells[0]) & 0x00ff0000) >> 16;
> +
> +	prop = get_property(node->parent, "bus-range");
> +	if (!prop) {
> +		min_bus = max_bus = 0;
> +	} else {
> +		cells = (cell_t *)prop->val.val;
> +		min_bus = fdt32_to_cpu(cells[0]);
> +		max_bus = fdt32_to_cpu(cells[0]);
> +	}
> +	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)",
> +			  bus_num, min_bus, max_bus);
> +}
> +WARNING(pci_device_bus_num, check_pci_device_bus_num, NULL, &reg_format, &pci_bridge);
> +
> +static void check_pci_device_reg(struct check *c, struct dt_info *dti, struct node *node)
> +{
> +	struct property *prop;
> +	const char *unitname = get_unitname(node);
> +	char unit_addr[5];
> +	unsigned int dev, func, reg;
> +	cell_t *cells;
> +
> +	if (!node->parent || (node->parent->bus != &pci_bus))
> +		return;
> +
> +	prop = get_property(node, "reg");
> +	if (!prop) {
> +		FAIL(c, dti, node, "missing PCI reg property");
> +		return;
> +	}
> +
> +	cells = (cell_t *)prop->val.val;
> +	if (cells[1] || cells[2])
> +		FAIL_PROP(c, dti, node, prop, "PCI reg config space address cells 2 and 3 must be 0");
> +
> +	reg = fdt32_to_cpu(cells[0]);
> +	dev = (reg & 0xf800) >> 11;
> +	func = (reg & 0x700) >> 8;
> +
> +	if (reg & 0xff000000)
> +		FAIL_PROP(c, dti, node, prop, "PCI reg address is not configuration space");
> +	if (reg & 0x000000ff)
> +		FAIL_PROP(c, dti, node, prop, "PCI reg config space address register number must be 0");
> +
> +	if (func == 0) {
> +		snprintf(unit_addr, sizeof(unit_addr), "%x", dev);
> +		if (streq(unitname, unit_addr))
> +			return;
> +	}
> +
> +	snprintf(unit_addr, sizeof(unit_addr), "%x,%x", dev, func);
> +	if (streq(unitname, unit_addr))
> +		return;
> +
> +	FAIL(c, dti, node, "PCI unit address format error, expected \"%s\"",
> +	     unit_addr);
> +}
> +WARNING(pci_device_reg, check_pci_device_reg, NULL, &reg_format, &pci_bridge);
> +
> +static const struct bus_type simple_bus = {
> +	.name = "simple-bus",
> +};
> +
> +static bool node_is_compatible(struct node *node, const char *compat)
> +{
> +	struct property *prop;
> +	const char *str, *end;
> +
> +	prop = get_property(node, "compatible");
> +	if (!prop)
> +		return false;
> +
> +	for (str = prop->val.val, end = str + prop->val.len; str < end;
> +	     str += strnlen(str, end - str) + 1) {
> +		if (strprefixeq(str, end - str, compat))
> +			return true;
>  	}
> +	return false;
> +}
> +
> +static void check_simple_bus_bridge(struct check *c, struct dt_info *dti, struct node *node)
> +{
> +	if (node_is_compatible(node, "simple-bus"))
> +		node->bus = &simple_bus;
>  }
> -NODE_WARNING(ranges_format, NULL, &addr_size_cells);
> +WARNING(simple_bus_bridge, check_simple_bus_bridge, NULL, &addr_size_cells);
> +
> +static void check_simple_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];
> +	unsigned int size;
> +	uint64_t reg = 0;
> +	cell_t *cells = NULL;
> +
> +	if (!node->parent || (node->parent->bus != &simple_bus))
> +		return;
> +
> +	prop = get_property(node, "reg");
> +	if (prop)
> +		cells = (cell_t *)prop->val.val;
> +	else {
> +		prop = get_property(node, "ranges");
> +		if (prop && prop->val.len)
> +			/* skip of child address */
> +			cells = ((cell_t *)prop->val.val) + node_addr_cells(node);
> +	}
> +
> +	if (!cells) {
> +		if (node->parent->parent && !(node->bus == &simple_bus))
> +			FAIL(c, dti, node, "missing or empty reg/ranges property");
> +		return;
> +	}
> +
> +	size = node_addr_cells(node->parent);
> +	while (size--)
> +		reg = (reg << 32) | fdt32_to_cpu(*(cells++));
> +
> +	snprintf(unit_addr, sizeof(unit_addr), "%"PRIx64, reg);
> +	if (!streq(unitname, unit_addr))
> +		FAIL(c, dti, node, "simple-bus unit address format error, expected \"%s\"",
> +		     unit_addr);
> +}
> +WARNING(simple_bus_reg, check_simple_bus_reg, NULL, &reg_format, &simple_bus_bridge);
> +
> +static void check_unit_address_format(struct check *c, struct dt_info *dti,
> +				      struct node *node)
> +{
> +	const char *unitname = get_unitname(node);
> +
> +	if (node->parent && node->parent->bus)
> +		return;
> +
> +	if (!unitname[0])
> +		return;
> +
> +	if (!strncmp(unitname, "0x", 2)) {
> +		FAIL(c, dti, node, "unit name should not have leading \"0x\"");
> +		/* skip over 0x for next test */
> +		unitname += 2;
> +	}
> +	if (unitname[0] == '0' && isxdigit(unitname[1]))
> +		FAIL(c, dti, node, "unit name should not have leading 0s");
> +}
> +WARNING(unit_address_format, check_unit_address_format, NULL,
> +	&node_name_format, &pci_bridge, &simple_bus_bridge);
>  
>  /*
>   * Style checks
>   */
> -static void check_avoid_default_addr_size(struct check *c, struct node *dt,
> +static void check_avoid_default_addr_size(struct check *c, struct dt_info *dti,
>  					  struct node *node)
>  {
>  	struct property *reg, *ranges;
> @@ -625,31 +985,377 @@ static void check_avoid_default_addr_size(struct check *c, struct node *dt,
>  		return;
>  
>  	if (node->parent->addr_cells == -1)
> -		FAIL(c, "Relying on default #address-cells value for %s",
> -		     node->fullpath);
> +		FAIL(c, dti, node, "Relying on default #address-cells value");
>  
>  	if (node->parent->size_cells == -1)
> -		FAIL(c, "Relying on default #size-cells value for %s",
> -		     node->fullpath);
> +		FAIL(c, dti, node, "Relying on default #size-cells value");
> +}
> +WARNING(avoid_default_addr_size, check_avoid_default_addr_size, NULL,
> +	&addr_size_cells);
> +
> +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)
> +		return;
> +
> +	for_each_child(node, child) {
> +		prop = get_property(child, "reg");
> +		if (prop)
> +			has_reg = true;
> +	}
> +
> +	if (!has_reg)
> +		FAIL(c, dti, node, "unnecessary #address-cells/#size-cells without \"ranges\" or child \"reg\" property");
>  }
> -NODE_WARNING(avoid_default_addr_size, NULL, &addr_size_cells);
> +WARNING(avoid_unnecessary_addr_size, check_avoid_unnecessary_addr_size, NULL, &avoid_default_addr_size);
>  
>  static void check_obsolete_chosen_interrupt_controller(struct check *c,
> -						       struct node *dt)
> +						       struct dt_info *dti,
> +						       struct node *node)
>  {
> +	struct node *dt = dti->dt;
>  	struct node *chosen;
>  	struct property *prop;
>  
> +	if (node != dt)
> +		return;
> +
> +
>  	chosen = get_node_by_path(dt, "/chosen");
>  	if (!chosen)
>  		return;
>  
>  	prop = get_property(chosen, "interrupt-controller");
>  	if (prop)
> -		FAIL(c, "/chosen has obsolete \"interrupt-controller\" "
> -		     "property");
> +		FAIL_PROP(c, dti, node, prop,
> +			  "/chosen has obsolete \"interrupt-controller\" property");
> +}
> +WARNING(obsolete_chosen_interrupt_controller,
> +	check_obsolete_chosen_interrupt_controller, NULL);
> +
> +static void check_chosen_node_is_root(struct check *c, struct dt_info *dti,
> +				      struct node *node)
> +{
> +	if (!streq(node->name, "chosen"))
> +		return;
> +
> +	if (node->parent != dti->dt)
> +		FAIL(c, dti, node, "chosen node must be at root node");
>  }
> -TREE_WARNING(obsolete_chosen_interrupt_controller, NULL);
> +WARNING(chosen_node_is_root, check_chosen_node_is_root, NULL);
> +
> +static void check_chosen_node_bootargs(struct check *c, struct dt_info *dti,
> +				       struct node *node)
> +{
> +	struct property *prop;
> +
> +	if (!streq(node->name, "chosen"))
> +		return;
> +
> +	prop = get_property(node, "bootargs");
> +	if (!prop)
> +		return;
> +
> +	c->data = prop->name;
> +	check_is_string(c, dti, node);
> +}
> +WARNING(chosen_node_bootargs, check_chosen_node_bootargs, NULL);
> +
> +static void check_chosen_node_stdout_path(struct check *c, struct dt_info *dti,
> +					  struct node *node)
> +{
> +	struct property *prop;
> +
> +	if (!streq(node->name, "chosen"))
> +		return;
> +
> +	prop = get_property(node, "stdout-path");
> +	if (!prop) {
> +		prop = get_property(node, "linux,stdout-path");
> +		if (!prop)
> +			return;
> +		FAIL_PROP(c, dti, node, prop, "Use 'stdout-path' instead");
> +	}
> +
> +	c->data = prop->name;
> +	check_is_string(c, dti, node);
> +}
> +WARNING(chosen_node_stdout_path, check_chosen_node_stdout_path, NULL);
> +
> +struct provider {
> +	const char *prop_name;
> +	const char *cell_name;
> +	bool optional;
> +};
> +
> +static void check_property_phandle_args(struct check *c,
> +					  struct dt_info *dti,
> +				          struct node *node,
> +				          struct property *prop,
> +				          const struct provider *provider)
> +{
> +	struct node *root = dti->dt;
> +	int cell, cellsize = 0;
> +
> +	if (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));
> +		return;
> +	}
> +
> +	for (cell = 0; cell < prop->val.len / sizeof(cell_t); cell += cellsize + 1) {
> +		struct node *provider_node;
> +		struct property *cellprop;
> +		int phandle;
> +
> +		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) {
> +			/* Give up if this is an overlay with external references */
> +			if (dti->dtsflags & DTSF_PLUGIN)
> +				break;
> +
> +			cellsize = 0;
> +			continue;
> +		}
> +
> +		/* If we have markers, verify the current cell is a phandle */
> +		if (prop->val.markers) {
> +			struct marker *m = prop->val.markers;
> +			for_each_marker_of_type(m, REF_PHANDLE) {
> +				if (m->offset == (cell * sizeof(cell_t)))
> +					break;
> +			}
> +			if (!m)
> +				FAIL_PROP(c, dti, node, prop,
> +					  "cell %d is not a phandle reference",
> +					  cell);
> +		}
> +
> +		provider_node = get_node_by_phandle(root, phandle);
> +		if (!provider_node) {
> +			FAIL_PROP(c, dti, node, prop,
> +				  "Could not get phandle node for (cell %d)",
> +				  cell);
> +			break;
> +		}
> +
> +		cellprop = get_property(provider_node, provider->cell_name);
> +		if (cellprop) {
> +			cellsize = propval_cell(cellprop);
> +		} else if (provider->optional) {
> +			cellsize = 0;
> +		} else {
> +			FAIL(c, dti, node, "Missing property '%s' in node %s or bad phandle (referred from %s[%d])",
> +			     provider->cell_name,
> +			     provider_node->fullpath,
> +			     prop->name, cell);
> +			break;
> +		}
> +
> +		if (prop->val.len < ((cell + cellsize + 1) * sizeof(cell_t))) {
> +			FAIL_PROP(c, dti, node, prop,
> +				  "property size (%d) too small for cell size %d",
> +				  prop->val.len, cellsize);
> +		}
> +	}
> +}
> +
> +static void check_provider_cells_property(struct check *c,
> +					  struct dt_info *dti,
> +				          struct node *node)
> +{
> +	struct provider *provider = c->data;
> +	struct property *prop;
> +
> +	prop = get_property(node, provider->prop_name);
> +	if (!prop)
> +		return;
> +
> +	check_property_phandle_args(c, dti, node, prop, provider);
> +}
> +#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_PROPERTY_PHANDLE_CELLS(clocks, "clocks", "#clock-cells");
> +WARNING_PROPERTY_PHANDLE_CELLS(cooling_device, "cooling-device", "#cooling-cells");
> +WARNING_PROPERTY_PHANDLE_CELLS(dmas, "dmas", "#dma-cells");
> +WARNING_PROPERTY_PHANDLE_CELLS(hwlocks, "hwlocks", "#hwlock-cells");
> +WARNING_PROPERTY_PHANDLE_CELLS(interrupts_extended, "interrupts-extended", "#interrupt-cells");
> +WARNING_PROPERTY_PHANDLE_CELLS(io_channels, "io-channels", "#io-channel-cells");
> +WARNING_PROPERTY_PHANDLE_CELLS(iommus, "iommus", "#iommu-cells");
> +WARNING_PROPERTY_PHANDLE_CELLS(mboxes, "mboxes", "#mbox-cells");
> +WARNING_PROPERTY_PHANDLE_CELLS(msi_parent, "msi-parent", "#msi-cells", true);
> +WARNING_PROPERTY_PHANDLE_CELLS(mux_controls, "mux-controls", "#mux-control-cells");
> +WARNING_PROPERTY_PHANDLE_CELLS(phys, "phys", "#phy-cells");
> +WARNING_PROPERTY_PHANDLE_CELLS(power_domains, "power-domains", "#power-domain-cells");
> +WARNING_PROPERTY_PHANDLE_CELLS(pwms, "pwms", "#pwm-cells");
> +WARNING_PROPERTY_PHANDLE_CELLS(resets, "resets", "#reset-cells");
> +WARNING_PROPERTY_PHANDLE_CELLS(sound_dai, "sound-dai", "#sound-dai-cells");
> +WARNING_PROPERTY_PHANDLE_CELLS(thermal_sensors, "thermal-sensors", "#thermal-sensor-cells");
> +
> +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"))
> +		return false;
> +
> +	str = strrchr(prop->name, '-');
> +	if (str)
> +		str++;
> +	else
> +		str = prop->name;
> +	if (!(streq(str, "gpios") || streq(str, "gpio")))
> +		return false;
> +
> +	return true;
> +}
> +
> +static void check_gpios_property(struct check *c,
> +					  struct dt_info *dti,
> +				          struct node *node)
> +{
> +	struct property *prop;
> +
> +	/* Skip GPIO hog nodes which have 'gpios' property */
> +	if (get_property(node, "gpio-hog"))
> +		return;
> +
> +	for_each_property(node, prop) {
> +		struct provider provider;
> +
> +		if (!prop_is_gpio(prop))
> +			continue;
> +
> +		provider.prop_name = prop->name;
> +		provider.cell_name = "#gpio-cells";
> +		provider.optional = false;
> +		check_property_phandle_args(c, dti, node, prop, &provider);
> +	}
> +
> +}
> +WARNING(gpios_property, check_gpios_property, NULL, &phandle_references);
> +
> +static void check_deprecated_gpio_property(struct check *c,
> +					   struct dt_info *dti,
> +				           struct node *node)
> +{
> +	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"))
> +			continue;
> +
> +		FAIL_PROP(c, dti, node, prop,
> +			  "'[*-]gpio' is deprecated, use '[*-]gpios' instead");
> +	}
> +
> +}
> +CHECK(deprecated_gpio_property, check_deprecated_gpio_property, NULL);
> +
> +static bool node_is_interrupt_provider(struct node *node)
> +{
> +	struct property *prop;
> +
> +	prop = get_property(node, "interrupt-controller");
> +	if (prop)
> +		return true;
> +
> +	prop = get_property(node, "interrupt-map");
> +	if (prop)
> +		return true;
> +
> +	return false;
> +}
> +static void check_interrupts_property(struct check *c,
> +				      struct dt_info *dti,
> +				      struct node *node)
> +{
> +	struct node *root = dti->dt;
> +	struct node *irq_node = NULL, *parent = node;
> +	struct property *irq_prop, *prop = NULL;
> +	int irq_cells, phandle;
> +
> +	irq_prop = get_property(node, "interrupts");
> +	if (!irq_prop)
> +		return;
> +
> +	if (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));
> +
> +	while (parent && !prop) {
> +		if (parent != node && node_is_interrupt_provider(parent)) {
> +			irq_node = parent;
> +			break;
> +		}
> +
> +		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))
> +					return;
> +
> +			irq_node = get_node_by_phandle(root, phandle);
> +			if (!irq_node) {
> +				FAIL_PROP(c, dti, parent, prop, "Bad phandle");
> +				return;
> +			}
> +			if (!node_is_interrupt_provider(irq_node))
> +				FAIL(c, dti, irq_node,
> +				     "Missing interrupt-controller or interrupt-map property");
> +
> +			break;
> +		}
> +
> +		parent = parent->parent;
> +	}
> +
> +	if (!irq_node) {
> +		FAIL(c, dti, node, "Missing interrupt-parent");
> +		return;
> +	}
> +
> +	prop = get_property(irq_node, "#interrupt-cells");
> +	if (!prop) {
> +		FAIL(c, dti, irq_node, "Missing #interrupt-cells in interrupt-parent");
> +		return;
> +	}
> +
> +	irq_cells = propval_cell(prop);
> +	if (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)));
> +	}
> +}
> +WARNING(interrupts_property, check_interrupts_property, &phandle_references);
>  
>  static struct check *check_table[] = {
>  	&duplicate_node_names, &duplicate_property_names,
> @@ -663,11 +1369,52 @@ static struct check *check_table[] = {
>  
>  	&address_cells_is_cell, &size_cells_is_cell, &interrupt_cells_is_cell,
>  	&device_type_is_string, &model_is_string, &status_is_string,
> +	&label_is_string,
> +
> +	&compatible_is_string_list, &names_is_string_list,
> +
> +	&property_name_chars_strict,
> +	&node_name_chars_strict,
>  
>  	&addr_size_cells, &reg_format, &ranges_format,
>  
> +	&unit_address_vs_reg,
> +	&unit_address_format,
> +
> +	&pci_bridge,
> +	&pci_device_reg,
> +	&pci_device_bus_num,
> +
> +	&simple_bus_bridge,
> +	&simple_bus_reg,
> +
>  	&avoid_default_addr_size,
> +	&avoid_unnecessary_addr_size,
>  	&obsolete_chosen_interrupt_controller,
> +	&chosen_node_is_root, &chosen_node_bootargs, &chosen_node_stdout_path,
> +
> +	&clocks_property,
> +	&cooling_device_property,
> +	&dmas_property,
> +	&hwlocks_property,
> +	&interrupts_extended_property,
> +	&io_channels_property,
> +	&iommus_property,
> +	&mboxes_property,
> +	&msi_parent_property,
> +	&mux_controls_property,
> +	&phys_property,
> +	&power_domains_property,
> +	&pwms_property,
> +	&resets_property,
> +	&sound_dai_property,
> +	&thermal_sensors_property,
> +
> +	&deprecated_gpio_property,
> +	&gpios_property,
> +	&interrupts_property,
> +
> +	&alias_paths,
>  
>  	&always_fail,
>  };
> @@ -733,9 +1480,8 @@ void parse_checks_option(bool warn, bool error, const char *arg)
>  	die("Unrecognized check name \"%s\"\n", name);
>  }
>  
> -void process_checks(bool force, struct boot_info *bi)
> +void process_checks(bool force, struct dt_info *dti)
>  {
> -	struct node *dt = bi->dt;
>  	int i;
>  	int error = 0;
>  
> @@ -743,7 +1489,7 @@ void process_checks(bool force, struct boot_info *bi)
>  		struct check *c = check_table[i];
>  
>  		if (c->warn || c->error)
> -			error = error || run_check(c, dt);
> +			error = error || run_check(c, dti);
>  	}
>  
>  	if (error) {
> diff --git a/scripts/dtc/data.c b/scripts/dtc/data.c
> index 8cae23746..aa37a16c8 100644
> --- a/scripts/dtc/data.c
> +++ b/scripts/dtc/data.c
> @@ -171,9 +171,9 @@ struct data data_merge(struct data d1, struct data d2)
>  struct data data_append_integer(struct data d, uint64_t value, int bits)
>  {
>  	uint8_t value_8;
> -	uint16_t value_16;
> -	uint32_t value_32;
> -	uint64_t value_64;
> +	fdt16_t value_16;
> +	fdt32_t value_32;
> +	fdt64_t value_64;
>  
>  	switch (bits) {
>  	case 8:
> @@ -197,14 +197,14 @@ struct data data_append_integer(struct data d, uint64_t value, int bits)
>  	}
>  }
>  
> -struct data data_append_re(struct data d, const struct fdt_reserve_entry *re)
> +struct data data_append_re(struct data d, uint64_t address, uint64_t size)
>  {
> -	struct fdt_reserve_entry bere;
> +	struct fdt_reserve_entry re;
>  
> -	bere.address = cpu_to_fdt64(re->address);
> -	bere.size = cpu_to_fdt64(re->size);
> +	re.address = cpu_to_fdt64(address);
> +	re.size = cpu_to_fdt64(size);
>  
> -	return data_append_data(d, &bere, sizeof(bere));
> +	return data_append_data(d, &re, sizeof(re));
>  }
>  
>  struct data data_append_cell(struct data d, cell_t word)
> diff --git a/scripts/dtc/dtc-lexer.l b/scripts/dtc/dtc-lexer.l
> index 0ee1caf03..fd825ebba 100644
> --- a/scripts/dtc/dtc-lexer.l
> +++ b/scripts/dtc/dtc-lexer.l
> @@ -62,7 +62,8 @@ static int dts_version = 1;
>  
>  static void push_input_file(const char *filename);
>  static bool pop_input_file(void);
> -static void lexical_error(const char *fmt, ...);
> +static void PRINTF(1, 2) lexical_error(const char *fmt, ...);
> +
>  %}
>  
>  %%
> @@ -73,24 +74,32 @@ static void lexical_error(const char *fmt, ...);
>  		}
>  
>  <*>^"#"(line)?[ \t]+[0-9]+[ \t]+{STRING}([ \t]+[0-9]+)? {
> -			char *line, *tmp, *fn;
> +			char *line, *fnstart, *fnend;
> +			struct data fn;
>  			/* skip text before line # */
>  			line = yytext;
>  			while (!isdigit((unsigned char)*line))
>  				line++;
> -			/* skip digits in line # */
> -			tmp = line;
> -			while (!isspace((unsigned char)*tmp))
> -				tmp++;
> -			/* "NULL"-terminate line # */
> -			*tmp = '\0';
> -			/* start of filename */
> -			fn = strchr(tmp + 1, '"') + 1;
> -			/* strip trailing " from filename */
> -			tmp = strchr(fn, '"');
> -			*tmp = 0;
> +
> +			/* regexp ensures that first and list "
> +			 * in the whole yytext are those at
> +			 * beginning and end of the filename string */
> +			fnstart = memchr(yytext, '"', yyleng);
> +			for (fnend = yytext + yyleng - 1;
> +			     *fnend != '"'; fnend--)
> +				;
> +			assert(fnstart && fnend && (fnend > fnstart));
> +
> +			fn = data_copy_escape_string(fnstart + 1,
> +						     fnend - fnstart - 1);
> +
> +			/* Don't allow nuls in filenames */
> +			if (memchr(fn.val, '\0', fn.len - 1))
> +				lexical_error("nul in line number directive");
> +
>  			/* -1 since #line is the number of the next line */
> -			srcpos_set_line(xstrdup(fn), atoi(line) - 1);
> +			srcpos_set_line(xstrdup(fn.val), atoi(line) - 1);
> +			data_free(fn);
>  		}
>  
>  <*><<EOF>>		{
> @@ -113,6 +122,11 @@ static void lexical_error(const char *fmt, ...);
>  			return DT_V1;
>  		}
>  
> +<*>"/plugin/"	{
> +			DPRINT("Keyword: /plugin/\n");
> +			return DT_PLUGIN;
> +		}
> +
>  <*>"/memreserve/"	{
>  			DPRINT("Keyword: /memreserve/\n");
>  			BEGIN_DEFAULT();
> @@ -153,7 +167,10 @@ static void lexical_error(const char *fmt, ...);
>  			errno = 0;
>  			yylval.integer = strtoull(yytext, &e, 0);
>  
> -			assert(!(*e) || !e[strspn(e, "UL")]);
> +			if (*e && e[strspn(e, "UL")]) {
> +				lexical_error("Bad integer literal '%s'",
> +					      yytext);
> +			}
>  
>  			if (errno == ERANGE)
>  				lexical_error("Integer literal '%s' out of range",
> @@ -173,16 +190,16 @@ static void lexical_error(const char *fmt, ...);
>  			if (d.len == 1) {
>  				lexical_error("Empty character literal");
>  				yylval.integer = 0;
> -				return DT_CHAR_LITERAL;
> -			}
> -
> -			yylval.integer = (unsigned char)d.val[0];
> +			} else {
> +				yylval.integer = (unsigned char)d.val[0];
>  
> -			if (d.len > 2)
> -				lexical_error("Character literal has %d"
> -					      " characters instead of 1",
> -					      d.len - 1);
> +				if (d.len > 2)
> +					lexical_error("Character literal has %d"
> +						      " characters instead of 1",
> +						      d.len - 1);
> +			}
>  
> +			data_free(d);
>  			return DT_CHAR_LITERAL;
>  		}
>  
> diff --git a/scripts/dtc/dtc-lexer.lex.c_shipped b/scripts/dtc/dtc-lexer.lex.c_shipped
> index 11cd78e72..f032b24b2 100644
> --- a/scripts/dtc/dtc-lexer.lex.c_shipped
> +++ b/scripts/dtc/dtc-lexer.lex.c_shipped
> @@ -1,6 +1,6 @@
> -#line 2 "dtc-lexer.lex.c"
> +#line 2 "dtc-lexer.l.c"
>  
> -#line 4 "dtc-lexer.lex.c"
> +#line 4 "dtc-lexer.l.c"
>  
>  #define  YY_INT_ALIGNED short int
>  
> @@ -8,8 +8,8 @@
>  
>  #define FLEX_SCANNER
>  #define YY_FLEX_MAJOR_VERSION 2
> -#define YY_FLEX_MINOR_VERSION 5
> -#define YY_FLEX_SUBMINOR_VERSION 39
> +#define YY_FLEX_MINOR_VERSION 6
> +#define YY_FLEX_SUBMINOR_VERSION 4
>  #if YY_FLEX_SUBMINOR_VERSION > 0
>  #define FLEX_BETA
>  #endif
> @@ -84,60 +84,48 @@ typedef unsigned int flex_uint32_t;
>  #define UINT32_MAX             (4294967295U)
>  #endif
>  
> +#ifndef SIZE_MAX
> +#define SIZE_MAX               (~(size_t)0)
> +#endif
> +
>  #endif /* ! C99 */
>  
>  #endif /* ! FLEXINT_H */
>  
> -#ifdef __cplusplus
> -
> -/* The "const" storage-class-modifier is valid. */
> -#define YY_USE_CONST
> -
> -#else	/* ! __cplusplus */
> -
> -/* C99 requires __STDC__ to be defined as 1. */
> -#if defined (__STDC__)
> -
> -#define YY_USE_CONST
> +/* begin standard C++ headers. */
>  
> -#endif	/* defined (__STDC__) */
> -#endif	/* ! __cplusplus */
> -
> -#ifdef YY_USE_CONST
> +/* TODO: this is always defined, so inline it */
>  #define yyconst const
> +
> +#if defined(__GNUC__) && __GNUC__ >= 3
> +#define yynoreturn __attribute__((__noreturn__))
>  #else
> -#define yyconst
> +#define yynoreturn
>  #endif
>  
>  /* Returned upon end-of-file. */
>  #define YY_NULL 0
>  
> -/* Promotes a possibly negative, possibly signed char to an unsigned
> - * integer for use as an array index.  If the signed char is negative,
> - * we want to instead treat it as an 8-bit unsigned char, hence the
> - * double cast.
> +/* Promotes a possibly negative, possibly signed char to an
> + *   integer in range [0..255] for use as an array index.
>   */
> -#define YY_SC_TO_UI(c) ((unsigned int) (unsigned char) c)
> +#define YY_SC_TO_UI(c) ((YY_CHAR) (c))
>  
>  /* Enter a start condition.  This macro really ought to take a parameter,
>   * but we do it the disgusting crufty way forced on us by the ()-less
>   * definition of BEGIN.
>   */
>  #define BEGIN (yy_start) = 1 + 2 *
> -
>  /* Translate the current start state into a value that can be later handed
>   * to BEGIN to return to the state.  The YYSTATE alias is for lex
>   * compatibility.
>   */
>  #define YY_START (((yy_start) - 1) / 2)
>  #define YYSTATE YY_START
> -
>  /* Action number for EOF rule of a given start state. */
>  #define YY_STATE_EOF(state) (YY_END_OF_BUFFER + state + 1)
> -
>  /* Special action meaning "start processing a new file". */
> -#define YY_NEW_FILE yyrestart(yyin  )
> -
> +#define YY_NEW_FILE yyrestart( yyin  )
>  #define YY_END_OF_BUFFER_CHAR 0
>  
>  /* Size of default input buffer. */
> @@ -167,14 +155,14 @@ typedef struct yy_buffer_state *YY_BUFFER_STATE;
>  typedef size_t yy_size_t;
>  #endif
>  
> -extern yy_size_t yyleng;
> +extern int yyleng;
>  
>  extern FILE *yyin, *yyout;
>  
>  #define EOB_ACT_CONTINUE_SCAN 0
>  #define EOB_ACT_END_OF_FILE 1
>  #define EOB_ACT_LAST_MATCH 2
> -
> +    
>      #define YY_LESS_LINENO(n)
>      #define YY_LINENO_REWIND_TO(ptr)
>      
> @@ -191,7 +179,6 @@ extern FILE *yyin, *yyout;
>  		YY_DO_BEFORE_ACTION; /* set up yytext again */ \
>  		} \
>  	while ( 0 )
> -
>  #define unput(c) yyunput( c, (yytext_ptr)  )
>  
>  #ifndef YY_STRUCT_YY_BUFFER_STATE
> @@ -206,12 +193,12 @@ struct yy_buffer_state
>  	/* Size of input buffer in bytes, not including room for EOB
>  	 * characters.
>  	 */
> -	yy_size_t yy_buf_size;
> +	int yy_buf_size;
>  
>  	/* Number of characters read into yy_ch_buf, not including EOB
>  	 * characters.
>  	 */
> -	yy_size_t yy_n_chars;
> +	int yy_n_chars;
>  
>  	/* Whether we "own" the buffer - i.e., we know we created it,
>  	 * and can realloc() it to grow it, and should free() it to
> @@ -234,7 +221,7 @@ struct yy_buffer_state
>  
>      int yy_bs_lineno; /**< The line count. */
>      int yy_bs_column; /**< The column count. */
> -    
> +
>  	/* Whether to try to fill the input buffer when we reach the
>  	 * end of it.
>  	 */
> @@ -262,7 +249,7 @@ struct yy_buffer_state
>  /* Stack of input buffers. */
>  static size_t yy_buffer_stack_top = 0; /**< index of top of stack. */
>  static size_t yy_buffer_stack_max = 0; /**< capacity of stack. */
> -static YY_BUFFER_STATE * yy_buffer_stack = 0; /**< Stack as an array. */
> +static YY_BUFFER_STATE * yy_buffer_stack = NULL; /**< Stack as an array. */
>  
>  /* We provide macros for accessing buffer states in case in the
>   * future we want to put the buffer states in a more general
> @@ -273,7 +260,6 @@ static YY_BUFFER_STATE * yy_buffer_stack = 0; /**< Stack as an array. */
>  #define YY_CURRENT_BUFFER ( (yy_buffer_stack) \
>                            ? (yy_buffer_stack)[(yy_buffer_stack_top)] \
>                            : NULL)
> -
>  /* Same as previous macro, but useful when we know that the buffer stack is not
>   * NULL or when we need an lvalue. For internal use only.
>   */
> @@ -281,11 +267,11 @@ static YY_BUFFER_STATE * yy_buffer_stack = 0; /**< Stack as an array. */
>  
>  /* yy_hold_char holds the character lost when yytext is formed. */
>  static char yy_hold_char;
> -static yy_size_t yy_n_chars;		/* number of characters read into yy_ch_buf */
> -yy_size_t yyleng;
> +static int yy_n_chars;		/* number of characters read into yy_ch_buf */
> +int yyleng;
>  
>  /* Points to current character in buffer. */
> -static char *yy_c_buf_p = (char *) 0;
> +static char *yy_c_buf_p = NULL;
>  static int yy_init = 0;		/* whether we need to initialize */
>  static int yy_start = 0;	/* start state number */
>  
> @@ -294,87 +280,83 @@ static int yy_start = 0;	/* start state number */
>   */
>  static int yy_did_buffer_switch_on_eof;
>  
> -void yyrestart (FILE *input_file  );
> -void yy_switch_to_buffer (YY_BUFFER_STATE new_buffer  );
> -YY_BUFFER_STATE yy_create_buffer (FILE *file,int size  );
> -void yy_delete_buffer (YY_BUFFER_STATE b  );
> -void yy_flush_buffer (YY_BUFFER_STATE b  );
> -void yypush_buffer_state (YY_BUFFER_STATE new_buffer  );
> -void yypop_buffer_state (void );
> -
> -static void yyensure_buffer_stack (void );
> -static void yy_load_buffer_state (void );
> -static void yy_init_buffer (YY_BUFFER_STATE b,FILE *file  );
> +void yyrestart ( FILE *input_file  );
> +void yy_switch_to_buffer ( YY_BUFFER_STATE new_buffer  );
> +YY_BUFFER_STATE yy_create_buffer ( FILE *file, int size  );
> +void yy_delete_buffer ( YY_BUFFER_STATE b  );
> +void yy_flush_buffer ( YY_BUFFER_STATE b  );
> +void yypush_buffer_state ( YY_BUFFER_STATE new_buffer  );
> +void yypop_buffer_state ( void );
>  
> -#define YY_FLUSH_BUFFER yy_flush_buffer(YY_CURRENT_BUFFER )
> +static void yyensure_buffer_stack ( void );
> +static void yy_load_buffer_state ( void );
> +static void yy_init_buffer ( YY_BUFFER_STATE b, FILE *file  );
> +#define YY_FLUSH_BUFFER yy_flush_buffer( YY_CURRENT_BUFFER )
>  
> -YY_BUFFER_STATE yy_scan_buffer (char *base,yy_size_t size  );
> -YY_BUFFER_STATE yy_scan_string (yyconst char *yy_str  );
> -YY_BUFFER_STATE yy_scan_bytes (yyconst char *bytes,yy_size_t len  );
> +YY_BUFFER_STATE yy_scan_buffer ( char *base, yy_size_t size  );
> +YY_BUFFER_STATE yy_scan_string ( const char *yy_str  );
> +YY_BUFFER_STATE yy_scan_bytes ( const char *bytes, int len  );
>  
> -void *yyalloc (yy_size_t  );
> -void *yyrealloc (void *,yy_size_t  );
> -void yyfree (void *  );
> +void *yyalloc ( yy_size_t  );
> +void *yyrealloc ( void *, yy_size_t  );
> +void yyfree ( void *  );
>  
>  #define yy_new_buffer yy_create_buffer
> -
>  #define yy_set_interactive(is_interactive) \
>  	{ \
>  	if ( ! YY_CURRENT_BUFFER ){ \
>          yyensure_buffer_stack (); \
>  		YY_CURRENT_BUFFER_LVALUE =    \
> -            yy_create_buffer(yyin,YY_BUF_SIZE ); \
> +            yy_create_buffer( yyin, YY_BUF_SIZE ); \
>  	} \
>  	YY_CURRENT_BUFFER_LVALUE->yy_is_interactive = is_interactive; \
>  	}
> -
>  #define yy_set_bol(at_bol) \
>  	{ \
>  	if ( ! YY_CURRENT_BUFFER ){\
>          yyensure_buffer_stack (); \
>  		YY_CURRENT_BUFFER_LVALUE =    \
> -            yy_create_buffer(yyin,YY_BUF_SIZE ); \
> +            yy_create_buffer( yyin, YY_BUF_SIZE ); \
>  	} \
>  	YY_CURRENT_BUFFER_LVALUE->yy_at_bol = at_bol; \
>  	}
> -
>  #define YY_AT_BOL() (YY_CURRENT_BUFFER_LVALUE->yy_at_bol)
>  
>  /* Begin user sect3 */
>  
> -#define yywrap() 1
> +#define yywrap() (/*CONSTCOND*/1)
>  #define YY_SKIP_YYWRAP
> +typedef flex_uint8_t YY_CHAR;
>  
> -typedef unsigned char YY_CHAR;
> -
> -FILE *yyin = (FILE *) 0, *yyout = (FILE *) 0;
> +FILE *yyin = NULL, *yyout = NULL;
>  
>  typedef int yy_state_type;
>  
>  extern int yylineno;
> -
>  int yylineno = 1;
>  
>  extern char *yytext;
> +#ifdef yytext_ptr
> +#undef yytext_ptr
> +#endif
>  #define yytext_ptr yytext
>  
> -static yy_state_type yy_get_previous_state (void );
> -static yy_state_type yy_try_NUL_trans (yy_state_type current_state  );
> -static int yy_get_next_buffer (void );
> -static void yy_fatal_error (yyconst char msg[]  );
> +static yy_state_type yy_get_previous_state ( void );
> +static yy_state_type yy_try_NUL_trans ( yy_state_type current_state  );
> +static int yy_get_next_buffer ( void );
> +static void yynoreturn yy_fatal_error ( const char* msg  );
>  
>  /* Done after the current pattern has been matched and before the
>   * corresponding action - sets up yytext.
>   */
>  #define YY_DO_BEFORE_ACTION \
>  	(yytext_ptr) = yy_bp; \
> -	yyleng = (size_t) (yy_cp - yy_bp); \
> +	yyleng = (int) (yy_cp - yy_bp); \
>  	(yy_hold_char) = *yy_cp; \
>  	*yy_cp = '\0'; \
>  	(yy_c_buf_p) = yy_cp;
> -
> -#define YY_NUM_RULES 30
> -#define YY_END_OF_BUFFER 31
> +#define YY_NUM_RULES 31
> +#define YY_END_OF_BUFFER 32
>  /* This struct is not used in this scanner,
>     but its presence is necessary. */
>  struct yy_trans_info
> @@ -382,28 +364,29 @@ struct yy_trans_info
>  	flex_int32_t yy_verify;
>  	flex_int32_t yy_nxt;
>  	};
> -static yyconst flex_int16_t yy_accept[159] =
> +static const flex_int16_t yy_accept[166] =
>      {   0,
> -        0,    0,    0,    0,    0,    0,    0,    0,   31,   29,
> -       18,   18,   29,   29,   29,   29,   29,   29,   29,   29,
> -       29,   29,   29,   29,   29,   29,   15,   16,   16,   29,
> -       16,   10,   10,   18,   26,    0,    3,    0,   27,   12,
> -        0,    0,   11,    0,    0,    0,    0,    0,    0,    0,
> -       21,   23,   25,   24,   22,    0,    9,   28,    0,    0,
> -        0,   14,   14,   16,   16,   16,   10,   10,   10,    0,
> -       12,    0,   11,    0,    0,    0,   20,    0,    0,    0,
> -        0,    0,    0,    0,    0,   16,   10,   10,   10,    0,
> -       13,   19,    0,    0,    0,    0,    0,    0,    0,    0,
> -
> -        0,   16,    0,    0,    0,    0,    0,    0,    0,    0,
> -        0,   16,    6,    0,    0,    0,    0,    0,    0,    2,
> -        0,    0,    0,    0,    0,    0,    0,    0,    4,   17,
> -        0,    0,    2,    0,    0,    0,    0,    0,    0,    0,
> -        0,    0,    0,    0,    0,    1,    0,    0,    0,    0,
> -        5,    8,    0,    0,    0,    0,    7,    0
> +        0,    0,    0,    0,    0,    0,    0,    0,   32,   30,
> +       19,   19,   30,   30,   30,   30,   30,   30,   30,   30,
> +       30,   30,   30,   30,   30,   30,   16,   17,   17,   30,
> +       17,   11,   11,   19,   27,    0,    3,    0,   28,   13,
> +        0,    0,   12,    0,    0,    0,    0,    0,    0,    0,
> +        0,   22,   24,   26,   25,   23,    0,   10,   29,    0,
> +        0,    0,   15,   15,   17,   17,   17,   11,   11,   11,
> +        0,   13,    0,   12,    0,    0,    0,   21,    0,    0,
> +        0,    0,    0,    0,    0,    0,    0,   17,   11,   11,
> +       11,    0,   14,   20,    0,    0,    0,    0,    0,    0,
> +
> +        0,    0,    0,    0,   17,    0,    0,    0,    0,    0,
> +        0,    0,    0,    0,    0,   17,    7,    0,    0,    0,
> +        0,    0,    0,    0,    2,    0,    0,    0,    0,    0,
> +        0,    0,    0,    0,    4,   18,    0,    0,    5,    2,
> +        0,    0,    0,    0,    0,    0,    0,    0,    0,    0,
> +        0,    0,    1,    0,    0,    0,    0,    6,    9,    0,
> +        0,    0,    0,    8,    0
>      } ;
>  
> -static yyconst flex_int32_t yy_ec[256] =
> +static const YY_CHAR yy_ec[256] =
>      {   0,
>          1,    1,    1,    1,    1,    1,    1,    1,    2,    3,
>          4,    4,    4,    1,    1,    1,    1,    1,    1,    1,
> @@ -416,9 +399,9 @@ static yyconst flex_int32_t yy_ec[256] =
>         22,   22,   22,   22,   24,   22,   22,   25,   22,   22,
>          1,   26,   27,    1,   22,    1,   21,   28,   29,   30,
>  
> -       31,   21,   22,   22,   32,   22,   22,   33,   34,   35,
> -       36,   37,   22,   38,   39,   40,   41,   42,   22,   25,
> -       43,   22,   44,   45,   46,    1,    1,    1,    1,    1,
> +       31,   21,   32,   22,   33,   22,   22,   34,   35,   36,
> +       37,   38,   22,   39,   40,   41,   42,   43,   22,   25,
> +       44,   22,   45,   46,   47,    1,    1,    1,    1,    1,
>          1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
>          1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
>          1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
> @@ -435,163 +418,165 @@ static yyconst flex_int32_t yy_ec[256] =
>          1,    1,    1,    1,    1
>      } ;
>  
> -static yyconst flex_int32_t yy_meta[47] =
> +static const YY_CHAR yy_meta[48] =
>      {   0,
>          1,    1,    1,    1,    1,    1,    2,    3,    1,    2,
>          2,    2,    4,    5,    5,    5,    6,    1,    1,    1,
>          7,    8,    8,    8,    8,    1,    1,    7,    7,    7,
>          7,    8,    8,    8,    8,    8,    8,    8,    8,    8,
> -        8,    8,    8,    3,    1,    4
> +        8,    8,    8,    8,    3,    1,    4
>      } ;
>  
> -static yyconst flex_int16_t yy_base[173] =
> +static const flex_int16_t yy_base[180] =
>      {   0,
> -        0,  383,   34,  382,   65,  381,   37,  105,  387,  391,
> -       54,  111,  367,  110,  109,  109,  112,   41,  366,  104,
> -      367,  338,  124,  117,    0,  144,  391,    0,  121,    0,
> -      135,  155,  140,  179,  391,  160,  391,  379,  391,    0,
> -      368,  141,  391,  167,  370,  376,  346,  103,  342,  345,
> -      391,  391,  391,  391,  391,  358,  391,  391,  175,  342,
> -      338,  391,  355,    0,  185,  339,  184,  347,  346,    0,
> -        0,  322,  175,  357,  175,  363,  352,  324,  330,  323,
> -      332,  326,  201,  324,  329,  322,  391,  333,  181,  309,
> -      391,  341,  340,  313,  320,  338,  178,  311,  146,  317,
> -
> -      314,  315,  335,  331,  303,  300,  309,  299,  308,  188,
> -      336,  335,  391,  305,  320,  281,  283,  271,  203,  288,
> -      281,  271,  266,  264,  245,  242,  208,  104,  391,  391,
> -      244,  218,  204,  219,  206,  224,  201,  212,  204,  229,
> -      215,  208,  207,  200,  219,  391,  233,  221,  200,  181,
> -      391,  391,  149,  122,   86,   41,  391,  391,  245,  251,
> -      259,  263,  267,  273,  280,  284,  292,  300,  304,  310,
> -      318,  326
> +        0,  393,   35,  392,   66,  391,   38,  107,  397,  401,
> +       55,  113,  377,  112,  111,  111,  114,   42,  376,  106,
> +      377,  347,  126,  120,    0,  147,  401,    0,  124,    0,
> +      137,  158,  170,  163,  401,  153,  401,  389,  401,    0,
> +      378,  120,  401,  131,  380,  386,  355,  139,  351,  355,
> +      351,  401,  401,  401,  401,  401,  367,  401,  401,  185,
> +      350,  346,  401,  364,    0,  185,  347,  189,  356,  355,
> +        0,    0,  330,  180,  366,  141,  372,  361,  332,  338,
> +      331,  341,  334,  326,  205,  331,  337,  329,  401,  341,
> +      167,  316,  401,  349,  348,  320,  328,  346,  180,  318,
> +
> +      324,  209,  324,  320,  322,  342,  338,  309,  306,  315,
> +      305,  315,  312,  192,  342,  341,  401,  293,  306,  282,
> +      268,  252,  255,  203,  285,  282,  272,  268,  252,  233,
> +      232,  239,  208,  107,  401,  401,  238,  211,  401,  211,
> +      212,  208,  228,  203,  215,  207,  233,  222,  212,  211,
> +      203,  227,  401,  237,  225,  204,  185,  401,  401,  149,
> +      128,   88,   42,  401,  401,  253,  259,  267,  271,  275,
> +      281,  288,  292,  300,  308,  312,  318,  326,  334
>      } ;
>  
> -static yyconst flex_int16_t yy_def[173] =
> +static const flex_int16_t yy_def[180] =
>      {   0,
> -      158,    1,    1,    3,  158,    5,    1,    1,  158,  158,
> -      158,  158,  158,  159,  160,  161,  158,  158,  158,  158,
> -      162,  158,  158,  158,  163,  162,  158,  164,  165,  164,
> -      164,  158,  158,  158,  158,  159,  158,  159,  158,  166,
> -      158,  161,  158,  161,  167,  168,  158,  158,  158,  158,
> -      158,  158,  158,  158,  158,  162,  158,  158,  158,  158,
> -      158,  158,  162,  164,  165,  164,  158,  158,  158,  169,
> -      166,  170,  161,  167,  167,  168,  158,  158,  158,  158,
> -      158,  158,  158,  158,  158,  164,  158,  158,  169,  170,
> -      158,  158,  158,  158,  158,  158,  158,  158,  158,  158,
> -
> -      158,  164,  158,  158,  158,  158,  158,  158,  158,  171,
> -      158,  164,  158,  158,  158,  158,  158,  158,  171,  158,
> -      171,  158,  158,  158,  158,  158,  158,  158,  158,  158,
> -      158,  158,  158,  158,  158,  158,  158,  158,  158,  158,
> -      172,  158,  158,  158,  172,  158,  172,  158,  158,  158,
> -      158,  158,  158,  158,  158,  158,  158,    0,  158,  158,
> -      158,  158,  158,  158,  158,  158,  158,  158,  158,  158,
> -      158,  158
> +      165,    1,    1,    3,  165,    5,    1,    1,  165,  165,
> +      165,  165,  165,  166,  167,  168,  165,  165,  165,  165,
> +      169,  165,  165,  165,  170,  169,  165,  171,  172,  171,
> +      171,  165,  165,  165,  165,  166,  165,  166,  165,  173,
> +      165,  168,  165,  168,  174,  175,  165,  165,  165,  165,
> +      165,  165,  165,  165,  165,  165,  169,  165,  165,  165,
> +      165,  165,  165,  169,  171,  172,  171,  165,  165,  165,
> +      176,  173,  177,  168,  174,  174,  175,  165,  165,  165,
> +      165,  165,  165,  165,  165,  165,  165,  171,  165,  165,
> +      176,  177,  165,  165,  165,  165,  165,  165,  165,  165,
> +
> +      165,  165,  165,  165,  171,  165,  165,  165,  165,  165,
> +      165,  165,  165,  178,  165,  171,  165,  165,  165,  165,
> +      165,  165,  165,  178,  165,  178,  165,  165,  165,  165,
> +      165,  165,  165,  165,  165,  165,  165,  165,  165,  165,
> +      165,  165,  165,  165,  165,  165,  165,  179,  165,  165,
> +      165,  179,  165,  179,  165,  165,  165,  165,  165,  165,
> +      165,  165,  165,  165,    0,  165,  165,  165,  165,  165,
> +      165,  165,  165,  165,  165,  165,  165,  165,  165
>      } ;
>  
> -static yyconst flex_int16_t yy_nxt[438] =
> +static const flex_int16_t yy_nxt[449] =
>      {   0,
>         10,   11,   12,   11,   13,   14,   10,   15,   16,   10,
>         10,   10,   17,   10,   10,   10,   10,   18,   19,   20,
>         21,   21,   21,   21,   21,   10,   10,   21,   21,   21,
>         21,   21,   21,   21,   21,   21,   21,   21,   21,   21,
> -       21,   21,   21,   10,   22,   10,   24,   25,   25,   25,
> -       32,   33,   33,  157,   26,   34,   34,   34,   51,   52,
> -       27,   26,   26,   26,   26,   10,   11,   12,   11,   13,
> -       14,   28,   15,   16,   28,   28,   28,   24,   28,   28,
> -       28,   10,   18,   19,   20,   29,   29,   29,   29,   29,
> -       30,   10,   29,   29,   29,   29,   29,   29,   29,   29,
> -
> -       29,   29,   29,   29,   29,   29,   29,   29,   10,   22,
> -       10,   23,   34,   34,   34,   37,   39,   43,   32,   33,
> -       33,   45,   54,   55,   46,   59,   45,   64,  156,   46,
> -       64,   64,   64,   79,   44,   38,   59,   57,  134,   47,
> -      135,   48,   80,   49,   47,   50,   48,   99,   61,   43,
> -       50,  110,   41,   67,   67,   67,   60,   63,   63,   63,
> -       57,  155,   68,   69,   63,   37,   44,   66,   67,   67,
> -       67,   63,   63,   63,   63,   73,   59,   68,   69,   70,
> -       34,   34,   34,   43,   75,   38,  154,   92,   83,   83,
> -       83,   64,   44,  120,   64,   64,   64,   67,   67,   67,
> -
> -       44,   57,   99,   68,   69,  107,   68,   69,  120,  127,
> -      108,  153,  152,  121,   83,   83,   83,  133,  133,  133,
> -      146,  133,  133,  133,  146,  140,  140,  140,  121,  141,
> -      140,  140,  140,  151,  141,  158,  150,  149,  148,  144,
> -      147,  143,  142,  139,  147,   36,   36,   36,   36,   36,
> -       36,   36,   36,   40,  138,  137,  136,   40,   40,   42,
> -       42,   42,   42,   42,   42,   42,   42,   56,   56,   56,
> -       56,   62,  132,   62,   64,  131,  130,   64,  129,   64,
> -       64,   65,  128,  158,   65,   65,   65,   65,   71,  127,
> -       71,   71,   74,   74,   74,   74,   74,   74,   74,   74,
> -
> -       76,   76,   76,   76,   76,   76,   76,   76,   89,  126,
> -       89,   90,  125,   90,   90,  124,   90,   90,  119,  119,
> -      119,  119,  119,  119,  119,  119,  145,  145,  145,  145,
> -      145,  145,  145,  145,  123,  122,   59,   59,  118,  117,
> -      116,  115,  114,  113,   45,  112,  108,  111,  109,  106,
> -      105,  104,   46,  103,   91,   87,  102,  101,  100,   98,
> -       97,   96,   95,   94,   93,   77,   75,   91,   88,   87,
> -       86,   57,   85,   84,   57,   82,   81,   78,   77,   75,
> -       72,  158,   58,   57,   53,   35,  158,   31,   23,   23,
> -        9,  158,  158,  158,  158,  158,  158,  158,  158,  158,
> -
> -      158,  158,  158,  158,  158,  158,  158,  158,  158,  158,
> -      158,  158,  158,  158,  158,  158,  158,  158,  158,  158,
> -      158,  158,  158,  158,  158,  158,  158,  158,  158,  158,
> -      158,  158,  158,  158,  158,  158,  158
> +       21,   21,   21,   21,   10,   22,   10,   24,   25,   25,
> +       25,   32,   33,   33,  164,   26,   34,   34,   34,   52,
> +       53,   27,   26,   26,   26,   26,   10,   11,   12,   11,
> +       13,   14,   28,   15,   16,   28,   28,   28,   24,   28,
> +       28,   28,   10,   18,   19,   20,   29,   29,   29,   29,
> +       29,   30,   10,   29,   29,   29,   29,   29,   29,   29,
> +
> +       29,   29,   29,   29,   29,   29,   29,   29,   29,   29,
> +       10,   22,   10,   23,   34,   34,   34,   37,   39,   43,
> +       32,   33,   33,   45,   55,   56,   46,   60,   43,   45,
> +       65,  163,   46,   65,   65,   65,   44,   38,   60,   74,
> +       58,   47,  141,   48,  142,   44,   49,   47,   50,   48,
> +       76,   51,   62,   94,   50,   41,   44,   51,   37,   61,
> +       64,   64,   64,   58,   34,   34,   34,   64,  162,   80,
> +       67,   68,   68,   68,   64,   64,   64,   64,   38,   81,
> +       69,   70,   71,   68,   68,   68,   60,  161,   43,   69,
> +       70,   65,   69,   70,   65,   65,   65,  125,   85,   85,
> +
> +       85,   58,   68,   68,   68,   44,  102,  110,  125,  133,
> +      102,   69,   70,  111,  114,  160,  159,  126,   85,   85,
> +       85,  140,  140,  140,  140,  140,  140,  153,  126,  147,
> +      147,  147,  153,  148,  147,  147,  147,  158,  148,  165,
> +      157,  156,  155,  151,  150,  149,  146,  154,  145,  144,
> +      143,  139,  154,   36,   36,   36,   36,   36,   36,   36,
> +       36,   40,  138,  137,  136,   40,   40,   42,   42,   42,
> +       42,   42,   42,   42,   42,   57,   57,   57,   57,   63,
> +      135,   63,   65,  134,  165,   65,  133,   65,   65,   66,
> +      132,  131,   66,   66,   66,   66,   72,  130,   72,   72,
> +
> +       75,   75,   75,   75,   75,   75,   75,   75,   77,   77,
> +       77,   77,   77,   77,   77,   77,   91,  129,   91,   92,
> +      128,   92,   92,  127,   92,   92,  124,  124,  124,  124,
> +      124,  124,  124,  124,  152,  152,  152,  152,  152,  152,
> +      152,  152,   60,   60,  123,  122,  121,  120,  119,  118,
> +      117,   45,  116,  111,  115,  113,  112,  109,  108,  107,
> +       46,  106,   93,   89,  105,  104,  103,  101,  100,   99,
> +       98,   97,   96,   95,   78,   76,   93,   90,   89,   88,
> +       58,   87,   86,   58,   84,   83,   82,   79,   78,   76,
> +       73,  165,   59,   58,   54,   35,  165,   31,   23,   23,
> +
> +        9,  165,  165,  165,  165,  165,  165,  165,  165,  165,
> +      165,  165,  165,  165,  165,  165,  165,  165,  165,  165,
> +      165,  165,  165,  165,  165,  165,  165,  165,  165,  165,
> +      165,  165,  165,  165,  165,  165,  165,  165,  165,  165,
> +      165,  165,  165,  165,  165,  165,  165,  165
>      } ;
>  
> -static yyconst flex_int16_t yy_chk[438] =
> +static const flex_int16_t yy_chk[449] =
>      {   0,
>          1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
>          1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
>          1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
>          1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
> -        1,    1,    1,    1,    1,    1,    3,    3,    3,    3,
> -        7,    7,    7,  156,    3,   11,   11,   11,   18,   18,
> -        3,    3,    3,    3,    3,    5,    5,    5,    5,    5,
> +        1,    1,    1,    1,    1,    1,    1,    3,    3,    3,
> +        3,    7,    7,    7,  163,    3,   11,   11,   11,   18,
> +       18,    3,    3,    3,    3,    3,    5,    5,    5,    5,
>          5,    5,    5,    5,    5,    5,    5,    5,    5,    5,
>          5,    5,    5,    5,    5,    5,    5,    5,    5,    5,
>          5,    5,    5,    5,    5,    5,    5,    5,    5,    5,
>  
>          5,    5,    5,    5,    5,    5,    5,    5,    5,    5,
> -        5,    8,   12,   12,   12,   14,   15,   16,    8,    8,
> -        8,   17,   20,   20,   17,   23,   24,   29,  155,   24,
> -       29,   29,   29,   48,   16,   14,   31,   29,  128,   17,
> -      128,   17,   48,   17,   24,   17,   24,   99,   24,   42,
> -       24,   99,   15,   33,   33,   33,   23,   26,   26,   26,
> -       26,  154,   33,   33,   26,   36,   42,   31,   32,   32,
> -       32,   26,   26,   26,   26,   44,   59,   32,   32,   32,
> -       34,   34,   34,   73,   75,   36,  153,   75,   59,   59,
> -       59,   65,   44,  110,   65,   65,   65,   67,   67,   67,
> -
> -       73,   65,   83,   89,   89,   97,   67,   67,  119,  127,
> -       97,  150,  149,  110,   83,   83,   83,  133,  133,  133,
> -      141,  127,  127,  127,  145,  136,  136,  136,  119,  136,
> -      140,  140,  140,  148,  140,  147,  144,  143,  142,  139,
> -      141,  138,  137,  135,  145,  159,  159,  159,  159,  159,
> -      159,  159,  159,  160,  134,  132,  131,  160,  160,  161,
> -      161,  161,  161,  161,  161,  161,  161,  162,  162,  162,
> -      162,  163,  126,  163,  164,  125,  124,  164,  123,  164,
> -      164,  165,  122,  121,  165,  165,  165,  165,  166,  120,
> -      166,  166,  167,  167,  167,  167,  167,  167,  167,  167,
> -
> -      168,  168,  168,  168,  168,  168,  168,  168,  169,  118,
> -      169,  170,  117,  170,  170,  116,  170,  170,  171,  171,
> -      171,  171,  171,  171,  171,  171,  172,  172,  172,  172,
> -      172,  172,  172,  172,  115,  114,  112,  111,  109,  108,
> -      107,  106,  105,  104,  103,  102,  101,  100,   98,   96,
> -       95,   94,   93,   92,   90,   88,   86,   85,   84,   82,
> -       81,   80,   79,   78,   77,   76,   74,   72,   69,   68,
> -       66,   63,   61,   60,   56,   50,   49,   47,   46,   45,
> +        5,    5,    5,    8,   12,   12,   12,   14,   15,   16,
> +        8,    8,    8,   17,   20,   20,   17,   23,   42,   24,
> +       29,  162,   24,   29,   29,   29,   16,   14,   31,   44,
> +       29,   17,  134,   17,  134,   42,   17,   24,   17,   24,
> +       76,   17,   24,   76,   24,   15,   44,   24,   36,   23,
> +       26,   26,   26,   26,   34,   34,   34,   26,  161,   48,
> +       31,   32,   32,   32,   26,   26,   26,   26,   36,   48,
> +       32,   32,   32,   33,   33,   33,   60,  160,   74,   91,
> +       91,   66,   33,   33,   66,   66,   66,  114,   60,   60,
> +
> +       60,   66,   68,   68,   68,   74,   85,   99,  124,  133,
> +      102,   68,   68,   99,  102,  157,  156,  114,   85,   85,
> +       85,  133,  133,  133,  140,  140,  140,  148,  124,  143,
> +      143,  143,  152,  143,  147,  147,  147,  155,  147,  154,
> +      151,  150,  149,  146,  145,  144,  142,  148,  141,  138,
> +      137,  132,  152,  166,  166,  166,  166,  166,  166,  166,
> +      166,  167,  131,  130,  129,  167,  167,  168,  168,  168,
> +      168,  168,  168,  168,  168,  169,  169,  169,  169,  170,
> +      128,  170,  171,  127,  126,  171,  125,  171,  171,  172,
> +      123,  122,  172,  172,  172,  172,  173,  121,  173,  173,
> +
> +      174,  174,  174,  174,  174,  174,  174,  174,  175,  175,
> +      175,  175,  175,  175,  175,  175,  176,  120,  176,  177,
> +      119,  177,  177,  118,  177,  177,  178,  178,  178,  178,
> +      178,  178,  178,  178,  179,  179,  179,  179,  179,  179,
> +      179,  179,  116,  115,  113,  112,  111,  110,  109,  108,
> +      107,  106,  105,  104,  103,  101,  100,   98,   97,   96,
> +       95,   94,   92,   90,   88,   87,   86,   84,   83,   82,
> +       81,   80,   79,   78,   77,   75,   73,   70,   69,   67,
> +       64,   62,   61,   57,   51,   50,   49,   47,   46,   45,
>         41,   38,   22,   21,   19,   13,    9,    6,    4,    2,
> -      158,  158,  158,  158,  158,  158,  158,  158,  158,  158,
>  
> -      158,  158,  158,  158,  158,  158,  158,  158,  158,  158,
> -      158,  158,  158,  158,  158,  158,  158,  158,  158,  158,
> -      158,  158,  158,  158,  158,  158,  158,  158,  158,  158,
> -      158,  158,  158,  158,  158,  158,  158
> +      165,  165,  165,  165,  165,  165,  165,  165,  165,  165,
> +      165,  165,  165,  165,  165,  165,  165,  165,  165,  165,
> +      165,  165,  165,  165,  165,  165,  165,  165,  165,  165,
> +      165,  165,  165,  165,  165,  165,  165,  165,  165,  165,
> +      165,  165,  165,  165,  165,  165,  165,  165
>      } ;
>  
>  static yy_state_type yy_last_accepting_state;
> @@ -608,7 +593,7 @@ int yy_flex_debug = 0;
>  #define YY_MORE_ADJ 0
>  #define YY_RESTORE_YY_MORE_OFFSET
>  char *yytext;
> -#line 1 "dtc-lexer.l"
> +#line 1 "<stdin>"
>  /*
>   * (C) Copyright David Gibson <dwg at au1.ibm.com>, IBM Corporation.  2005.
>   *
> @@ -632,7 +617,7 @@ char *yytext;
>  
>  
>  
> -#line 37 "dtc-lexer.l"
> +#line 37 "<stdin>"
>  #include "dtc.h"
>  #include "srcpos.h"
>  #include "dtc-parser.tab.h"
> @@ -661,8 +646,10 @@ static int dts_version = 1;
>  
>  static void push_input_file(const char *filename);
>  static bool pop_input_file(void);
> -static void lexical_error(const char *fmt, ...);
> -#line 666 "dtc-lexer.lex.c"
> +static void PRINTF(1, 2) lexical_error(const char *fmt, ...);
> +
> +#line 652 "dtc-lexer.l.c"
> +#line 653 "dtc-lexer.l.c"
>  
>  #define INITIAL 0
>  #define BYTESTRING 1
> @@ -681,36 +668,36 @@ static void lexical_error(const char *fmt, ...);
>  #define YY_EXTRA_TYPE void *
>  #endif
>  
> -static int yy_init_globals (void );
> +static int yy_init_globals ( void );
>  
>  /* Accessor methods to globals.
>     These are made visible to non-reentrant scanners for convenience. */
>  
> -int yylex_destroy (void );
> +int yylex_destroy ( void );
>  
> -int yyget_debug (void );
> +int yyget_debug ( void );
>  
> -void yyset_debug (int debug_flag  );
> +void yyset_debug ( int debug_flag  );
>  
> -YY_EXTRA_TYPE yyget_extra (void );
> +YY_EXTRA_TYPE yyget_extra ( void );
>  
> -void yyset_extra (YY_EXTRA_TYPE user_defined  );
> +void yyset_extra ( YY_EXTRA_TYPE user_defined  );
>  
> -FILE *yyget_in (void );
> +FILE *yyget_in ( void );
>  
> -void yyset_in  (FILE * in_str  );
> +void yyset_in  ( FILE * _in_str  );
>  
> -FILE *yyget_out (void );
> +FILE *yyget_out ( void );
>  
> -void yyset_out  (FILE * out_str  );
> +void yyset_out  ( FILE * _out_str  );
>  
> -yy_size_t yyget_leng (void );
> +			int yyget_leng ( void );
>  
> -char *yyget_text (void );
> +char *yyget_text ( void );
>  
> -int yyget_lineno (void );
> +int yyget_lineno ( void );
>  
> -void yyset_lineno (int line_number  );
> +void yyset_lineno ( int _line_number  );
>  
>  /* Macros after this point can all be overridden by user definitions in
>   * section 1.
> @@ -718,26 +705,29 @@ void yyset_lineno (int line_number  );
>  
>  #ifndef YY_SKIP_YYWRAP
>  #ifdef __cplusplus
> -extern "C" int yywrap (void );
> +extern "C" int yywrap ( void );
>  #else
> -extern int yywrap (void );
> +extern int yywrap ( void );
> +#endif
>  #endif
> +
> +#ifndef YY_NO_UNPUT
> +    
>  #endif
>  
>  #ifndef yytext_ptr
> -static void yy_flex_strncpy (char *,yyconst char *,int );
> +static void yy_flex_strncpy ( char *, const char *, int );
>  #endif
>  
>  #ifdef YY_NEED_STRLEN
> -static int yy_flex_strlen (yyconst char * );
> +static int yy_flex_strlen ( const char * );
>  #endif
>  
>  #ifndef YY_NO_INPUT
> -
>  #ifdef __cplusplus
> -static int yyinput (void );
> +static int yyinput ( void );
>  #else
> -static int input (void );
> +static int input ( void );
>  #endif
>  
>  #endif
> @@ -757,7 +747,7 @@ static int input (void );
>  /* This used to be an fputs(), but since the string might contain NUL's,
>   * we now use fwrite().
>   */
> -#define ECHO do { if (fwrite( yytext, yyleng, 1, yyout )) {} } while (0)
> +#define ECHO do { if (fwrite( yytext, (size_t) yyleng, 1, yyout )) {} } while (0)
>  #endif
>  
>  /* Gets input and stuffs it into "buf".  number of characters read, or YY_NULL,
> @@ -768,7 +758,7 @@ static int input (void );
>  	if ( YY_CURRENT_BUFFER_LVALUE->yy_is_interactive ) \
>  		{ \
>  		int c = '*'; \
> -		size_t n; \
> +		int n; \
>  		for ( n = 0; n < max_size && \
>  			     (c = getc( yyin )) != EOF && c != '\n'; ++n ) \
>  			buf[n] = (char) c; \
> @@ -781,7 +771,7 @@ static int input (void );
>  	else \
>  		{ \
>  		errno=0; \
> -		while ( (result = fread(buf, 1, max_size, yyin))==0 && ferror(yyin)) \
> +		while ( (result = (int) fread(buf, 1, (yy_size_t) max_size, yyin)) == 0 && ferror(yyin)) \
>  			{ \
>  			if( errno != EINTR) \
>  				{ \
> @@ -836,7 +826,7 @@ extern int yylex (void);
>  
>  /* Code executed at the end of each rule. */
>  #ifndef YY_BREAK
> -#define YY_BREAK break;
> +#define YY_BREAK /*LINTED*/break;
>  #endif
>  
>  #define YY_RULE_SETUP \
> @@ -849,9 +839,9 @@ extern int yylex (void);
>   */
>  YY_DECL
>  {
> -	register yy_state_type yy_current_state;
> -	register char *yy_cp, *yy_bp;
> -	register int yy_act;
> +	yy_state_type yy_current_state;
> +	char *yy_cp, *yy_bp;
> +	int yy_act;
>      
>  	if ( !(yy_init) )
>  		{
> @@ -873,18 +863,18 @@ YY_DECL
>  		if ( ! YY_CURRENT_BUFFER ) {
>  			yyensure_buffer_stack ();
>  			YY_CURRENT_BUFFER_LVALUE =
> -				yy_create_buffer(yyin,YY_BUF_SIZE );
> +				yy_create_buffer( yyin, YY_BUF_SIZE );
>  		}
>  
> -		yy_load_buffer_state( );
> +		yy_load_buffer_state(  );
>  		}
>  
>  	{
> -#line 68 "dtc-lexer.l"
> +#line 69 "<stdin>"
>  
> -#line 886 "dtc-lexer.lex.c"
> +#line 876 "dtc-lexer.l.c"
>  
> -	while ( 1 )		/* loops until end-of-file is reached */
> +	while ( /*CONSTCOND*/1 )		/* loops until end-of-file is reached */
>  		{
>  		yy_cp = (yy_c_buf_p);
>  
> @@ -901,7 +891,7 @@ YY_DECL
>  yy_match:
>  		do
>  			{
> -			register YY_CHAR yy_c = yy_ec[YY_SC_TO_UI(*yy_cp)] ;
> +			YY_CHAR yy_c = yy_ec[YY_SC_TO_UI(*yy_cp)] ;
>  			if ( yy_accept[yy_current_state] )
>  				{
>  				(yy_last_accepting_state) = yy_current_state;
> @@ -910,13 +900,13 @@ yy_match:
>  			while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
>  				{
>  				yy_current_state = (int) yy_def[yy_current_state];
> -				if ( yy_current_state >= 159 )
> -					yy_c = yy_meta[(unsigned int) yy_c];
> +				if ( yy_current_state >= 166 )
> +					yy_c = yy_meta[yy_c];
>  				}
> -			yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];
> +			yy_current_state = yy_nxt[yy_base[yy_current_state] + yy_c];
>  			++yy_cp;
>  			}
> -		while ( yy_current_state != 158 );
> +		while ( yy_current_state != 165 );
>  		yy_cp = (yy_last_accepting_cpos);
>  		yy_current_state = (yy_last_accepting_state);
>  
> @@ -939,7 +929,7 @@ do_action:	/* This label is used only to access EOF actions. */
>  case 1:
>  /* rule 1 can match eol */
>  YY_RULE_SETUP
> -#line 69 "dtc-lexer.l"
> +#line 70 "<stdin>"
>  {
>  			char *name = strchr(yytext, '\"') + 1;
>  			yytext[yyleng-1] = '\0';
> @@ -949,33 +939,41 @@ YY_RULE_SETUP
>  case 2:
>  /* rule 2 can match eol */
>  YY_RULE_SETUP
> -#line 75 "dtc-lexer.l"
> +#line 76 "<stdin>"
>  {
> -			char *line, *tmp, *fn;
> +			char *line, *fnstart, *fnend;
> +			struct data fn;
>  			/* skip text before line # */
>  			line = yytext;
>  			while (!isdigit((unsigned char)*line))
>  				line++;
> -			/* skip digits in line # */
> -			tmp = line;
> -			while (!isspace((unsigned char)*tmp))
> -				tmp++;
> -			/* "NULL"-terminate line # */
> -			*tmp = '\0';
> -			/* start of filename */
> -			fn = strchr(tmp + 1, '"') + 1;
> -			/* strip trailing " from filename */
> -			tmp = strchr(fn, '"');
> -			*tmp = 0;
> +
> +			/* regexp ensures that first and list "
> +			 * in the whole yytext are those at
> +			 * beginning and end of the filename string */
> +			fnstart = memchr(yytext, '"', yyleng);
> +			for (fnend = yytext + yyleng - 1;
> +			     *fnend != '"'; fnend--)
> +				;
> +			assert(fnstart && fnend && (fnend > fnstart));
> +
> +			fn = data_copy_escape_string(fnstart + 1,
> +						     fnend - fnstart - 1);
> +
> +			/* Don't allow nuls in filenames */
> +			if (memchr(fn.val, '\0', fn.len - 1))
> +				lexical_error("nul in line number directive");
> +
>  			/* -1 since #line is the number of the next line */
> -			srcpos_set_line(xstrdup(fn), atoi(line) - 1);
> +			srcpos_set_line(xstrdup(fn.val), atoi(line) - 1);
> +			data_free(fn);
>  		}
>  	YY_BREAK
>  case YY_STATE_EOF(INITIAL):
>  case YY_STATE_EOF(BYTESTRING):
>  case YY_STATE_EOF(PROPNODENAME):
>  case YY_STATE_EOF(V1):
> -#line 96 "dtc-lexer.l"
> +#line 105 "<stdin>"
>  {
>  			if (!pop_input_file()) {
>  				yyterminate();
> @@ -985,7 +983,7 @@ case YY_STATE_EOF(V1):
>  case 3:
>  /* rule 3 can match eol */
>  YY_RULE_SETUP
> -#line 102 "dtc-lexer.l"
> +#line 111 "<stdin>"
>  {
>  			DPRINT("String: %s\n", yytext);
>  			yylval.data = data_copy_escape_string(yytext+1,
> @@ -995,7 +993,7 @@ YY_RULE_SETUP
>  	YY_BREAK
>  case 4:
>  YY_RULE_SETUP
> -#line 109 "dtc-lexer.l"
> +#line 118 "<stdin>"
>  {
>  			DPRINT("Keyword: /dts-v1/\n");
>  			dts_version = 1;
> @@ -1005,25 +1003,33 @@ YY_RULE_SETUP
>  	YY_BREAK
>  case 5:
>  YY_RULE_SETUP
> -#line 116 "dtc-lexer.l"
> +#line 125 "<stdin>"
> +{
> +			DPRINT("Keyword: /plugin/\n");
> +			return DT_PLUGIN;
> +		}
> +	YY_BREAK
> +case 6:
> +YY_RULE_SETUP
> +#line 130 "<stdin>"
>  {
>  			DPRINT("Keyword: /memreserve/\n");
>  			BEGIN_DEFAULT();
>  			return DT_MEMRESERVE;
>  		}
>  	YY_BREAK
> -case 6:
> +case 7:
>  YY_RULE_SETUP
> -#line 122 "dtc-lexer.l"
> +#line 136 "<stdin>"
>  {
>  			DPRINT("Keyword: /bits/\n");
>  			BEGIN_DEFAULT();
>  			return DT_BITS;
>  		}
>  	YY_BREAK
> -case 7:
> +case 8:
>  YY_RULE_SETUP
> -#line 128 "dtc-lexer.l"
> +#line 142 "<stdin>"
>  {
>  			DPRINT("Keyword: /delete-property/\n");
>  			DPRINT("<PROPNODENAME>\n");
> @@ -1031,9 +1037,9 @@ YY_RULE_SETUP
>  			return DT_DEL_PROP;
>  		}
>  	YY_BREAK
> -case 8:
> +case 9:
>  YY_RULE_SETUP
> -#line 135 "dtc-lexer.l"
> +#line 149 "<stdin>"
>  {
>  			DPRINT("Keyword: /delete-node/\n");
>  			DPRINT("<PROPNODENAME>\n");
> @@ -1041,9 +1047,9 @@ YY_RULE_SETUP
>  			return DT_DEL_NODE;
>  		}
>  	YY_BREAK
> -case 9:
> +case 10:
>  YY_RULE_SETUP
> -#line 142 "dtc-lexer.l"
> +#line 156 "<stdin>"
>  {
>  			DPRINT("Label: %s\n", yytext);
>  			yylval.labelref = xstrdup(yytext);
> @@ -1051,9 +1057,9 @@ YY_RULE_SETUP
>  			return DT_LABEL;
>  		}
>  	YY_BREAK
> -case 10:
> +case 11:
>  YY_RULE_SETUP
> -#line 149 "dtc-lexer.l"
> +#line 163 "<stdin>"
>  {
>  			char *e;
>  			DPRINT("Integer Literal: '%s'\n", yytext);
> @@ -1061,7 +1067,10 @@ YY_RULE_SETUP
>  			errno = 0;
>  			yylval.integer = strtoull(yytext, &e, 0);
>  
> -			assert(!(*e) || !e[strspn(e, "UL")]);
> +			if (*e && e[strspn(e, "UL")]) {
> +				lexical_error("Bad integer literal '%s'",
> +					      yytext);
> +			}
>  
>  			if (errno == ERANGE)
>  				lexical_error("Integer literal '%s' out of range",
> @@ -1073,10 +1082,10 @@ YY_RULE_SETUP
>  			return DT_LITERAL;
>  		}
>  	YY_BREAK
> -case 11:
> -/* rule 11 can match eol */
> +case 12:
> +/* rule 12 can match eol */
>  YY_RULE_SETUP
> -#line 168 "dtc-lexer.l"
> +#line 185 "<stdin>"
>  {
>  			struct data d;
>  			DPRINT("Character literal: %s\n", yytext);
> @@ -1085,31 +1094,31 @@ YY_RULE_SETUP
>  			if (d.len == 1) {
>  				lexical_error("Empty character literal");
>  				yylval.integer = 0;
> -				return DT_CHAR_LITERAL;
> -			}
> +			} else {
> +				yylval.integer = (unsigned char)d.val[0];
>  
> -			yylval.integer = (unsigned char)d.val[0];
> -
> -			if (d.len > 2)
> -				lexical_error("Character literal has %d"
> -					      " characters instead of 1",
> -					      d.len - 1);
> +				if (d.len > 2)
> +					lexical_error("Character literal has %d"
> +						      " characters instead of 1",
> +						      d.len - 1);
> +			}
>  
> +			data_free(d);
>  			return DT_CHAR_LITERAL;
>  		}
>  	YY_BREAK
> -case 12:
> +case 13:
>  YY_RULE_SETUP
> -#line 189 "dtc-lexer.l"
> +#line 206 "<stdin>"
>  {	/* label reference */
>  			DPRINT("Ref: %s\n", yytext+1);
>  			yylval.labelref = xstrdup(yytext+1);
>  			return DT_REF;
>  		}
>  	YY_BREAK
> -case 13:
> +case 14:
>  YY_RULE_SETUP
> -#line 195 "dtc-lexer.l"
> +#line 212 "<stdin>"
>  {	/* new-style path reference */
>  			yytext[yyleng-1] = '\0';
>  			DPRINT("Ref: %s\n", yytext+2);
> @@ -1117,27 +1126,27 @@ YY_RULE_SETUP
>  			return DT_REF;
>  		}
>  	YY_BREAK
> -case 14:
> +case 15:
>  YY_RULE_SETUP
> -#line 202 "dtc-lexer.l"
> +#line 219 "<stdin>"
>  {
>  			yylval.byte = strtol(yytext, NULL, 16);
>  			DPRINT("Byte: %02x\n", (int)yylval.byte);
>  			return DT_BYTE;
>  		}
>  	YY_BREAK
> -case 15:
> +case 16:
>  YY_RULE_SETUP
> -#line 208 "dtc-lexer.l"
> +#line 225 "<stdin>"
>  {
>  			DPRINT("/BYTESTRING\n");
>  			BEGIN_DEFAULT();
>  			return ']';
>  		}
>  	YY_BREAK
> -case 16:
> +case 17:
>  YY_RULE_SETUP
> -#line 214 "dtc-lexer.l"
> +#line 231 "<stdin>"
>  {
>  			DPRINT("PropNodeName: %s\n", yytext);
>  			yylval.propnodename = xstrdup((yytext[0] == '\\') ?
> @@ -1146,75 +1155,75 @@ YY_RULE_SETUP
>  			return DT_PROPNODENAME;
>  		}
>  	YY_BREAK
> -case 17:
> +case 18:
>  YY_RULE_SETUP
> -#line 222 "dtc-lexer.l"
> +#line 239 "<stdin>"
>  {
>  			DPRINT("Binary Include\n");
>  			return DT_INCBIN;
>  		}
>  	YY_BREAK
> -case 18:
> -/* rule 18 can match eol */
> -YY_RULE_SETUP
> -#line 227 "dtc-lexer.l"
> -/* eat whitespace */
> -	YY_BREAK
>  case 19:
>  /* rule 19 can match eol */
>  YY_RULE_SETUP
> -#line 228 "dtc-lexer.l"
> -/* eat C-style comments */
> +#line 244 "<stdin>"
> +/* eat whitespace */
>  	YY_BREAK
>  case 20:
>  /* rule 20 can match eol */
>  YY_RULE_SETUP
> -#line 229 "dtc-lexer.l"
> -/* eat C++-style comments */
> +#line 245 "<stdin>"
> +/* eat C-style comments */
>  	YY_BREAK
>  case 21:
> +/* rule 21 can match eol */
>  YY_RULE_SETUP
> -#line 231 "dtc-lexer.l"
> -{ return DT_LSHIFT; };
> +#line 246 "<stdin>"
> +/* eat C++-style comments */
>  	YY_BREAK
>  case 22:
>  YY_RULE_SETUP
> -#line 232 "dtc-lexer.l"
> -{ return DT_RSHIFT; };
> +#line 248 "<stdin>"
> +{ return DT_LSHIFT; };
>  	YY_BREAK
>  case 23:
>  YY_RULE_SETUP
> -#line 233 "dtc-lexer.l"
> -{ return DT_LE; };
> +#line 249 "<stdin>"
> +{ return DT_RSHIFT; };
>  	YY_BREAK
>  case 24:
>  YY_RULE_SETUP
> -#line 234 "dtc-lexer.l"
> -{ return DT_GE; };
> +#line 250 "<stdin>"
> +{ return DT_LE; };
>  	YY_BREAK
>  case 25:
>  YY_RULE_SETUP
> -#line 235 "dtc-lexer.l"
> -{ return DT_EQ; };
> +#line 251 "<stdin>"
> +{ return DT_GE; };
>  	YY_BREAK
>  case 26:
>  YY_RULE_SETUP
> -#line 236 "dtc-lexer.l"
> -{ return DT_NE; };
> +#line 252 "<stdin>"
> +{ return DT_EQ; };
>  	YY_BREAK
>  case 27:
>  YY_RULE_SETUP
> -#line 237 "dtc-lexer.l"
> -{ return DT_AND; };
> +#line 253 "<stdin>"
> +{ return DT_NE; };
>  	YY_BREAK
>  case 28:
>  YY_RULE_SETUP
> -#line 238 "dtc-lexer.l"
> -{ return DT_OR; };
> +#line 254 "<stdin>"
> +{ return DT_AND; };
>  	YY_BREAK
>  case 29:
>  YY_RULE_SETUP
> -#line 240 "dtc-lexer.l"
> +#line 255 "<stdin>"
> +{ return DT_OR; };
> +	YY_BREAK
> +case 30:
> +YY_RULE_SETUP
> +#line 257 "<stdin>"
>  {
>  			DPRINT("Char: %c (\\x%02x)\n", yytext[0],
>  				(unsigned)yytext[0]);
> @@ -1230,12 +1239,12 @@ YY_RULE_SETUP
>  			return yytext[0];
>  		}
>  	YY_BREAK
> -case 30:
> +case 31:
>  YY_RULE_SETUP
> -#line 255 "dtc-lexer.l"
> +#line 272 "<stdin>"
>  ECHO;
>  	YY_BREAK
> -#line 1239 "dtc-lexer.lex.c"
> +#line 1248 "dtc-lexer.l.c"
>  
>  	case YY_END_OF_BUFFER:
>  		{
> @@ -1312,7 +1321,7 @@ ECHO;
>  				{
>  				(yy_did_buffer_switch_on_eof) = 0;
>  
> -				if ( yywrap( ) )
> +				if ( yywrap(  ) )
>  					{
>  					/* Note: because we've taken care in
>  					 * yy_get_next_buffer() to have set up
> @@ -1377,9 +1386,9 @@ ECHO;
>   */
>  static int yy_get_next_buffer (void)
>  {
> -    	register char *dest = YY_CURRENT_BUFFER_LVALUE->yy_ch_buf;
> -	register char *source = (yytext_ptr);
> -	register int number_to_move, i;
> +    	char *dest = YY_CURRENT_BUFFER_LVALUE->yy_ch_buf;
> +	char *source = (yytext_ptr);
> +	int number_to_move, i;
>  	int ret_val;
>  
>  	if ( (yy_c_buf_p) > &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars) + 1] )
> @@ -1408,7 +1417,7 @@ static int yy_get_next_buffer (void)
>  	/* Try to read more data. */
>  
>  	/* First move last chars to start of buffer. */
> -	number_to_move = (int) ((yy_c_buf_p) - (yytext_ptr)) - 1;
> +	number_to_move = (int) ((yy_c_buf_p) - (yytext_ptr) - 1);
>  
>  	for ( i = 0; i < number_to_move; ++i )
>  		*(dest++) = *(source++);
> @@ -1421,7 +1430,7 @@ static int yy_get_next_buffer (void)
>  
>  	else
>  		{
> -			yy_size_t num_to_read =
> +			int num_to_read =
>  			YY_CURRENT_BUFFER_LVALUE->yy_buf_size - number_to_move - 1;
>  
>  		while ( num_to_read <= 0 )
> @@ -1435,7 +1444,7 @@ static int yy_get_next_buffer (void)
>  
>  			if ( b->yy_is_our_buffer )
>  				{
> -				yy_size_t new_size = b->yy_buf_size * 2;
> +				int new_size = b->yy_buf_size * 2;
>  
>  				if ( new_size <= 0 )
>  					b->yy_buf_size += b->yy_buf_size / 8;
> @@ -1444,11 +1453,12 @@ static int yy_get_next_buffer (void)
>  
>  				b->yy_ch_buf = (char *)
>  					/* Include room in for 2 EOB chars. */
> -					yyrealloc((void *) b->yy_ch_buf,b->yy_buf_size + 2  );
> +					yyrealloc( (void *) b->yy_ch_buf,
> +							 (yy_size_t) (b->yy_buf_size + 2)  );
>  				}
>  			else
>  				/* Can't grow it, we don't own it. */
> -				b->yy_ch_buf = 0;
> +				b->yy_ch_buf = NULL;
>  
>  			if ( ! b->yy_ch_buf )
>  				YY_FATAL_ERROR(
> @@ -1476,7 +1486,7 @@ static int yy_get_next_buffer (void)
>  		if ( number_to_move == YY_MORE_ADJ )
>  			{
>  			ret_val = EOB_ACT_END_OF_FILE;
> -			yyrestart(yyin  );
> +			yyrestart( yyin  );
>  			}
>  
>  		else
> @@ -1490,12 +1500,15 @@ static int yy_get_next_buffer (void)
>  	else
>  		ret_val = EOB_ACT_CONTINUE_SCAN;
>  
> -	if ((yy_size_t) ((yy_n_chars) + number_to_move) > YY_CURRENT_BUFFER_LVALUE->yy_buf_size) {
> +	if (((yy_n_chars) + number_to_move) > YY_CURRENT_BUFFER_LVALUE->yy_buf_size) {
>  		/* Extend the array by 50%, plus the number we really need. */
> -		yy_size_t new_size = (yy_n_chars) + number_to_move + ((yy_n_chars) >> 1);
> -		YY_CURRENT_BUFFER_LVALUE->yy_ch_buf = (char *) yyrealloc((void *) YY_CURRENT_BUFFER_LVALUE->yy_ch_buf,new_size  );
> +		int new_size = (yy_n_chars) + number_to_move + ((yy_n_chars) >> 1);
> +		YY_CURRENT_BUFFER_LVALUE->yy_ch_buf = (char *) yyrealloc(
> +			(void *) YY_CURRENT_BUFFER_LVALUE->yy_ch_buf, (yy_size_t) new_size  );
>  		if ( ! YY_CURRENT_BUFFER_LVALUE->yy_ch_buf )
>  			YY_FATAL_ERROR( "out of dynamic memory in yy_get_next_buffer()" );
> +		/* "- 2" to take care of EOB's */
> +		YY_CURRENT_BUFFER_LVALUE->yy_buf_size = (int) (new_size - 2);
>  	}
>  
>  	(yy_n_chars) += number_to_move;
> @@ -1511,15 +1524,15 @@ static int yy_get_next_buffer (void)
>  
>      static yy_state_type yy_get_previous_state (void)
>  {
> -	register yy_state_type yy_current_state;
> -	register char *yy_cp;
> +	yy_state_type yy_current_state;
> +	char *yy_cp;
>      
>  	yy_current_state = (yy_start);
>  	yy_current_state += YY_AT_BOL();
>  
>  	for ( yy_cp = (yytext_ptr) + YY_MORE_ADJ; yy_cp < (yy_c_buf_p); ++yy_cp )
>  		{
> -		register YY_CHAR yy_c = (*yy_cp ? yy_ec[YY_SC_TO_UI(*yy_cp)] : 1);
> +		YY_CHAR yy_c = (*yy_cp ? yy_ec[YY_SC_TO_UI(*yy_cp)] : 1);
>  		if ( yy_accept[yy_current_state] )
>  			{
>  			(yy_last_accepting_state) = yy_current_state;
> @@ -1528,10 +1541,10 @@ static int yy_get_next_buffer (void)
>  		while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
>  			{
>  			yy_current_state = (int) yy_def[yy_current_state];
> -			if ( yy_current_state >= 159 )
> -				yy_c = yy_meta[(unsigned int) yy_c];
> +			if ( yy_current_state >= 166 )
> +				yy_c = yy_meta[yy_c];
>  			}
> -		yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];
> +		yy_current_state = yy_nxt[yy_base[yy_current_state] + yy_c];
>  		}
>  
>  	return yy_current_state;
> @@ -1544,10 +1557,10 @@ static int yy_get_next_buffer (void)
>   */
>      static yy_state_type yy_try_NUL_trans  (yy_state_type yy_current_state )
>  {
> -	register int yy_is_jam;
> -    	register char *yy_cp = (yy_c_buf_p);
> +	int yy_is_jam;
> +    	char *yy_cp = (yy_c_buf_p);
>  
> -	register YY_CHAR yy_c = 1;
> +	YY_CHAR yy_c = 1;
>  	if ( yy_accept[yy_current_state] )
>  		{
>  		(yy_last_accepting_state) = yy_current_state;
> @@ -1556,15 +1569,19 @@ static int yy_get_next_buffer (void)
>  	while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
>  		{
>  		yy_current_state = (int) yy_def[yy_current_state];
> -		if ( yy_current_state >= 159 )
> -			yy_c = yy_meta[(unsigned int) yy_c];
> +		if ( yy_current_state >= 166 )
> +			yy_c = yy_meta[yy_c];
>  		}
> -	yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];
> -	yy_is_jam = (yy_current_state == 158);
> +	yy_current_state = yy_nxt[yy_base[yy_current_state] + yy_c];
> +	yy_is_jam = (yy_current_state == 165);
>  
>  		return yy_is_jam ? 0 : yy_current_state;
>  }
>  
> +#ifndef YY_NO_UNPUT
> +
> +#endif
> +
>  #ifndef YY_NO_INPUT
>  #ifdef __cplusplus
>      static int yyinput (void)
> @@ -1589,7 +1606,7 @@ static int yy_get_next_buffer (void)
>  
>  		else
>  			{ /* need more input */
> -			yy_size_t offset = (yy_c_buf_p) - (yytext_ptr);
> +			int offset = (int) ((yy_c_buf_p) - (yytext_ptr));
>  			++(yy_c_buf_p);
>  
>  			switch ( yy_get_next_buffer(  ) )
> @@ -1606,14 +1623,14 @@ static int yy_get_next_buffer (void)
>  					 */
>  
>  					/* Reset buffer status. */
> -					yyrestart(yyin );
> +					yyrestart( yyin );
>  
>  					/*FALLTHROUGH*/
>  
>  				case EOB_ACT_END_OF_FILE:
>  					{
> -					if ( yywrap( ) )
> -						return EOF;
> +					if ( yywrap(  ) )
> +						return 0;
>  
>  					if ( ! (yy_did_buffer_switch_on_eof) )
>  						YY_NEW_FILE;
> @@ -1652,11 +1669,11 @@ static int yy_get_next_buffer (void)
>  	if ( ! YY_CURRENT_BUFFER ){
>          yyensure_buffer_stack ();
>  		YY_CURRENT_BUFFER_LVALUE =
> -            yy_create_buffer(yyin,YY_BUF_SIZE );
> +            yy_create_buffer( yyin, YY_BUF_SIZE );
>  	}
>  
> -	yy_init_buffer(YY_CURRENT_BUFFER,input_file );
> -	yy_load_buffer_state( );
> +	yy_init_buffer( YY_CURRENT_BUFFER, input_file );
> +	yy_load_buffer_state(  );
>  }
>  
>  /** Switch to a different input buffer.
> @@ -1684,7 +1701,7 @@ static int yy_get_next_buffer (void)
>  		}
>  
>  	YY_CURRENT_BUFFER_LVALUE = new_buffer;
> -	yy_load_buffer_state( );
> +	yy_load_buffer_state(  );
>  
>  	/* We don't actually know whether we did this switch during
>  	 * EOF (yywrap()) processing, but the only time this flag
> @@ -1712,7 +1729,7 @@ static void yy_load_buffer_state  (void)
>  {
>  	YY_BUFFER_STATE b;
>      
> -	b = (YY_BUFFER_STATE) yyalloc(sizeof( struct yy_buffer_state )  );
> +	b = (YY_BUFFER_STATE) yyalloc( sizeof( struct yy_buffer_state )  );
>  	if ( ! b )
>  		YY_FATAL_ERROR( "out of dynamic memory in yy_create_buffer()" );
>  
> @@ -1721,13 +1738,13 @@ static void yy_load_buffer_state  (void)
>  	/* yy_ch_buf has to be 2 characters longer than the size given because
>  	 * we need to put in 2 end-of-buffer characters.
>  	 */
> -	b->yy_ch_buf = (char *) yyalloc(b->yy_buf_size + 2  );
> +	b->yy_ch_buf = (char *) yyalloc( (yy_size_t) (b->yy_buf_size + 2)  );
>  	if ( ! b->yy_ch_buf )
>  		YY_FATAL_ERROR( "out of dynamic memory in yy_create_buffer()" );
>  
>  	b->yy_is_our_buffer = 1;
>  
> -	yy_init_buffer(b,file );
> +	yy_init_buffer( b, file );
>  
>  	return b;
>  }
> @@ -1746,9 +1763,9 @@ static void yy_load_buffer_state  (void)
>  		YY_CURRENT_BUFFER_LVALUE = (YY_BUFFER_STATE) 0;
>  
>  	if ( b->yy_is_our_buffer )
> -		yyfree((void *) b->yy_ch_buf  );
> +		yyfree( (void *) b->yy_ch_buf  );
>  
> -	yyfree((void *) b  );
> +	yyfree( (void *) b  );
>  }
>  
>  /* Initializes or reinitializes a buffer.
> @@ -1760,7 +1777,7 @@ static void yy_load_buffer_state  (void)
>  {
>  	int oerrno = errno;
>      
> -	yy_flush_buffer(b );
> +	yy_flush_buffer( b );
>  
>  	b->yy_input_file = file;
>  	b->yy_fill_buffer = 1;
> @@ -1803,7 +1820,7 @@ static void yy_load_buffer_state  (void)
>  	b->yy_buffer_status = YY_BUFFER_NEW;
>  
>  	if ( b == YY_CURRENT_BUFFER )
> -		yy_load_buffer_state( );
> +		yy_load_buffer_state(  );
>  }
>  
>  /** Pushes the new state onto the stack. The new state becomes
> @@ -1834,7 +1851,7 @@ void yypush_buffer_state (YY_BUFFER_STATE new_buffer )
>  	YY_CURRENT_BUFFER_LVALUE = new_buffer;
>  
>  	/* copied from yy_switch_to_buffer. */
> -	yy_load_buffer_state( );
> +	yy_load_buffer_state(  );
>  	(yy_did_buffer_switch_on_eof) = 1;
>  }
>  
> @@ -1853,7 +1870,7 @@ void yypop_buffer_state (void)
>  		--(yy_buffer_stack_top);
>  
>  	if (YY_CURRENT_BUFFER) {
> -		yy_load_buffer_state( );
> +		yy_load_buffer_state(  );
>  		(yy_did_buffer_switch_on_eof) = 1;
>  	}
>  }
> @@ -1871,15 +1888,15 @@ static void yyensure_buffer_stack (void)
>  		 * scanner will even need a stack. We use 2 instead of 1 to avoid an
>  		 * immediate realloc on the next call.
>           */
> -		num_to_alloc = 1;
> +      num_to_alloc = 1; /* After all that talk, this was set to 1 anyways... */
>  		(yy_buffer_stack) = (struct yy_buffer_state**)yyalloc
>  								(num_to_alloc * sizeof(struct yy_buffer_state*)
>  								);
>  		if ( ! (yy_buffer_stack) )
>  			YY_FATAL_ERROR( "out of dynamic memory in yyensure_buffer_stack()" );
> -								  
> +
>  		memset((yy_buffer_stack), 0, num_to_alloc * sizeof(struct yy_buffer_state*));
> -				
> +
>  		(yy_buffer_stack_max) = num_to_alloc;
>  		(yy_buffer_stack_top) = 0;
>  		return;
> @@ -1888,7 +1905,7 @@ static void yyensure_buffer_stack (void)
>  	if ((yy_buffer_stack_top) >= ((yy_buffer_stack_max)) - 1){
>  
>  		/* Increase the buffer to prepare for a possible push. */
> -		int grow_size = 8 /* arbitrary grow size */;
> +		yy_size_t grow_size = 8 /* arbitrary grow size */;
>  
>  		num_to_alloc = (yy_buffer_stack_max) + grow_size;
>  		(yy_buffer_stack) = (struct yy_buffer_state**)yyrealloc
> @@ -1908,7 +1925,7 @@ static void yyensure_buffer_stack (void)
>   * @param base the character buffer
>   * @param size the size in bytes of the character buffer
>   * 
> - * @return the newly allocated buffer state object. 
> + * @return the newly allocated buffer state object.
>   */
>  YY_BUFFER_STATE yy_scan_buffer  (char * base, yy_size_t  size )
>  {
> @@ -1918,23 +1935,23 @@ YY_BUFFER_STATE yy_scan_buffer  (char * base, yy_size_t  size )
>  	     base[size-2] != YY_END_OF_BUFFER_CHAR ||
>  	     base[size-1] != YY_END_OF_BUFFER_CHAR )
>  		/* They forgot to leave room for the EOB's. */
> -		return 0;
> +		return NULL;
>  
> -	b = (YY_BUFFER_STATE) yyalloc(sizeof( struct yy_buffer_state )  );
> +	b = (YY_BUFFER_STATE) yyalloc( sizeof( struct yy_buffer_state )  );
>  	if ( ! b )
>  		YY_FATAL_ERROR( "out of dynamic memory in yy_scan_buffer()" );
>  
> -	b->yy_buf_size = size - 2;	/* "- 2" to take care of EOB's */
> +	b->yy_buf_size = (int) (size - 2);	/* "- 2" to take care of EOB's */
>  	b->yy_buf_pos = b->yy_ch_buf = base;
>  	b->yy_is_our_buffer = 0;
> -	b->yy_input_file = 0;
> +	b->yy_input_file = NULL;
>  	b->yy_n_chars = b->yy_buf_size;
>  	b->yy_is_interactive = 0;
>  	b->yy_at_bol = 1;
>  	b->yy_fill_buffer = 0;
>  	b->yy_buffer_status = YY_BUFFER_NEW;
>  
> -	yy_switch_to_buffer(b  );
> +	yy_switch_to_buffer( b  );
>  
>  	return b;
>  }
> @@ -1947,10 +1964,10 @@ YY_BUFFER_STATE yy_scan_buffer  (char * base, yy_size_t  size )
>   * @note If you want to scan bytes that may contain NUL values, then use
>   *       yy_scan_bytes() instead.
>   */
> -YY_BUFFER_STATE yy_scan_string (yyconst char * yystr )
> +YY_BUFFER_STATE yy_scan_string (const char * yystr )
>  {
>      
> -	return yy_scan_bytes(yystr,strlen(yystr) );
> +	return yy_scan_bytes( yystr, (int) strlen(yystr) );
>  }
>  
>  /** Setup the input buffer state to scan the given bytes. The next call to yylex() will
> @@ -1960,16 +1977,16 @@ YY_BUFFER_STATE yy_scan_string (yyconst char * yystr )
>   * 
>   * @return the newly allocated buffer state object.
>   */
> -YY_BUFFER_STATE yy_scan_bytes  (yyconst char * yybytes, yy_size_t  _yybytes_len )
> +YY_BUFFER_STATE yy_scan_bytes  (const char * yybytes, int  _yybytes_len )
>  {
>  	YY_BUFFER_STATE b;
>  	char *buf;
>  	yy_size_t n;
> -	yy_size_t i;
> +	int i;
>      
>  	/* Get memory for full buffer, including space for trailing EOB's. */
> -	n = _yybytes_len + 2;
> -	buf = (char *) yyalloc(n  );
> +	n = (yy_size_t) (_yybytes_len + 2);
> +	buf = (char *) yyalloc( n  );
>  	if ( ! buf )
>  		YY_FATAL_ERROR( "out of dynamic memory in yy_scan_bytes()" );
>  
> @@ -1978,7 +1995,7 @@ YY_BUFFER_STATE yy_scan_bytes  (yyconst char * yybytes, yy_size_t  _yybytes_len
>  
>  	buf[_yybytes_len] = buf[_yybytes_len+1] = YY_END_OF_BUFFER_CHAR;
>  
> -	b = yy_scan_buffer(buf,n );
> +	b = yy_scan_buffer( buf, n );
>  	if ( ! b )
>  		YY_FATAL_ERROR( "bad buffer in yy_scan_bytes()" );
>  
> @@ -1994,9 +2011,9 @@ YY_BUFFER_STATE yy_scan_bytes  (yyconst char * yybytes, yy_size_t  _yybytes_len
>  #define YY_EXIT_FAILURE 2
>  #endif
>  
> -static void yy_fatal_error (yyconst char* msg )
> +static void yynoreturn yy_fatal_error (const char* msg )
>  {
> -    	(void) fprintf( stderr, "%s\n", msg );
> +			fprintf( stderr, "%s\n", msg );
>  	exit( YY_EXIT_FAILURE );
>  }
>  
> @@ -2024,7 +2041,7 @@ static void yy_fatal_error (yyconst char* msg )
>   */
>  int yyget_lineno  (void)
>  {
> -        
> +    
>      return yylineno;
>  }
>  
> @@ -2047,7 +2064,7 @@ FILE *yyget_out  (void)
>  /** Get the length of the current token.
>   * 
>   */
> -yy_size_t yyget_leng  (void)
> +int yyget_leng  (void)
>  {
>          return yyleng;
>  }
> @@ -2062,29 +2079,29 @@ char *yyget_text  (void)
>  }
>  
>  /** Set the current line number.
> - * @param line_number
> + * @param _line_number line number
>   * 
>   */
> -void yyset_lineno (int  line_number )
> +void yyset_lineno (int  _line_number )
>  {
>      
> -    yylineno = line_number;
> +    yylineno = _line_number;
>  }
>  
>  /** Set the input stream. This does not discard the current
>   * input buffer.
> - * @param in_str A readable stream.
> + * @param _in_str A readable stream.
>   * 
>   * @see yy_switch_to_buffer
>   */
> -void yyset_in (FILE *  in_str )
> +void yyset_in (FILE *  _in_str )
>  {
> -        yyin = in_str ;
> +        yyin = _in_str ;
>  }
>  
> -void yyset_out (FILE *  out_str )
> +void yyset_out (FILE *  _out_str )
>  {
> -        yyout = out_str ;
> +        yyout = _out_str ;
>  }
>  
>  int yyget_debug  (void)
> @@ -2092,9 +2109,9 @@ int yyget_debug  (void)
>          return yy_flex_debug;
>  }
>  
> -void yyset_debug (int  bdebug )
> +void yyset_debug (int  _bdebug )
>  {
> -        yy_flex_debug = bdebug ;
> +        yy_flex_debug = _bdebug ;
>  }
>  
>  static int yy_init_globals (void)
> @@ -2103,10 +2120,10 @@ static int yy_init_globals (void)
>       * This function is called from yylex_destroy(), so don't allocate here.
>       */
>  
> -    (yy_buffer_stack) = 0;
> +    (yy_buffer_stack) = NULL;
>      (yy_buffer_stack_top) = 0;
>      (yy_buffer_stack_max) = 0;
> -    (yy_c_buf_p) = (char *) 0;
> +    (yy_c_buf_p) = NULL;
>      (yy_init) = 0;
>      (yy_start) = 0;
>  
> @@ -2115,8 +2132,8 @@ static int yy_init_globals (void)
>      yyin = stdin;
>      yyout = stdout;
>  #else
> -    yyin = (FILE *) 0;
> -    yyout = (FILE *) 0;
> +    yyin = NULL;
> +    yyout = NULL;
>  #endif
>  
>      /* For future reference: Set errno on error, since we are called by
> @@ -2131,7 +2148,7 @@ int yylex_destroy  (void)
>      
>      /* Pop the buffer stack, destroying each element. */
>  	while(YY_CURRENT_BUFFER){
> -		yy_delete_buffer(YY_CURRENT_BUFFER  );
> +		yy_delete_buffer( YY_CURRENT_BUFFER  );
>  		YY_CURRENT_BUFFER_LVALUE = NULL;
>  		yypop_buffer_state();
>  	}
> @@ -2152,18 +2169,19 @@ int yylex_destroy  (void)
>   */
>  
>  #ifndef yytext_ptr
> -static void yy_flex_strncpy (char* s1, yyconst char * s2, int n )
> +static void yy_flex_strncpy (char* s1, const char * s2, int n )
>  {
> -	register int i;
> +		
> +	int i;
>  	for ( i = 0; i < n; ++i )
>  		s1[i] = s2[i];
>  }
>  #endif
>  
>  #ifdef YY_NEED_STRLEN
> -static int yy_flex_strlen (yyconst char * s )
> +static int yy_flex_strlen (const char * s )
>  {
> -	register int n;
> +	int n;
>  	for ( n = 0; s[n]; ++n )
>  		;
>  
> @@ -2173,11 +2191,12 @@ static int yy_flex_strlen (yyconst char * s )
>  
>  void *yyalloc (yy_size_t  size )
>  {
> -	return (void *) malloc( size );
> +			return malloc(size);
>  }
>  
>  void *yyrealloc  (void * ptr, yy_size_t  size )
>  {
> +		
>  	/* The cast to (char *) in the following accommodates both
>  	 * implementations that use char* generic pointers, and those
>  	 * that use void* generic pointers.  It works with the latter
> @@ -2185,18 +2204,17 @@ void *yyrealloc  (void * ptr, yy_size_t  size )
>  	 * any pointer type to void*, and deal with argument conversions
>  	 * as though doing an assignment.
>  	 */
> -	return (void *) realloc( (char *) ptr, size );
> +	return realloc(ptr, size);
>  }
>  
>  void yyfree (void * ptr )
>  {
> -	free( (char *) ptr );	/* see yyrealloc() for (char *) cast */
> +			free( (char *) ptr );	/* see yyrealloc() for (char *) cast */
>  }
>  
>  #define YYTABLES_NAME "yytables"
>  
> -#line 254 "dtc-lexer.l"
> -
> +#line 272 "<stdin>"
>  
>  
>  static void push_input_file(const char *filename)
> @@ -2207,7 +2225,7 @@ static void push_input_file(const char *filename)
>  
>  	yyin = current_srcfile->f;
>  
> -	yypush_buffer_state(yy_create_buffer(yyin,YY_BUF_SIZE));
> +	yypush_buffer_state(yy_create_buffer(yyin, YY_BUF_SIZE));
>  }
>  
>  
> diff --git a/scripts/dtc/dtc-parser.tab.c_shipped b/scripts/dtc/dtc-parser.tab.c_shipped
> index 27fac4b9c..06a6e9414 100644
> --- a/scripts/dtc/dtc-parser.tab.c_shipped
> +++ b/scripts/dtc/dtc-parser.tab.c_shipped
> @@ -1,8 +1,8 @@
> -/* A Bison parser, made by GNU Bison 3.0.2.  */
> +/* A Bison parser, made by GNU Bison 3.0.4.  */
>  
>  /* Bison implementation for Yacc-like parsers in C
>  
> -   Copyright (C) 1984, 1989-1990, 2000-2013 Free Software Foundation, Inc.
> +   Copyright (C) 1984, 1989-1990, 2000-2015 Free Software Foundation, 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
> @@ -44,7 +44,7 @@
>  #define YYBISON 1
>  
>  /* Bison version.  */
> -#define YYBISON_VERSION "3.0.2"
> +#define YYBISON_VERSION "3.0.4"
>  
>  /* Skeleton name.  */
>  #define YYSKELETON_NAME "yacc.c"
> @@ -65,6 +65,7 @@
>  #line 20 "dtc-parser.y" /* yacc.c:339  */
>  
>  #include <stdio.h>
> +#include <inttypes.h>
>  
>  #include "dtc.h"
>  #include "srcpos.h"
> @@ -77,10 +78,10 @@ extern void yyerror(char const *s);
>  		treesource_error = true; \
>  	} while (0)
>  
> -extern struct boot_info *the_boot_info;
> +extern struct dt_info *parser_output;
>  extern bool treesource_error;
>  
> -#line 84 "dtc-parser.tab.c" /* yacc.c:339  */
> +#line 85 "dtc-parser.tab.c" /* yacc.c:339  */
>  
>  # ifndef YY_NULLPTR
>  #  if defined __cplusplus && 201103L <= __cplusplus
> @@ -116,35 +117,36 @@ extern int yydebug;
>    enum yytokentype
>    {
>      DT_V1 = 258,
> -    DT_MEMRESERVE = 259,
> -    DT_LSHIFT = 260,
> -    DT_RSHIFT = 261,
> -    DT_LE = 262,
> -    DT_GE = 263,
> -    DT_EQ = 264,
> -    DT_NE = 265,
> -    DT_AND = 266,
> -    DT_OR = 267,
> -    DT_BITS = 268,
> -    DT_DEL_PROP = 269,
> -    DT_DEL_NODE = 270,
> -    DT_PROPNODENAME = 271,
> -    DT_LITERAL = 272,
> -    DT_CHAR_LITERAL = 273,
> -    DT_BYTE = 274,
> -    DT_STRING = 275,
> -    DT_LABEL = 276,
> -    DT_REF = 277,
> -    DT_INCBIN = 278
> +    DT_PLUGIN = 259,
> +    DT_MEMRESERVE = 260,
> +    DT_LSHIFT = 261,
> +    DT_RSHIFT = 262,
> +    DT_LE = 263,
> +    DT_GE = 264,
> +    DT_EQ = 265,
> +    DT_NE = 266,
> +    DT_AND = 267,
> +    DT_OR = 268,
> +    DT_BITS = 269,
> +    DT_DEL_PROP = 270,
> +    DT_DEL_NODE = 271,
> +    DT_PROPNODENAME = 272,
> +    DT_LITERAL = 273,
> +    DT_CHAR_LITERAL = 274,
> +    DT_BYTE = 275,
> +    DT_STRING = 276,
> +    DT_LABEL = 277,
> +    DT_REF = 278,
> +    DT_INCBIN = 279
>    };
>  #endif
>  
>  /* Value type.  */
>  #if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED
> -typedef union YYSTYPE YYSTYPE;
> +
>  union YYSTYPE
>  {
> -#line 38 "dtc-parser.y" /* yacc.c:355  */
> +#line 39 "dtc-parser.y" /* yacc.c:355  */
>  
>  	char *propnodename;
>  	char *labelref;
> @@ -162,9 +164,12 @@ union YYSTYPE
>  	struct node *nodelist;
>  	struct reserve_info *re;
>  	uint64_t integer;
> +	unsigned int flags;
>  
> -#line 167 "dtc-parser.tab.c" /* yacc.c:355  */
> +#line 170 "dtc-parser.tab.c" /* yacc.c:355  */
>  };
> +
> +typedef union YYSTYPE YYSTYPE;
>  # define YYSTYPE_IS_TRIVIAL 1
>  # define YYSTYPE_IS_DECLARED 1
>  #endif
> @@ -192,7 +197,7 @@ int yyparse (void);
>  
>  /* Copy the second part of user declarations.  */
>  
> -#line 196 "dtc-parser.tab.c" /* yacc.c:358  */
> +#line 201 "dtc-parser.tab.c" /* yacc.c:358  */
>  
>  #ifdef short
>  # undef short
> @@ -434,23 +439,23 @@ union yyalloc
>  #endif /* !YYCOPY_NEEDED */
>  
>  /* YYFINAL -- State number of the termination state.  */
> -#define YYFINAL  4
> +#define YYFINAL  6
>  /* YYLAST -- Last index in YYTABLE.  */
> -#define YYLAST   133
> +#define YYLAST   140
>  
>  /* YYNTOKENS -- Number of terminals.  */
> -#define YYNTOKENS  47
> +#define YYNTOKENS  48
>  /* YYNNTS -- Number of nonterminals.  */
> -#define YYNNTS  28
> +#define YYNNTS  30
>  /* YYNRULES -- Number of rules.  */
> -#define YYNRULES  79
> +#define YYNRULES  85
>  /* YYNSTATES -- Number of states.  */
> -#define YYNSTATES  141
> +#define YYNSTATES  151
>  
>  /* YYTRANSLATE[YYX] -- Symbol number corresponding to YYX as returned
>     by yylex, with out-of-bounds checking.  */
>  #define YYUNDEFTOK  2
> -#define YYMAXUTOK   278
> +#define YYMAXUTOK   279
>  
>  #define YYTRANSLATE(YYX)                                                \
>    ((unsigned int) (YYX) <= YYMAXUTOK ? yytranslate[YYX] : YYUNDEFTOK)
> @@ -462,16 +467,16 @@ static const yytype_uint8 yytranslate[] =
>         0,     2,     2,     2,     2,     2,     2,     2,     2,     2,
>         2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
>         2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
> -       2,     2,     2,    46,     2,     2,     2,    44,    40,     2,
> -      32,    34,    43,    41,    33,    42,     2,    25,     2,     2,
> -       2,     2,     2,     2,     2,     2,     2,     2,    37,    24,
> -      35,    28,    29,    36,     2,     2,     2,     2,     2,     2,
> +       2,     2,     2,    47,     2,     2,     2,    45,    41,     2,
> +      33,    35,    44,    42,    34,    43,     2,    26,     2,     2,
> +       2,     2,     2,     2,     2,     2,     2,     2,    38,    25,
> +      36,    29,    30,    37,     2,     2,     2,     2,     2,     2,
>         2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
>         2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
> -       2,    30,     2,    31,    39,     2,     2,     2,     2,     2,
> +       2,    31,     2,    32,    40,     2,     2,     2,     2,     2,
>         2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
>         2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
> -       2,     2,     2,    26,    38,    27,    45,     2,     2,     2,
> +       2,     2,     2,    27,    39,    28,    46,     2,     2,     2,
>         2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
>         2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
>         2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
> @@ -486,21 +491,22 @@ static const yytype_uint8 yytranslate[] =
>         2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
>         2,     2,     2,     2,     2,     2,     1,     2,     3,     4,
>         5,     6,     7,     8,     9,    10,    11,    12,    13,    14,
> -      15,    16,    17,    18,    19,    20,    21,    22,    23
> +      15,    16,    17,    18,    19,    20,    21,    22,    23,    24
>  };
>  
>  #if YYDEBUG
>    /* YYRLINE[YYN] -- Source line where rule number YYN was defined.  */
>  static const yytype_uint16 yyrline[] =
>  {
> -       0,   104,   104,   113,   116,   123,   127,   135,   139,   143,
> -     153,   168,   176,   179,   186,   190,   194,   198,   206,   210,
> -     214,   218,   222,   238,   248,   256,   259,   263,   270,   286,
> -     291,   310,   324,   331,   332,   333,   340,   344,   345,   349,
> -     350,   354,   355,   359,   360,   364,   365,   369,   370,   374,
> -     375,   376,   380,   381,   382,   383,   384,   388,   389,   390,
> -     394,   395,   396,   400,   401,   402,   403,   407,   408,   409,
> -     410,   415,   418,   422,   430,   433,   437,   445,   449,   453
> +       0,   109,   109,   117,   121,   128,   129,   139,   142,   149,
> +     153,   161,   165,   169,   180,   191,   210,   225,   233,   236,
> +     243,   247,   251,   255,   263,   267,   271,   275,   279,   295,
> +     305,   313,   316,   320,   327,   343,   348,   367,   381,   388,
> +     389,   390,   397,   401,   402,   406,   407,   411,   412,   416,
> +     417,   421,   422,   426,   427,   431,   432,   433,   437,   438,
> +     439,   440,   441,   445,   446,   447,   451,   452,   453,   457,
> +     458,   467,   476,   480,   481,   482,   483,   488,   491,   495,
> +     503,   506,   510,   518,   522,   526
>  };
>  #endif
>  
> @@ -509,19 +515,20 @@ static const yytype_uint16 yyrline[] =
>     First, the terminals, then, starting at YYNTOKENS, nonterminals.  */
>  static const char *const yytname[] =
>  {
> -  "$end", "error", "$undefined", "DT_V1", "DT_MEMRESERVE", "DT_LSHIFT",
> -  "DT_RSHIFT", "DT_LE", "DT_GE", "DT_EQ", "DT_NE", "DT_AND", "DT_OR",
> -  "DT_BITS", "DT_DEL_PROP", "DT_DEL_NODE", "DT_PROPNODENAME", "DT_LITERAL",
> -  "DT_CHAR_LITERAL", "DT_BYTE", "DT_STRING", "DT_LABEL", "DT_REF",
> -  "DT_INCBIN", "';'", "'/'", "'{'", "'}'", "'='", "'>'", "'['", "']'",
> -  "'('", "','", "')'", "'<'", "'?'", "':'", "'|'", "'^'", "'&'", "'+'",
> -  "'-'", "'*'", "'%'", "'~'", "'!'", "$accept", "sourcefile",
> -  "memreserves", "memreserve", "devicetree", "nodedef", "proplist",
> -  "propdef", "propdata", "propdataprefix", "arrayprefix", "integer_prim",
> -  "integer_expr", "integer_trinary", "integer_or", "integer_and",
> -  "integer_bitor", "integer_bitxor", "integer_bitand", "integer_eq",
> -  "integer_rela", "integer_shift", "integer_add", "integer_mul",
> -  "integer_unary", "bytestring", "subnodes", "subnode", YY_NULLPTR
> +  "$end", "error", "$undefined", "DT_V1", "DT_PLUGIN", "DT_MEMRESERVE",
> +  "DT_LSHIFT", "DT_RSHIFT", "DT_LE", "DT_GE", "DT_EQ", "DT_NE", "DT_AND",
> +  "DT_OR", "DT_BITS", "DT_DEL_PROP", "DT_DEL_NODE", "DT_PROPNODENAME",
> +  "DT_LITERAL", "DT_CHAR_LITERAL", "DT_BYTE", "DT_STRING", "DT_LABEL",
> +  "DT_REF", "DT_INCBIN", "';'", "'/'", "'{'", "'}'", "'='", "'>'", "'['",
> +  "']'", "'('", "','", "')'", "'<'", "'?'", "':'", "'|'", "'^'", "'&'",
> +  "'+'", "'-'", "'*'", "'%'", "'~'", "'!'", "$accept", "sourcefile",
> +  "header", "headers", "memreserves", "memreserve", "devicetree",
> +  "nodedef", "proplist", "propdef", "propdata", "propdataprefix",
> +  "arrayprefix", "integer_prim", "integer_expr", "integer_trinary",
> +  "integer_or", "integer_and", "integer_bitor", "integer_bitxor",
> +  "integer_bitand", "integer_eq", "integer_rela", "integer_shift",
> +  "integer_add", "integer_mul", "integer_unary", "bytestring", "subnodes",
> +  "subnode", YY_NULLPTR
>  };
>  #endif
>  
> @@ -532,16 +539,16 @@ static const yytype_uint16 yytoknum[] =
>  {
>         0,   256,   257,   258,   259,   260,   261,   262,   263,   264,
>       265,   266,   267,   268,   269,   270,   271,   272,   273,   274,
> -     275,   276,   277,   278,    59,    47,   123,   125,    61,    62,
> -      91,    93,    40,    44,    41,    60,    63,    58,   124,    94,
> -      38,    43,    45,    42,    37,   126,    33
> +     275,   276,   277,   278,   279,    59,    47,   123,   125,    61,
> +      62,    91,    93,    40,    44,    41,    60,    63,    58,   124,
> +      94,    38,    43,    45,    42,    37,   126,    33
>  };
>  # endif
>  
> -#define YYPACT_NINF -38
> +#define YYPACT_NINF -81
>  
>  #define yypact_value_is_default(Yystate) \
> -  (!!((Yystate) == (-38)))
> +  (!!((Yystate) == (-81)))
>  
>  #define YYTABLE_NINF -1
>  
> @@ -552,21 +559,22 @@ static const yytype_uint16 yytoknum[] =
>       STATE-NUM.  */
>  static const yytype_int8 yypact[] =
>  {
> -      21,    11,    45,    10,   -38,     9,    10,    15,    10,   -38,
> -     -38,    -9,     9,   -38,    56,    40,   -38,    -9,    -9,    -9,
> -     -38,    51,   -38,    -6,    75,    49,    52,    48,    50,     3,
> -      66,    33,     0,   -38,    65,   -38,   -38,    68,    56,    56,
> -     -38,   -38,   -38,   -38,    -9,    -9,    -9,    -9,    -9,    -9,
> -      -9,    -9,    -9,    -9,    -9,    -9,    -9,    -9,    -9,    -9,
> -      -9,    -9,    -9,   -38,    42,    69,   -38,   -38,    75,    55,
> -      49,    52,    48,    50,     3,     3,    66,    66,    66,    66,
> -      33,    33,     0,     0,   -38,   -38,   -38,    78,    79,   -11,
> -      42,   -38,    70,    42,   -38,    -9,    72,    74,   -38,   -38,
> -     -38,   -38,   -38,    76,   -38,   -38,   -38,   -38,   -38,    18,
> -      -1,   -38,   -38,   -38,   -38,    82,   -38,   -38,   -38,    71,
> -     -38,   -38,    32,    67,    81,    -3,   -38,   -38,   -38,   -38,
> -     -38,    43,   -38,   -38,   -38,     9,   -38,    73,     9,    77,
> -     -38
> +      11,    17,    23,    11,    10,    56,   -81,   -81,    21,    10,
> +      -5,    10,    39,   -81,   -81,   -13,    21,   -81,    44,    44,
> +      43,   -81,   -81,   -13,   -13,   -13,   -81,    38,   -81,    -2,
> +      67,    53,    55,    57,    41,     1,    75,    42,   -19,   -81,
> +      58,   -81,   -81,   -81,    73,    74,    44,    44,   -81,   -81,
> +     -81,   -81,   -13,   -13,   -13,   -13,   -13,   -13,   -13,   -13,
> +     -13,   -13,   -13,   -13,   -13,   -13,   -13,   -13,   -13,   -13,
> +     -13,   -81,    46,    76,    44,   -81,   -81,    67,    61,    53,
> +      55,    57,    41,     1,     1,    75,    75,    75,    75,    42,
> +      42,   -19,   -19,   -81,   -81,   -81,    83,    85,    45,    46,
> +     -81,    77,    46,   -81,   -81,   -13,    78,    79,   -81,   -81,
> +     -81,   -81,   -81,    81,   -81,   -81,   -81,   -81,   -81,    16,
> +      22,   -81,   -81,   -81,   -81,    89,   -81,   -81,   -81,    80,
> +     -81,   -81,    -6,    72,    88,    35,   -81,   -81,   -81,   -81,
> +     -81,    52,   -81,   -81,   -81,    21,   -81,    82,    21,    84,
> +     -81
>  };
>  
>    /* YYDEFACT[STATE-NUM] -- Default reduction number in state STATE-NUM.
> @@ -574,37 +582,38 @@ static const yytype_int8 yypact[] =
>       means the default is an error.  */
>  static const yytype_uint8 yydefact[] =
>  {
> -       0,     0,     0,     3,     1,     0,     0,     0,     3,    33,
> -      34,     0,     0,     6,     0,     2,     4,     0,     0,     0,
> -      67,     0,    36,    37,    39,    41,    43,    45,    47,    49,
> -      52,    59,    62,    66,     0,    12,     7,     0,     0,     0,
> -      68,    69,    70,    35,     0,     0,     0,     0,     0,     0,
> +       0,     0,     0,     5,     7,     3,     1,     6,     0,     0,
> +       0,     7,     0,    39,    40,     0,     0,    10,     0,     0,
> +       2,     8,     4,     0,     0,     0,    73,     0,    42,    43,
> +      45,    47,    49,    51,    53,    55,    58,    65,    68,    72,
> +       0,    18,    13,    11,     0,     0,     0,     0,    74,    75,
> +      76,    41,     0,     0,     0,     0,     0,     0,     0,     0,
>         0,     0,     0,     0,     0,     0,     0,     0,     0,     0,
> -       0,     0,     0,     5,    74,     0,     9,     8,    40,     0,
> -      42,    44,    46,    48,    50,    51,    55,    56,    54,    53,
> -      57,    58,    60,    61,    64,    63,    65,     0,     0,     0,
> -       0,    13,     0,    74,    10,     0,     0,     0,    15,    25,
> -      77,    17,    79,     0,    76,    75,    38,    16,    78,     0,
> -       0,    11,    24,    14,    26,     0,    18,    27,    21,     0,
> -      71,    29,     0,     0,     0,     0,    32,    31,    19,    30,
> -      28,     0,    72,    73,    20,     0,    23,     0,     0,     0,
> -      22
> +       0,     9,    80,     0,     0,    15,    12,    46,     0,    48,
> +      50,    52,    54,    56,    57,    61,    62,    60,    59,    63,
> +      64,    66,    67,    70,    69,    71,     0,     0,     0,     0,
> +      19,     0,    80,    16,    14,     0,     0,     0,    21,    31,
> +      83,    23,    85,     0,    82,    81,    44,    22,    84,     0,
> +       0,    17,    30,    20,    32,     0,    24,    33,    27,     0,
> +      77,    35,     0,     0,     0,     0,    38,    37,    25,    36,
> +      34,     0,    78,    79,    26,     0,    29,     0,     0,     0,
> +      28
>  };
>  
>    /* YYPGOTO[NTERM-NUM].  */
>  static const yytype_int8 yypgoto[] =
>  {
> -     -38,   -38,    96,    99,   -38,   -37,   -38,   -20,   -38,   -38,
> -     -38,    -5,    62,    13,   -38,    80,    63,    84,    64,    61,
> -      28,    14,    24,    25,   -14,   -38,    20,    26
> +     -81,   -81,   -81,   107,   100,   103,   -81,   -18,   -81,   -80,
> +     -81,   -81,   -81,    -8,    62,     9,   -81,    65,    64,    66,
> +      69,    63,    30,    15,    26,    27,   -21,   -81,    20,    24
>  };
>  
>    /* YYDEFGOTO[NTERM-NUM].  */
> -static const yytype_int8 yydefgoto[] =
> +static const yytype_int16 yydefgoto[] =
>  {
> -      -1,     2,     7,     8,    15,    36,    64,    91,   109,   110,
> -     122,    20,    21,    22,    23,    24,    25,    26,    27,    28,
> -      29,    30,    31,    32,    33,   125,    92,    93
> +      -1,     2,     3,     4,    10,    11,    20,    42,    72,   100,
> +     119,   120,   132,    26,    27,    28,    29,    30,    31,    32,
> +      33,    34,    35,    36,    37,    38,    39,   135,   101,   102
>  };
>  
>    /* YYTABLE[YYPACT[STATE-NUM]] -- What to do in state STATE-NUM.  If
> @@ -612,85 +621,90 @@ static const yytype_int8 yydefgoto[] =
>       number is the opposite.  If YYTABLE_NINF, syntax error.  */
>  static const yytype_uint8 yytable[] =
>  {
> -      12,    66,    67,    40,    41,    42,    44,    34,     9,    10,
> -      52,    53,   115,    98,     5,    35,   132,    99,   133,   116,
> -     117,   118,   119,    11,     1,    60,     9,    10,   134,   120,
> -      45,     6,    54,    17,   121,     3,    18,    19,    55,   112,
> -      14,    11,   113,    61,    62,     4,    84,    85,    86,     9,
> -      10,   114,   100,   126,   127,    37,    87,    88,    89,    50,
> -      51,   128,    38,    90,    11,    39,    76,    77,    78,    79,
> -     101,    56,    57,   104,    58,    59,   135,   136,    74,    75,
> -      80,    81,    35,    82,    83,    43,    46,    47,    49,    63,
> -      65,    48,    95,    94,    96,    97,   107,   103,   108,   123,
> -     111,   131,   130,   124,    16,    13,   138,    69,   106,    70,
> -      73,   140,    72,   105,     0,     0,   102,   129,     0,     0,
> -       0,     0,     0,     0,    68,     0,     0,     0,     0,     0,
> -     137,    71,     0,   139
> +      16,    43,    48,    49,    50,    13,    14,    68,    40,    60,
> +      61,    52,    13,    14,     1,     8,   136,   137,    18,   111,
> +      15,    19,   114,     6,   138,    69,    70,    15,    75,    76,
> +      23,    62,     9,    24,    25,    53,   125,    63,   122,    13,
> +      14,   123,     5,   126,   127,   128,   129,    93,    94,    95,
> +     124,    58,    59,   130,    15,   142,   104,   143,   131,    44,
> +      12,    96,    97,    98,    22,    45,    46,   144,    99,    47,
> +     108,    41,    41,    51,   109,    85,    86,    87,    88,    54,
> +     110,    64,    65,    71,    66,    67,   145,   146,    83,    84,
> +      89,    90,    55,    91,    92,    56,    73,    74,    57,   105,
> +     106,   103,   107,   117,   118,   113,   121,   133,   140,   141,
> +       7,    21,    17,   134,   116,    78,   148,    77,    79,   150,
> +      82,    80,   115,   112,   139,    81,     0,     0,     0,     0,
> +       0,     0,     0,     0,     0,     0,     0,   147,     0,     0,
> +     149
>  };
>  
>  static const yytype_int16 yycheck[] =
>  {
> -       5,    38,    39,    17,    18,    19,    12,    12,    17,    18,
> -       7,     8,    13,    24,     4,    26,    19,    28,    21,    20,
> -      21,    22,    23,    32,     3,    25,    17,    18,    31,    30,
> -      36,    21,    29,    42,    35,    24,    45,    46,    35,    21,
> -      25,    32,    24,    43,    44,     0,    60,    61,    62,    17,
> -      18,    33,    89,    21,    22,    15,    14,    15,    16,     9,
> -      10,    29,    22,    21,    32,    25,    52,    53,    54,    55,
> -      90,     5,     6,    93,    41,    42,    33,    34,    50,    51,
> -      56,    57,    26,    58,    59,    34,    11,    38,    40,    24,
> -      22,    39,    37,    24,    16,    16,    24,    27,    24,    17,
> -      24,    20,    35,    32,     8,     6,    33,    45,    95,    46,
> -      49,    34,    48,    93,    -1,    -1,    90,   122,    -1,    -1,
> -      -1,    -1,    -1,    -1,    44,    -1,    -1,    -1,    -1,    -1,
> -     135,    47,    -1,   138
> +       8,    19,    23,    24,    25,    18,    19,    26,    16,     8,
> +       9,    13,    18,    19,     3,     5,    22,    23,    23,    99,
> +      33,    26,   102,     0,    30,    44,    45,    33,    46,    47,
> +      43,    30,    22,    46,    47,    37,    14,    36,    22,    18,
> +      19,    25,    25,    21,    22,    23,    24,    68,    69,    70,
> +      34,    10,    11,    31,    33,    20,    74,    22,    36,    16,
> +       4,    15,    16,    17,    25,    22,    23,    32,    22,    26,
> +      25,    27,    27,    35,    29,    60,    61,    62,    63,    12,
> +      98,     6,     7,    25,    42,    43,    34,    35,    58,    59,
> +      64,    65,    39,    66,    67,    40,    23,    23,    41,    38,
> +      17,    25,    17,    25,    25,    28,    25,    18,    36,    21,
> +       3,    11,     9,    33,   105,    53,    34,    52,    54,    35,
> +      57,    55,   102,    99,   132,    56,    -1,    -1,    -1,    -1,
> +      -1,    -1,    -1,    -1,    -1,    -1,    -1,   145,    -1,    -1,
> +     148
>  };
>  
>    /* YYSTOS[STATE-NUM] -- The (internal number of the) accessing
>       symbol of state STATE-NUM.  */
>  static const yytype_uint8 yystos[] =
>  {
> -       0,     3,    48,    24,     0,     4,    21,    49,    50,    17,
> -      18,    32,    58,    50,    25,    51,    49,    42,    45,    46,
> -      58,    59,    60,    61,    62,    63,    64,    65,    66,    67,
> -      68,    69,    70,    71,    58,    26,    52,    15,    22,    25,
> -      71,    71,    71,    34,    12,    36,    11,    38,    39,    40,
> -       9,    10,     7,     8,    29,    35,     5,     6,    41,    42,
> -      25,    43,    44,    24,    53,    22,    52,    52,    62,    59,
> -      63,    64,    65,    66,    67,    67,    68,    68,    68,    68,
> -      69,    69,    70,    70,    71,    71,    71,    14,    15,    16,
> -      21,    54,    73,    74,    24,    37,    16,    16,    24,    28,
> -      52,    54,    74,    27,    54,    73,    60,    24,    24,    55,
> -      56,    24,    21,    24,    33,    13,    20,    21,    22,    23,
> -      30,    35,    57,    17,    32,    72,    21,    22,    29,    58,
> -      35,    20,    19,    21,    31,    33,    34,    58,    33,    58,
> -      34
> +       0,     3,    49,    50,    51,    25,     0,    51,     5,    22,
> +      52,    53,     4,    18,    19,    33,    61,    53,    23,    26,
> +      54,    52,    25,    43,    46,    47,    61,    62,    63,    64,
> +      65,    66,    67,    68,    69,    70,    71,    72,    73,    74,
> +      61,    27,    55,    55,    16,    22,    23,    26,    74,    74,
> +      74,    35,    13,    37,    12,    39,    40,    41,    10,    11,
> +       8,     9,    30,    36,     6,     7,    42,    43,    26,    44,
> +      45,    25,    56,    23,    23,    55,    55,    65,    62,    66,
> +      67,    68,    69,    70,    70,    71,    71,    71,    71,    72,
> +      72,    73,    73,    74,    74,    74,    15,    16,    17,    22,
> +      57,    76,    77,    25,    55,    38,    17,    17,    25,    29,
> +      55,    57,    77,    28,    57,    76,    63,    25,    25,    58,
> +      59,    25,    22,    25,    34,    14,    21,    22,    23,    24,
> +      31,    36,    60,    18,    33,    75,    22,    23,    30,    61,
> +      36,    21,    20,    22,    32,    34,    35,    61,    34,    61,
> +      35
>  };
>  
>    /* YYR1[YYN] -- Symbol number of symbol that rule YYN derives.  */
>  static const yytype_uint8 yyr1[] =
>  {
> -       0,    47,    48,    49,    49,    50,    50,    51,    51,    51,
> -      51,    52,    53,    53,    54,    54,    54,    54,    55,    55,
> -      55,    55,    55,    55,    55,    56,    56,    56,    57,    57,
> -      57,    57,    57,    58,    58,    58,    59,    60,    60,    61,
> -      61,    62,    62,    63,    63,    64,    64,    65,    65,    66,
> -      66,    66,    67,    67,    67,    67,    67,    68,    68,    68,
> -      69,    69,    69,    70,    70,    70,    70,    71,    71,    71,
> -      71,    72,    72,    72,    73,    73,    73,    74,    74,    74
> +       0,    48,    49,    50,    50,    51,    51,    52,    52,    53,
> +      53,    54,    54,    54,    54,    54,    54,    55,    56,    56,
> +      57,    57,    57,    57,    58,    58,    58,    58,    58,    58,
> +      58,    59,    59,    59,    60,    60,    60,    60,    60,    61,
> +      61,    61,    62,    63,    63,    64,    64,    65,    65,    66,
> +      66,    67,    67,    68,    68,    69,    69,    69,    70,    70,
> +      70,    70,    70,    71,    71,    71,    72,    72,    72,    73,
> +      73,    73,    73,    74,    74,    74,    74,    75,    75,    75,
> +      76,    76,    76,    77,    77,    77
>  };
>  
>    /* YYR2[YYN] -- Number of symbols on the right hand side of rule YYN.  */
>  static const yytype_uint8 yyr2[] =
>  {
> -       0,     2,     4,     0,     2,     4,     2,     2,     3,     3,
> -       4,     5,     0,     2,     4,     2,     3,     2,     2,     3,
> -       4,     2,     9,     5,     2,     0,     2,     2,     3,     1,
> -       2,     2,     2,     1,     1,     3,     1,     1,     5,     1,
> -       3,     1,     3,     1,     3,     1,     3,     1,     3,     1,
> -       3,     3,     1,     3,     3,     3,     3,     3,     3,     1,
> -       3,     3,     1,     3,     3,     3,     1,     1,     2,     2,
> -       2,     0,     2,     2,     0,     2,     2,     2,     3,     2
> +       0,     2,     3,     2,     4,     1,     2,     0,     2,     4,
> +       2,     2,     3,     2,     4,     3,     4,     5,     0,     2,
> +       4,     2,     3,     2,     2,     3,     4,     2,     9,     5,
> +       2,     0,     2,     2,     3,     1,     2,     2,     2,     1,
> +       1,     3,     1,     1,     5,     1,     3,     1,     3,     1,
> +       3,     1,     3,     1,     3,     1,     3,     3,     1,     3,
> +       3,     3,     3,     3,     3,     1,     3,     3,     1,     3,
> +       3,     3,     1,     1,     2,     2,     2,     0,     2,     2,
> +       0,     2,     2,     2,     3,     2
>  };
>  
>  
> @@ -1460,79 +1474,144 @@ yyreduce:
>    switch (yyn)
>      {
>          case 2:
> -#line 105 "dtc-parser.y" /* yacc.c:1646  */
> +#line 110 "dtc-parser.y" /* yacc.c:1646  */
>      {
> -			the_boot_info = build_boot_info((yyvsp[-1].re), (yyvsp[0].node),
> -							guess_boot_cpuid((yyvsp[0].node)));
> +			parser_output = build_dt_info((yyvsp[-2].flags), (yyvsp[-1].re), (yyvsp[0].node),
> +			                              guess_boot_cpuid((yyvsp[0].node)));
>  		}
> -#line 1469 "dtc-parser.tab.c" /* yacc.c:1646  */
> +#line 1483 "dtc-parser.tab.c" /* yacc.c:1646  */
>      break;
>  
>    case 3:
> -#line 113 "dtc-parser.y" /* yacc.c:1646  */
> +#line 118 "dtc-parser.y" /* yacc.c:1646  */
>      {
> -			(yyval.re) = NULL;
> +			(yyval.flags) = DTSF_V1;
>  		}
> -#line 1477 "dtc-parser.tab.c" /* yacc.c:1646  */
> +#line 1491 "dtc-parser.tab.c" /* yacc.c:1646  */
>      break;
>  
>    case 4:
> -#line 117 "dtc-parser.y" /* yacc.c:1646  */
> +#line 122 "dtc-parser.y" /* yacc.c:1646  */
> +    {
> +			(yyval.flags) = DTSF_V1 | DTSF_PLUGIN;
> +		}
> +#line 1499 "dtc-parser.tab.c" /* yacc.c:1646  */
> +    break;
> +
> +  case 6:
> +#line 130 "dtc-parser.y" /* yacc.c:1646  */
> +    {
> +			if ((yyvsp[0].flags) != (yyvsp[-1].flags))
> +				ERROR(&(yylsp[0]), "Header flags don't match earlier ones");
> +			(yyval.flags) = (yyvsp[-1].flags);
> +		}
> +#line 1509 "dtc-parser.tab.c" /* yacc.c:1646  */
> +    break;
> +
> +  case 7:
> +#line 139 "dtc-parser.y" /* yacc.c:1646  */
> +    {
> +			(yyval.re) = NULL;
> +		}
> +#line 1517 "dtc-parser.tab.c" /* yacc.c:1646  */
> +    break;
> +
> +  case 8:
> +#line 143 "dtc-parser.y" /* yacc.c:1646  */
>      {
>  			(yyval.re) = chain_reserve_entry((yyvsp[-1].re), (yyvsp[0].re));
>  		}
> -#line 1485 "dtc-parser.tab.c" /* yacc.c:1646  */
> +#line 1525 "dtc-parser.tab.c" /* yacc.c:1646  */
>      break;
>  
> -  case 5:
> -#line 124 "dtc-parser.y" /* yacc.c:1646  */
> +  case 9:
> +#line 150 "dtc-parser.y" /* yacc.c:1646  */
>      {
>  			(yyval.re) = build_reserve_entry((yyvsp[-2].integer), (yyvsp[-1].integer));
>  		}
> -#line 1493 "dtc-parser.tab.c" /* yacc.c:1646  */
> +#line 1533 "dtc-parser.tab.c" /* yacc.c:1646  */
>      break;
>  
> -  case 6:
> -#line 128 "dtc-parser.y" /* yacc.c:1646  */
> +  case 10:
> +#line 154 "dtc-parser.y" /* yacc.c:1646  */
>      {
>  			add_label(&(yyvsp[0].re)->labels, (yyvsp[-1].labelref));
>  			(yyval.re) = (yyvsp[0].re);
>  		}
> -#line 1502 "dtc-parser.tab.c" /* yacc.c:1646  */
> +#line 1542 "dtc-parser.tab.c" /* yacc.c:1646  */
>      break;
>  
> -  case 7:
> -#line 136 "dtc-parser.y" /* yacc.c:1646  */
> +  case 11:
> +#line 162 "dtc-parser.y" /* yacc.c:1646  */
>      {
>  			(yyval.node) = name_node((yyvsp[0].node), "");
>  		}
> -#line 1510 "dtc-parser.tab.c" /* yacc.c:1646  */
> +#line 1550 "dtc-parser.tab.c" /* yacc.c:1646  */
>      break;
>  
> -  case 8:
> -#line 140 "dtc-parser.y" /* yacc.c:1646  */
> +  case 12:
> +#line 166 "dtc-parser.y" /* yacc.c:1646  */
>      {
>  			(yyval.node) = merge_nodes((yyvsp[-2].node), (yyvsp[0].node));
>  		}
> -#line 1518 "dtc-parser.tab.c" /* yacc.c:1646  */
> +#line 1558 "dtc-parser.tab.c" /* yacc.c:1646  */
>      break;
>  
> -  case 9:
> -#line 144 "dtc-parser.y" /* yacc.c:1646  */
> +  case 13:
> +#line 170 "dtc-parser.y" /* yacc.c:1646  */
>      {
> -			struct node *target = get_node_by_ref((yyvsp[-2].node), (yyvsp[-1].labelref));
> +			/*
> +			 * We rely on the rule being always:
> +			 *   versioninfo plugindecl memreserves devicetree
> +			 * so $-1 is what we want (plugindecl)
> +			 */
> +			if (!((yyvsp[(-1) - (2)].flags) & DTSF_PLUGIN))
> +				ERROR(&(yylsp[0]), "Label or path %s not found", (yyvsp[-1].labelref));
> +			(yyval.node) = add_orphan_node(name_node(build_node(NULL, NULL), ""), (yyvsp[0].node), (yyvsp[-1].labelref));
> +		}
> +#line 1573 "dtc-parser.tab.c" /* yacc.c:1646  */
> +    break;
>  
> -			if (target)
> +  case 14:
> +#line 181 "dtc-parser.y" /* yacc.c:1646  */
> +    {
> +			struct node *target = get_node_by_ref((yyvsp[-3].node), (yyvsp[-1].labelref));
> +
> +			if (target) {
> +				add_label(&target->labels, (yyvsp[-2].labelref));
>  				merge_nodes(target, (yyvsp[0].node));
> -			else
> +			} else
>  				ERROR(&(yylsp[-1]), "Label or path %s not found", (yyvsp[-1].labelref));
> +			(yyval.node) = (yyvsp[-3].node);
> +		}
> +#line 1588 "dtc-parser.tab.c" /* yacc.c:1646  */
> +    break;
> +
> +  case 15:
> +#line 192 "dtc-parser.y" /* yacc.c:1646  */
> +    {
> +			struct node *target = get_node_by_ref((yyvsp[-2].node), (yyvsp[-1].labelref));
> +
> +			if (target) {
> +				merge_nodes(target, (yyvsp[0].node));
> +			} else {
> +				/*
> +				 * We rely on the rule being always:
> +				 *   versioninfo plugindecl memreserves devicetree
> +				 * so $-1 is what we want (plugindecl)
> +				 */
> +				if ((yyvsp[(-1) - (3)].flags) & DTSF_PLUGIN)
> +					add_orphan_node((yyvsp[-2].node), (yyvsp[0].node), (yyvsp[-1].labelref));
> +				else
> +					ERROR(&(yylsp[-1]), "Label or path %s not found", (yyvsp[-1].labelref));
> +			}
>  			(yyval.node) = (yyvsp[-2].node);
>  		}
> -#line 1532 "dtc-parser.tab.c" /* yacc.c:1646  */
> +#line 1611 "dtc-parser.tab.c" /* yacc.c:1646  */
>      break;
>  
> -  case 10:
> -#line 154 "dtc-parser.y" /* yacc.c:1646  */
> +  case 16:
> +#line 211 "dtc-parser.y" /* yacc.c:1646  */
>      {
>  			struct node *target = get_node_by_ref((yyvsp[-3].node), (yyvsp[-1].labelref));
>  
> @@ -1544,100 +1623,100 @@ yyreduce:
>  
>  			(yyval.node) = (yyvsp[-3].node);
>  		}
> -#line 1548 "dtc-parser.tab.c" /* yacc.c:1646  */
> +#line 1627 "dtc-parser.tab.c" /* yacc.c:1646  */
>      break;
>  
> -  case 11:
> -#line 169 "dtc-parser.y" /* yacc.c:1646  */
> +  case 17:
> +#line 226 "dtc-parser.y" /* yacc.c:1646  */
>      {
>  			(yyval.node) = build_node((yyvsp[-3].proplist), (yyvsp[-2].nodelist));
>  		}
> -#line 1556 "dtc-parser.tab.c" /* yacc.c:1646  */
> +#line 1635 "dtc-parser.tab.c" /* yacc.c:1646  */
>      break;
>  
> -  case 12:
> -#line 176 "dtc-parser.y" /* yacc.c:1646  */
> +  case 18:
> +#line 233 "dtc-parser.y" /* yacc.c:1646  */
>      {
>  			(yyval.proplist) = NULL;
>  		}
> -#line 1564 "dtc-parser.tab.c" /* yacc.c:1646  */
> +#line 1643 "dtc-parser.tab.c" /* yacc.c:1646  */
>      break;
>  
> -  case 13:
> -#line 180 "dtc-parser.y" /* yacc.c:1646  */
> +  case 19:
> +#line 237 "dtc-parser.y" /* yacc.c:1646  */
>      {
>  			(yyval.proplist) = chain_property((yyvsp[0].prop), (yyvsp[-1].proplist));
>  		}
> -#line 1572 "dtc-parser.tab.c" /* yacc.c:1646  */
> +#line 1651 "dtc-parser.tab.c" /* yacc.c:1646  */
>      break;
>  
> -  case 14:
> -#line 187 "dtc-parser.y" /* yacc.c:1646  */
> +  case 20:
> +#line 244 "dtc-parser.y" /* yacc.c:1646  */
>      {
>  			(yyval.prop) = build_property((yyvsp[-3].propnodename), (yyvsp[-1].data));
>  		}
> -#line 1580 "dtc-parser.tab.c" /* yacc.c:1646  */
> +#line 1659 "dtc-parser.tab.c" /* yacc.c:1646  */
>      break;
>  
> -  case 15:
> -#line 191 "dtc-parser.y" /* yacc.c:1646  */
> +  case 21:
> +#line 248 "dtc-parser.y" /* yacc.c:1646  */
>      {
>  			(yyval.prop) = build_property((yyvsp[-1].propnodename), empty_data);
>  		}
> -#line 1588 "dtc-parser.tab.c" /* yacc.c:1646  */
> +#line 1667 "dtc-parser.tab.c" /* yacc.c:1646  */
>      break;
>  
> -  case 16:
> -#line 195 "dtc-parser.y" /* yacc.c:1646  */
> +  case 22:
> +#line 252 "dtc-parser.y" /* yacc.c:1646  */
>      {
>  			(yyval.prop) = build_property_delete((yyvsp[-1].propnodename));
>  		}
> -#line 1596 "dtc-parser.tab.c" /* yacc.c:1646  */
> +#line 1675 "dtc-parser.tab.c" /* yacc.c:1646  */
>      break;
>  
> -  case 17:
> -#line 199 "dtc-parser.y" /* yacc.c:1646  */
> +  case 23:
> +#line 256 "dtc-parser.y" /* yacc.c:1646  */
>      {
>  			add_label(&(yyvsp[0].prop)->labels, (yyvsp[-1].labelref));
>  			(yyval.prop) = (yyvsp[0].prop);
>  		}
> -#line 1605 "dtc-parser.tab.c" /* yacc.c:1646  */
> +#line 1684 "dtc-parser.tab.c" /* yacc.c:1646  */
>      break;
>  
> -  case 18:
> -#line 207 "dtc-parser.y" /* yacc.c:1646  */
> +  case 24:
> +#line 264 "dtc-parser.y" /* yacc.c:1646  */
>      {
>  			(yyval.data) = data_merge((yyvsp[-1].data), (yyvsp[0].data));
>  		}
> -#line 1613 "dtc-parser.tab.c" /* yacc.c:1646  */
> +#line 1692 "dtc-parser.tab.c" /* yacc.c:1646  */
>      break;
>  
> -  case 19:
> -#line 211 "dtc-parser.y" /* yacc.c:1646  */
> +  case 25:
> +#line 268 "dtc-parser.y" /* yacc.c:1646  */
>      {
>  			(yyval.data) = data_merge((yyvsp[-2].data), (yyvsp[-1].array).data);
>  		}
> -#line 1621 "dtc-parser.tab.c" /* yacc.c:1646  */
> +#line 1700 "dtc-parser.tab.c" /* yacc.c:1646  */
>      break;
>  
> -  case 20:
> -#line 215 "dtc-parser.y" /* yacc.c:1646  */
> +  case 26:
> +#line 272 "dtc-parser.y" /* yacc.c:1646  */
>      {
>  			(yyval.data) = data_merge((yyvsp[-3].data), (yyvsp[-1].data));
>  		}
> -#line 1629 "dtc-parser.tab.c" /* yacc.c:1646  */
> +#line 1708 "dtc-parser.tab.c" /* yacc.c:1646  */
>      break;
>  
> -  case 21:
> -#line 219 "dtc-parser.y" /* yacc.c:1646  */
> +  case 27:
> +#line 276 "dtc-parser.y" /* yacc.c:1646  */
>      {
>  			(yyval.data) = data_add_marker((yyvsp[-1].data), REF_PATH, (yyvsp[0].labelref));
>  		}
> -#line 1637 "dtc-parser.tab.c" /* yacc.c:1646  */
> +#line 1716 "dtc-parser.tab.c" /* yacc.c:1646  */
>      break;
>  
> -  case 22:
> -#line 223 "dtc-parser.y" /* yacc.c:1646  */
> +  case 28:
> +#line 280 "dtc-parser.y" /* yacc.c:1646  */
>      {
>  			FILE *f = srcfile_relative_open((yyvsp[-5].data).val, NULL);
>  			struct data d;
> @@ -1653,11 +1732,11 @@ yyreduce:
>  			(yyval.data) = data_merge((yyvsp[-8].data), d);
>  			fclose(f);
>  		}
> -#line 1657 "dtc-parser.tab.c" /* yacc.c:1646  */
> +#line 1736 "dtc-parser.tab.c" /* yacc.c:1646  */
>      break;
>  
> -  case 23:
> -#line 239 "dtc-parser.y" /* yacc.c:1646  */
> +  case 29:
> +#line 296 "dtc-parser.y" /* yacc.c:1646  */
>      {
>  			FILE *f = srcfile_relative_open((yyvsp[-1].data).val, NULL);
>  			struct data d = empty_data;
> @@ -1667,43 +1746,43 @@ yyreduce:
>  			(yyval.data) = data_merge((yyvsp[-4].data), d);
>  			fclose(f);
>  		}
> -#line 1671 "dtc-parser.tab.c" /* yacc.c:1646  */
> +#line 1750 "dtc-parser.tab.c" /* yacc.c:1646  */
>      break;
>  
> -  case 24:
> -#line 249 "dtc-parser.y" /* yacc.c:1646  */
> +  case 30:
> +#line 306 "dtc-parser.y" /* yacc.c:1646  */
>      {
>  			(yyval.data) = data_add_marker((yyvsp[-1].data), LABEL, (yyvsp[0].labelref));
>  		}
> -#line 1679 "dtc-parser.tab.c" /* yacc.c:1646  */
> +#line 1758 "dtc-parser.tab.c" /* yacc.c:1646  */
>      break;
>  
> -  case 25:
> -#line 256 "dtc-parser.y" /* yacc.c:1646  */
> +  case 31:
> +#line 313 "dtc-parser.y" /* yacc.c:1646  */
>      {
>  			(yyval.data) = empty_data;
>  		}
> -#line 1687 "dtc-parser.tab.c" /* yacc.c:1646  */
> +#line 1766 "dtc-parser.tab.c" /* yacc.c:1646  */
>      break;
>  
> -  case 26:
> -#line 260 "dtc-parser.y" /* yacc.c:1646  */
> +  case 32:
> +#line 317 "dtc-parser.y" /* yacc.c:1646  */
>      {
>  			(yyval.data) = (yyvsp[-1].data);
>  		}
> -#line 1695 "dtc-parser.tab.c" /* yacc.c:1646  */
> +#line 1774 "dtc-parser.tab.c" /* yacc.c:1646  */
>      break;
>  
> -  case 27:
> -#line 264 "dtc-parser.y" /* yacc.c:1646  */
> +  case 33:
> +#line 321 "dtc-parser.y" /* yacc.c:1646  */
>      {
>  			(yyval.data) = data_add_marker((yyvsp[-1].data), LABEL, (yyvsp[0].labelref));
>  		}
> -#line 1703 "dtc-parser.tab.c" /* yacc.c:1646  */
> +#line 1782 "dtc-parser.tab.c" /* yacc.c:1646  */
>      break;
>  
> -  case 28:
> -#line 271 "dtc-parser.y" /* yacc.c:1646  */
> +  case 34:
> +#line 328 "dtc-parser.y" /* yacc.c:1646  */
>      {
>  			unsigned long long bits;
>  
> @@ -1719,20 +1798,20 @@ yyreduce:
>  			(yyval.array).data = empty_data;
>  			(yyval.array).bits = bits;
>  		}
> -#line 1723 "dtc-parser.tab.c" /* yacc.c:1646  */
> +#line 1802 "dtc-parser.tab.c" /* yacc.c:1646  */
>      break;
>  
> -  case 29:
> -#line 287 "dtc-parser.y" /* yacc.c:1646  */
> +  case 35:
> +#line 344 "dtc-parser.y" /* yacc.c:1646  */
>      {
>  			(yyval.array).data = empty_data;
>  			(yyval.array).bits = 32;
>  		}
> -#line 1732 "dtc-parser.tab.c" /* yacc.c:1646  */
> +#line 1811 "dtc-parser.tab.c" /* yacc.c:1646  */
>      break;
>  
> -  case 30:
> -#line 292 "dtc-parser.y" /* yacc.c:1646  */
> +  case 36:
> +#line 349 "dtc-parser.y" /* yacc.c:1646  */
>      {
>  			if ((yyvsp[-1].array).bits < 64) {
>  				uint64_t mask = (1ULL << (yyvsp[-1].array).bits) - 1;
> @@ -1751,11 +1830,11 @@ yyreduce:
>  
>  			(yyval.array).data = data_append_integer((yyvsp[-1].array).data, (yyvsp[0].integer), (yyvsp[-1].array).bits);
>  		}
> -#line 1755 "dtc-parser.tab.c" /* yacc.c:1646  */
> +#line 1834 "dtc-parser.tab.c" /* yacc.c:1646  */
>      break;
>  
> -  case 31:
> -#line 311 "dtc-parser.y" /* yacc.c:1646  */
> +  case 37:
> +#line 368 "dtc-parser.y" /* yacc.c:1646  */
>      {
>  			uint64_t val = ~0ULL >> (64 - (yyvsp[-1].array).bits);
>  
> @@ -1769,233 +1848,247 @@ yyreduce:
>  
>  			(yyval.array).data = data_append_integer((yyvsp[-1].array).data, val, (yyvsp[-1].array).bits);
>  		}
> -#line 1773 "dtc-parser.tab.c" /* yacc.c:1646  */
> +#line 1852 "dtc-parser.tab.c" /* yacc.c:1646  */
>      break;
>  
> -  case 32:
> -#line 325 "dtc-parser.y" /* yacc.c:1646  */
> +  case 38:
> +#line 382 "dtc-parser.y" /* yacc.c:1646  */
>      {
>  			(yyval.array).data = data_add_marker((yyvsp[-1].array).data, LABEL, (yyvsp[0].labelref));
>  		}
> -#line 1781 "dtc-parser.tab.c" /* yacc.c:1646  */
> +#line 1860 "dtc-parser.tab.c" /* yacc.c:1646  */
>      break;
>  
> -  case 35:
> -#line 334 "dtc-parser.y" /* yacc.c:1646  */
> +  case 41:
> +#line 391 "dtc-parser.y" /* yacc.c:1646  */
>      {
>  			(yyval.integer) = (yyvsp[-1].integer);
>  		}
> -#line 1789 "dtc-parser.tab.c" /* yacc.c:1646  */
> +#line 1868 "dtc-parser.tab.c" /* yacc.c:1646  */
>      break;
>  
> -  case 38:
> -#line 345 "dtc-parser.y" /* yacc.c:1646  */
> +  case 44:
> +#line 402 "dtc-parser.y" /* yacc.c:1646  */
>      { (yyval.integer) = (yyvsp[-4].integer) ? (yyvsp[-2].integer) : (yyvsp[0].integer); }
> -#line 1795 "dtc-parser.tab.c" /* yacc.c:1646  */
> +#line 1874 "dtc-parser.tab.c" /* yacc.c:1646  */
>      break;
>  
> -  case 40:
> -#line 350 "dtc-parser.y" /* yacc.c:1646  */
> +  case 46:
> +#line 407 "dtc-parser.y" /* yacc.c:1646  */
>      { (yyval.integer) = (yyvsp[-2].integer) || (yyvsp[0].integer); }
> -#line 1801 "dtc-parser.tab.c" /* yacc.c:1646  */
> +#line 1880 "dtc-parser.tab.c" /* yacc.c:1646  */
>      break;
>  
> -  case 42:
> -#line 355 "dtc-parser.y" /* yacc.c:1646  */
> +  case 48:
> +#line 412 "dtc-parser.y" /* yacc.c:1646  */
>      { (yyval.integer) = (yyvsp[-2].integer) && (yyvsp[0].integer); }
> -#line 1807 "dtc-parser.tab.c" /* yacc.c:1646  */
> +#line 1886 "dtc-parser.tab.c" /* yacc.c:1646  */
>      break;
>  
> -  case 44:
> -#line 360 "dtc-parser.y" /* yacc.c:1646  */
> +  case 50:
> +#line 417 "dtc-parser.y" /* yacc.c:1646  */
>      { (yyval.integer) = (yyvsp[-2].integer) | (yyvsp[0].integer); }
> -#line 1813 "dtc-parser.tab.c" /* yacc.c:1646  */
> +#line 1892 "dtc-parser.tab.c" /* yacc.c:1646  */
>      break;
>  
> -  case 46:
> -#line 365 "dtc-parser.y" /* yacc.c:1646  */
> +  case 52:
> +#line 422 "dtc-parser.y" /* yacc.c:1646  */
>      { (yyval.integer) = (yyvsp[-2].integer) ^ (yyvsp[0].integer); }
> -#line 1819 "dtc-parser.tab.c" /* yacc.c:1646  */
> +#line 1898 "dtc-parser.tab.c" /* yacc.c:1646  */
>      break;
>  
> -  case 48:
> -#line 370 "dtc-parser.y" /* yacc.c:1646  */
> +  case 54:
> +#line 427 "dtc-parser.y" /* yacc.c:1646  */
>      { (yyval.integer) = (yyvsp[-2].integer) & (yyvsp[0].integer); }
> -#line 1825 "dtc-parser.tab.c" /* yacc.c:1646  */
> +#line 1904 "dtc-parser.tab.c" /* yacc.c:1646  */
>      break;
>  
> -  case 50:
> -#line 375 "dtc-parser.y" /* yacc.c:1646  */
> +  case 56:
> +#line 432 "dtc-parser.y" /* yacc.c:1646  */
>      { (yyval.integer) = (yyvsp[-2].integer) == (yyvsp[0].integer); }
> -#line 1831 "dtc-parser.tab.c" /* yacc.c:1646  */
> +#line 1910 "dtc-parser.tab.c" /* yacc.c:1646  */
>      break;
>  
> -  case 51:
> -#line 376 "dtc-parser.y" /* yacc.c:1646  */
> +  case 57:
> +#line 433 "dtc-parser.y" /* yacc.c:1646  */
>      { (yyval.integer) = (yyvsp[-2].integer) != (yyvsp[0].integer); }
> -#line 1837 "dtc-parser.tab.c" /* yacc.c:1646  */
> +#line 1916 "dtc-parser.tab.c" /* yacc.c:1646  */
>      break;
>  
> -  case 53:
> -#line 381 "dtc-parser.y" /* yacc.c:1646  */
> +  case 59:
> +#line 438 "dtc-parser.y" /* yacc.c:1646  */
>      { (yyval.integer) = (yyvsp[-2].integer) < (yyvsp[0].integer); }
> -#line 1843 "dtc-parser.tab.c" /* yacc.c:1646  */
> +#line 1922 "dtc-parser.tab.c" /* yacc.c:1646  */
>      break;
>  
> -  case 54:
> -#line 382 "dtc-parser.y" /* yacc.c:1646  */
> +  case 60:
> +#line 439 "dtc-parser.y" /* yacc.c:1646  */
>      { (yyval.integer) = (yyvsp[-2].integer) > (yyvsp[0].integer); }
> -#line 1849 "dtc-parser.tab.c" /* yacc.c:1646  */
> +#line 1928 "dtc-parser.tab.c" /* yacc.c:1646  */
>      break;
>  
> -  case 55:
> -#line 383 "dtc-parser.y" /* yacc.c:1646  */
> +  case 61:
> +#line 440 "dtc-parser.y" /* yacc.c:1646  */
>      { (yyval.integer) = (yyvsp[-2].integer) <= (yyvsp[0].integer); }
> -#line 1855 "dtc-parser.tab.c" /* yacc.c:1646  */
> +#line 1934 "dtc-parser.tab.c" /* yacc.c:1646  */
>      break;
>  
> -  case 56:
> -#line 384 "dtc-parser.y" /* yacc.c:1646  */
> +  case 62:
> +#line 441 "dtc-parser.y" /* yacc.c:1646  */
>      { (yyval.integer) = (yyvsp[-2].integer) >= (yyvsp[0].integer); }
> -#line 1861 "dtc-parser.tab.c" /* yacc.c:1646  */
> +#line 1940 "dtc-parser.tab.c" /* yacc.c:1646  */
>      break;
>  
> -  case 57:
> -#line 388 "dtc-parser.y" /* yacc.c:1646  */
> +  case 63:
> +#line 445 "dtc-parser.y" /* yacc.c:1646  */
>      { (yyval.integer) = (yyvsp[-2].integer) << (yyvsp[0].integer); }
> -#line 1867 "dtc-parser.tab.c" /* yacc.c:1646  */
> +#line 1946 "dtc-parser.tab.c" /* yacc.c:1646  */
>      break;
>  
> -  case 58:
> -#line 389 "dtc-parser.y" /* yacc.c:1646  */
> +  case 64:
> +#line 446 "dtc-parser.y" /* yacc.c:1646  */
>      { (yyval.integer) = (yyvsp[-2].integer) >> (yyvsp[0].integer); }
> -#line 1873 "dtc-parser.tab.c" /* yacc.c:1646  */
> +#line 1952 "dtc-parser.tab.c" /* yacc.c:1646  */
>      break;
>  
> -  case 60:
> -#line 394 "dtc-parser.y" /* yacc.c:1646  */
> +  case 66:
> +#line 451 "dtc-parser.y" /* yacc.c:1646  */
>      { (yyval.integer) = (yyvsp[-2].integer) + (yyvsp[0].integer); }
> -#line 1879 "dtc-parser.tab.c" /* yacc.c:1646  */
> +#line 1958 "dtc-parser.tab.c" /* yacc.c:1646  */
>      break;
>  
> -  case 61:
> -#line 395 "dtc-parser.y" /* yacc.c:1646  */
> +  case 67:
> +#line 452 "dtc-parser.y" /* yacc.c:1646  */
>      { (yyval.integer) = (yyvsp[-2].integer) - (yyvsp[0].integer); }
> -#line 1885 "dtc-parser.tab.c" /* yacc.c:1646  */
> +#line 1964 "dtc-parser.tab.c" /* yacc.c:1646  */
>      break;
>  
> -  case 63:
> -#line 400 "dtc-parser.y" /* yacc.c:1646  */
> +  case 69:
> +#line 457 "dtc-parser.y" /* yacc.c:1646  */
>      { (yyval.integer) = (yyvsp[-2].integer) * (yyvsp[0].integer); }
> -#line 1891 "dtc-parser.tab.c" /* yacc.c:1646  */
> +#line 1970 "dtc-parser.tab.c" /* yacc.c:1646  */
>      break;
>  
> -  case 64:
> -#line 401 "dtc-parser.y" /* yacc.c:1646  */
> -    { (yyval.integer) = (yyvsp[-2].integer) / (yyvsp[0].integer); }
> -#line 1897 "dtc-parser.tab.c" /* yacc.c:1646  */
> +  case 70:
> +#line 459 "dtc-parser.y" /* yacc.c:1646  */
> +    {
> +			if ((yyvsp[0].integer) != 0) {
> +				(yyval.integer) = (yyvsp[-2].integer) / (yyvsp[0].integer);
> +			} else {
> +				ERROR(&(yyloc), "Division by zero");
> +				(yyval.integer) = 0;
> +			}
> +		}
> +#line 1983 "dtc-parser.tab.c" /* yacc.c:1646  */
>      break;
>  
> -  case 65:
> -#line 402 "dtc-parser.y" /* yacc.c:1646  */
> -    { (yyval.integer) = (yyvsp[-2].integer) % (yyvsp[0].integer); }
> -#line 1903 "dtc-parser.tab.c" /* yacc.c:1646  */
> +  case 71:
> +#line 468 "dtc-parser.y" /* yacc.c:1646  */
> +    {
> +			if ((yyvsp[0].integer) != 0) {
> +				(yyval.integer) = (yyvsp[-2].integer) % (yyvsp[0].integer);
> +			} else {
> +				ERROR(&(yyloc), "Division by zero");
> +				(yyval.integer) = 0;
> +			}
> +		}
> +#line 1996 "dtc-parser.tab.c" /* yacc.c:1646  */
>      break;
>  
> -  case 68:
> -#line 408 "dtc-parser.y" /* yacc.c:1646  */
> +  case 74:
> +#line 481 "dtc-parser.y" /* yacc.c:1646  */
>      { (yyval.integer) = -(yyvsp[0].integer); }
> -#line 1909 "dtc-parser.tab.c" /* yacc.c:1646  */
> +#line 2002 "dtc-parser.tab.c" /* yacc.c:1646  */
>      break;
>  
> -  case 69:
> -#line 409 "dtc-parser.y" /* yacc.c:1646  */
> +  case 75:
> +#line 482 "dtc-parser.y" /* yacc.c:1646  */
>      { (yyval.integer) = ~(yyvsp[0].integer); }
> -#line 1915 "dtc-parser.tab.c" /* yacc.c:1646  */
> +#line 2008 "dtc-parser.tab.c" /* yacc.c:1646  */
>      break;
>  
> -  case 70:
> -#line 410 "dtc-parser.y" /* yacc.c:1646  */
> +  case 76:
> +#line 483 "dtc-parser.y" /* yacc.c:1646  */
>      { (yyval.integer) = !(yyvsp[0].integer); }
> -#line 1921 "dtc-parser.tab.c" /* yacc.c:1646  */
> +#line 2014 "dtc-parser.tab.c" /* yacc.c:1646  */
>      break;
>  
> -  case 71:
> -#line 415 "dtc-parser.y" /* yacc.c:1646  */
> +  case 77:
> +#line 488 "dtc-parser.y" /* yacc.c:1646  */
>      {
>  			(yyval.data) = empty_data;
>  		}
> -#line 1929 "dtc-parser.tab.c" /* yacc.c:1646  */
> +#line 2022 "dtc-parser.tab.c" /* yacc.c:1646  */
>      break;
>  
> -  case 72:
> -#line 419 "dtc-parser.y" /* yacc.c:1646  */
> +  case 78:
> +#line 492 "dtc-parser.y" /* yacc.c:1646  */
>      {
>  			(yyval.data) = data_append_byte((yyvsp[-1].data), (yyvsp[0].byte));
>  		}
> -#line 1937 "dtc-parser.tab.c" /* yacc.c:1646  */
> +#line 2030 "dtc-parser.tab.c" /* yacc.c:1646  */
>      break;
>  
> -  case 73:
> -#line 423 "dtc-parser.y" /* yacc.c:1646  */
> +  case 79:
> +#line 496 "dtc-parser.y" /* yacc.c:1646  */
>      {
>  			(yyval.data) = data_add_marker((yyvsp[-1].data), LABEL, (yyvsp[0].labelref));
>  		}
> -#line 1945 "dtc-parser.tab.c" /* yacc.c:1646  */
> +#line 2038 "dtc-parser.tab.c" /* yacc.c:1646  */
>      break;
>  
> -  case 74:
> -#line 430 "dtc-parser.y" /* yacc.c:1646  */
> +  case 80:
> +#line 503 "dtc-parser.y" /* yacc.c:1646  */
>      {
>  			(yyval.nodelist) = NULL;
>  		}
> -#line 1953 "dtc-parser.tab.c" /* yacc.c:1646  */
> +#line 2046 "dtc-parser.tab.c" /* yacc.c:1646  */
>      break;
>  
> -  case 75:
> -#line 434 "dtc-parser.y" /* yacc.c:1646  */
> +  case 81:
> +#line 507 "dtc-parser.y" /* yacc.c:1646  */
>      {
>  			(yyval.nodelist) = chain_node((yyvsp[-1].node), (yyvsp[0].nodelist));
>  		}
> -#line 1961 "dtc-parser.tab.c" /* yacc.c:1646  */
> +#line 2054 "dtc-parser.tab.c" /* yacc.c:1646  */
>      break;
>  
> -  case 76:
> -#line 438 "dtc-parser.y" /* yacc.c:1646  */
> +  case 82:
> +#line 511 "dtc-parser.y" /* yacc.c:1646  */
>      {
>  			ERROR(&(yylsp[0]), "Properties must precede subnodes");
>  			YYERROR;
>  		}
> -#line 1970 "dtc-parser.tab.c" /* yacc.c:1646  */
> +#line 2063 "dtc-parser.tab.c" /* yacc.c:1646  */
>      break;
>  
> -  case 77:
> -#line 446 "dtc-parser.y" /* yacc.c:1646  */
> +  case 83:
> +#line 519 "dtc-parser.y" /* yacc.c:1646  */
>      {
>  			(yyval.node) = name_node((yyvsp[0].node), (yyvsp[-1].propnodename));
>  		}
> -#line 1978 "dtc-parser.tab.c" /* yacc.c:1646  */
> +#line 2071 "dtc-parser.tab.c" /* yacc.c:1646  */
>      break;
>  
> -  case 78:
> -#line 450 "dtc-parser.y" /* yacc.c:1646  */
> +  case 84:
> +#line 523 "dtc-parser.y" /* yacc.c:1646  */
>      {
>  			(yyval.node) = name_node(build_node_delete(), (yyvsp[-1].propnodename));
>  		}
> -#line 1986 "dtc-parser.tab.c" /* yacc.c:1646  */
> +#line 2079 "dtc-parser.tab.c" /* yacc.c:1646  */
>      break;
>  
> -  case 79:
> -#line 454 "dtc-parser.y" /* yacc.c:1646  */
> +  case 85:
> +#line 527 "dtc-parser.y" /* yacc.c:1646  */
>      {
>  			add_label(&(yyvsp[0].node)->labels, (yyvsp[-1].labelref));
>  			(yyval.node) = (yyvsp[0].node);
>  		}
> -#line 1995 "dtc-parser.tab.c" /* yacc.c:1646  */
> +#line 2088 "dtc-parser.tab.c" /* yacc.c:1646  */
>      break;
>  
>  
> -#line 1999 "dtc-parser.tab.c" /* yacc.c:1646  */
> +#line 2092 "dtc-parser.tab.c" /* yacc.c:1646  */
>        default: break;
>      }
>    /* User semantic actions sometimes alter yychar, and that requires
> @@ -2230,7 +2323,7 @@ yyreturn:
>  #endif
>    return yyresult;
>  }
> -#line 460 "dtc-parser.y" /* yacc.c:1906  */
> +#line 533 "dtc-parser.y" /* yacc.c:1906  */
>  
>  
>  void yyerror(char const *s)
> diff --git a/scripts/dtc/dtc-parser.tab.h_shipped b/scripts/dtc/dtc-parser.tab.h_shipped
> index 30867c688..6aa512c1b 100644
> --- a/scripts/dtc/dtc-parser.tab.h_shipped
> +++ b/scripts/dtc/dtc-parser.tab.h_shipped
> @@ -1,8 +1,8 @@
> -/* A Bison parser, made by GNU Bison 3.0.2.  */
> +/* A Bison parser, made by GNU Bison 3.0.4.  */
>  
>  /* Bison interface for Yacc-like parsers in C
>  
> -   Copyright (C) 1984, 1989-1990, 2000-2013 Free Software Foundation, Inc.
> +   Copyright (C) 1984, 1989-1990, 2000-2015 Free Software Foundation, 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
> @@ -46,35 +46,36 @@ extern int yydebug;
>    enum yytokentype
>    {
>      DT_V1 = 258,
> -    DT_MEMRESERVE = 259,
> -    DT_LSHIFT = 260,
> -    DT_RSHIFT = 261,
> -    DT_LE = 262,
> -    DT_GE = 263,
> -    DT_EQ = 264,
> -    DT_NE = 265,
> -    DT_AND = 266,
> -    DT_OR = 267,
> -    DT_BITS = 268,
> -    DT_DEL_PROP = 269,
> -    DT_DEL_NODE = 270,
> -    DT_PROPNODENAME = 271,
> -    DT_LITERAL = 272,
> -    DT_CHAR_LITERAL = 273,
> -    DT_BYTE = 274,
> -    DT_STRING = 275,
> -    DT_LABEL = 276,
> -    DT_REF = 277,
> -    DT_INCBIN = 278
> +    DT_PLUGIN = 259,
> +    DT_MEMRESERVE = 260,
> +    DT_LSHIFT = 261,
> +    DT_RSHIFT = 262,
> +    DT_LE = 263,
> +    DT_GE = 264,
> +    DT_EQ = 265,
> +    DT_NE = 266,
> +    DT_AND = 267,
> +    DT_OR = 268,
> +    DT_BITS = 269,
> +    DT_DEL_PROP = 270,
> +    DT_DEL_NODE = 271,
> +    DT_PROPNODENAME = 272,
> +    DT_LITERAL = 273,
> +    DT_CHAR_LITERAL = 274,
> +    DT_BYTE = 275,
> +    DT_STRING = 276,
> +    DT_LABEL = 277,
> +    DT_REF = 278,
> +    DT_INCBIN = 279
>    };
>  #endif
>  
>  /* Value type.  */
>  #if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED
> -typedef union YYSTYPE YYSTYPE;
> +
>  union YYSTYPE
>  {
> -#line 38 "dtc-parser.y" /* yacc.c:1909  */
> +#line 39 "dtc-parser.y" /* yacc.c:1909  */
>  
>  	char *propnodename;
>  	char *labelref;
> @@ -92,9 +93,12 @@ union YYSTYPE
>  	struct node *nodelist;
>  	struct reserve_info *re;
>  	uint64_t integer;
> +	unsigned int flags;
>  
> -#line 97 "dtc-parser.tab.h" /* yacc.c:1909  */
> +#line 99 "dtc-parser.tab.h" /* yacc.c:1909  */
>  };
> +
> +typedef union YYSTYPE YYSTYPE;
>  # define YYSTYPE_IS_TRIVIAL 1
>  # define YYSTYPE_IS_DECLARED 1
>  #endif
> diff --git a/scripts/dtc/dtc-parser.y b/scripts/dtc/dtc-parser.y
> index ea57e0a05..44af170ab 100644
> --- a/scripts/dtc/dtc-parser.y
> +++ b/scripts/dtc/dtc-parser.y
> @@ -19,6 +19,7 @@
>   */
>  %{
>  #include <stdio.h>
> +#include <inttypes.h>
>  
>  #include "dtc.h"
>  #include "srcpos.h"
> @@ -31,7 +32,7 @@ extern void yyerror(char const *s);
>  		treesource_error = true; \
>  	} while (0)
>  
> -extern struct boot_info *the_boot_info;
> +extern struct dt_info *parser_output;
>  extern bool treesource_error;
>  %}
>  
> @@ -52,9 +53,11 @@ extern bool treesource_error;
>  	struct node *nodelist;
>  	struct reserve_info *re;
>  	uint64_t integer;
> +	unsigned int flags;
>  }
>  
>  %token DT_V1
> +%token DT_PLUGIN
>  %token DT_MEMRESERVE
>  %token DT_LSHIFT DT_RSHIFT DT_LE DT_GE DT_EQ DT_NE DT_AND DT_OR
>  %token DT_BITS
> @@ -71,6 +74,8 @@ extern bool treesource_error;
>  
>  %type <data> propdata
>  %type <data> propdataprefix
> +%type <flags> header
> +%type <flags> headers
>  %type <re> memreserve
>  %type <re> memreserves
>  %type <array> arrayprefix
> @@ -101,10 +106,31 @@ extern bool treesource_error;
>  %%
>  
>  sourcefile:
> -	  DT_V1 ';' memreserves devicetree
> +	  headers memreserves devicetree
>  		{
> -			the_boot_info = build_boot_info($3, $4,
> -							guess_boot_cpuid($4));
> +			parser_output = build_dt_info($1, $2, $3,
> +			                              guess_boot_cpuid($3));
> +		}
> +	;
> +
> +header:
> +	  DT_V1 ';'
> +		{
> +			$$ = DTSF_V1;
> +		}
> +	| DT_V1 ';' DT_PLUGIN ';'
> +		{
> +			$$ = DTSF_V1 | DTSF_PLUGIN;
> +		}
> +	;
> +
> +headers:
> +	  header
> +	| header headers
> +		{
> +			if ($2 != $1)
> +				ERROR(&@2, "Header flags don't match earlier ones");
> +			$$ = $1;
>  		}
>  	;
>  
> @@ -140,14 +166,45 @@ devicetree:
>  		{
>  			$$ = merge_nodes($1, $3);
>  		}
> +	| DT_REF nodedef
> +		{
> +			/*
> +			 * We rely on the rule being always:
> +			 *   versioninfo plugindecl memreserves devicetree
> +			 * so $-1 is what we want (plugindecl)
> +			 */
> +			if (!($<flags>-1 & DTSF_PLUGIN))
> +				ERROR(&@2, "Label or path %s not found", $1);
> +			$$ = add_orphan_node(name_node(build_node(NULL, NULL), ""), $2, $1);
> +		}
> +	| devicetree DT_LABEL DT_REF nodedef
> +		{
> +			struct node *target = get_node_by_ref($1, $3);
> +
> +			if (target) {
> +				add_label(&target->labels, $2);
> +				merge_nodes(target, $4);
> +			} else
> +				ERROR(&@3, "Label or path %s not found", $3);
> +			$$ = $1;
> +		}
>  	| devicetree DT_REF nodedef
>  		{
>  			struct node *target = get_node_by_ref($1, $2);
>  
> -			if (target)
> +			if (target) {
>  				merge_nodes(target, $3);
> -			else
> -				ERROR(&@2, "Label or path %s not found", $2);
> +			} 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 ';'
> @@ -398,8 +455,24 @@ integer_add:
>  
>  integer_mul:
>  	  integer_mul '*' integer_unary { $$ = $1 * $3; }
> -	| integer_mul '/' integer_unary { $$ = $1 / $3; }
> -	| integer_mul '%' integer_unary { $$ = $1 % $3; }
> +	| integer_mul '/' integer_unary
> +		{
> +			if ($3 != 0) {
> +				$$ = $1 / $3;
> +			} else {
> +				ERROR(&@$, "Division by zero");
> +				$$ = 0;
> +			}
> +		}
> +	| integer_mul '%' integer_unary
> +		{
> +			if ($3 != 0) {
> +				$$ = $1 % $3;
> +			} else {
> +				ERROR(&@$, "Division by zero");
> +				$$ = 0;
> +			}
> +		}
>  	| integer_unary
>  	;
>  
> diff --git a/scripts/dtc/dtc.c b/scripts/dtc/dtc.c
> index 8c4add69a..c36994e6e 100644
> --- a/scripts/dtc/dtc.c
> +++ b/scripts/dtc/dtc.c
> @@ -18,6 +18,8 @@
>   *                                                                   USA
>   */
>  
> +#include <sys/stat.h>
> +
>  #include "dtc.h"
>  #include "srcpos.h"
>  
> @@ -28,7 +30,16 @@ int quiet;		/* Level of quietness */
>  int reservenum;		/* Number of memory reservation slots */
>  int minsize;		/* Minimum blob size */
>  int padsize;		/* Additional padding to blob */
> -int phandle_format = PHANDLE_BOTH;	/* Use linux,phandle or phandle properties */
> +int alignsize;		/* Additional padding to blob accroding 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 */
> +
> +static int is_power_of_2(int x)
> +{
> +	return (x > 0) && ((x & (x - 1)) == 0);
> +}
>  
>  static void fill_fullpaths(struct node *tree, const char *prefix)
>  {
> @@ -48,10 +59,8 @@ static void fill_fullpaths(struct node *tree, const char *prefix)
>  }
>  
>  /* Usage related data. */
> -#define FDT_VERSION(version)	_FDT_VERSION(version)
> -#define _FDT_VERSION(version)	#version
>  static const char usage_synopsis[] = "dtc [options] <input file>";
> -static const char usage_short_opts[] = "qI:O:o:V:d:R:S:p:fb:i:H:sW:E:hv";
> +static const char usage_short_opts[] = "qI:O:o:V:d:R:S:p:a:fb:i:H:sW:E:@Ahv";
>  static struct option const usage_long_opts[] = {
>  	{"quiet",            no_argument, NULL, 'q'},
>  	{"in-format",         a_argument, NULL, 'I'},
> @@ -62,6 +71,7 @@ static struct option const usage_long_opts[] = {
>  	{"reserve",           a_argument, NULL, 'R'},
>  	{"space",             a_argument, NULL, 'S'},
>  	{"pad",               a_argument, NULL, 'p'},
> +	{"align",             a_argument, NULL, 'a'},
>  	{"boot-cpu",          a_argument, NULL, 'b'},
>  	{"force",            no_argument, NULL, 'f'},
>  	{"include",           a_argument, NULL, 'i'},
> @@ -69,6 +79,8 @@ static struct option const usage_long_opts[] = {
>  	{"phandle",           a_argument, NULL, 'H'},
>  	{"warning",           a_argument, NULL, 'W'},
>  	{"error",             a_argument, NULL, 'E'},
> +	{"symbols",	     no_argument, NULL, '@'},
> +	{"auto-alias",       no_argument, NULL, 'A'},
>  	{"help",             no_argument, NULL, 'h'},
>  	{"version",          no_argument, NULL, 'v'},
>  	{NULL,               no_argument, NULL, 0x0},
> @@ -84,11 +96,12 @@ static const char * const usage_opts_help[] = {
>  	 "\t\tdts - device tree source text\n"
>  	 "\t\tdtb - device tree blob\n"
>  	 "\t\tasm - assembler source",
> -	"\n\tBlob version to produce, defaults to "FDT_VERSION(DEFAULT_FDT_VERSION)" (for dtb and asm output)",
> +	"\n\tBlob version to produce, defaults to "stringify(DEFAULT_FDT_VERSION)" (for dtb and asm output)",
>  	"\n\tOutput dependency file",
>  	"\n\tMake space for <number> reserve map entries (for dtb and asm output)",
>  	"\n\tMake the blob at least <bytes> long (extra space)",
>  	"\n\tAdd padding to the blob of <bytes> long (extra space)",
> +	"\n\tMake the blob align to the <bytes> (extra space)",
>  	"\n\tSet the physical boot cpu",
>  	"\n\tTry to produce output even if the input tree has errors",
>  	"\n\tAdd a path to search for include files",
> @@ -99,16 +112,62 @@ static const char * const usage_opts_help[] = {
>  	 "\t\tboth   - Both \"linux,phandle\" and \"phandle\" properties",
>  	"\n\tEnable/disable warnings (prefix with \"no-\")",
>  	"\n\tEnable/disable errors (prefix with \"no-\")",
> +	"\n\tEnable generation of symbols",
> +	"\n\tEnable auto-alias of labels",
>  	"\n\tPrint this help and exit",
>  	"\n\tPrint version and exit",
>  	NULL,
>  };
>  
> +static const char *guess_type_by_name(const char *fname, const char *fallback)
> +{
> +	const char *s;
> +
> +	s = strrchr(fname, '.');
> +	if (s == NULL)
> +		return fallback;
> +	if (!strcasecmp(s, ".dts"))
> +		return "dts";
> +	if (!strcasecmp(s, ".dtb"))
> +		return "dtb";
> +	return fallback;
> +}
> +
> +static const char *guess_input_format(const char *fname, const char *fallback)
> +{
> +	struct stat statbuf;
> +	fdt32_t magic;
> +	FILE *f;
> +
> +	if (stat(fname, &statbuf) != 0)
> +		return fallback;
> +
> +	if (S_ISDIR(statbuf.st_mode))
> +		return "fs";
> +
> +	if (!S_ISREG(statbuf.st_mode))
> +		return fallback;
> +
> +	f = fopen(fname, "r");
> +	if (f == NULL)
> +		return fallback;
> +	if (fread(&magic, 4, 1, f) != 1) {
> +		fclose(f);
> +		return fallback;
> +	}
> +	fclose(f);
> +
> +	if (fdt32_to_cpu(magic) == FDT_MAGIC)
> +		return "dtb";
> +
> +	return guess_type_by_name(fname, fallback);
> +}
> +
>  int main(int argc, char *argv[])
>  {
> -	struct boot_info *bi;
> -	const char *inform = "dts";
> -	const char *outform = "dts";
> +	struct dt_info *dti;
> +	const char *inform = NULL;
> +	const char *outform = NULL;
>  	const char *outname = "-";
>  	const char *depname = NULL;
>  	bool force = false, sort = false;
> @@ -122,6 +181,7 @@ int main(int argc, char *argv[])
>  	reservenum = 0;
>  	minsize    = 0;
>  	padsize    = 0;
> +	alignsize  = 0;
>  
>  	while ((opt = util_getopt_long()) != EOF) {
>  		switch (opt) {
> @@ -149,6 +209,12 @@ int main(int argc, char *argv[])
>  		case 'p':
>  			padsize = strtol(optarg, NULL, 0);
>  			break;
> +		case 'a':
> +			alignsize = strtol(optarg, NULL, 0);
> +			if (!is_power_of_2(alignsize))
> +				die("Invalid argument \"%d\" to -a option\n",
> +				    alignsize);
> +			break;
>  		case 'f':
>  			force = true;
>  			break;
> @@ -187,6 +253,13 @@ int main(int argc, char *argv[])
>  			parse_checks_option(false, true, optarg);
>  			break;
>  
> +		case '@':
> +			generate_symbols = 1;
> +			break;
> +		case 'A':
> +			auto_label_aliases = 1;
> +			break;
> +
>  		case 'h':
>  			usage(NULL);
>  		default:
> @@ -213,28 +286,58 @@ int main(int argc, char *argv[])
>  		fprintf(depfile, "%s:", outname);
>  	}
>  
> +	if (inform == NULL)
> +		inform = guess_input_format(arg, "dts");
> +	if (outform == NULL) {
> +		outform = guess_type_by_name(outname, NULL);
> +		if (outform == NULL) {
> +			if (streq(inform, "dts"))
> +				outform = "dtb";
> +			else
> +				outform = "dts";
> +		}
> +	}
>  	if (streq(inform, "dts"))
> -		bi = dt_from_source(arg);
> +		dti = dt_from_source(arg);
>  	else if (streq(inform, "fs"))
> -		bi = dt_from_fs(arg);
> +		dti = dt_from_fs(arg);
>  	else if(streq(inform, "dtb"))
> -		bi = dt_from_blob(arg);
> +		dti = dt_from_blob(arg);
>  	else
>  		die("Unknown input format \"%s\"\n", inform);
>  
> +	dti->outname = outname;
> +
>  	if (depfile) {
>  		fputc('\n', depfile);
>  		fclose(depfile);
>  	}
>  
>  	if (cmdline_boot_cpuid != -1)
> -		bi->boot_cpuid_phys = cmdline_boot_cpuid;
> +		dti->boot_cpuid_phys = cmdline_boot_cpuid;
> +
> +	fill_fullpaths(dti->dt, "");
> +
> +	/* on a plugin, generate by default */
> +	if (dti->dtsflags & DTSF_PLUGIN) {
> +		generate_fixups = 1;
> +	}
>  
> -	fill_fullpaths(bi->dt, "");
> -	process_checks(force, bi);
> +	process_checks(force, dti);
> +
> +	if (auto_label_aliases)
> +		generate_label_tree(dti, "aliases", false);
> +
> +	if (generate_symbols)
> +		generate_label_tree(dti, "__symbols__", true);
> +
> +	if (generate_fixups) {
> +		generate_fixups_tree(dti, "__fixups__");
> +		generate_local_fixups_tree(dti, "__local_fixups__");
> +	}
>  
>  	if (sort)
> -		sort_tree(bi);
> +		sort_tree(dti);
>  
>  	if (streq(outname, "-")) {
>  		outf = stdout;
> @@ -246,11 +349,11 @@ int main(int argc, char *argv[])
>  	}
>  
>  	if (streq(outform, "dts")) {
> -		dt_to_source(outf, bi);
> +		dt_to_source(outf, dti);
>  	} else if (streq(outform, "dtb")) {
> -		dt_to_blob(outf, bi, outversion);
> +		dt_to_blob(outf, dti, outversion);
>  	} else if (streq(outform, "asm")) {
> -		dt_to_asm(outf, bi, outversion);
> +		dt_to_asm(outf, dti, outversion);
>  	} else if (streq(outform, "null")) {
>  		/* do nothing */
>  	} else {
> diff --git a/scripts/dtc/dtc.h b/scripts/dtc/dtc.h
> index 56212c8df..3b18a42b8 100644
> --- a/scripts/dtc/dtc.h
> +++ b/scripts/dtc/dtc.h
> @@ -1,5 +1,5 @@
> -#ifndef _DTC_H
> -#define _DTC_H
> +#ifndef DTC_H
> +#define DTC_H
>  
>  /*
>   * (C) Copyright David Gibson <dwg at au1.ibm.com>, IBM Corporation.  2005.
> @@ -31,6 +31,7 @@
>  #include <ctype.h>
>  #include <errno.h>
>  #include <unistd.h>
> +#include <inttypes.h>
>  
>  #include <libfdt_env.h>
>  #include <fdt.h>
> @@ -43,7 +44,6 @@
>  #define debug(...)
>  #endif
>  
> -
>  #define DEFAULT_FDT_VERSION	17
>  
>  /*
> @@ -53,7 +53,11 @@ extern int quiet;		/* Level of quietness */
>  extern 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 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 */
>  
>  #define PHANDLE_LEGACY	0x1
>  #define PHANDLE_EPAPR	0x2
> @@ -63,7 +67,8 @@ typedef uint32_t cell_t;
>  
>  
>  #define streq(a, b)	(strcmp((a), (b)) == 0)
> -#define strneq(a, b, n)	(strncmp((a), (b), (n)) == 0)
> +#define strstarts(s, prefix)	(strncmp((s), (prefix), strlen(prefix)) == 0)
> +#define strprefixeq(a, n, b)	(strlen(b) == (n) && (memcmp(a, b, n) == 0))
>  
>  #define ALIGN(x, a)	(((x) + (a) - 1) & ~((a) - 1))
>  
> @@ -110,7 +115,7 @@ struct data data_insert_at_marker(struct data d, struct marker *m,
>  struct data data_merge(struct data d1, struct data d2);
>  struct data data_append_cell(struct data d, cell_t word);
>  struct data data_append_integer(struct data d, uint64_t word, int bits);
> -struct data data_append_re(struct data d, const struct fdt_reserve_entry *re);
> +struct data data_append_re(struct data d, uint64_t address, uint64_t size);
>  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);
> @@ -132,6 +137,10 @@ struct label {
>  	struct label *next;
>  };
>  
> +struct bus_type {
> +	const char *name;
> +};
> +
>  struct property {
>  	bool deleted;
>  	char *name;
> @@ -158,6 +167,7 @@ struct node {
>  	int addr_cells, size_cells;
>  
>  	struct label *labels;
> +	const struct bus_type *bus;
>  };
>  
>  #define for_each_label_withdel(l0, l) \
> @@ -194,6 +204,7 @@ struct node *build_node_delete(void);
>  struct node *name_node(struct node *node, char *name);
>  struct node *chain_node(struct node *first, struct node *list);
>  struct node *merge_nodes(struct node *old_node, struct node *new_node);
> +struct node *add_orphan_node(struct node *old_node, struct node *new_node, char *ref);
>  
>  void add_property(struct node *node, struct property *prop);
>  void delete_property_by_name(struct node *node, char *name);
> @@ -201,10 +212,13 @@ void delete_property(struct property *prop);
>  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);
>  
>  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);
>  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,
> @@ -221,7 +235,7 @@ uint32_t guess_boot_cpuid(struct node *tree);
>  /* Boot info (tree plus memreserve information */
>  
>  struct reserve_info {
> -	struct fdt_reserve_entry re;
> +	uint64_t address, size;
>  
>  	struct reserve_info *next;
>  
> @@ -235,35 +249,45 @@ struct reserve_info *add_reserve_entry(struct reserve_info *list,
>  				       struct reserve_info *new);
>  
>  
> -struct boot_info {
> +struct dt_info {
> +	unsigned int dtsflags;
>  	struct reserve_info *reservelist;
> -	struct node *dt;		/* the device tree */
>  	uint32_t boot_cpuid_phys;
> +	struct node *dt;		/* the device tree */
> +	const char *outname;		/* filename being written to, "-" for stdout */
>  };
>  
> -struct boot_info *build_boot_info(struct reserve_info *reservelist,
> -				  struct node *tree, uint32_t boot_cpuid_phys);
> -void sort_tree(struct boot_info *bi);
> +/* DTS version flags definitions */
> +#define DTSF_V1		0x0001	/* /dts-v1/ */
> +#define DTSF_PLUGIN	0x0002	/* /plugin/ */
> +
> +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);
>  
>  /* Checks */
>  
>  void parse_checks_option(bool warn, bool error, const char *arg);
> -void process_checks(bool force, struct boot_info *bi);
> +void process_checks(bool force, struct dt_info *dti);
>  
>  /* Flattened trees */
>  
> -void dt_to_blob(FILE *f, struct boot_info *bi, int version);
> -void dt_to_asm(FILE *f, struct boot_info *bi, int version);
> +void dt_to_blob(FILE *f, struct dt_info *dti, int version);
> +void dt_to_asm(FILE *f, struct dt_info *dti, int version);
>  
> -struct boot_info *dt_from_blob(const char *fname);
> +struct dt_info *dt_from_blob(const char *fname);
>  
>  /* Tree source */
>  
> -void dt_to_source(FILE *f, struct boot_info *bi);
> -struct boot_info *dt_from_source(const char *f);
> +void dt_to_source(FILE *f, struct dt_info *dti);
> +struct dt_info *dt_from_source(const char *f);
>  
>  /* FS trees */
>  
> -struct boot_info *dt_from_fs(const char *dirname);
> +struct dt_info *dt_from_fs(const char *dirname);
>  
> -#endif /* _DTC_H */
> +#endif /* DTC_H */
> diff --git a/scripts/dtc/fdt.c b/scripts/dtc/fdt.c
> index 2ce6a4417..7855a1787 100644
> --- a/scripts/dtc/fdt.c
> +++ b/scripts/dtc/fdt.c
> @@ -76,18 +76,19 @@ int fdt_check_header(const void *fdt)
>  
>  const void *fdt_offset_ptr(const void *fdt, int offset, unsigned int len)
>  {
> -	const char *p;
> +	unsigned absoffset = offset + fdt_off_dt_struct(fdt);
> +
> +	if ((absoffset < offset)
> +	    || ((absoffset + len) < absoffset)
> +	    || (absoffset + len) > fdt_totalsize(fdt))
> +		return NULL;
>  
>  	if (fdt_version(fdt) >= 0x11)
>  		if (((offset + len) < offset)
>  		    || ((offset + len) > fdt_size_dt_struct(fdt)))
>  			return NULL;
>  
> -	p = _fdt_offset_ptr(fdt, offset);
> -
> -	if (p + len < p)
> -		return NULL;
> -	return p;
> +	return fdt_offset_ptr_(fdt, offset);
>  }
>  
>  uint32_t fdt_next_tag(const void *fdt, int startoffset, int *nextoffset)
> @@ -122,6 +123,9 @@ uint32_t fdt_next_tag(const void *fdt, int startoffset, int *nextoffset)
>  		/* skip-name offset, length and value */
>  		offset += sizeof(struct fdt_property) - FDT_TAGSIZE
>  			+ fdt32_to_cpu(*lenp);
> +		if (fdt_version(fdt) < 0x10 && fdt32_to_cpu(*lenp) >= 8 &&
> +		    ((offset - fdt32_to_cpu(*lenp)) % 8) != 0)
> +			offset += 4;
>  		break;
>  
>  	case FDT_END:
> @@ -140,7 +144,7 @@ uint32_t fdt_next_tag(const void *fdt, int startoffset, int *nextoffset)
>  	return tag;
>  }
>  
> -int _fdt_check_node_offset(const void *fdt, int offset)
> +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))
> @@ -149,7 +153,7 @@ int _fdt_check_node_offset(const void *fdt, int offset)
>  	return offset;
>  }
>  
> -int _fdt_check_prop_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))
> @@ -164,7 +168,7 @@ int fdt_next_node(const void *fdt, int offset, int *depth)
>  	uint32_t tag;
>  
>  	if (offset >= 0)
> -		if ((nextoffset = _fdt_check_node_offset(fdt, offset)) < 0)
> +		if ((nextoffset = fdt_check_node_offset_(fdt, offset)) < 0)
>  			return nextoffset;
>  
>  	do {
> @@ -226,7 +230,7 @@ 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_(const char *strtab, int tabsize, const char *s)
>  {
>  	int len = strlen(s) + 1;
>  	const char *last = strtab + tabsize - len;
> diff --git a/scripts/dtc/fdt.h b/scripts/dtc/fdt.h
> index 526aedb51..74961f902 100644
> --- a/scripts/dtc/fdt.h
> +++ b/scripts/dtc/fdt.h
> @@ -1,5 +1,5 @@
> -#ifndef _FDT_H
> -#define _FDT_H
> +#ifndef FDT_H
> +#define FDT_H
>  /*
>   * libfdt - Flat Device Tree manipulation
>   * Copyright (C) 2006 David Gibson, IBM Corporation.
> @@ -108,4 +108,4 @@ struct fdt_property {
>  #define FDT_V16_SIZE	FDT_V3_SIZE
>  #define FDT_V17_SIZE	(FDT_V16_SIZE + sizeof(fdt32_t))
>  
> -#endif /* _FDT_H */
> +#endif /* FDT_H */
> diff --git a/scripts/dtc/fdt_empty_tree.c b/scripts/dtc/fdt_empty_tree.c
> index f72d13b1d..f2ae9b77c 100644
> --- a/scripts/dtc/fdt_empty_tree.c
> +++ b/scripts/dtc/fdt_empty_tree.c
> @@ -81,4 +81,3 @@ int fdt_create_empty_tree(void *buf, int bufsize)
>  
>  	return fdt_open_into(buf, buf, bufsize);
>  }
> -
> diff --git a/scripts/dtc/fdt_overlay.c b/scripts/dtc/fdt_overlay.c
> new file mode 100644
> index 000000000..bf75388ec
> --- /dev/null
> +++ b/scripts/dtc/fdt_overlay.c
> @@ -0,0 +1,912 @@
> +/*
> + * libfdt - Flat Device Tree manipulation
> + * Copyright (C) 2016 Free Electrons
> + * Copyright (C) 2016 NextThing Co.
> + *
> + * libfdt is dual licensed: you can use it either under the terms of
> + * the GPL, or the BSD license, at your option.
> + *
> + *  a) This library is free software; you can redistribute it and/or
> + *     modify it under the terms of the GNU General Public License as
> + *     published by the Free Software Foundation; either version 2 of the
> + *     License, or (at your option) any later version.
> + *
> + *     This library is distributed in the hope that it will be useful,
> + *     but WITHOUT ANY WARRANTY; without even the implied warranty of
> + *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> + *     GNU General Public License for more details.
> + *
> + *     You should have received a copy of the GNU General Public
> + *     License along with this library; if not, write to the Free
> + *     Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
> + *     MA 02110-1301 USA
> + *
> + * Alternatively,
> + *
> + *  b) Redistribution and use in source and binary forms, with or
> + *     without modification, are permitted provided that the following
> + *     conditions are met:
> + *
> + *     1. Redistributions of source code must retain the above
> + *        copyright notice, this list of conditions and the following
> + *        disclaimer.
> + *     2. Redistributions in binary form must reproduce the above
> + *        copyright notice, this list of conditions and the following
> + *        disclaimer in the documentation and/or other materials
> + *        provided with the distribution.
> + *
> + *     THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
> + *     CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
> + *     INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
> + *     MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
> + *     DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
> + *     CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
> + *     SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
> + *     NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
> + *     LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
> + *     HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
> + *     CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
> + *     OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
> + *     EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
> + */
> +#include "libfdt_env.h"
> +
> +#include <fdt.h>
> +#include <libfdt.h>
> +
> +#include "libfdt_internal.h"
> +
> +/**
> + * overlay_get_target_phandle - retrieves the target phandle of a fragment
> + * @fdto: pointer to the device tree overlay blob
> + * @fragment: node offset of the fragment in the overlay
> + *
> + * overlay_get_target_phandle() retrieves the target phandle of an
> + * overlay fragment when that fragment uses a phandle (target
> + * property) instead of a path (target-path property).
> + *
> + * returns:
> + *      the phandle pointed by the target property
> + *      0, if the phandle was not found
> + *	-1, if the phandle was malformed
> + */
> +static uint32_t overlay_get_target_phandle(const void *fdto, int fragment)
> +{
> +	const fdt32_t *val;
> +	int len;
> +
> +	val = fdt_getprop(fdto, fragment, "target", &len);
> +	if (!val)
> +		return 0;
> +
> +	if ((len != sizeof(*val)) || (fdt32_to_cpu(*val) == (uint32_t)-1))
> +		return (uint32_t)-1;
> +
> +	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 targetting is
> + * done (through a phandle or a path)
> + *
> + * returns:
> + *      the targetted 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)
> +{
> +	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);
> +	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);
> +		if (path)
> +			ret = fdt_path_offset(fdt, path);
> +		else
> +			ret = path_len;
> +	} else
> +		ret = fdt_node_offset_by_phandle(fdt, phandle);
> +
> +	/*
> +	* If we haven't found either a target or a
> +	* target-path property in a node that contains a
> +	* __overlay__ subnode (we wouldn't be called
> +	* otherwise), consider it a improperly written
> +	* overlay
> +	*/
> +	if (ret < 0 && path_len == -FDT_ERR_NOTFOUND)
> +		ret = -FDT_ERR_BADOVERLAY;
> +
> +	/* return on error */
> +	if (ret < 0)
> +		return ret;
> +
> +	/* return pointer to path (if available) */
> +	if (pathp)
> +		*pathp = path ? path : NULL;
> +
> +	return ret;
> +}
> +
> +/**
> + * overlay_phandle_add_offset - Increases a phandle by an offset
> + * @fdt: Base device tree blob
> + * @node: Device tree overlay blob
> + * @name: Name of the property to modify (phandle or linux,phandle)
> + * @delta: offset to apply
> + *
> + * overlay_phandle_add_offset() increments a node phandle by a given
> + * offset.
> + *
> + * returns:
> + *      0 on success.
> + *      Negative error code on error
> + */
> +static int overlay_phandle_add_offset(void *fdt, int node,
> +				      const char *name, uint32_t delta)
> +{
> +	const fdt32_t *val;
> +	uint32_t adj_val;
> +	int len;
> +
> +	val = fdt_getprop(fdt, node, name, &len);
> +	if (!val)
> +		return len;
> +
> +	if (len != sizeof(*val))
> +		return -FDT_ERR_BADPHANDLE;
> +
> +	adj_val = fdt32_to_cpu(*val);
> +	if ((adj_val + delta) < adj_val)
> +		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);
> +}
> +
> +/**
> + * overlay_adjust_node_phandles - Offsets the phandles of a node
> + * @fdto: Device tree overlay blob
> + * @node: Offset of the node we want to adjust
> + * @delta: Offset to shift the phandles of
> + *
> + * overlay_adjust_node_phandles() adds a constant to all the phandles
> + * of a given node. This is mainly use as part of the overlay
> + * application process, when we want to update all the overlay
> + * phandles to not conflict with the overlays of the base device tree.
> + *
> + * returns:
> + *      0 on success
> + *      Negative error code on failure
> + */
> +static int overlay_adjust_node_phandles(void *fdto, int node,
> +					uint32_t delta)
> +{
> +	int child;
> +	int ret;
> +
> +	ret = overlay_phandle_add_offset(fdto, node, "phandle", delta);
> +	if (ret && ret != -FDT_ERR_NOTFOUND)
> +		return ret;
> +
> +	ret = overlay_phandle_add_offset(fdto, node, "linux,phandle", delta);
> +	if (ret && ret != -FDT_ERR_NOTFOUND)
> +		return ret;
> +
> +	fdt_for_each_subnode(child, fdto, node) {
> +		ret = overlay_adjust_node_phandles(fdto, child, delta);
> +		if (ret)
> +			return ret;
> +	}
> +
> +	return 0;
> +}
> +
> +/**
> + * overlay_adjust_local_phandles - Adjust the phandles of a whole overlay
> + * @fdto: Device tree overlay blob
> + * @delta: Offset to shift the phandles of
> + *
> + * overlay_adjust_local_phandles() adds a constant to all the
> + * phandles of an overlay. This is mainly use as part of the overlay
> + * application process, when we want to update all the overlay
> + * phandles to not conflict with the overlays of the base device tree.
> + *
> + * returns:
> + *      0 on success
> + *      Negative error code on failure
> + */
> +static int overlay_adjust_local_phandles(void *fdto, uint32_t delta)
> +{
> +	/*
> +	 * Start adjusting the phandles from the overlay root
> +	 */
> +	return overlay_adjust_node_phandles(fdto, 0, delta);
> +}
> +
> +/**
> + * overlay_update_local_node_references - Adjust the overlay references
> + * @fdto: Device tree overlay blob
> + * @tree_node: Node offset of the node to operate on
> + * @fixup_node: Node offset of the matching local fixups node
> + * @delta: Offset to shift the phandles of
> + *
> + * overlay_update_local_nodes_references() update the phandles
> + * pointing to a node within the device tree overlay by adding a
> + * constant delta.
> + *
> + * This is mainly used as part of a device tree application process,
> + * where you want the device tree overlays phandles to not conflict
> + * with the ones from the base device tree before merging them.
> + *
> + * returns:
> + *      0 on success
> + *      Negative error code on failure
> + */
> +static int overlay_update_local_node_references(void *fdto,
> +						int tree_node,
> +						int fixup_node,
> +						uint32_t delta)
> +{
> +	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 *tree_val;
> +		const char *name;
> +		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;
> +
> +		tree_val = fdt_getprop(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 / sizeof(uint32_t)); i++) {
> +			fdt32_t adj_val;
> +			uint32_t poffset;
> +
> +			poffset = fdt32_to_cpu(fixup_val[i]);
> +
> +			/*
> +			 * phandles to fixup can be unaligned.
> +			 *
> +			 * Use a memcpy for the architectures that do
> +			 * not support unaligned accesses.
> +			 */
> +			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;
> +		}
> +	}
> +
> +	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_local_node_references(fdto,
> +							   tree_child,
> +							   fixup_child,
> +							   delta);
> +		if (ret)
> +			return ret;
> +	}
> +
> +	return 0;
> +}
> +
> +/**
> + * overlay_update_local_references - Adjust the overlay references
> + * @fdto: Device tree overlay blob
> + * @delta: Offset to shift the phandles of
> + *
> + * overlay_update_local_references() update all the phandles pointing
> + * to a node within the device tree overlay by adding a constant
> + * delta to not conflict with the base overlay.
> + *
> + * This is mainly used as part of a device tree application process,
> + * where you want the device tree overlays phandles to not conflict
> + * with the ones from the base device tree before merging them.
> + *
> + * returns:
> + *      0 on success
> + *      Negative error code on failure
> + */
> +static int overlay_update_local_references(void *fdto, uint32_t delta)
> +{
> +	int fixups;
> +
> +	fixups = fdt_path_offset(fdto, "/__local_fixups__");
> +	if (fixups < 0) {
> +		/* There's no local phandles to adjust, bail out */
> +		if (fixups == -FDT_ERR_NOTFOUND)
> +			return 0;
> +
> +		return fixups;
> +	}
> +
> +	/*
> +	 * Update our local references from the root of the tree
> +	 */
> +	return overlay_update_local_node_references(fdto, 0, fixups,
> +						    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
> + * @path_len: number of path characters to consider
> + * @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
> + *
> + * overlay_fixup_one_phandle() resolves an overlay phandle pointing to
> + * a node in the base device tree.
> + *
> + * This is part of the device tree overlay application process, when
> + * you want all the phandles in the overlay to point to the actual
> + * base dt nodes.
> + *
> + * returns:
> + *      0 on success
> + *      Negative error code on failure
> + */
> +static int overlay_fixup_one_phandle(void *fdt, void *fdto,
> +				     int symbols_off,
> +				     const char *path, uint32_t path_len,
> +				     const char *name, uint32_t name_len,
> +				     int poffset, const char *label)
> +{
> +	const char *symbol_path;
> +	uint32_t phandle;
> +	fdt32_t phandle_prop;
> +	int symbol_off, fixup_off;
> +	int prop_len;
> +
> +	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;
> +	if (fixup_off < 0)
> +		return fixup_off;
> +
> +	phandle_prop = cpu_to_fdt32(phandle);
> +	return fdt_setprop_inplace_namelen_partial(fdto, fixup_off,
> +						   name, name_len, poffset,
> +						   &phandle_prop,
> +						   sizeof(phandle_prop));
> +};
> +
> +/**
> + * overlay_fixup_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
> + * @property: Property offset in the overlay holding the list of fixups
> + *
> + * overlay_fixup_phandle() resolves all the overlay phandles pointed
> + * to in a __fixups__ property, and updates them to match the phandles
> + * in use in the base device tree.
> + *
> + * This is part of the device tree overlay application process, when
> + * you want all the phandles in the overlay to point to the actual
> + * base dt nodes.
> + *
> + * returns:
> + *      0 on success
> + *      Negative error code on failure
> + */
> +static int overlay_fixup_phandle(void *fdt, void *fdto, int symbols_off,
> +				 int property)
> +{
> +	const char *value;
> +	const char *label;
> +	int len;
> +
> +	value = fdt_getprop_by_offset(fdto, property,
> +				      &label, &len);
> +	if (!value) {
> +		if (len == -FDT_ERR_NOTFOUND)
> +			return -FDT_ERR_INTERNAL;
> +
> +		return len;
> +	}
> +
> +	do {
> +		const char *path, *name, *fixup_end;
> +		const char *fixup_str = value;
> +		uint32_t path_len, name_len;
> +		uint32_t fixup_len;
> +		char *sep, *endptr;
> +		int poffset, ret;
> +
> +		fixup_end = memchr(value, '\0', len);
> +		if (!fixup_end)
> +			return -FDT_ERR_BADOVERLAY;
> +		fixup_len = fixup_end - fixup_str;
> +
> +		len -= fixup_len + 1;
> +		value += fixup_len + 1;
> +
> +		path = fixup_str;
> +		sep = memchr(fixup_str, ':', fixup_len);
> +		if (!sep || *sep != ':')
> +			return -FDT_ERR_BADOVERLAY;
> +
> +		path_len = sep - path;
> +		if (path_len == (fixup_len - 1))
> +			return -FDT_ERR_BADOVERLAY;
> +
> +		fixup_len -= path_len + 1;
> +		name = sep + 1;
> +		sep = memchr(name, ':', fixup_len);
> +		if (!sep || *sep != ':')
> +			return -FDT_ERR_BADOVERLAY;
> +
> +		name_len = sep - name;
> +		if (!name_len)
> +			return -FDT_ERR_BADOVERLAY;
> +
> +		poffset = strtoul(sep + 1, &endptr, 10);
> +		if ((*endptr != '\0') || (endptr <= (sep + 1)))
> +			return -FDT_ERR_BADOVERLAY;
> +
> +		ret = overlay_fixup_one_phandle(fdt, fdto, symbols_off,
> +						path, path_len, name, name_len,
> +						poffset, label);
> +		if (ret)
> +			return ret;
> +	} while (len > 0);
> +
> +	return 0;
> +}
> +
> +/**
> + * overlay_fixup_phandles - Resolve the overlay phandles to the base
> + *                          device tree
> + * @fdt: Base Device Tree blob
> + * @fdto: Device tree overlay blob
> + *
> + * overlay_fixup_phandles() resolves all the overlay phandles pointing
> + * to nodes in the base device tree.
> + *
> + * This is one of the steps of the device tree overlay application
> + * process, when you want all the phandles in the overlay to point to
> + * the actual base dt nodes.
> + *
> + * returns:
> + *      0 on success
> + *      Negative error code on failure
> + */
> +static int overlay_fixup_phandles(void *fdt, void *fdto)
> +{
> +	int fixups_off, symbols_off;
> +	int property;
> +
> +	/* We can have overlays without any fixups */
> +	fixups_off = fdt_path_offset(fdto, "/__fixups__");
> +	if (fixups_off == -FDT_ERR_NOTFOUND)
> +		return 0; /* nothing to do */
> +	if (fixups_off < 0)
> +		return fixups_off;
> +
> +	/* And base DTs without symbols */
> +	symbols_off = fdt_path_offset(fdt, "/__symbols__");
> +	if ((symbols_off < 0 && (symbols_off != -FDT_ERR_NOTFOUND)))
> +		return symbols_off;
> +
> +	fdt_for_each_property_offset(property, fdto, fixups_off) {
> +		int ret;
> +
> +		ret = overlay_fixup_phandle(fdt, fdto, symbols_off, property);
> +		if (ret)
> +			return ret;
> +	}
> +
> +	return 0;
> +}
> +
> +/**
> + * overlay_apply_node - Merges a node into the base device tree
> + * @fdt: Base Device Tree blob
> + * @target: Node offset in the base device tree to apply the fragment to
> + * @fdto: Device tree overlay blob
> + * @node: Node offset in the overlay holding the changes to merge
> + *
> + * overlay_apply_node() merges a node into a target base device tree
> + * node pointed.
> + *
> + * This is part of the final step in the device tree overlay
> + * application process, when all the phandles have been adjusted and
> + * resolved and you just have to merge overlay into the base device
> + * tree.
> + *
> + * returns:
> + *      0 on success
> + *      Negative error code on failure
> + */
> +static int overlay_apply_node(void *fdt, int target,
> +			      void *fdto, int node)
> +{
> +	int property;
> +	int subnode;
> +
> +	fdt_for_each_property_offset(property, fdto, node) {
> +		const char *name;
> +		const void *prop;
> +		int prop_len;
> +		int ret;
> +
> +		prop = fdt_getprop_by_offset(fdto, property, &name,
> +					     &prop_len);
> +		if (prop_len == -FDT_ERR_NOTFOUND)
> +			return -FDT_ERR_INTERNAL;
> +		if (prop_len < 0)
> +			return prop_len;
> +
> +		ret = fdt_setprop(fdt, target, name, prop, prop_len);
> +		if (ret)
> +			return ret;
> +	}
> +
> +	fdt_for_each_subnode(subnode, fdto, node) {
> +		const char *name = fdt_get_name(fdto, subnode, NULL);
> +		int nnode;
> +		int ret;
> +
> +		nnode = fdt_add_subnode(fdt, target, name);
> +		if (nnode == -FDT_ERR_EXISTS) {
> +			nnode = fdt_subnode_offset(fdt, target, name);
> +			if (nnode == -FDT_ERR_NOTFOUND)
> +				return -FDT_ERR_INTERNAL;
> +		}
> +
> +		if (nnode < 0)
> +			return nnode;
> +
> +		ret = overlay_apply_node(fdt, nnode, fdto, subnode);
> +		if (ret)
> +			return ret;
> +	}
> +
> +	return 0;
> +}
> +
> +/**
> + * overlay_merge - Merge an overlay into its base device tree
> + * @fdt: Base Device Tree blob
> + * @fdto: Device tree overlay blob
> + *
> + * overlay_merge() merges an overlay into its base device tree.
> + *
> + * This is the next to last step in the device tree overlay application
> + * process, when all the phandles have been adjusted and resolved and
> + * you just have to merge overlay into the base device tree.
> + *
> + * returns:
> + *      0 on success
> + *      Negative error code on failure
> + */
> +static int overlay_merge(void *fdt, void *fdto)
> +{
> +	int fragment;
> +
> +	fdt_for_each_subnode(fragment, fdto, 0) {
> +		int overlay;
> +		int target;
> +		int ret;
> +
> +		/*
> +		 * Each fragments will have an __overlay__ node. If
> +		 * they don't, it's not supposed to be merged
> +		 */
> +		overlay = fdt_subnode_offset(fdto, fragment, "__overlay__");
> +		if (overlay == -FDT_ERR_NOTFOUND)
> +			continue;
> +
> +		if (overlay < 0)
> +			return overlay;
> +
> +		target = overlay_get_target(fdt, fdto, fragment, NULL);
> +		if (target < 0)
> +			return target;
> +
> +		ret = overlay_apply_node(fdt, target, fdto, overlay);
> +		if (ret)
> +			return ret;
> +	}
> +
> +	return 0;
> +}
> +
> +static int get_path_len(const void *fdt, int nodeoffset)
> +{
> +	int len = 0, namelen;
> +	const char *name;
> +
> +	FDT_CHECK_HEADER(fdt);
> +
> +	for (;;) {
> +		name = fdt_get_name(fdt, nodeoffset, &namelen);
> +		if (!name)
> +			return namelen;
> +
> +		/* root? we're done */
> +		if (namelen == 0)
> +			break;
> +
> +		nodeoffset = fdt_parent_offset(fdt, nodeoffset);
> +		if (nodeoffset < 0)
> +			return nodeoffset;
> +		len += namelen + 1;
> +	}
> +
> +	/* in case of root pretend it's "/" */
> +	if (len == 0)
> +		len++;
> +	return len;
> +}
> +
> +/**
> + * overlay_symbol_update - Update the symbols of base tree after a merge
> + * @fdt: Base Device Tree blob
> + * @fdto: Device tree overlay blob
> + *
> + * overlay_symbol_update() updates the symbols of the base tree with the
> + * symbols of the applied overlay
> + *
> + * This is the last step in the device tree overlay application
> + * process, allowing the reference of overlay symbols by subsequent
> + * overlay operations.
> + *
> + * returns:
> + *      0 on success
> + *      Negative error code on failure
> + */
> +static int overlay_symbol_update(void *fdt, void *fdto)
> +{
> +	int root_sym, ov_sym, prop, path_len, fragment, target;
> +	int len, frag_name_len, ret, rel_path_len;
> +	const char *s, *e;
> +	const char *path;
> +	const char *name;
> +	const char *frag_name;
> +	const char *rel_path;
> +	const char *target_path;
> +	char *buf;
> +	void *p;
> +
> +	ov_sym = fdt_subnode_offset(fdto, 0, "__symbols__");
> +
> +	/* if no overlay symbols exist no problem */
> +	if (ov_sym < 0)
> +		return 0;
> +
> +	root_sym = fdt_subnode_offset(fdt, 0, "__symbols__");
> +
> +	/* it no root symbols exist we should create them */
> +	if (root_sym == -FDT_ERR_NOTFOUND)
> +		root_sym = fdt_add_subnode(fdt, 0, "__symbols__");
> +
> +	/* any error is fatal now */
> +	if (root_sym < 0)
> +		return root_sym;
> +
> +	/* iterate over each overlay symbol */
> +	fdt_for_each_property_offset(prop, fdto, ov_sym) {
> +		path = fdt_getprop_by_offset(fdto, prop, &name, &path_len);
> +		if (!path)
> +			return path_len;
> +
> +		/* verify it's a string property (terminated by a single \0) */
> +		if (path_len < 1 || memchr(path, '\0', path_len) != &path[path_len - 1])
> +			return -FDT_ERR_BADVALUE;
> +
> +		/* keep end marker to avoid strlen() */
> +		e = path + path_len;
> +
> +		/* format: /<fragment-name>/__overlay__/<relative-subnode-path> */
> +
> +		if (*path != '/')
> +			return -FDT_ERR_BADVALUE;
> +
> +		/* get fragment name first */
> +		s = strchr(path + 1, '/');
> +		if (!s)
> +			return -FDT_ERR_BADOVERLAY;
> +
> +		frag_name = path + 1;
> +		frag_name_len = s - path - 1;
> +
> +		/* verify format; safe since "s" lies in \0 terminated prop */
> +		len = sizeof("/__overlay__/") - 1;
> +		if ((e - s) < len || memcmp(s, "/__overlay__/", len))
> +			return -FDT_ERR_BADOVERLAY;
> +
> +		rel_path = s + len;
> +		rel_path_len = e - rel_path;
> +
> +		/* find the fragment index in which the symbol lies */
> +		ret = fdt_subnode_offset_namelen(fdto, 0, frag_name,
> +					       frag_name_len);
> +		/* not found? */
> +		if (ret < 0)
> +			return -FDT_ERR_BADOVERLAY;
> +		fragment = ret;
> +
> +		/* an __overlay__ subnode must exist */
> +		ret = fdt_subnode_offset(fdto, fragment, "__overlay__");
> +		if (ret < 0)
> +			return -FDT_ERR_BADOVERLAY;
> +
> +		/* get the target of the fragment */
> +		ret = overlay_get_target(fdt, fdto, fragment, &target_path);
> +		if (ret < 0)
> +			return ret;
> +		target = ret;
> +
> +		/* if we have a target path use */
> +		if (!target_path) {
> +			ret = get_path_len(fdt, target);
> +			if (ret < 0)
> +				return ret;
> +			len = ret;
> +		} else {
> +			len = strlen(target_path);
> +		}
> +
> +		ret = fdt_setprop_placeholder(fdt, root_sym, name,
> +				len + (len > 1) + rel_path_len + 1, &p);
> +		if (ret < 0)
> +			return ret;
> +
> +		if (!target_path) {
> +			/* again in case setprop_placeholder changed it */
> +			ret = overlay_get_target(fdt, fdto, fragment, &target_path);
> +			if (ret < 0)
> +				return ret;
> +			target = ret;
> +		}
> +
> +		buf = p;
> +		if (len > 1) { /* target is not root */
> +			if (!target_path) {
> +				ret = fdt_get_path(fdt, target, buf, len + 1);
> +				if (ret < 0)
> +					return ret;
> +			} else
> +				memcpy(buf, target_path, len + 1);
> +
> +		} else
> +			len--;
> +
> +		buf[len] = '/';
> +		memcpy(buf + len + 1, rel_path, rel_path_len);
> +		buf[len + 1 + rel_path_len] = '\0';
> +	}
> +
> +	return 0;
> +}
> +
> +int fdt_overlay_apply(void *fdt, void *fdto)
> +{
> +	uint32_t delta = fdt_get_max_phandle(fdt);
> +	int ret;
> +
> +	FDT_CHECK_HEADER(fdt);
> +	FDT_CHECK_HEADER(fdto);
> +
> +	ret = overlay_adjust_local_phandles(fdto, delta);
> +	if (ret)
> +		goto err;
> +
> +	ret = overlay_update_local_references(fdto, delta);
> +	if (ret)
> +		goto err;
> +
> +	ret = overlay_fixup_phandles(fdt, fdto);
> +	if (ret)
> +		goto err;
> +
> +	ret = overlay_merge(fdt, fdto);
> +	if (ret)
> +		goto err;
> +
> +	ret = overlay_symbol_update(fdt, fdto);
> +	if (ret)
> +		goto err;
> +
> +	/*
> +	 * The overlay has been damaged, erase its magic.
> +	 */
> +	fdt_set_magic(fdto, ~0);
> +
> +	return 0;
> +
> +err:
> +	/*
> +	 * The overlay might have been damaged, erase its magic.
> +	 */
> +	fdt_set_magic(fdto, ~0);
> +
> +	/*
> +	 * The base device tree might have been damaged, erase its
> +	 * magic.
> +	 */
> +	fdt_set_magic(fdt, ~0);
> +
> +	return ret;
> +}
> diff --git a/scripts/dtc/fdt_ro.c b/scripts/dtc/fdt_ro.c
> index 50007f61c..dfb3236da 100644
> --- a/scripts/dtc/fdt_ro.c
> +++ b/scripts/dtc/fdt_ro.c
> @@ -55,12 +55,13 @@
>  
>  #include "libfdt_internal.h"
>  
> -static int _fdt_nodename_eq(const void *fdt, int offset,
> +static int fdt_nodename_eq_(const void *fdt, int offset,
>  			    const char *s, int len)
>  {
> -	const char *p = fdt_offset_ptr(fdt, offset + FDT_TAGSIZE, len+1);
> +	int olen;
> +	const char *p = fdt_get_name(fdt, offset, &olen);
>  
> -	if (! p)
> +	if (!p || olen < len)
>  		/* short match */
>  		return 0;
>  
> @@ -80,7 +81,7 @@ const char *fdt_string(const void *fdt, int stroffset)
>  	return (const char *)fdt + fdt_off_dt_strings(fdt) + stroffset;
>  }
>  
> -static int _fdt_string_eq(const void *fdt, int stroffset,
> +static int fdt_string_eq_(const void *fdt, int stroffset,
>  			  const char *s, int len)
>  {
>  	const char *p = fdt_string(fdt, stroffset);
> @@ -88,11 +89,37 @@ static int _fdt_string_eq(const void *fdt, int stroffset,
>  	return (strlen(p) == len) && (memcmp(p, s, len) == 0);
>  }
>  
> +uint32_t fdt_get_max_phandle(const void *fdt)
> +{
> +	uint32_t max_phandle = 0;
> +	int offset;
> +
> +	for (offset = fdt_next_node(fdt, -1, NULL);;
> +	     offset = fdt_next_node(fdt, offset, NULL)) {
> +		uint32_t phandle;
> +
> +		if (offset == -FDT_ERR_NOTFOUND)
> +			return max_phandle;
> +
> +		if (offset < 0)
> +			return (uint32_t)-1;
> +
> +		phandle = fdt_get_phandle(fdt, offset);
> +		if (phandle == (uint32_t)-1)
> +			continue;
> +
> +		if (phandle > max_phandle)
> +			max_phandle = phandle;
> +	}
> +
> +	return 0;
> +}
> +
>  int fdt_get_mem_rsv(const void *fdt, int n, uint64_t *address, uint64_t *size)
>  {
>  	FDT_CHECK_HEADER(fdt);
> -	*address = fdt64_to_cpu(_fdt_mem_rsv(fdt, n)->address);
> -	*size = fdt64_to_cpu(_fdt_mem_rsv(fdt, n)->size);
> +	*address = fdt64_to_cpu(fdt_mem_rsv_(fdt, n)->address);
> +	*size = fdt64_to_cpu(fdt_mem_rsv_(fdt, n)->size);
>  	return 0;
>  }
>  
> @@ -100,12 +127,12 @@ int fdt_num_mem_rsv(const void *fdt)
>  {
>  	int i = 0;
>  
> -	while (fdt64_to_cpu(_fdt_mem_rsv(fdt, i)->size) != 0)
> +	while (fdt64_to_cpu(fdt_mem_rsv_(fdt, i)->size) != 0)
>  		i++;
>  	return i;
>  }
>  
> -static int _nextprop(const void *fdt, int offset)
> +static int nextprop_(const void *fdt, int offset)
>  {
>  	uint32_t tag;
>  	int nextoffset;
> @@ -140,7 +167,7 @@ int fdt_subnode_offset_namelen(const void *fdt, int offset,
>  	     (offset >= 0) && (depth >= 0);
>  	     offset = fdt_next_node(fdt, offset, &depth))
>  		if ((depth == 1)
> -		    && _fdt_nodename_eq(fdt, offset, name, namelen))
> +		    && fdt_nodename_eq_(fdt, offset, name, namelen))
>  			return offset;
>  
>  	if (depth < 0)
> @@ -154,9 +181,9 @@ int fdt_subnode_offset(const void *fdt, int parentoffset,
>  	return fdt_subnode_offset_namelen(fdt, parentoffset, name, strlen(name));
>  }
>  
> -int fdt_path_offset(const void *fdt, const char *path)
> +int fdt_path_offset_namelen(const void *fdt, const char *path, int namelen)
>  {
> -	const char *end = path + strlen(path);
> +	const char *end = path + namelen;
>  	const char *p = path;
>  	int offset = 0;
>  
> @@ -164,7 +191,7 @@ int fdt_path_offset(const void *fdt, const char *path)
>  
>  	/* see if we have an alias */
>  	if (*path != '/') {
> -		const char *q = strchr(path, '/');
> +		const char *q = memchr(path, '/', end - p);
>  
>  		if (!q)
>  			q = end;
> @@ -177,14 +204,15 @@ int fdt_path_offset(const void *fdt, const char *path)
>  		p = q;
>  	}
>  
> -	while (*p) {
> +	while (p < end) {
>  		const char *q;
>  
> -		while (*p == '/')
> +		while (*p == '/') {
>  			p++;
> -		if (! *p)
> -			return offset;
> -		q = strchr(p, '/');
> +			if (p == end)
> +				return offset;
> +		}
> +		q = memchr(p, '/', end - p);
>  		if (! q)
>  			q = end;
>  
> @@ -198,19 +226,42 @@ int fdt_path_offset(const void *fdt, const char *path)
>  	return offset;
>  }
>  
> +int fdt_path_offset(const void *fdt, const char *path)
> +{
> +	return fdt_path_offset_namelen(fdt, path, strlen(path));
> +}
> +
>  const char *fdt_get_name(const void *fdt, int nodeoffset, int *len)
>  {
> -	const struct fdt_node_header *nh = _fdt_offset_ptr(fdt, nodeoffset);
> +	const struct fdt_node_header *nh = fdt_offset_ptr_(fdt, nodeoffset);
> +	const char *nameptr;
>  	int err;
>  
>  	if (((err = fdt_check_header(fdt)) != 0)
> -	    || ((err = _fdt_check_node_offset(fdt, nodeoffset)) < 0))
> +	    || ((err = fdt_check_node_offset_(fdt, nodeoffset)) < 0))
>  			goto fail;
>  
> +	nameptr = nh->name;
> +
> +	if (fdt_version(fdt) < 0x10) {
> +		/*
> +		 * For old FDT versions, match the naming conventions of V16:
> +		 * give only the leaf name (after all /). The actual tree
> +		 * contents are loosely checked.
> +		 */
> +		const char *leaf;
> +		leaf = strrchr(nameptr, '/');
> +		if (leaf == NULL) {
> +			err = -FDT_ERR_BADSTRUCTURE;
> +			goto fail;
> +		}
> +		nameptr = leaf+1;
> +	}
> +
>  	if (len)
> -		*len = strlen(nh->name);
> +		*len = strlen(nameptr);
>  
> -	return nh->name;
> +	return nameptr;
>  
>   fail:
>  	if (len)
> @@ -222,34 +273,34 @@ int fdt_first_property_offset(const void *fdt, int nodeoffset)
>  {
>  	int offset;
>  
> -	if ((offset = _fdt_check_node_offset(fdt, nodeoffset)) < 0)
> +	if ((offset = fdt_check_node_offset_(fdt, nodeoffset)) < 0)
>  		return offset;
>  
> -	return _nextprop(fdt, offset);
> +	return nextprop_(fdt, offset);
>  }
>  
>  int fdt_next_property_offset(const void *fdt, int offset)
>  {
> -	if ((offset = _fdt_check_prop_offset(fdt, offset)) < 0)
> +	if ((offset = fdt_check_prop_offset_(fdt, offset)) < 0)
>  		return offset;
>  
> -	return _nextprop(fdt, offset);
> +	return nextprop_(fdt, offset);
>  }
>  
> -const struct fdt_property *fdt_get_property_by_offset(const void *fdt,
> -						      int offset,
> -						      int *lenp)
> +static const struct fdt_property *fdt_get_property_by_offset_(const void *fdt,
> +						              int offset,
> +						              int *lenp)
>  {
>  	int err;
>  	const struct fdt_property *prop;
>  
> -	if ((err = _fdt_check_prop_offset(fdt, offset)) < 0) {
> +	if ((err = fdt_check_prop_offset_(fdt, offset)) < 0) {
>  		if (lenp)
>  			*lenp = err;
>  		return NULL;
>  	}
>  
> -	prop = _fdt_offset_ptr(fdt, offset);
> +	prop = fdt_offset_ptr_(fdt, offset);
>  
>  	if (lenp)
>  		*lenp = fdt32_to_cpu(prop->len);
> @@ -257,23 +308,44 @@ const struct fdt_property *fdt_get_property_by_offset(const void *fdt,
>  	return prop;
>  }
>  
> -const struct fdt_property *fdt_get_property_namelen(const void *fdt,
> -						    int offset,
> -						    const char *name,
> -						    int namelen, int *lenp)
> +const struct fdt_property *fdt_get_property_by_offset(const void *fdt,
> +						      int offset,
> +						      int *lenp)
> +{
> +	/* Prior to version 16, properties may need realignment
> +	 * and this API does not work. fdt_getprop_*() will, however. */
> +
> +	if (fdt_version(fdt) < 0x10) {
> +		if (lenp)
> +			*lenp = -FDT_ERR_BADVERSION;
> +		return NULL;
> +	}
> +
> +	return fdt_get_property_by_offset_(fdt, offset, lenp);
> +}
> +
> +static const struct fdt_property *fdt_get_property_namelen_(const void *fdt,
> +						            int offset,
> +						            const char *name,
> +						            int namelen,
> +							    int *lenp,
> +							    int *poffset)
>  {
>  	for (offset = fdt_first_property_offset(fdt, offset);
>  	     (offset >= 0);
>  	     (offset = fdt_next_property_offset(fdt, offset))) {
>  		const struct fdt_property *prop;
>  
> -		if (!(prop = fdt_get_property_by_offset(fdt, offset, lenp))) {
> +		if (!(prop = fdt_get_property_by_offset_(fdt, offset, lenp))) {
>  			offset = -FDT_ERR_INTERNAL;
>  			break;
>  		}
> -		if (_fdt_string_eq(fdt, fdt32_to_cpu(prop->nameoff),
> -				   name, namelen))
> +		if (fdt_string_eq_(fdt, fdt32_to_cpu(prop->nameoff),
> +				   name, namelen)) {
> +			if (poffset)
> +				*poffset = offset;
>  			return prop;
> +		}
>  	}
>  
>  	if (lenp)
> @@ -281,6 +353,25 @@ const struct fdt_property *fdt_get_property_namelen(const void *fdt,
>  	return NULL;
>  }
>  
> +
> +const struct fdt_property *fdt_get_property_namelen(const void *fdt,
> +						    int offset,
> +						    const char *name,
> +						    int namelen, int *lenp)
> +{
> +	/* Prior to version 16, properties may need realignment
> +	 * and this API does not work. fdt_getprop_*() will, however. */
> +	if (fdt_version(fdt) < 0x10) {
> +		if (lenp)
> +			*lenp = -FDT_ERR_BADVERSION;
> +		return NULL;
> +	}
> +
> +	return fdt_get_property_namelen_(fdt, offset, name, namelen, lenp,
> +					 NULL);
> +}
> +
> +
>  const struct fdt_property *fdt_get_property(const void *fdt,
>  					    int nodeoffset,
>  					    const char *name, int *lenp)
> @@ -292,12 +383,18 @@ const struct fdt_property *fdt_get_property(const void *fdt,
>  const void *fdt_getprop_namelen(const void *fdt, int nodeoffset,
>  				const char *name, int namelen, int *lenp)
>  {
> +	int poffset;
>  	const struct fdt_property *prop;
>  
> -	prop = fdt_get_property_namelen(fdt, nodeoffset, name, namelen, lenp);
> -	if (! prop)
> +	prop = fdt_get_property_namelen_(fdt, nodeoffset, name, namelen, lenp,
> +					 &poffset);
> +	if (!prop)
>  		return NULL;
>  
> +	/* Handle realignment */
> +	if (fdt_version(fdt) < 0x10 && (poffset + sizeof(*prop)) % 8 &&
> +	    fdt32_to_cpu(prop->len) >= 8)
> +		return prop->data + 4;
>  	return prop->data;
>  }
>  
> @@ -306,11 +403,16 @@ const void *fdt_getprop_by_offset(const void *fdt, int offset,
>  {
>  	const struct fdt_property *prop;
>  
> -	prop = fdt_get_property_by_offset(fdt, offset, lenp);
> +	prop = fdt_get_property_by_offset_(fdt, offset, lenp);
>  	if (!prop)
>  		return NULL;
>  	if (namep)
>  		*namep = fdt_string(fdt, fdt32_to_cpu(prop->nameoff));
> +
> +	/* Handle realignment */
> +	if (fdt_version(fdt) < 0x10 && (offset + sizeof(*prop)) % 8 &&
> +	    fdt32_to_cpu(prop->len) >= 8)
> +		return prop->data + 4;
>  	return prop->data;
>  }
>  
> @@ -532,6 +634,106 @@ int fdt_stringlist_contains(const char *strlist, int listlen, const char *str)
>  	return 0;
>  }
>  
> +int fdt_stringlist_count(const void *fdt, int nodeoffset, const char *property)
> +{
> +	const char *list, *end;
> +	int length, count = 0;
> +
> +	list = fdt_getprop(fdt, nodeoffset, property, &length);
> +	if (!list)
> +		return length;
> +
> +	end = list + length;
> +
> +	while (list < end) {
> +		length = strnlen(list, end - list) + 1;
> +
> +		/* Abort if the last string isn't properly NUL-terminated. */
> +		if (list + length > end)
> +			return -FDT_ERR_BADVALUE;
> +
> +		list += length;
> +		count++;
> +	}
> +
> +	return count;
> +}
> +
> +int fdt_stringlist_search(const void *fdt, int nodeoffset, const char *property,
> +			  const char *string)
> +{
> +	int length, len, idx = 0;
> +	const char *list, *end;
> +
> +	list = fdt_getprop(fdt, nodeoffset, property, &length);
> +	if (!list)
> +		return length;
> +
> +	len = strlen(string) + 1;
> +	end = list + length;
> +
> +	while (list < end) {
> +		length = strnlen(list, end - list) + 1;
> +
> +		/* Abort if the last string isn't properly NUL-terminated. */
> +		if (list + length > end)
> +			return -FDT_ERR_BADVALUE;
> +
> +		if (length == len && memcmp(list, string, length) == 0)
> +			return idx;
> +
> +		list += length;
> +		idx++;
> +	}
> +
> +	return -FDT_ERR_NOTFOUND;
> +}
> +
> +const char *fdt_stringlist_get(const void *fdt, int nodeoffset,
> +			       const char *property, int idx,
> +			       int *lenp)
> +{
> +	const char *list, *end;
> +	int length;
> +
> +	list = fdt_getprop(fdt, nodeoffset, property, &length);
> +	if (!list) {
> +		if (lenp)
> +			*lenp = length;
> +
> +		return NULL;
> +	}
> +
> +	end = list + length;
> +
> +	while (list < end) {
> +		length = strnlen(list, end - list) + 1;
> +
> +		/* Abort if the last string isn't properly NUL-terminated. */
> +		if (list + length > end) {
> +			if (lenp)
> +				*lenp = -FDT_ERR_BADVALUE;
> +
> +			return NULL;
> +		}
> +
> +		if (idx == 0) {
> +			if (lenp)
> +				*lenp = length - 1;
> +
> +			return list;
> +		}
> +
> +		list += length;
> +		idx--;
> +	}
> +
> +	if (lenp)
> +		*lenp = -FDT_ERR_NOTFOUND;
> +
> +	return NULL;
> +}
> +
>  int fdt_node_check_compatible(const void *fdt, int nodeoffset,
>  			      const char *compatible)
>  {
> @@ -541,10 +743,8 @@ int fdt_node_check_compatible(const void *fdt, int nodeoffset,
>  	prop = fdt_getprop(fdt, nodeoffset, "compatible", &len);
>  	if (!prop)
>  		return len;
> -	if (fdt_stringlist_contains(prop, len, compatible))
> -		return 0;
> -	else
> -		return 1;
> +
> +	return !fdt_stringlist_contains(prop, len, compatible);
>  }
>  
>  int fdt_node_offset_by_compatible(const void *fdt, int startoffset,
> diff --git a/scripts/dtc/fdt_rw.c b/scripts/dtc/fdt_rw.c
> index 70adec6c3..9b829051e 100644
> --- a/scripts/dtc/fdt_rw.c
> +++ b/scripts/dtc/fdt_rw.c
> @@ -55,8 +55,8 @@
>  
>  #include "libfdt_internal.h"
>  
> -static int _fdt_blocks_misordered(const void *fdt,
> -			      int mem_rsv_size, int struct_size)
> +static int fdt_blocks_misordered_(const void *fdt,
> +				  int mem_rsv_size, int struct_size)
>  {
>  	return (fdt_off_mem_rsvmap(fdt) < FDT_ALIGN(sizeof(struct fdt_header), 8))
>  		|| (fdt_off_dt_struct(fdt) <
> @@ -67,13 +67,13 @@ static int _fdt_blocks_misordered(const void *fdt,
>  		    (fdt_off_dt_strings(fdt) + fdt_size_dt_strings(fdt)));
>  }
>  
> -static int _fdt_rw_check_header(void *fdt)
> +static int fdt_rw_check_header_(void *fdt)
>  {
>  	FDT_CHECK_HEADER(fdt);
>  
>  	if (fdt_version(fdt) < 17)
>  		return -FDT_ERR_BADVERSION;
> -	if (_fdt_blocks_misordered(fdt, sizeof(struct fdt_reserve_entry),
> +	if (fdt_blocks_misordered_(fdt, sizeof(struct fdt_reserve_entry),
>  				   fdt_size_dt_struct(fdt)))
>  		return -FDT_ERR_BADLAYOUT;
>  	if (fdt_version(fdt) > 17)
> @@ -84,35 +84,37 @@ static int _fdt_rw_check_header(void *fdt)
>  
>  #define FDT_RW_CHECK_HEADER(fdt) \
>  	{ \
> -		int __err; \
> -		if ((__err = _fdt_rw_check_header(fdt)) != 0) \
> -			return __err; \
> +		int err_; \
> +		if ((err_ = fdt_rw_check_header_(fdt)) != 0) \
> +			return err_; \
>  	}
>  
> -static inline int _fdt_data_size(void *fdt)
> +static inline int fdt_data_size_(void *fdt)
>  {
>  	return fdt_off_dt_strings(fdt) + fdt_size_dt_strings(fdt);
>  }
>  
> -static int _fdt_splice(void *fdt, void *splicepoint, int oldlen, int newlen)
> +static int fdt_splice_(void *fdt, void *splicepoint, int oldlen, int newlen)
>  {
>  	char *p = splicepoint;
> -	char *end = (char *)fdt + _fdt_data_size(fdt);
> +	char *end = (char *)fdt + fdt_data_size_(fdt);
>  
>  	if (((p + oldlen) < p) || ((p + oldlen) > end))
>  		return -FDT_ERR_BADOFFSET;
> +	if ((p < (char *)fdt) || ((end - oldlen + newlen) < (char *)fdt))
> +		return -FDT_ERR_BADOFFSET;
>  	if ((end - oldlen + newlen) > ((char *)fdt + fdt_totalsize(fdt)))
>  		return -FDT_ERR_NOSPACE;
>  	memmove(p + newlen, p + oldlen, end - p - oldlen);
>  	return 0;
>  }
>  
> -static int _fdt_splice_mem_rsv(void *fdt, struct fdt_reserve_entry *p,
> +static int fdt_splice_mem_rsv_(void *fdt, struct fdt_reserve_entry *p,
>  			       int oldn, int newn)
>  {
>  	int delta = (newn - oldn) * sizeof(*p);
>  	int err;
> -	err = _fdt_splice(fdt, p, oldn * sizeof(*p), newn * sizeof(*p));
> +	err = fdt_splice_(fdt, p, oldn * sizeof(*p), newn * sizeof(*p));
>  	if (err)
>  		return err;
>  	fdt_set_off_dt_struct(fdt, fdt_off_dt_struct(fdt) + delta);
> @@ -120,13 +122,13 @@ static int _fdt_splice_mem_rsv(void *fdt, struct fdt_reserve_entry *p,
>  	return 0;
>  }
>  
> -static int _fdt_splice_struct(void *fdt, void *p,
> +static int fdt_splice_struct_(void *fdt, void *p,
>  			      int oldlen, int newlen)
>  {
>  	int delta = newlen - oldlen;
>  	int err;
>  
> -	if ((err = _fdt_splice(fdt, p, oldlen, newlen)))
> +	if ((err = fdt_splice_(fdt, p, oldlen, newlen)))
>  		return err;
>  
>  	fdt_set_size_dt_struct(fdt, fdt_size_dt_struct(fdt) + delta);
> @@ -134,20 +136,20 @@ static int _fdt_splice_struct(void *fdt, void *p,
>  	return 0;
>  }
>  
> -static int _fdt_splice_string(void *fdt, int newlen)
> +static int fdt_splice_string_(void *fdt, int newlen)
>  {
>  	void *p = (char *)fdt
>  		+ fdt_off_dt_strings(fdt) + fdt_size_dt_strings(fdt);
>  	int err;
>  
> -	if ((err = _fdt_splice(fdt, p, 0, newlen)))
> +	if ((err = fdt_splice_(fdt, p, 0, newlen)))
>  		return err;
>  
>  	fdt_set_size_dt_strings(fdt, fdt_size_dt_strings(fdt) + newlen);
>  	return 0;
>  }
>  
> -static int _fdt_find_add_string(void *fdt, const char *s)
> +static int fdt_find_add_string_(void *fdt, const char *s)
>  {
>  	char *strtab = (char *)fdt + fdt_off_dt_strings(fdt);
>  	const char *p;
> @@ -155,13 +157,13 @@ static int _fdt_find_add_string(void *fdt, const char *s)
>  	int len = strlen(s) + 1;
>  	int err;
>  
> -	p = _fdt_find_string(strtab, fdt_size_dt_strings(fdt), s);
> +	p = fdt_find_string_(strtab, fdt_size_dt_strings(fdt), s);
>  	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, len);
>  	if (err)
>  		return err;
>  
> @@ -176,8 +178,8 @@ int fdt_add_mem_rsv(void *fdt, uint64_t address, uint64_t size)
>  
>  	FDT_RW_CHECK_HEADER(fdt);
>  
> -	re = _fdt_mem_rsv_w(fdt, fdt_num_mem_rsv(fdt));
> -	err = _fdt_splice_mem_rsv(fdt, re, 0, 1);
> +	re = fdt_mem_rsv_w_(fdt, fdt_num_mem_rsv(fdt));
> +	err = fdt_splice_mem_rsv_(fdt, re, 0, 1);
>  	if (err)
>  		return err;
>  
> @@ -188,31 +190,27 @@ int fdt_add_mem_rsv(void *fdt, uint64_t address, uint64_t size)
>  
>  int fdt_del_mem_rsv(void *fdt, int n)
>  {
> -	struct fdt_reserve_entry *re = _fdt_mem_rsv_w(fdt, n);
> -	int err;
> +	struct fdt_reserve_entry *re = fdt_mem_rsv_w_(fdt, n);
>  
>  	FDT_RW_CHECK_HEADER(fdt);
>  
>  	if (n >= fdt_num_mem_rsv(fdt))
>  		return -FDT_ERR_NOTFOUND;
>  
> -	err = _fdt_splice_mem_rsv(fdt, re, 1, 0);
> -	if (err)
> -		return err;
> -	return 0;
> +	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 len, struct fdt_property **prop)
>  {
>  	int oldlen;
>  	int err;
>  
>  	*prop = fdt_get_property_w(fdt, nodeoffset, name, &oldlen);
> -	if (! (*prop))
> +	if (!*prop)
>  		return oldlen;
>  
> -	if ((err = _fdt_splice_struct(fdt, (*prop)->data, FDT_TAGALIGN(oldlen),
> +	if ((err = fdt_splice_struct_(fdt, (*prop)->data, FDT_TAGALIGN(oldlen),
>  				      FDT_TAGALIGN(len))))
>  		return err;
>  
> @@ -220,7 +218,7 @@ static int _fdt_resize_property(void *fdt, int nodeoffset, const char *name,
>  	return 0;
>  }
>  
> -static int _fdt_add_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 proplen;
> @@ -228,17 +226,17 @@ static int _fdt_add_property(void *fdt, int nodeoffset, const char *name,
>  	int namestroff;
>  	int err;
>  
> -	if ((nextoffset = _fdt_check_node_offset(fdt, nodeoffset)) < 0)
> +	if ((nextoffset = fdt_check_node_offset_(fdt, nodeoffset)) < 0)
>  		return nextoffset;
>  
> -	namestroff = _fdt_find_add_string(fdt, name);
> +	namestroff = fdt_find_add_string_(fdt, name);
>  	if (namestroff < 0)
>  		return namestroff;
>  
> -	*prop = _fdt_offset_ptr_w(fdt, nextoffset);
> +	*prop = fdt_offset_ptr_w_(fdt, nextoffset);
>  	proplen = sizeof(**prop) + FDT_TAGALIGN(len);
>  
> -	err = _fdt_splice_struct(fdt, *prop, 0, proplen);
> +	err = fdt_splice_struct_(fdt, *prop, 0, proplen);
>  	if (err)
>  		return err;
>  
> @@ -262,7 +260,7 @@ int fdt_set_name(void *fdt, int nodeoffset, const char *name)
>  
>  	newlen = strlen(name);
>  
> -	err = _fdt_splice_struct(fdt, namep, FDT_TAGALIGN(oldlen+1),
> +	err = fdt_splice_struct_(fdt, namep, FDT_TAGALIGN(oldlen+1),
>  				 FDT_TAGALIGN(newlen+1));
>  	if (err)
>  		return err;
> @@ -271,21 +269,36 @@ int fdt_set_name(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_placeholder(void *fdt, int nodeoffset, const char *name,
> +			    int len, void **prop_data)
>  {
>  	struct fdt_property *prop;
>  	int err;
>  
>  	FDT_RW_CHECK_HEADER(fdt);
>  
> -	err = _fdt_resize_property(fdt, nodeoffset, name, len, &prop);
> +	err = fdt_resize_property_(fdt, nodeoffset, name, len, &prop);
>  	if (err == -FDT_ERR_NOTFOUND)
> -		err = _fdt_add_property(fdt, nodeoffset, name, len, &prop);
> +		err = fdt_add_property_(fdt, nodeoffset, name, len, &prop);
> +	if (err)
> +		return err;
> +
> +	*prop_data = prop->data;
> +	return 0;
> +}
> +
> +int fdt_setprop(void *fdt, int nodeoffset, const char *name,
> +		const void *val, int len)
> +{
> +	void *prop_data;
> +	int err;
> +
> +	err = fdt_setprop_placeholder(fdt, nodeoffset, name, len, &prop_data);
>  	if (err)
>  		return err;
>  
> -	memcpy(prop->data, val, len);
> +	if (len)
> +		memcpy(prop_data, val, len);
>  	return 0;
>  }
>  
> @@ -300,7 +313,7 @@ int fdt_appendprop(void *fdt, int nodeoffset, const char *name,
>  	prop = fdt_get_property_w(fdt, nodeoffset, name, &oldlen);
>  	if (prop) {
>  		newlen = len + oldlen;
> -		err = _fdt_splice_struct(fdt, prop->data,
> +		err = fdt_splice_struct_(fdt, prop->data,
>  					 FDT_TAGALIGN(oldlen),
>  					 FDT_TAGALIGN(newlen));
>  		if (err)
> @@ -308,7 +321,7 @@ 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, len, &prop);
>  		if (err)
>  			return err;
>  		memcpy(prop->data, val, len);
> @@ -324,11 +337,11 @@ int fdt_delprop(void *fdt, int nodeoffset, const char *name)
>  	FDT_RW_CHECK_HEADER(fdt);
>  
>  	prop = fdt_get_property_w(fdt, nodeoffset, name, &len);
> -	if (! prop)
> +	if (!prop)
>  		return len;
>  
>  	proplen = sizeof(*prop) + FDT_TAGALIGN(len);
> -	return _fdt_splice_struct(fdt, prop, proplen, 0);
> +	return fdt_splice_struct_(fdt, prop, proplen, 0);
>  }
>  
>  int fdt_add_subnode_namelen(void *fdt, int parentoffset,
> @@ -356,10 +369,10 @@ int fdt_add_subnode_namelen(void *fdt, int parentoffset,
>  		tag = fdt_next_tag(fdt, offset, &nextoffset);
>  	} while ((tag == FDT_PROP) || (tag == FDT_NOP));
>  
> -	nh = _fdt_offset_ptr_w(fdt, offset);
> +	nh = fdt_offset_ptr_w_(fdt, offset);
>  	nodelen = sizeof(*nh) + FDT_TAGALIGN(namelen+1) + FDT_TAGSIZE;
>  
> -	err = _fdt_splice_struct(fdt, nh, 0, nodelen);
> +	err = fdt_splice_struct_(fdt, nh, 0, nodelen);
>  	if (err)
>  		return err;
>  
> @@ -383,15 +396,15 @@ int fdt_del_node(void *fdt, int nodeoffset)
>  
>  	FDT_RW_CHECK_HEADER(fdt);
>  
> -	endoffset = _fdt_node_end_offset(fdt, nodeoffset);
> +	endoffset = fdt_node_end_offset_(fdt, nodeoffset);
>  	if (endoffset < 0)
>  		return endoffset;
>  
> -	return _fdt_splice_struct(fdt, _fdt_offset_ptr_w(fdt, nodeoffset),
> +	return fdt_splice_struct_(fdt, fdt_offset_ptr_w_(fdt, nodeoffset),
>  				  endoffset - nodeoffset, 0);
>  }
>  
> -static void _fdt_packblocks(const char *old, char *new,
> +static void fdt_packblocks_(const char *old, char *new,
>  			    int mem_rsv_size, int struct_size)
>  {
>  	int mem_rsv_off, struct_off, strings_off;
> @@ -437,7 +450,7 @@ int fdt_open_into(const void *fdt, void *buf, int bufsize)
>  			return struct_size;
>  	}
>  
> -	if (!_fdt_blocks_misordered(fdt, mem_rsv_size, struct_size)) {
> +	if (!fdt_blocks_misordered_(fdt, mem_rsv_size, struct_size)) {
>  		/* no further work necessary */
>  		err = fdt_move(fdt, buf, bufsize);
>  		if (err)
> @@ -465,7 +478,7 @@ 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);
>  	memmove(buf, tmp, newsize);
>  
>  	fdt_set_magic(buf, FDT_MAGIC);
> @@ -485,8 +498,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_set_totalsize(fdt, _fdt_data_size(fdt));
> +	fdt_packblocks_(fdt, fdt, mem_rsv_size, fdt_size_dt_struct(fdt));
> +	fdt_set_totalsize(fdt, fdt_data_size_(fdt));
>  
>  	return 0;
>  }
> diff --git a/scripts/dtc/fdt_strerror.c b/scripts/dtc/fdt_strerror.c
> index e6c3ceee8..9677a1887 100644
> --- a/scripts/dtc/fdt_strerror.c
> +++ b/scripts/dtc/fdt_strerror.c
> @@ -69,6 +69,7 @@ static struct fdt_errtabent fdt_errtable[] = {
>  
>  	FDT_ERRTABENT(FDT_ERR_BADOFFSET),
>  	FDT_ERRTABENT(FDT_ERR_BADPATH),
> +	FDT_ERRTABENT(FDT_ERR_BADPHANDLE),
>  	FDT_ERRTABENT(FDT_ERR_BADSTATE),
>  
>  	FDT_ERRTABENT(FDT_ERR_TRUNCATED),
> @@ -76,6 +77,11 @@ static struct fdt_errtabent fdt_errtable[] = {
>  	FDT_ERRTABENT(FDT_ERR_BADVERSION),
>  	FDT_ERRTABENT(FDT_ERR_BADSTRUCTURE),
>  	FDT_ERRTABENT(FDT_ERR_BADLAYOUT),
> +	FDT_ERRTABENT(FDT_ERR_INTERNAL),
> +	FDT_ERRTABENT(FDT_ERR_BADNCELLS),
> +	FDT_ERRTABENT(FDT_ERR_BADVALUE),
> +	FDT_ERRTABENT(FDT_ERR_BADOVERLAY),
> +	FDT_ERRTABENT(FDT_ERR_NOPHANDLES),
>  };
>  #define FDT_ERRTABSIZE	(sizeof(fdt_errtable) / sizeof(fdt_errtable[0]))
>  
> diff --git a/scripts/dtc/fdt_sw.c b/scripts/dtc/fdt_sw.c
> index 6a804859f..6d33cc29d 100644
> --- a/scripts/dtc/fdt_sw.c
> +++ b/scripts/dtc/fdt_sw.c
> @@ -55,7 +55,7 @@
>  
>  #include "libfdt_internal.h"
>  
> -static int _fdt_sw_check_header(void *fdt)
> +static int fdt_sw_check_header_(void *fdt)
>  {
>  	if (fdt_magic(fdt) != FDT_SW_MAGIC)
>  		return -FDT_ERR_BADMAGIC;
> @@ -66,11 +66,11 @@ static int _fdt_sw_check_header(void *fdt)
>  #define FDT_SW_CHECK_HEADER(fdt) \
>  	{ \
>  		int err; \
> -		if ((err = _fdt_sw_check_header(fdt)) != 0) \
> +		if ((err = fdt_sw_check_header_(fdt)) != 0) \
>  			return err; \
>  	}
>  
> -static void *_fdt_grab_space(void *fdt, size_t len)
> +static void *fdt_grab_space_(void *fdt, size_t len)
>  {
>  	int offset = fdt_size_dt_struct(fdt);
>  	int spaceleft;
> @@ -82,7 +82,7 @@ static void *_fdt_grab_space(void *fdt, size_t len)
>  		return NULL;
>  
>  	fdt_set_size_dt_struct(fdt, offset + len);
> -	return _fdt_offset_ptr_w(fdt, offset);
> +	return fdt_offset_ptr_w_(fdt, offset);
>  }
>  
>  int fdt_create(void *buf, int bufsize)
> @@ -174,7 +174,7 @@ int fdt_begin_node(void *fdt, const char *name)
>  
>  	FDT_SW_CHECK_HEADER(fdt);
>  
> -	nh = _fdt_grab_space(fdt, sizeof(*nh) + FDT_TAGALIGN(namelen));
> +	nh = fdt_grab_space_(fdt, sizeof(*nh) + FDT_TAGALIGN(namelen));
>  	if (! nh)
>  		return -FDT_ERR_NOSPACE;
>  
> @@ -189,7 +189,7 @@ int fdt_end_node(void *fdt)
>  
>  	FDT_SW_CHECK_HEADER(fdt);
>  
> -	en = _fdt_grab_space(fdt, FDT_TAGSIZE);
> +	en = fdt_grab_space_(fdt, FDT_TAGSIZE);
>  	if (! en)
>  		return -FDT_ERR_NOSPACE;
>  
> @@ -197,7 +197,7 @@ int fdt_end_node(void *fdt)
>  	return 0;
>  }
>  
> -static int _fdt_find_add_string(void *fdt, const char *s)
> +static int fdt_find_add_string_(void *fdt, const char *s)
>  {
>  	char *strtab = (char *)fdt + fdt_totalsize(fdt);
>  	const char *p;
> @@ -205,7 +205,7 @@ static int _fdt_find_add_string(void *fdt, const char *s)
>  	int len = strlen(s) + 1;
>  	int struct_top, offset;
>  
> -	p = _fdt_find_string(strtab - strtabsize, strtabsize, s);
> +	p = fdt_find_string_(strtab - strtabsize, strtabsize, s);
>  	if (p)
>  		return p - strtab;
>  
> @@ -220,25 +220,37 @@ static int _fdt_find_add_string(void *fdt, const char *s)
>  	return offset;
>  }
>  
> -int fdt_property(void *fdt, const char *name, const void *val, int len)
> +int fdt_property_placeholder(void *fdt, const char *name, int len, void **valp)
>  {
>  	struct fdt_property *prop;
>  	int nameoff;
>  
>  	FDT_SW_CHECK_HEADER(fdt);
>  
> -	nameoff = _fdt_find_add_string(fdt, name);
> +	nameoff = fdt_find_add_string_(fdt, name);
>  	if (nameoff == 0)
>  		return -FDT_ERR_NOSPACE;
>  
> -	prop = _fdt_grab_space(fdt, sizeof(*prop) + FDT_TAGALIGN(len));
> +	prop = fdt_grab_space_(fdt, sizeof(*prop) + FDT_TAGALIGN(len));
>  	if (! prop)
>  		return -FDT_ERR_NOSPACE;
>  
>  	prop->tag = cpu_to_fdt32(FDT_PROP);
>  	prop->nameoff = cpu_to_fdt32(nameoff);
>  	prop->len = cpu_to_fdt32(len);
> -	memcpy(prop->data, val, len);
> +	*valp = prop->data;
> +	return 0;
> +}
> +
> +int fdt_property(void *fdt, const char *name, const void *val, int len)
> +{
> +	void *ptr;
> +	int ret;
> +
> +	ret = fdt_property_placeholder(fdt, name, len, &ptr);
> +	if (ret)
> +		return ret;
> +	memcpy(ptr, val, len);
>  	return 0;
>  }
>  
> @@ -253,7 +265,7 @@ int fdt_finish(void *fdt)
>  	FDT_SW_CHECK_HEADER(fdt);
>  
>  	/* Add terminator */
> -	end = _fdt_grab_space(fdt, sizeof(*end));
> +	end = fdt_grab_space_(fdt, sizeof(*end));
>  	if (! end)
>  		return -FDT_ERR_NOSPACE;
>  	*end = cpu_to_fdt32(FDT_END);
> @@ -269,7 +281,7 @@ int fdt_finish(void *fdt)
>  	while ((tag = fdt_next_tag(fdt, offset, &nextoffset)) != FDT_END) {
>  		if (tag == FDT_PROP) {
>  			struct fdt_property *prop =
> -				_fdt_offset_ptr_w(fdt, offset);
> +				fdt_offset_ptr_w_(fdt, offset);
>  			int nameoff;
>  
>  			nameoff = fdt32_to_cpu(prop->nameoff);
> diff --git a/scripts/dtc/fdt_wip.c b/scripts/dtc/fdt_wip.c
> index c5bbb68d3..534c1cbbb 100644
> --- a/scripts/dtc/fdt_wip.c
> +++ b/scripts/dtc/fdt_wip.c
> @@ -55,24 +55,45 @@
>  
>  #include "libfdt_internal.h"
>  
> +int fdt_setprop_inplace_namelen_partial(void *fdt, int nodeoffset,
> +					const char *name, int namelen,
> +					uint32_t idx, const void *val,
> +					int len)
> +{
> +	void *propval;
> +	int proplen;
> +
> +	propval = fdt_getprop_namelen_w(fdt, nodeoffset, name, namelen,
> +					&proplen);
> +	if (!propval)
> +		return proplen;
> +
> +	if (proplen < (len + idx))
> +		return -FDT_ERR_NOSPACE;
> +
> +	memcpy((char *)propval + idx, val, len);
> +	return 0;
> +}
> +
>  int fdt_setprop_inplace(void *fdt, int nodeoffset, const char *name,
>  			const void *val, int len)
>  {
> -	void *propval;
> +	const void *propval;
>  	int proplen;
>  
> -	propval = fdt_getprop_w(fdt, nodeoffset, name, &proplen);
> -	if (! propval)
> +	propval = fdt_getprop(fdt, nodeoffset, name, &proplen);
> +	if (!propval)
>  		return proplen;
>  
>  	if (proplen != len)
>  		return -FDT_ERR_NOSPACE;
>  
> -	memcpy(propval, val, len);
> -	return 0;
> +	return fdt_setprop_inplace_namelen_partial(fdt, nodeoffset, name,
> +						   strlen(name), 0,
> +						   val, len);
>  }
>  
> -static void _fdt_nop_region(void *start, int len)
> +static void fdt_nop_region_(void *start, int len)
>  {
>  	fdt32_t *p;
>  
> @@ -86,15 +107,15 @@ int fdt_nop_property(void *fdt, int nodeoffset, const char *name)
>  	int len;
>  
>  	prop = fdt_get_property_w(fdt, nodeoffset, name, &len);
> -	if (! prop)
> +	if (!prop)
>  		return len;
>  
> -	_fdt_nop_region(prop, len + sizeof(*prop));
> +	fdt_nop_region_(prop, len + sizeof(*prop));
>  
>  	return 0;
>  }
>  
> -int _fdt_node_end_offset(void *fdt, int offset)
> +int fdt_node_end_offset_(void *fdt, int offset)
>  {
>  	int depth = 0;
>  
> @@ -108,11 +129,11 @@ int fdt_nop_node(void *fdt, int nodeoffset)
>  {
>  	int endoffset;
>  
> -	endoffset = _fdt_node_end_offset(fdt, nodeoffset);
> +	endoffset = fdt_node_end_offset_(fdt, nodeoffset);
>  	if (endoffset < 0)
>  		return endoffset;
>  
> -	_fdt_nop_region(fdt_offset_ptr_w(fdt, nodeoffset, 0),
> +	fdt_nop_region_(fdt_offset_ptr_w(fdt, nodeoffset, 0),
>  			endoffset - nodeoffset);
>  	return 0;
>  }
> diff --git a/scripts/dtc/fdtdump.c b/scripts/dtc/fdtdump.c
> index 95a6a2016..7d460a50b 100644
> --- a/scripts/dtc/fdtdump.c
> +++ b/scripts/dtc/fdtdump.c
> @@ -1,17 +1,16 @@
> +// SPDX-License-Identifier: GPL-2.0
>  /*
>   * fdtdump.c - Contributed by Pantelis Antoniou <pantelis.antoniou AT gmail.com>
>   */
>  
> -#include <stdbool.h>
>  #include <stdint.h>
>  #include <stdio.h>
>  #include <stdlib.h>
>  #include <string.h>
>  #include <ctype.h>
>  
> -#include <libfdt.h>
> -#include <libfdt_env.h>
>  #include <fdt.h>
> +#include <libfdt_env.h>
>  
>  #include "util.h"
>  
> @@ -19,29 +18,33 @@
>  #define PALIGN(p, a)	((void *)(ALIGN((unsigned long)(p), (a))))
>  #define GET_CELL(p)	(p += 4, *((const uint32_t *)(p-4)))
>  
> -static const char *tagname(uint32_t tag)
> +static void print_data(const char *data, int len)
>  {
> -	static const char * const names[] = {
> -#define TN(t) [t] = #t
> -		TN(FDT_BEGIN_NODE),
> -		TN(FDT_END_NODE),
> -		TN(FDT_PROP),
> -		TN(FDT_NOP),
> -		TN(FDT_END),
> -#undef TN
> -	};
> -	if (tag < ARRAY_SIZE(names))
> -		if (names[tag])
> -			return names[tag];
> -	return "FDT_???";
> +	int i;
> +	const char *p = data;
> +
> +	/* no data, don't print */
> +	if (len == 0)
> +		return;
> +
> +	if (util_is_printable_string(data, len)) {
> +		printf(" = \"%s\"", (const char *)data);
> +	} else if ((len % 4) == 0) {
> +		printf(" = <");
> +		for (i = 0; i < len; i += 4)
> +			printf("0x%08x%s", fdt32_to_cpu(GET_CELL(p)),
> +			       i < (len - 4) ? " " : "");
> +		printf(">");
> +	} else {
> +		printf(" = [");
> +		for (i = 0; i < len; i++)
> +			printf("%02x%s", *p++, i < len - 1 ? " " : "");
> +		printf("]");
> +	}
>  }
>  
> -#define dumpf(fmt, args...) \
> -	do { if (debug) printf("// " fmt, ## args); } while (0)
> -
> -static void dump_blob(void *blob, bool debug)
> +static void dump_blob(void *blob)
>  {
> -	uintptr_t blob_off = (uintptr_t)blob;
>  	struct fdt_header *bph = blob;
>  	uint32_t off_mem_rsvmap = fdt32_to_cpu(bph->off_mem_rsvmap);
>  	uint32_t off_dt = fdt32_to_cpu(bph->off_dt_struct);
> @@ -88,15 +91,14 @@ static void dump_blob(void *blob, bool debug)
>  		if (addr == 0 && size == 0)
>  			break;
>  
> -		printf("/memreserve/ %#llx %#llx;\n",
> +		printf("/memreserve/ %llx %llx;\n",
>  		       (unsigned long long)addr, (unsigned long long)size);
>  	}
>  
>  	p = p_struct;
>  	while ((tag = fdt32_to_cpu(GET_CELL(p))) != FDT_END) {
>  
> -		dumpf("%04zx: tag: 0x%08x (%s)\n",
> -		        (uintptr_t)p - blob_off - 4, tag, tagname(tag));
> +		/* printf("tag: 0x%08x (%d)\n", tag, p - p_struct); */
>  
>  		if (tag == FDT_BEGIN_NODE) {
>  			s = p;
> @@ -135,93 +137,27 @@ static void dump_blob(void *blob, bool debug)
>  
>  		p = PALIGN(p + sz, 4);
>  
> -		dumpf("%04zx: string: %s\n", (uintptr_t)s - blob_off, s);
> -		dumpf("%04zx: value\n", (uintptr_t)t - blob_off);
>  		printf("%*s%s", depth * shift, "", s);
> -		utilfdt_print_data(t, sz);
> +		print_data(t, sz);
>  		printf(";\n");
>  	}
>  }
>  
> -/* Usage related data. */
> -static const char usage_synopsis[] = "fdtdump [options] <file>";
> -static const char usage_short_opts[] = "ds" USAGE_COMMON_SHORT_OPTS;
> -static struct option const usage_long_opts[] = {
> -	{"debug",            no_argument, NULL, 'd'},
> -	{"scan",             no_argument, NULL, 's'},
> -	USAGE_COMMON_LONG_OPTS
> -};
> -static const char * const usage_opts_help[] = {
> -	"Dump debug information while decoding the file",
> -	"Scan for an embedded fdt in file",
> -	USAGE_COMMON_OPTS_HELP
> -};
>  
>  int main(int argc, char *argv[])
>  {
> -	int opt;
> -	const char *file;
>  	char *buf;
> -	bool debug = false;
> -	bool scan = false;
> -	off_t len;
> -
> -	while ((opt = util_getopt_long()) != EOF) {
> -		switch (opt) {
> -		case_USAGE_COMMON_FLAGS
>  
> -		case 'd':
> -			debug = true;
> -			break;
> -		case 's':
> -			scan = true;
> -			break;
> -		}
> -	}
> -	if (optind != argc - 1)
> -		usage("missing input filename");
> -	file = argv[optind];
> -
> -	buf = utilfdt_read_len(file, &len);
> -	if (!buf)
> -		die("could not read: %s\n", file);
> -
> -	/* try and locate an embedded fdt in a bigger blob */
> -	if (scan) {
> -		unsigned char smagic[4];
> -		char *p = buf;
> -		char *endp = buf + len;
> -
> -		fdt_set_magic(smagic, FDT_MAGIC);
> -
> -		/* poor man's memmem */
> -		while (true) {
> -			p = memchr(p, smagic[0], endp - p - 4);
> -			if (!p)
> -				break;
> -			if (fdt_magic(p) == FDT_MAGIC) {
> -				/* try and validate the main struct */
> -				off_t this_len = endp - p;
> -				fdt32_t max_version = 17;
> -				if (fdt_version(p) <= max_version &&
> -				    fdt_last_comp_version(p) < max_version &&
> -				    fdt_totalsize(p) < this_len &&
> -				    fdt_off_dt_struct(p) < this_len &&
> -					fdt_off_dt_strings(p) < this_len)
> -					break;
> -				if (debug)
> -					printf("%s: skipping fdt magic at offset %#zx\n",
> -						file, p - buf);
> -			}
> -			++p;
> -		}
> -		if (!p)
> -			die("%s: could not locate fdt magic\n", file);
> -		printf("%s: found fdt at offset %#zx\n", file, p - buf);
> -		buf = p;
> +	if (argc < 2) {
> +		fprintf(stderr, "supply input filename\n");
> +		return 5;
>  	}
>  
> -	dump_blob(buf, debug);
> +	buf = utilfdt_read(argv[1]);
> +	if (buf)
> +		dump_blob(buf);
> +	else
> +		return 10;
>  
>  	return 0;
>  }
> diff --git a/scripts/dtc/fdtget.c b/scripts/dtc/fdtget.c
> index 437741922..c2fbab2a5 100644
> --- a/scripts/dtc/fdtget.c
> +++ b/scripts/dtc/fdtget.c
> @@ -277,33 +277,33 @@ static int do_fdtget(struct display_info *disp, const char *filename,
>  	return 0;
>  }
>  
> -/* Usage related data. */
> -static const char usage_synopsis[] =
> -	"read values from device tree\n"
> +static const char *usage_msg =
> +	"fdtget - read values from device tree\n"
> +	"\n"
> +	"Each value is printed on a new line.\n\n"
> +	"Usage:\n"
>  	"	fdtget <options> <dt file> [<node> <property>]...\n"
>  	"	fdtget -p <options> <dt file> [<node> ]...\n"
> -	"\n"
> -	"Each value is printed on a new line.\n"
> +	"Options:\n"
> +	"\t-t <type>\tType of data\n"
> +	"\t-p\t\tList properties for each node\n"
> +	"\t-l\t\tList subnodes for each node\n"
> +	"\t-d\t\tDefault value to display when the property is "
> +			"missing\n"
> +	"\t-h\t\tPrint this help\n\n"
>  	USAGE_TYPE_MSG;
> -static const char usage_short_opts[] = "t:pld:" USAGE_COMMON_SHORT_OPTS;
> -static struct option const usage_long_opts[] = {
> -	{"type",              a_argument, NULL, 't'},
> -	{"properties",       no_argument, NULL, 'p'},
> -	{"list",             no_argument, NULL, 'l'},
> -	{"default",           a_argument, NULL, 'd'},
> -	USAGE_COMMON_LONG_OPTS,
> -};
> -static const char * const usage_opts_help[] = {
> -	"Type of data",
> -	"List properties for each node",
> -	"List subnodes for each node",
> -	"Default value to display when the property is missing",
> -	USAGE_COMMON_OPTS_HELP
> -};
> +
> +static void usage(const char *msg)
> +{
> +	if (msg)
> +		fprintf(stderr, "Error: %s\n\n", msg);
> +
> +	fprintf(stderr, "%s", usage_msg);
> +	exit(2);
> +}
>  
>  int main(int argc, char *argv[])
>  {
> -	int opt;
>  	char *filename = NULL;
>  	struct display_info disp;
>  	int args_per_step = 2;
> @@ -312,14 +312,20 @@ int main(int argc, char *argv[])
>  	memset(&disp, '\0', sizeof(disp));
>  	disp.size = -1;
>  	disp.mode = MODE_SHOW_VALUE;
> -	while ((opt = util_getopt_long()) != EOF) {
> -		switch (opt) {
> -		case_USAGE_COMMON_FLAGS
> +	for (;;) {
> +		int c = getopt(argc, argv, "d:hlpt:");
> +		if (c == -1)
> +			break;
> +
> +		switch (c) {
> +		case 'h':
> +		case '?':
> +			usage(NULL);
>  
>  		case 't':
>  			if (utilfdt_decode_type(optarg, &disp.type,
>  					&disp.size))
> -				usage("invalid type string");
> +				usage("Invalid type string");
>  			break;
>  
>  		case 'p':
> @@ -341,7 +347,7 @@ int main(int argc, char *argv[])
>  	if (optind < argc)
>  		filename = argv[optind++];
>  	if (!filename)
> -		usage("missing filename");
> +		usage("Missing filename");
>  
>  	argv += optind;
>  	argc -= optind;
> @@ -352,7 +358,7 @@ int main(int argc, char *argv[])
>  
>  	/* Check for node, property arguments */
>  	if (args_per_step == 2 && (argc % 2))
> -		usage("must have an even number of arguments");
> +		usage("Must have an even number of arguments");
>  
>  	if (do_fdtget(&disp, filename, argv, argc, args_per_step))
>  		return 1;
> diff --git a/scripts/dtc/fdtput.c b/scripts/dtc/fdtput.c
> index 2a8d67447..f2197f519 100644
> --- a/scripts/dtc/fdtput.c
> +++ b/scripts/dtc/fdtput.c
> @@ -96,7 +96,12 @@ static int encode_value(struct display_info *disp, char **arg, int arg_count,
>  		/* enlarge our value buffer by a suitable margin if needed */
>  		if (upto + len > value_size) {
>  			value_size = (upto + len) + 500;
> -			value = xrealloc(value, value_size);
> +			value = realloc(value, value_size);
> +			if (!value) {
> +				fprintf(stderr, "Out of mmory: cannot alloc "
> +					"%d bytes\n", value_size);
> +				return -1;
> +			}
>  		}
>  
>  		ptr = value + upto;
> @@ -126,59 +131,19 @@ static int encode_value(struct display_info *disp, char **arg, int arg_count,
>  	return 0;
>  }
>  
> -#define ALIGN(x)		(((x) + (FDT_TAGSIZE) - 1) & ~((FDT_TAGSIZE) - 1))
> -
> -static char *_realloc_fdt(char *fdt, int delta)
> -{
> -	int new_sz = fdt_totalsize(fdt) + delta;
> -	fdt = xrealloc(fdt, new_sz);
> -	fdt_open_into(fdt, fdt, new_sz);
> -	return fdt;
> -}
> -
> -static char *realloc_node(char *fdt, const char *name)
> -{
> -	int delta;
> -	/* FDT_BEGIN_NODE, node name in off_struct and FDT_END_NODE */
> -	delta = sizeof(struct fdt_node_header) + ALIGN(strlen(name) + 1)
> -			+ FDT_TAGSIZE;
> -	return _realloc_fdt(fdt, delta);
> -}
> -
> -static char *realloc_property(char *fdt, int nodeoffset,
> -		const char *name, int newlen)
> -{
> -	int delta = 0;
> -	int oldlen = 0;
> -
> -	if (!fdt_get_property(fdt, nodeoffset, name, &oldlen))
> -		/* strings + property header */
> -		delta = sizeof(struct fdt_property) + strlen(name) + 1;
> -
> -	if (newlen > oldlen)
> -		/* actual value in off_struct */
> -		delta += ALIGN(newlen) - ALIGN(oldlen);
> -
> -	return _realloc_fdt(fdt, delta);
> -}
> -
> -static int store_key_value(char **blob, const char *node_name,
> +static int store_key_value(void *blob, const char *node_name,
>  		const char *property, const char *buf, int len)
>  {
>  	int node;
>  	int err;
>  
> -	node = fdt_path_offset(*blob, node_name);
> +	node = fdt_path_offset(blob, node_name);
>  	if (node < 0) {
>  		report_error(node_name, -1, node);
>  		return -1;
>  	}
>  
> -	err = fdt_setprop(*blob, node, property, buf, len);
> -	if (err == -FDT_ERR_NOSPACE) {
> -		*blob = realloc_property(*blob, node, property, len);
> -		err = fdt_setprop(*blob, node, property, buf, len);
> -	}
> +	err = fdt_setprop(blob, node, property, buf, len);
>  	if (err) {
>  		report_error(property, -1, err);
>  		return -1;
> @@ -196,7 +161,7 @@ static int store_key_value(char **blob, const char *node_name,
>   * @param in_path	Path to process
>   * @return 0 if ok, -1 on error
>   */
> -static int create_paths(char **blob, const char *in_path)
> +static int create_paths(void *blob, const char *in_path)
>  {
>  	const char *path = in_path;
>  	const char *sep;
> @@ -212,11 +177,10 @@ static int create_paths(char **blob, const char *in_path)
>  		if (!sep)
>  			sep = path + strlen(path);
>  
> -		node = fdt_subnode_offset_namelen(*blob, offset, path,
> +		node = fdt_subnode_offset_namelen(blob, offset, path,
>  				sep - path);
>  		if (node == -FDT_ERR_NOTFOUND) {
> -			*blob = realloc_node(*blob, path);
> -			node = fdt_add_subnode_namelen(*blob, offset, path,
> +			node = fdt_add_subnode_namelen(blob, offset, path,
>  						       sep - path);
>  		}
>  		if (node < 0) {
> @@ -239,7 +203,7 @@ static int create_paths(char **blob, const char *in_path)
>   * @param node_name	Name of node to create
>   * @return new node offset if found, or -1 on failure
>   */
> -static int create_node(char **blob, const char *node_name)
> +static int create_node(void *blob, const char *node_name)
>  {
>  	int node = 0;
>  	char *p;
> @@ -251,17 +215,15 @@ static int create_node(char **blob, const char *node_name)
>  	}
>  	*p = '\0';
>  
> -	*blob = realloc_node(*blob, p + 1);
> -
>  	if (p > node_name) {
> -		node = fdt_path_offset(*blob, node_name);
> +		node = fdt_path_offset(blob, node_name);
>  		if (node < 0) {
>  			report_error(node_name, -1, node);
>  			return -1;
>  		}
>  	}
>  
> -	node = fdt_add_subnode(*blob, node, p + 1);
> +	node = fdt_add_subnode(blob, node, p + 1);
>  	if (node < 0) {
>  		report_error(p + 1, -1, node);
>  		return -1;
> @@ -288,64 +250,66 @@ static int do_fdtput(struct display_info *disp, const char *filename,
>  		 * store them into the property.
>  		 */
>  		assert(arg_count >= 2);
> -		if (disp->auto_path && create_paths(&blob, *arg))
> +		if (disp->auto_path && create_paths(blob, *arg))
>  			return -1;
>  		if (encode_value(disp, arg + 2, arg_count - 2, &value, &len) ||
> -			store_key_value(&blob, *arg, arg[1], value, len))
> +			store_key_value(blob, *arg, arg[1], value, len))
>  			ret = -1;
>  		break;
>  	case OPER_CREATE_NODE:
>  		for (; ret >= 0 && arg_count--; arg++) {
>  			if (disp->auto_path)
> -				ret = create_paths(&blob, *arg);
> +				ret = create_paths(blob, *arg);
>  			else
> -				ret = create_node(&blob, *arg);
> +				ret = create_node(blob, *arg);
>  		}
>  		break;
>  	}
> -	if (ret >= 0) {
> -		fdt_pack(blob);
> +	if (ret >= 0)
>  		ret = utilfdt_write(filename, blob);
> -	}
>  
>  	free(blob);
>  	return ret;
>  }
>  
> -/* Usage related data. */
> -static const char usage_synopsis[] =
> -	"write a property value to a device tree\n"
> -	"	fdtput <options> <dt file> <node> <property> [<value>...]\n"
> -	"	fdtput -c <options> <dt file> [<node>...]\n"
> +static const char *usage_msg =
> +	"fdtput - write a property value to a device tree\n"
>  	"\n"
>  	"The command line arguments are joined together into a single value.\n"
> +	"\n"
> +	"Usage:\n"
> +	"	fdtput <options> <dt file> <node> <property> [<value>...]\n"
> +	"	fdtput -c <options> <dt file> [<node>...]\n"
> +	"Options:\n"
> +	"\t-c\t\tCreate nodes if they don't already exist\n"
> +	"\t-p\t\tAutomatically create nodes as needed for the node path\n"
> +	"\t-t <type>\tType of data\n"
> +	"\t-v\t\tVerbose: display each value decoded from command line\n"
> +	"\t-h\t\tPrint this help\n\n"
>  	USAGE_TYPE_MSG;
> -static const char usage_short_opts[] = "cpt:v" USAGE_COMMON_SHORT_OPTS;
> -static struct option const usage_long_opts[] = {
> -	{"create",           no_argument, NULL, 'c'},
> -	{"auto-path",        no_argument, NULL, 'p'},
> -	{"type",              a_argument, NULL, 't'},
> -	{"verbose",          no_argument, NULL, 'v'},
> -	USAGE_COMMON_LONG_OPTS,
> -};
> -static const char * const usage_opts_help[] = {
> -	"Create nodes if they don't already exist",
> -	"Automatically create nodes as needed for the node path",
> -	"Type of data",
> -	"Display each value decoded from command line",
> -	USAGE_COMMON_OPTS_HELP
> -};
> +
> +static void usage(const char *msg)
> +{
> +	if (msg)
> +		fprintf(stderr, "Error: %s\n\n", msg);
> +
> +	fprintf(stderr, "%s", usage_msg);
> +	exit(2);
> +}
>  
>  int main(int argc, char *argv[])
>  {
> -	int opt;
>  	struct display_info disp;
>  	char *filename = NULL;
>  
>  	memset(&disp, '\0', sizeof(disp));
>  	disp.size = -1;
>  	disp.oper = OPER_WRITE_PROP;
> -	while ((opt = util_getopt_long()) != EOF) {
> +	for (;;) {
> +		int c = getopt(argc, argv, "chpt:v");
> +		if (c == -1)
> +			break;
> +
>  		/*
>  		 * TODO: add options to:
>  		 * - delete property
> @@ -353,13 +317,15 @@ int main(int argc, char *argv[])
>  		 * - rename node
>  		 * - pack fdt before writing
>  		 * - set amount of free space when writing
> +		 * - expand fdt if value doesn't fit
>  		 */
> -		switch (opt) {
> -		case_USAGE_COMMON_FLAGS
> -
> +		switch (c) {
>  		case 'c':
>  			disp.oper = OPER_CREATE_NODE;
>  			break;
> +		case 'h':
> +		case '?':
> +			usage(NULL);
>  		case 'p':
>  			disp.auto_path = 1;
>  			break;
> @@ -378,16 +344,16 @@ int main(int argc, char *argv[])
>  	if (optind < argc)
>  		filename = argv[optind++];
>  	if (!filename)
> -		usage("missing filename");
> +		usage("Missing filename");
>  
>  	argv += optind;
>  	argc -= optind;
>  
>  	if (disp.oper == OPER_WRITE_PROP) {
>  		if (argc < 1)
> -			usage("missing node");
> +			usage("Missing node");
>  		if (argc < 2)
> -			usage("missing property");
> +			usage("Missing property");
>  	}
>  
>  	if (do_fdtput(&disp, filename, argv, argc))
> diff --git a/scripts/dtc/flattree.c b/scripts/dtc/flattree.c
> index bd99fa2d3..8d268fb78 100644
> --- a/scripts/dtc/flattree.c
> +++ b/scripts/dtc/flattree.c
> @@ -49,7 +49,7 @@ static struct version_info {
>  
>  struct emitter {
>  	void (*cell)(void *, cell_t);
> -	void (*string)(void *, char *, int);
> +	void (*string)(void *, const char *, int);
>  	void (*align)(void *, int);
>  	void (*data)(void *, struct data);
>  	void (*beginnode)(void *, struct label *labels);
> @@ -64,7 +64,7 @@ static void bin_emit_cell(void *e, cell_t val)
>  	*dtbuf = data_append_cell(*dtbuf, val);
>  }
>  
> -static void bin_emit_string(void *e, char *str, int len)
> +static void bin_emit_string(void *e, const char *str, int len)
>  {
>  	struct data *dtbuf = e;
>  
> @@ -144,22 +144,14 @@ static void asm_emit_cell(void *e, cell_t val)
>  		(val >> 8) & 0xff, val & 0xff);
>  }
>  
> -static void asm_emit_string(void *e, char *str, int len)
> +static void asm_emit_string(void *e, const char *str, int len)
>  {
>  	FILE *f = e;
> -	char c = 0;
>  
> -	if (len != 0) {
> -		/* XXX: ewww */
> -		c = str[len];
> -		str[len] = '\0';
> -	}
> -
> -	fprintf(f, "\t.string\t\"%s\"\n", str);
> -
> -	if (len != 0) {
> -		str[len] = c;
> -	}
> +	if (len != 0)
> +		fprintf(f, "\t.string\t\"%.*s\"\n", len, str);
> +	else
> +		fprintf(f, "\t.string\t\"%s\"\n", str);
>  }
>  
>  static void asm_emit_align(void *e, int a)
> @@ -179,7 +171,7 @@ static void asm_emit_data(void *e, struct data d)
>  		emit_offset_label(f, m->ref, m->offset);
>  
>  	while ((d.len - off) >= sizeof(uint32_t)) {
> -		asm_emit_cell(e, fdt32_to_cpu(*((uint32_t *)(d.val+off))));
> +		asm_emit_cell(e, fdt32_to_cpu(*((fdt32_t *)(d.val+off))));
>  		off += sizeof(uint32_t);
>  	}
>  
> @@ -318,17 +310,16 @@ static struct data flatten_reserve_list(struct reserve_info *reservelist,
>  {
>  	struct reserve_info *re;
>  	struct data d = empty_data;
> -	static struct fdt_reserve_entry null_re = {0,0};
>  	int    j;
>  
>  	for (re = reservelist; re; re = re->next) {
> -		d = data_append_re(d, &re->re);
> +		d = data_append_re(d, re->address, re->size);
>  	}
>  	/*
>  	 * Add additional reserved slots if the user asked for them.
>  	 */
>  	for (j = 0; j < reservenum; j++) {
> -		d = data_append_re(d, &null_re);
> +		d = data_append_re(d, 0, 0);
>  	}
>  
>  	return d;
> @@ -366,7 +357,7 @@ static void make_fdt_header(struct fdt_header *fdt,
>  		fdt->size_dt_struct = cpu_to_fdt32(dtsize);
>  }
>  
> -void dt_to_blob(FILE *f, struct boot_info *bi, int version)
> +void dt_to_blob(FILE *f, struct dt_info *dti, int version)
>  {
>  	struct version_info *vi = NULL;
>  	int i;
> @@ -384,29 +375,36 @@ void dt_to_blob(FILE *f, struct boot_info *bi, int version)
>  	if (!vi)
>  		die("Unknown device tree blob version %d\n", version);
>  
> -	flatten_tree(bi->dt, &bin_emitter, &dtbuf, &strbuf, vi);
> +	flatten_tree(dti->dt, &bin_emitter, &dtbuf, &strbuf, vi);
>  	bin_emit_cell(&dtbuf, FDT_END);
>  
> -	reservebuf = flatten_reserve_list(bi->reservelist, vi);
> +	reservebuf = flatten_reserve_list(dti->reservelist, vi);
>  
>  	/* Make header */
>  	make_fdt_header(&fdt, vi, reservebuf.len, dtbuf.len, strbuf.len,
> -			bi->boot_cpuid_phys);
> +			dti->boot_cpuid_phys);
>  
>  	/*
>  	 * If the user asked for more space than is used, adjust the totalsize.
>  	 */
>  	if (minsize > 0) {
>  		padlen = minsize - fdt32_to_cpu(fdt.totalsize);
> -		if ((padlen < 0) && (quiet < 1))
> -			fprintf(stderr,
> -				"Warning: blob size %d >= minimum size %d\n",
> -				fdt32_to_cpu(fdt.totalsize), minsize);
> +		if (padlen < 0) {
> +			padlen = 0;
> +			if (quiet < 1)
> +				fprintf(stderr,
> +					"Warning: blob size %d >= minimum size %d\n",
> +					fdt32_to_cpu(fdt.totalsize), minsize);
> +		}
>  	}
>  
>  	if (padsize > 0)
>  		padlen = padsize;
>  
> +	if (alignsize > 0)
> +		padlen = ALIGN(fdt32_to_cpu(fdt.totalsize) + padlen, alignsize)
> +			- fdt32_to_cpu(fdt.totalsize);
> +
>  	if (padlen > 0) {
>  		int tsize = fdt32_to_cpu(fdt.totalsize);
>  		tsize += padlen;
> @@ -460,7 +458,7 @@ static void dump_stringtable_asm(FILE *f, struct data strbuf)
>  	}
>  }
>  
> -void dt_to_asm(FILE *f, struct boot_info *bi, int version)
> +void dt_to_asm(FILE *f, struct dt_info *dti, int version)
>  {
>  	struct version_info *vi = NULL;
>  	int i;
> @@ -500,7 +498,7 @@ void dt_to_asm(FILE *f, struct boot_info *bi, int version)
>  
>  	if (vi->flags & FTF_BOOTCPUID) {
>  		fprintf(f, "\t/* boot_cpuid_phys */\n");
> -		asm_emit_cell(f, bi->boot_cpuid_phys);
> +		asm_emit_cell(f, dti->boot_cpuid_phys);
>  	}
>  
>  	if (vi->flags & FTF_STRTABSIZE) {
> @@ -530,18 +528,18 @@ void dt_to_asm(FILE *f, struct boot_info *bi, int version)
>  	 * Use .long on high and low halfs of u64s to avoid .quad
>  	 * as it appears .quad isn't available in some assemblers.
>  	 */
> -	for (re = bi->reservelist; re; re = re->next) {
> +	for (re = dti->reservelist; re; re = re->next) {
>  		struct label *l;
>  
>  		for_each_label(re->labels, l) {
>  			fprintf(f, "\t.globl\t%s\n", l->label);
>  			fprintf(f, "%s:\n", l->label);
>  		}
> -		ASM_EMIT_BELONG(f, "0x%08x", (unsigned int)(re->re.address >> 32));
> +		ASM_EMIT_BELONG(f, "0x%08x", (unsigned int)(re->address >> 32));
>  		ASM_EMIT_BELONG(f, "0x%08x",
> -				(unsigned int)(re->re.address & 0xffffffff));
> -		ASM_EMIT_BELONG(f, "0x%08x", (unsigned int)(re->re.size >> 32));
> -		ASM_EMIT_BELONG(f, "0x%08x", (unsigned int)(re->re.size & 0xffffffff));
> +				(unsigned int)(re->address & 0xffffffff));
> +		ASM_EMIT_BELONG(f, "0x%08x", (unsigned int)(re->size >> 32));
> +		ASM_EMIT_BELONG(f, "0x%08x", (unsigned int)(re->size & 0xffffffff));
>  	}
>  	for (i = 0; i < reservenum; i++) {
>  		fprintf(f, "\t.long\t0, 0\n\t.long\t0, 0\n");
> @@ -550,7 +548,7 @@ void dt_to_asm(FILE *f, struct boot_info *bi, int version)
>  	fprintf(f, "\t.long\t0, 0\n\t.long\t0, 0\n");
>  
>  	emit_label(f, symprefix, "struct_start");
> -	flatten_tree(bi->dt, &asm_emitter, f, &strbuf, vi);
> +	flatten_tree(dti->dt, &asm_emitter, f, &strbuf, vi);
>  
>  	fprintf(f, "\t/* FDT_END */\n");
>  	asm_emit_cell(f, FDT_END);
> @@ -572,6 +570,8 @@ void dt_to_asm(FILE *f, struct boot_info *bi, int version)
>  	if (padsize > 0) {
>  		fprintf(f, "\t.space\t%d, 0\n", padsize);
>  	}
> +	if (alignsize > 0)
> +		asm_emit_align(f, alignsize);
>  	emit_label(f, symprefix, "blob_abs_end");
>  
>  	data_free(strbuf);
> @@ -600,7 +600,7 @@ static void flat_read_chunk(struct inbuf *inb, void *p, int len)
>  
>  static uint32_t flat_read_word(struct inbuf *inb)
>  {
> -	uint32_t val;
> +	fdt32_t val;
>  
>  	assert(((inb->ptr - inb->base) % sizeof(val)) == 0);
>  
> @@ -709,13 +709,15 @@ static struct reserve_info *flat_read_mem_reserve(struct inbuf *inb)
>  	 * First pass, count entries.
>  	 */
>  	while (1) {
> +		uint64_t address, size;
> +
>  		flat_read_chunk(inb, &re, sizeof(re));
> -		re.address  = fdt64_to_cpu(re.address);
> -		re.size = fdt64_to_cpu(re.size);
> -		if (re.size == 0)
> +		address  = fdt64_to_cpu(re.address);
> +		size = fdt64_to_cpu(re.size);
> +		if (size == 0)
>  			break;
>  
> -		new = build_reserve_entry(re.address, re.size);
> +		new = build_reserve_entry(address, size);
>  		reservelist = add_reserve_entry(reservelist, new);
>  	}
>  
> @@ -729,7 +731,7 @@ static char *nodename_from_path(const char *ppath, const char *cpath)
>  
>  	plen = strlen(ppath);
>  
> -	if (!strneq(ppath, cpath, plen))
> +	if (!strstarts(cpath, ppath))
>  		die("Path \"%s\" is not valid as a child of \"%s\"\n",
>  		    cpath, ppath);
>  
> @@ -797,13 +799,18 @@ static struct node *unflatten_tree(struct inbuf *dtbuf,
>  		}
>  	} while (val != FDT_END_NODE);
>  
> +	if (node->name != flatname) {
> +		free(flatname);
> +	}
> +
>  	return node;
>  }
>  
>  
> -struct boot_info *dt_from_blob(const char *fname)
> +struct dt_info *dt_from_blob(const char *fname)
>  {
>  	FILE *f;
> +	fdt32_t magic_buf, totalsize_buf;
>  	uint32_t magic, totalsize, version, size_dt, boot_cpuid_phys;
>  	uint32_t off_dt, off_str, off_mem_rsvmap;
>  	int rc;
> @@ -820,7 +827,7 @@ struct boot_info *dt_from_blob(const char *fname)
>  
>  	f = srcfile_relative_open(fname, NULL);
>  
> -	rc = fread(&magic, sizeof(magic), 1, f);
> +	rc = fread(&magic_buf, sizeof(magic_buf), 1, f);
>  	if (ferror(f))
>  		die("Error reading DT blob magic number: %s\n",
>  		    strerror(errno));
> @@ -831,11 +838,11 @@ struct boot_info *dt_from_blob(const char *fname)
>  			die("Mysterious short read reading magic number\n");
>  	}
>  
> -	magic = fdt32_to_cpu(magic);
> +	magic = fdt32_to_cpu(magic_buf);
>  	if (magic != FDT_MAGIC)
>  		die("Blob has incorrect magic number\n");
>  
> -	rc = fread(&totalsize, sizeof(totalsize), 1, f);
> +	rc = fread(&totalsize_buf, sizeof(totalsize_buf), 1, f);
>  	if (ferror(f))
>  		die("Error reading DT blob size: %s\n", strerror(errno));
>  	if (rc < 1) {
> @@ -845,7 +852,7 @@ struct boot_info *dt_from_blob(const char *fname)
>  			die("Mysterious short read reading blob size\n");
>  	}
>  
> -	totalsize = fdt32_to_cpu(totalsize);
> +	totalsize = fdt32_to_cpu(totalsize_buf);
>  	if (totalsize < FDT_V1_SIZE)
>  		die("DT blob size (%d) is too small\n", totalsize);
>  
> @@ -889,7 +896,7 @@ struct boot_info *dt_from_blob(const char *fname)
>  
>  	if (version >= 3) {
>  		uint32_t size_str = fdt32_to_cpu(fdt->size_dt_strings);
> -		if (off_str+size_str > totalsize)
> +		if ((off_str+size_str < off_str) || (off_str+size_str > totalsize))
>  			die("String table extends past total size\n");
>  		inbuf_init(&strbuf, blob + off_str, blob + off_str + size_str);
>  	} else {
> @@ -898,7 +905,7 @@ struct boot_info *dt_from_blob(const char *fname)
>  
>  	if (version >= 17) {
>  		size_dt = fdt32_to_cpu(fdt->size_dt_struct);
> -		if (off_dt+size_dt > totalsize)
> +		if ((off_dt+size_dt < off_dt) || (off_dt+size_dt > totalsize))
>  			die("Structure block extends past total size\n");
>  	}
>  
> @@ -929,5 +936,5 @@ struct boot_info *dt_from_blob(const char *fname)
>  
>  	fclose(f);
>  
> -	return build_boot_info(reservelist, tree, boot_cpuid_phys);
> +	return build_dt_info(DTSF_V1, reservelist, tree, boot_cpuid_phys);
>  }
> diff --git a/scripts/dtc/fstree.c b/scripts/dtc/fstree.c
> index 6d1beec95..ae7d06c3c 100644
> --- a/scripts/dtc/fstree.c
> +++ b/scripts/dtc/fstree.c
> @@ -79,13 +79,12 @@ static struct node *read_fstree(const char *dirname)
>  	return tree;
>  }
>  
> -struct boot_info *dt_from_fs(const char *dirname)
> +struct dt_info *dt_from_fs(const char *dirname)
>  {
>  	struct node *tree;
>  
>  	tree = read_fstree(dirname);
>  	tree = name_node(tree, "");
>  
> -	return build_boot_info(NULL, tree, guess_boot_cpuid(tree));
> +	return build_dt_info(DTSF_V1, NULL, tree, guess_boot_cpuid(tree));
>  }
> -
> diff --git a/scripts/dtc/libfdt.h b/scripts/dtc/libfdt.h
> index 32d52276d..1e27780e1 100644
> --- a/scripts/dtc/libfdt.h
> +++ b/scripts/dtc/libfdt.h
> @@ -1,5 +1,5 @@
> -#ifndef _LIBFDT_H
> -#define _LIBFDT_H
> +#ifndef LIBFDT_H
> +#define LIBFDT_H
>  /*
>   * libfdt - Flat Device Tree manipulation
>   * Copyright (C) 2006 David Gibson, IBM Corporation.
> @@ -51,17 +51,17 @@
>   *     EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
>   */
>  
> -#include <libfdt_env.h>
> -#include <fdt.h>
> +#include "libfdt_env.h"
> +#include "fdt.h"
>  
> -#define FDT_FIRST_SUPPORTED_VERSION	0x10
> +#define FDT_FIRST_SUPPORTED_VERSION	0x02
>  #define FDT_LAST_SUPPORTED_VERSION	0x11
>  
>  /* Error codes: informative error codes */
>  #define FDT_ERR_NOTFOUND	1
>  	/* FDT_ERR_NOTFOUND: The requested node or property does not exist */
>  #define FDT_ERR_EXISTS		2
> -	/* FDT_ERR_EXISTS: Attemped to create a node or property which
> +	/* FDT_ERR_EXISTS: Attempted to create a node or property which
>  	 * already exists */
>  #define FDT_ERR_NOSPACE		3
>  	/* FDT_ERR_NOSPACE: Operation needed to expand the device
> @@ -79,8 +79,10 @@
>  	 * (e.g. missing a leading / for a function which requires an
>  	 * absolute path) */
>  #define FDT_ERR_BADPHANDLE	6
> -	/* FDT_ERR_BADPHANDLE: Function was passed an invalid phandle
> -	 * value.  phandle values of 0 and -1 are not permitted. */
> +	/* FDT_ERR_BADPHANDLE: Function was passed an invalid phandle.
> +	 * This can be caused either by an invalid phandle property
> +	 * length, or the phandle value was either 0 or -1, which are
> +	 * not permitted. */
>  #define FDT_ERR_BADSTATE	7
>  	/* FDT_ERR_BADSTATE: Function was passed an incomplete device
>  	 * tree created by the sequential-write functions, which is
> @@ -121,13 +123,29 @@
>  	/* FDT_ERR_BADNCELLS: Device tree has a #address-cells, #size-cells
>  	 * or similar property with a bad format or value */
>  
> -#define FDT_ERR_MAX		14
> +#define FDT_ERR_BADVALUE	15
> +	/* FDT_ERR_BADVALUE: Device tree has a property with an unexpected
> +	 * value. For example: a property expected to contain a string list
> +	 * is not NUL-terminated within the length of its value. */
> +
> +#define FDT_ERR_BADOVERLAY	16
> +	/* FDT_ERR_BADOVERLAY: The device tree overlay, while
> +	 * correctly structured, cannot be applied due to some
> +	 * unexpected or missing value, property or node. */
> +
> +#define FDT_ERR_NOPHANDLES	17
> +	/* FDT_ERR_NOPHANDLES: The device tree doesn't have any
> +	 * phandle available anymore without causing an overflow */
> +
> +#define FDT_ERR_MAX		17
>  
>  /**********************************************************************/
>  /* Low-level functions (you probably don't need these)                */
>  /**********************************************************************/
>  
> +#ifndef SWIG /* This function is not useful in Python */
>  const void *fdt_offset_ptr(const void *fdt, int offset, unsigned int checklen);
> +#endif
>  static inline void *fdt_offset_ptr_w(void *fdt, int offset, int checklen)
>  {
>  	return (void *)(uintptr_t)fdt_offset_ptr(fdt, offset, checklen);
> @@ -163,40 +181,67 @@ int fdt_first_subnode(const void *fdt, int offset);
>   */
>  int fdt_next_subnode(const void *fdt, int offset);
>  
> +/**
> + * fdt_for_each_subnode - iterate over all subnodes of a parent
> + *
> + * @node:	child node (int, lvalue)
> + * @fdt:	FDT blob (const void *)
> + * @parent:	parent node (int)
> + *
> + * This is actually a wrapper around a for loop and would be used like so:
> + *
> + *	fdt_for_each_subnode(node, fdt, parent) {
> + *		Use node
> + *		...
> + *	}
> + *
> + *	if ((node < 0) && (node != -FDT_ERR_NOT_FOUND)) {
> + *		Error handling
> + *	}
> + *
> + * 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);	\
> +	     node >= 0;					\
> +	     node = fdt_next_subnode(fdt, node))
> +
>  /**********************************************************************/
>  /* General functions                                                  */
>  /**********************************************************************/
> -
>  #define fdt_get_header(fdt, field) \
>  	(fdt32_to_cpu(((const struct fdt_header *)(fdt))->field))
> -#define fdt_magic(fdt) 			(fdt_get_header(fdt, magic))
> +#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))
>  #define fdt_off_dt_strings(fdt)		(fdt_get_header(fdt, off_dt_strings))
>  #define fdt_off_mem_rsvmap(fdt)		(fdt_get_header(fdt, off_mem_rsvmap))
>  #define fdt_version(fdt)		(fdt_get_header(fdt, version))
> -#define fdt_last_comp_version(fdt) 	(fdt_get_header(fdt, last_comp_version))
> -#define fdt_boot_cpuid_phys(fdt) 	(fdt_get_header(fdt, boot_cpuid_phys))
> -#define fdt_size_dt_strings(fdt) 	(fdt_get_header(fdt, size_dt_strings))
> +#define fdt_last_comp_version(fdt)	(fdt_get_header(fdt, last_comp_version))
> +#define fdt_boot_cpuid_phys(fdt)	(fdt_get_header(fdt, boot_cpuid_phys))
> +#define fdt_size_dt_strings(fdt)	(fdt_get_header(fdt, size_dt_strings))
>  #define fdt_size_dt_struct(fdt)		(fdt_get_header(fdt, size_dt_struct))
>  
> -#define __fdt_set_hdr(name) \
> +#define fdt_set_hdr_(name) \
>  	static inline void fdt_set_##name(void *fdt, uint32_t val) \
>  	{ \
> -		struct fdt_header *fdth = (struct fdt_header*)fdt; \
> +		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);
> -#undef __fdt_set_hdr
> +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_check_header - sanity check a device tree or possible device tree
> @@ -253,6 +298,21 @@ int fdt_move(const void *fdt, void *buf, int bufsize);
>   */
>  const char *fdt_string(const void *fdt, int stroffset);
>  
> +/**
> + * fdt_get_max_phandle - retrieves the highest phandle in a tree
> + * @fdt: pointer to the device tree blob
> + *
> + * fdt_get_max_phandle retrieves the highest phandle in the given
> + * device tree. This will ignore badly formatted phandles, or phandles
> + * with a value of 0 or -1.
> + *
> + * returns:
> + *      the highest phandle on success
> + *      0, if no phandle was found in the device tree
> + *      -1, if an error occurred
> + */
> +uint32_t fdt_get_max_phandle(const void *fdt);
> +
>  /**
>   * fdt_num_mem_rsv - retrieve the number of memory reserve map entries
>   * @fdt: pointer to the device tree blob
> @@ -295,8 +355,10 @@ int fdt_get_mem_rsv(const void *fdt, int n, uint64_t *address, uint64_t *size);
>   * useful for finding subnodes based on a portion of a larger string,
>   * such as a full path.
>   */
> +#ifndef SWIG /* Not available in Python */
>  int fdt_subnode_offset_namelen(const void *fdt, int parentoffset,
>  			       const char *name, int namelen);
> +#endif
>  /**
>   * fdt_subnode_offset - find a subnode of a given node
>   * @fdt: pointer to the device tree blob
> @@ -313,8 +375,9 @@ int fdt_subnode_offset_namelen(const void *fdt, int parentoffset,
>   * returns:
>   *	structure block offset of the requested 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
> - *      -FDT_ERR_BADMAGIC,
> + *	-FDT_ERR_BADOFFSET, if parentoffset did not point to an FDT_BEGIN_NODE
> + *		tag
> + *	-FDT_ERR_BADMAGIC,
>   *	-FDT_ERR_BADVERSION,
>   *	-FDT_ERR_BADSTATE,
>   *	-FDT_ERR_BADSTRUCTURE,
> @@ -322,6 +385,19 @@ int fdt_subnode_offset_namelen(const void *fdt, int parentoffset,
>   */
>  int fdt_subnode_offset(const void *fdt, int parentoffset, const char *name);
>  
> +/**
> + * fdt_path_offset_namelen - find a tree node by its full path
> + * @fdt: pointer to the device tree blob
> + * @path: full path of the node to locate
> + * @namelen: number of characters of path to consider
> + *
> + * Identical to fdt_path_offset(), but only consider the first namelen
> + * characters of path as the path name.
> + */
> +#ifndef SWIG /* Not available in Python */
> +int fdt_path_offset_namelen(const void *fdt, const char *path, int namelen);
> +#endif
> +
>  /**
>   * fdt_path_offset - find a tree node by its full path
>   * @fdt: pointer to the device tree blob
> @@ -335,7 +411,8 @@ int fdt_subnode_offset(const void *fdt, int parentoffset, const char *name);
>   * address).
>   *
>   * returns:
> - *	structure block offset of the node with the requested path (>=0), on success
> + *	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_NOTFOUND, if the requested node does not exist
>   *      -FDT_ERR_BADMAGIC,
> @@ -359,10 +436,12 @@ int fdt_path_offset(const void *fdt, const char *path);
>   *
>   * returns:
>   *	pointer to the node's name, on success
> - *		If lenp is non-NULL, *lenp contains the length of that name (>=0)
> + *		If lenp is non-NULL, *lenp contains the length of that name
> + *			(>=0)
>   *	NULL, on error
>   *		if lenp is non-NULL *lenp contains an error code (<0):
> - *		-FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag
> + *		-FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE
> + *			tag
>   *		-FDT_ERR_BADMAGIC,
>   *		-FDT_ERR_BADVERSION,
>   *		-FDT_ERR_BADSTATE, standard meanings
> @@ -410,6 +489,33 @@ int fdt_first_property_offset(const void *fdt, int nodeoffset);
>   */
>  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)
> + *
> + * This is actually a wrapper around a for loop and would be used like so:
> + *
> + *	fdt_for_each_property_offset(property, fdt, node) {
> + *		Use property
> + *		...
> + *	}
> + *
> + *	if ((property < 0) && (property != -FDT_ERR_NOT_FOUND)) {
> + *		Error handling
> + *	}
> + *
> + * Note that this is implemented as a macro and property is used as
> + * iterator in the loop. The node variable can be constant or even a
> + * literal.
> + */
> +#define fdt_for_each_property_offset(property, fdt, node)	\
> +	for (property = fdt_first_property_offset(fdt, node);	\
> +	     property >= 0;					\
> +	     property = fdt_next_property_offset(fdt, property))
> +
>  /**
>   * fdt_get_property_by_offset - retrieve the property at a given offset
>   * @fdt: pointer to the device tree blob
> @@ -421,6 +527,9 @@ int fdt_next_property_offset(const void *fdt, int offset);
>   * offset.  If lenp is non-NULL, the length of the property value is
>   * also returned, in the integer pointed to by lenp.
>   *
> + * Note that this code only works on device tree versions >= 16. fdt_getprop()
> + * works on all versions.
> + *
>   * returns:
>   *	pointer to the structure representing the property
>   *		if lenp is non-NULL, *lenp contains the length of the property
> @@ -446,13 +555,15 @@ const struct fdt_property *fdt_get_property_by_offset(const void *fdt,
>   * @namelen: number of characters of name to consider
>   * @lenp: pointer to an integer variable (will be overwritten) or NULL
>   *
> - * Identical to fdt_get_property_namelen(), but only examine the first
> - * namelen characters of name for matching the property name.
> + * Identical to fdt_get_property(), but only examine the first namelen
> + * characters of name for matching the property name.
>   */
> +#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);
> +#endif
>  
>  /**
>   * fdt_get_property - find a given property in a given node
> @@ -474,7 +585,8 @@ const struct fdt_property *fdt_get_property_namelen(const void *fdt,
>   *	NULL, on error
>   *		if lenp is non-NULL, *lenp contains an error code (<0):
>   *		-FDT_ERR_NOTFOUND, node does not have named property
> - *		-FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag
> + *		-FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE
> + *			tag
>   *		-FDT_ERR_BADMAGIC,
>   *		-FDT_ERR_BADVERSION,
>   *		-FDT_ERR_BADSTATE,
> @@ -522,8 +634,10 @@ static inline struct fdt_property *fdt_get_property_w(void *fdt, int nodeoffset,
>   *		-FDT_ERR_BADSTRUCTURE,
>   *		-FDT_ERR_TRUNCATED, standard meanings
>   */
> +#ifndef SWIG /* This function is not useful in Python */
>  const void *fdt_getprop_by_offset(const void *fdt, int offset,
>  				  const char **namep, int *lenp);
> +#endif
>  
>  /**
>   * fdt_getprop_namelen - get property value based on substring
> @@ -536,8 +650,17 @@ 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.
>   */
> +#ifndef SWIG /* Not available in Python */
>  const void *fdt_getprop_namelen(const void *fdt, int nodeoffset,
>  				const char *name, int namelen, int *lenp);
> +static inline void *fdt_getprop_namelen_w(void *fdt, int nodeoffset,
> +					  const char *name, int namelen,
> +					  int *lenp)
> +{
> +	return (void *)(uintptr_t)fdt_getprop_namelen(fdt, nodeoffset, name,
> +						      namelen, lenp);
> +}
> +#endif
>  
>  /**
>   * fdt_getprop - retrieve the value of a given property
> @@ -559,7 +682,8 @@ const void *fdt_getprop_namelen(const void *fdt, int nodeoffset,
>   *	NULL, on error
>   *		if lenp is non-NULL, *lenp contains an error code (<0):
>   *		-FDT_ERR_NOTFOUND, node does not have named property
> - *		-FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag
> + *		-FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE
> + *			tag
>   *		-FDT_ERR_BADMAGIC,
>   *		-FDT_ERR_BADVERSION,
>   *		-FDT_ERR_BADSTATE,
> @@ -597,11 +721,13 @@ uint32_t fdt_get_phandle(const void *fdt, int nodeoffset);
>   * Identical to fdt_get_alias(), but only examine the first namelen
>   * characters of name for matching the alias name.
>   */
> +#ifndef SWIG /* Not available in Python */
>  const char *fdt_get_alias_namelen(const void *fdt,
>  				  const char *name, int namelen);
> +#endif
>  
>  /**
> - * fdt_get_alias - retreive the path referenced by a given alias
> + * 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
>   *
> @@ -631,7 +757,7 @@ const char *fdt_get_alias(const void *fdt, const char *name);
>   *	0, on success
>   *		buf contains the absolute path of the node at
>   *		nodeoffset, as a NUL-terminated string.
> - * 	-FDT_ERR_BADOFFSET, nodeoffset does not refer to a BEGIN_NODE tag
> + *	-FDT_ERR_BADOFFSET, nodeoffset does not refer to a BEGIN_NODE tag
>   *	-FDT_ERR_NOSPACE, the path of the given node is longer than (bufsize-1)
>   *		characters and will not fit in the given buffer.
>   *	-FDT_ERR_BADMAGIC,
> @@ -661,11 +787,11 @@ int fdt_get_path(const void *fdt, int nodeoffset, char *buf, int buflen);
>   * structure from the start to nodeoffset.
>   *
>   * returns:
> -
>   *	structure block offset of the node at node offset's ancestor
>   *		of depth supernodedepth (>=0), on success
> - * 	-FDT_ERR_BADOFFSET, nodeoffset does not refer to a BEGIN_NODE tag
> -*	-FDT_ERR_NOTFOUND, supernodedepth was greater than the depth of nodeoffset
> + *	-FDT_ERR_BADOFFSET, nodeoffset does not refer to a BEGIN_NODE tag
> + *	-FDT_ERR_NOTFOUND, supernodedepth was greater than the depth of
> + *		nodeoffset
>   *	-FDT_ERR_BADMAGIC,
>   *	-FDT_ERR_BADVERSION,
>   *	-FDT_ERR_BADSTATE,
> @@ -687,7 +813,7 @@ int fdt_supernode_atdepth_offset(const void *fdt, int nodeoffset,
>   *
>   * returns:
>   *	depth of the node at nodeoffset (>=0), on success
> - * 	-FDT_ERR_BADOFFSET, nodeoffset does not refer to a BEGIN_NODE tag
> + *	-FDT_ERR_BADOFFSET, nodeoffset does not refer to a BEGIN_NODE tag
>   *	-FDT_ERR_BADMAGIC,
>   *	-FDT_ERR_BADVERSION,
>   *	-FDT_ERR_BADSTATE,
> @@ -710,7 +836,7 @@ int fdt_node_depth(const void *fdt, int nodeoffset);
>   * returns:
>   *	structure block offset of the parent of the node at nodeoffset
>   *		(>=0), on success
> - * 	-FDT_ERR_BADOFFSET, nodeoffset does not refer to a BEGIN_NODE tag
> + *	-FDT_ERR_BADOFFSET, nodeoffset does not refer to a BEGIN_NODE tag
>   *	-FDT_ERR_BADMAGIC,
>   *	-FDT_ERR_BADVERSION,
>   *	-FDT_ERR_BADSTATE,
> @@ -750,7 +876,7 @@ int fdt_parent_offset(const void *fdt, int nodeoffset);
>   *		 on success
>   *	-FDT_ERR_NOTFOUND, no node matching the criterion exists in the
>   *		tree after startoffset
> - * 	-FDT_ERR_BADOFFSET, nodeoffset does not refer to a BEGIN_NODE tag
> + *	-FDT_ERR_BADOFFSET, nodeoffset does not refer to a BEGIN_NODE tag
>   *	-FDT_ERR_BADMAGIC,
>   *	-FDT_ERR_BADVERSION,
>   *	-FDT_ERR_BADSTATE,
> @@ -797,7 +923,7 @@ int fdt_node_offset_by_phandle(const void *fdt, uint32_t phandle);
>   *	1, if the node has a 'compatible' property, but it does not list
>   *		the given string
>   *	-FDT_ERR_NOTFOUND, if the given node has no 'compatible' property
> - * 	-FDT_ERR_BADOFFSET, if nodeoffset does not refer to a BEGIN_NODE tag
> + *	-FDT_ERR_BADOFFSET, if nodeoffset does not refer to a BEGIN_NODE tag
>   *	-FDT_ERR_BADMAGIC,
>   *	-FDT_ERR_BADVERSION,
>   *	-FDT_ERR_BADSTATE,
> @@ -834,7 +960,7 @@ int fdt_node_check_compatible(const void *fdt, int nodeoffset,
>   *		 on success
>   *	-FDT_ERR_NOTFOUND, no node matching the criterion exists in the
>   *		tree after startoffset
> - * 	-FDT_ERR_BADOFFSET, nodeoffset does not refer to a BEGIN_NODE tag
> + *	-FDT_ERR_BADOFFSET, nodeoffset does not refer to a BEGIN_NODE tag
>   *	-FDT_ERR_BADMAGIC,
>   *	-FDT_ERR_BADVERSION,
>   *	-FDT_ERR_BADSTATE,
> @@ -857,6 +983,68 @@ int fdt_node_offset_by_compatible(const void *fdt, int startoffset,
>   */
>  int fdt_stringlist_contains(const char *strlist, int listlen, const char *str);
>  
> +/**
> + * fdt_stringlist_count - count the number of strings in a string list
> + * @fdt: pointer to the device tree blob
> + * @nodeoffset: offset of a tree node
> + * @property: name of the property containing the string list
> + * @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
> + */
> +int fdt_stringlist_count(const void *fdt, int nodeoffset, const char *property);
> +
> +/**
> + * fdt_stringlist_search - find a string in a string list and return its index
> + * @fdt: pointer to the device tree blob
> + * @nodeoffset: offset of a tree node
> + * @property: name of the property containing the string list
> + * @string: string to look up in the string list
> + *
> + * Note that it is possible for this function to succeed on property values
> + * that are not NUL-terminated. That's because the function will stop after
> + * finding the first occurrence of @string. This can for example happen with
> + * small-valued cell properties, such as #address-cells, when searching for
> + * the empty string.
> + *
> + * @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
> + *                     the given string
> + */
> +int fdt_stringlist_search(const void *fdt, int nodeoffset, const char *property,
> +			  const char *string);
> +
> +/**
> + * fdt_stringlist_get() - obtain the string at a given index in a string list
> + * @fdt: pointer to the device tree blob
> + * @nodeoffset: offset of a tree node
> + * @property: name of the property containing the string list
> + * @index: index of the string to return
> + * @lenp: return location for the string length or an error code on failure
> + *
> + * Note that this will successfully extract strings from properties with
> + * non-NUL-terminated values. For example on small-valued cell properties
> + * this function will return the empty string.
> + *
> + * 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:
> + *   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
> + *   the following negative error codes will be returned in the lenp parameter
> + *   (if non-NULL):
> + *     -FDT_ERR_BADVALUE if the property value is not NUL-terminated
> + *     -FDT_ERR_NOTFOUND if the property does not exist
> + */
> +const char *fdt_stringlist_get(const void *fdt, int nodeoffset,
> +			       const char *property, int index,
> +			       int *lenp);
> +
>  /**********************************************************************/
>  /* Read-only functions (addressing related)                           */
>  /**********************************************************************/
> @@ -882,7 +1070,8 @@ int fdt_stringlist_contains(const char *strlist, int listlen, const char *str);
>   * 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 #address-cells property
> + *      -FDT_ERR_BADNCELLS, if the node has a badly formatted or invalid
> + *		#address-cells property
>   *	-FDT_ERR_BADMAGIC,
>   *	-FDT_ERR_BADVERSION,
>   *	-FDT_ERR_BADSTATE,
> @@ -902,7 +1091,8 @@ int fdt_address_cells(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 #size-cells property
> + *      -FDT_ERR_BADNCELLS, if the node has a badly formatted or invalid
> + *		#size-cells property
>   *	-FDT_ERR_BADMAGIC,
>   *	-FDT_ERR_BADVERSION,
>   *	-FDT_ERR_BADSTATE,
> @@ -916,6 +1106,29 @@ int fdt_size_cells(const void *fdt, int nodeoffset);
>  /* Write-in-place functions                                           */
>  /**********************************************************************/
>  
> +/**
> + * fdt_setprop_inplace_namelen_partial - change a property's value,
> + *                                       but not its size
> + * @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
> + * @idx: index of the property to change in the array
> + * @val: pointer to data to replace the property value with
> + * @len: length of the property value
> + *
> + * Identical to fdt_setprop_inplace(), but modifies the given property
> + * 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.
> + */
> +#ifndef SWIG /* Not available in Python */
> +int fdt_setprop_inplace_namelen_partial(void *fdt, int nodeoffset,
> +					const char *name, int namelen,
> +					uint32_t idx, const void *val,
> +					int len);
> +#endif
> +
>  /**
>   * fdt_setprop_inplace - change a property's value, but not its size
>   * @fdt: pointer to the device tree blob
> @@ -944,8 +1157,10 @@ int fdt_size_cells(const void *fdt, int nodeoffset);
>   *	-FDT_ERR_BADSTRUCTURE,
>   *	-FDT_ERR_TRUNCATED, standard meanings
>   */
> +#ifndef SWIG /* Not available in Python */
>  int fdt_setprop_inplace(void *fdt, int nodeoffset, const char *name,
>  			const void *val, int len);
> +#endif
>  
>  /**
>   * fdt_setprop_inplace_u32 - change the value of a 32-bit integer property
> @@ -1102,6 +1317,22 @@ static inline int fdt_property_cell(void *fdt, const char *name, uint32_t val)
>  {
>  	return fdt_property_u32(fdt, name, val);
>  }
> +
> +/**
> + * fdt_property_placeholder - add a new property and return a ptr to its value
> + *
> + * @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
> + *
> + * returns:
> + *	0, on success
> + *	-FDT_ERR_BADMAGIC,
> + *	-FDT_ERR_NOSPACE, standard meanings
> + */
> +int fdt_property_placeholder(void *fdt, const char *name, int len, void **valp);
> +
>  #define fdt_property_string(fdt, name, str) \
>  	fdt_property(fdt, name, str, strlen(str)+1)
>  int fdt_end_node(void *fdt);
> @@ -1220,6 +1451,37 @@ int fdt_set_name(void *fdt, int nodeoffset, const char *name);
>  int fdt_setprop(void *fdt, int nodeoffset, const char *name,
>  		const void *val, int len);
>  
> +/**
> + * fdt_setprop_placeholder - 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
> + * @len: length of the property value
> + * @prop_data: return pointer to property data
> + *
> + * fdt_setprop_placeholer() 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(void *fdt, int nodeoffset, const char *name,
> +			    int len, void **prop_data);
> +
>  /**
>   * fdt_setprop_u32 - set a property to a 32-bit integer
>   * @fdt: pointer to the device tree blob
> @@ -1332,6 +1594,36 @@ 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_empty - set a property to an empty value
> + * @fdt: pointer to the device tree blob
> + * @nodeoffset: offset of the node whose property to change
> + * @name: name of the property to change
> + *
> + * fdt_setprop_empty() sets the value of the named property in the
> + * given node to an empty (zero length) value, or creates a new empty
> + * 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
> + */
> +#define fdt_setprop_empty(fdt, nodeoffset, name) \
> +	fdt_setprop((fdt), (nodeoffset), (name), NULL, 0)
> +
>  /**
>   * fdt_appendprop - append to or create a property
>   * @fdt: pointer to the device tree blob
> @@ -1509,8 +1801,10 @@ int fdt_delprop(void *fdt, int nodeoffset, const char *name);
>   * creating subnodes based on a portion of a larger string, such as a
>   * full path.
>   */
> +#ifndef SWIG /* Not available in Python */
>  int fdt_add_subnode_namelen(void *fdt, int parentoffset,
>  			    const char *name, int namelen);
> +#endif
>  
>  /**
>   * fdt_add_subnode - creates a new node
> @@ -1526,9 +1820,11 @@ int fdt_add_subnode_namelen(void *fdt, int parentoffset,
>   * 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 nodeequested 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
> + *	-FDT_ERR_BADOFFSET, if parentoffset did not point to an FDT_BEGIN_NODE
> + *		tag
>   *	-FDT_ERR_EXISTS, if the node at parentoffset already has a subnode of
>   *		the given name
>   *	-FDT_ERR_NOSPACE, if there is insufficient free space in the
> @@ -1566,10 +1862,41 @@ int fdt_add_subnode(void *fdt, int parentoffset, const char *name);
>   */
>  int fdt_del_node(void *fdt, int nodeoffset);
>  
> +/**
> + * fdt_overlay_apply - Applies a DT overlay on a base DT
> + * @fdt: pointer to the base device tree blob
> + * @fdto: pointer to the device tree overlay blob
> + *
> + * fdt_overlay_apply() will apply the given device tree overlay on the
> + * given base device tree.
> + *
> + * Expect the base device tree to be modified, even if the function
> + * returns an error.
> + *
> + * 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
> + *		properties in the base DT
> + *	-FDT_ERR_BADPHANDLE,
> + *	-FDT_ERR_BADOVERLAY,
> + *	-FDT_ERR_NOPHANDLES,
> + *	-FDT_ERR_INTERNAL,
> + *	-FDT_ERR_BADLAYOUT,
> + *	-FDT_ERR_BADMAGIC,
> + *	-FDT_ERR_BADOFFSET,
> + *	-FDT_ERR_BADPATH,
> + *	-FDT_ERR_BADVERSION,
> + *	-FDT_ERR_BADSTRUCTURE,
> + *	-FDT_ERR_BADSTATE,
> + *	-FDT_ERR_TRUNCATED, standard meanings
> + */
> +int fdt_overlay_apply(void *fdt, void *fdto);
> +
>  /**********************************************************************/
>  /* Debugging / informational functions                                */
>  /**********************************************************************/
>  
>  const char *fdt_strerror(int errval);
>  
> -#endif /* _LIBFDT_H */
> +#endif /* LIBFDT_H */
> diff --git a/scripts/dtc/libfdt_env.h b/scripts/dtc/libfdt_env.h
> index 9dea97dff..bd2474628 100644
> --- a/scripts/dtc/libfdt_env.h
> +++ b/scripts/dtc/libfdt_env.h
> @@ -1,5 +1,5 @@
> -#ifndef _LIBFDT_ENV_H
> -#define _LIBFDT_ENV_H
> +#ifndef LIBFDT_ENV_H
> +#define LIBFDT_ENV_H
>  /*
>   * libfdt - Flat Device Tree manipulation
>   * Copyright (C) 2006 David Gibson, IBM Corporation.
> @@ -54,19 +54,20 @@
>  
>  #include <stddef.h>
>  #include <stdint.h>
> +#include <stdlib.h>
>  #include <string.h>
>  
>  #ifdef __CHECKER__
> -#define __force __attribute__((force))
> -#define __bitwise __attribute__((bitwise))
> +#define FDT_FORCE __attribute__((force))
> +#define FDT_BITWISE __attribute__((bitwise))
>  #else
> -#define __force
> -#define __bitwise
> +#define FDT_FORCE
> +#define FDT_BITWISE
>  #endif
>  
> -typedef uint16_t __bitwise fdt16_t;
> -typedef uint32_t __bitwise fdt32_t;
> -typedef uint64_t __bitwise fdt64_t;
> +typedef uint16_t FDT_BITWISE fdt16_t;
> +typedef uint32_t FDT_BITWISE fdt32_t;
> +typedef uint64_t FDT_BITWISE fdt64_t;
>  
>  #define EXTRACT_BYTE(x, n)	((unsigned long long)((uint8_t *)&x)[n])
>  #define CPU_TO_FDT16(x) ((EXTRACT_BYTE(x, 0) << 8) | EXTRACT_BYTE(x, 1))
> @@ -79,33 +80,60 @@ typedef uint64_t __bitwise fdt64_t;
>  
>  static inline uint16_t fdt16_to_cpu(fdt16_t x)
>  {
> -	return (__force uint16_t)CPU_TO_FDT16(x);
> +	return (FDT_FORCE uint16_t)CPU_TO_FDT16(x);
>  }
>  static inline fdt16_t cpu_to_fdt16(uint16_t x)
>  {
> -	return (__force fdt16_t)CPU_TO_FDT16(x);
> +	return (FDT_FORCE fdt16_t)CPU_TO_FDT16(x);
>  }
>  
>  static inline uint32_t fdt32_to_cpu(fdt32_t x)
>  {
> -	return (__force uint32_t)CPU_TO_FDT32(x);
> +	return (FDT_FORCE uint32_t)CPU_TO_FDT32(x);
>  }
>  static inline fdt32_t cpu_to_fdt32(uint32_t x)
>  {
> -	return (__force fdt32_t)CPU_TO_FDT32(x);
> +	return (FDT_FORCE fdt32_t)CPU_TO_FDT32(x);
>  }
>  
>  static inline uint64_t fdt64_to_cpu(fdt64_t x)
>  {
> -	return (__force uint64_t)CPU_TO_FDT64(x);
> +	return (FDT_FORCE uint64_t)CPU_TO_FDT64(x);
>  }
>  static inline fdt64_t cpu_to_fdt64(uint64_t x)
>  {
> -	return (__force fdt64_t)CPU_TO_FDT64(x);
> +	return (FDT_FORCE fdt64_t)CPU_TO_FDT64(x);
>  }
>  #undef CPU_TO_FDT64
>  #undef CPU_TO_FDT32
>  #undef CPU_TO_FDT16
>  #undef EXTRACT_BYTE
>  
> -#endif /* _LIBFDT_ENV_H */
> +#ifdef __APPLE__
> +#include <AvailabilityMacros.h>
> +
> +/* strnlen() is not available on Mac OS < 10.7 */
> +# if !defined(MAC_OS_X_VERSION_10_7) || (MAC_OS_X_VERSION_MAX_ALLOWED < \
> +                                         MAC_OS_X_VERSION_10_7)
> +
> +#define strnlen fdt_strnlen
> +
> +/*
> + * fdt_strnlen: returns the length of a string or max_count - which ever is
> + * smallest.
> + * Input 1 string: the string whose size is to be determined
> + * Input 2 max_count: the maximum value returned by this function
> + * Output: length of the string or max_count (the smallest of the two)
> + */
> +static inline size_t fdt_strnlen(const char *string, size_t max_count)
> +{
> +    const char *p = memchr(string, 0, max_count);
> +    return p ? p - string : max_count;
> +}
> +
> +#endif /* !defined(MAC_OS_X_VERSION_10_7) || (MAC_OS_X_VERSION_MAX_ALLOWED <
> +          MAC_OS_X_VERSION_10_7) */
> +
> +#endif /* __APPLE__ */
> +
> +#endif /* LIBFDT_ENV_H */
> diff --git a/scripts/dtc/libfdt_internal.h b/scripts/dtc/libfdt_internal.h
> index 02cfa6fb6..7681e1922 100644
> --- a/scripts/dtc/libfdt_internal.h
> +++ b/scripts/dtc/libfdt_internal.h
> @@ -1,5 +1,5 @@
> -#ifndef _LIBFDT_INTERNAL_H
> -#define _LIBFDT_INTERNAL_H
> +#ifndef LIBFDT_INTERNAL_H
> +#define LIBFDT_INTERNAL_H
>  /*
>   * libfdt - Flat Device Tree manipulation
>   * Copyright (C) 2006 David Gibson, IBM Corporation.
> @@ -57,27 +57,27 @@
>  
>  #define FDT_CHECK_HEADER(fdt) \
>  	{ \
> -		int __err; \
> -		if ((__err = fdt_check_header(fdt)) != 0) \
> -			return __err; \
> +		int err_; \
> +		if ((err_ = fdt_check_header(fdt)) != 0) \
> +			return err_; \
>  	}
>  
> -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);
> -int _fdt_node_end_offset(void *fdt, int nodeoffset);
> +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);
> +int fdt_node_end_offset_(void *fdt, int nodeoffset);
>  
> -static inline const void *_fdt_offset_ptr(const void *fdt, int offset)
> +static inline const void *fdt_offset_ptr_(const void *fdt, int offset)
>  {
>  	return (const char *)fdt + fdt_off_dt_struct(fdt) + offset;
>  }
>  
> -static inline void *_fdt_offset_ptr_w(void *fdt, int offset)
> +static inline void *fdt_offset_ptr_w_(void *fdt, int offset)
>  {
> -	return (void *)(uintptr_t)_fdt_offset_ptr(fdt, offset);
> +	return (void *)(uintptr_t)fdt_offset_ptr_(fdt, offset);
>  }
>  
> -static inline const struct fdt_reserve_entry *_fdt_mem_rsv(const void *fdt, int n)
> +static inline const struct fdt_reserve_entry *fdt_mem_rsv_(const void *fdt, int n)
>  {
>  	const struct fdt_reserve_entry *rsv_table =
>  		(const struct fdt_reserve_entry *)
> @@ -85,11 +85,11 @@ static inline const struct fdt_reserve_entry *_fdt_mem_rsv(const void *fdt, int
>  
>  	return rsv_table + n;
>  }
> -static inline struct fdt_reserve_entry *_fdt_mem_rsv_w(void *fdt, int n)
> +static inline struct fdt_reserve_entry *fdt_mem_rsv_w_(void *fdt, int n)
>  {
> -	return (void *)(uintptr_t)_fdt_mem_rsv(fdt, n);
> +	return (void *)(uintptr_t)fdt_mem_rsv_(fdt, n);
>  }
>  
>  #define FDT_SW_MAGIC		(~FDT_MAGIC)
>  
> -#endif /* _LIBFDT_INTERNAL_H */
> +#endif /* LIBFDT_INTERNAL_H */
> diff --git a/scripts/dtc/livetree.c b/scripts/dtc/livetree.c
> index e229b8443..57b7db2ed 100644
> --- a/scripts/dtc/livetree.c
> +++ b/scripts/dtc/livetree.c
> @@ -204,7 +204,7 @@ struct node *merge_nodes(struct node *old_node, struct node *new_node)
>  			}
>  		}
>  
> -		/* if no collision occured, add child to the old node. */
> +		/* if no collision occurred, add child to the old node. */
>  		if (new_child)
>  			add_child(old_node, new_child);
>  	}
> @@ -216,6 +216,29 @@ struct node *merge_nodes(struct node *old_node, struct node *new_node)
>  	return old_node;
>  }
>  
> +struct node * add_orphan_node(struct node *dt, struct node *new_node, char *ref)
> +{
> +	static unsigned int next_orphan_fragment = 0;
> +	struct node *node;
> +	struct property *p;
> +	struct data d = empty_data;
> +	char *name;
> +
> +	d = data_add_marker(d, REF_PHANDLE, ref);
> +	d = data_append_integer(d, 0xffffffff, 32);
> +
> +	p = build_property("target", d);
> +
> +	xasprintf(&name, "fragment@%u",
> +			next_orphan_fragment++);
> +	name_node(new_node, "__overlay__");
> +	node = build_node(p, new_node);
> +	name_node(node, name);
> +
> +	add_child(dt, node);
> +	return dt;
> +}
> +
>  struct node *chain_node(struct node *first, struct node *list)
>  {
>  	assert(first->next_sibling == NULL);
> @@ -242,7 +265,7 @@ void delete_property_by_name(struct node *node, char *name)
>  	struct property *prop = node->proplist;
>  
>  	while (prop) {
> -		if (!strcmp(prop->name, name)) {
> +		if (streq(prop->name, name)) {
>  			delete_property(prop);
>  			return;
>  		}
> @@ -275,7 +298,7 @@ void delete_node_by_name(struct node *parent, char *name)
>  	struct node *node = parent->children;
>  
>  	while (node) {
> -		if (!strcmp(node->name, name)) {
> +		if (streq(node->name, name)) {
>  			delete_node(node);
>  			return;
>  		}
> @@ -296,14 +319,31 @@ void delete_node(struct node *node)
>  	delete_labels(&node->labels);
>  }
>  
> +void append_to_property(struct node *node,
> +				    char *name, const void *data, int len)
> +{
> +	struct data d;
> +	struct property *p;
> +
> +	p = get_property(node, name);
> +	if (p) {
> +		d = data_append_data(p->val, data, len);
> +		p->val = d;
> +	} else {
> +		d = data_append_data(empty_data, data, len);
> +		p = build_property(name, d);
> +		add_property(node, p);
> +	}
> +}
> +
>  struct reserve_info *build_reserve_entry(uint64_t address, uint64_t size)
>  {
>  	struct reserve_info *new = xmalloc(sizeof(*new));
>  
>  	memset(new, 0, sizeof(*new));
>  
> -	new->re.address = address;
> -	new->re.size = size;
> +	new->address = address;
> +	new->size = size;
>  
>  	return new;
>  }
> @@ -335,17 +375,19 @@ struct reserve_info *add_reserve_entry(struct reserve_info *list,
>  	return list;
>  }
>  
> -struct boot_info *build_boot_info(struct reserve_info *reservelist,
> -				  struct node *tree, uint32_t boot_cpuid_phys)
> +struct dt_info *build_dt_info(unsigned int dtsflags,
> +			      struct reserve_info *reservelist,
> +			      struct node *tree, uint32_t boot_cpuid_phys)
>  {
> -	struct boot_info *bi;
> +	struct dt_info *dti;
>  
> -	bi = xmalloc(sizeof(*bi));
> -	bi->reservelist = reservelist;
> -	bi->dt = tree;
> -	bi->boot_cpuid_phys = boot_cpuid_phys;
> +	dti = xmalloc(sizeof(*dti));
> +	dti->dtsflags = dtsflags;
> +	dti->reservelist = reservelist;
> +	dti->dt = tree;
> +	dti->boot_cpuid_phys = boot_cpuid_phys;
>  
> -	return bi;
> +	return dti;
>  }
>  
>  /*
> @@ -374,7 +416,13 @@ struct property *get_property(struct node *node, const char *propname)
>  cell_t propval_cell(struct property *prop)
>  {
>  	assert(prop->val.len == sizeof(cell_t));
> -	return fdt32_to_cpu(*((cell_t *)prop->val.val));
> +	return fdt32_to_cpu(*((fdt32_t *)prop->val.val));
> +}
> +
> +cell_t propval_cell_n(struct property *prop, int n)
> +{
> +	assert(prop->val.len / sizeof(cell_t) >= n);
> +	return fdt32_to_cpu(*((fdt32_t *)prop->val.val + n));
>  }
>  
>  struct property *get_property_by_label(struct node *tree, const char *label,
> @@ -459,7 +507,8 @@ struct node *get_node_by_path(struct node *tree, const char *path)
>  	p = strchr(path, '/');
>  
>  	for_each_child(tree, child) {
> -		if (p && strneq(path, child->name, p-path))
> +		if (p && (strlen(child->name) == p-path) &&
> +		    strprefixeq(path, p - path, child->name))
>  			return get_node_by_path(child, p+1);
>  		else if (!p && streq(path, child->name))
>  			return child;
> @@ -492,7 +541,10 @@ struct node *get_node_by_phandle(struct node *tree, cell_t phandle)
>  {
>  	struct node *child, *node;
>  
> -	assert((phandle != 0) && (phandle != -1));
> +	if ((phandle == 0) || (phandle == -1)) {
> +		assert(generate_fixups);
> +		return NULL;
> +	}
>  
>  	if (tree->phandle == phandle) {
>  		if (tree->deleted)
> @@ -580,24 +632,24 @@ static int cmp_reserve_info(const void *ax, const void *bx)
>  	a = *((const struct reserve_info * const *)ax);
>  	b = *((const struct reserve_info * const *)bx);
>  
> -	if (a->re.address < b->re.address)
> +	if (a->address < b->address)
>  		return -1;
> -	else if (a->re.address > b->re.address)
> +	else if (a->address > b->address)
>  		return 1;
> -	else if (a->re.size < b->re.size)
> +	else if (a->size < b->size)
>  		return -1;
> -	else if (a->re.size > b->re.size)
> +	else if (a->size > b->size)
>  		return 1;
>  	else
>  		return 0;
>  }
>  
> -static void sort_reserve_entries(struct boot_info *bi)
> +static void sort_reserve_entries(struct dt_info *dti)
>  {
>  	struct reserve_info *ri, **tbl;
>  	int n = 0, i = 0;
>  
> -	for (ri = bi->reservelist;
> +	for (ri = dti->reservelist;
>  	     ri;
>  	     ri = ri->next)
>  		n++;
> @@ -607,14 +659,14 @@ static void sort_reserve_entries(struct boot_info *bi)
>  
>  	tbl = xmalloc(n * sizeof(*tbl));
>  
> -	for (ri = bi->reservelist;
> +	for (ri = dti->reservelist;
>  	     ri;
>  	     ri = ri->next)
>  		tbl[i++] = ri;
>  
>  	qsort(tbl, n, sizeof(*tbl), cmp_reserve_info);
>  
> -	bi->reservelist = tbl[0];
> +	dti->reservelist = tbl[0];
>  	for (i = 0; i < (n-1); i++)
>  		tbl[i]->next = tbl[i+1];
>  	tbl[n-1]->next = NULL;
> @@ -704,8 +756,258 @@ static void sort_node(struct node *node)
>  		sort_node(c);
>  }
>  
> -void sort_tree(struct boot_info *bi)
> +void sort_tree(struct dt_info *dti)
> +{
> +	sort_reserve_entries(dti);
> +	sort_node(dti->dt);
> +}
> +
> +/* utility helper to avoid code duplication */
> +static struct node *build_and_name_child_node(struct node *parent, char *name)
> +{
> +	struct node *node;
> +
> +	node = build_node(NULL, NULL);
> +	name_node(node, xstrdup(name));
> +	add_child(parent, node);
> +
> +	return node;
> +}
> +
> +static struct node *build_root_node(struct node *dt, char *name)
> +{
> +	struct node *an;
> +
> +	an = get_subnode(dt, name);
> +	if (!an)
> +		an = build_and_name_child_node(dt, name);
> +
> +	if (!an)
> +		die("Could not build root node /%s\n", name);
> +
> +	return an;
> +}
> +
> +static bool any_label_tree(struct dt_info *dti, struct node *node)
> +{
> +	struct node *c;
> +
> +	if (node->labels)
> +		return true;
> +
> +	for_each_child(node, c)
> +		if (any_label_tree(dti, c))
> +			return true;
> +
> +	return false;
> +}
> +
> +static void generate_label_tree_internal(struct dt_info *dti,
> +					 struct node *an, struct node *node,
> +					 bool allocph)
>  {
> -	sort_reserve_entries(bi);
> -	sort_node(bi->dt);
> +	struct node *dt = dti->dt;
> +	struct node *c;
> +	struct property *p;
> +	struct label *l;
> +
> +	/* if there are labels */
> +	if (node->labels) {
> +
> +		/* now add the label in the node */
> +		for_each_label(node->labels, l) {
> +
> +			/* check whether the label already exists */
> +			p = get_property(an, l->label);
> +			if (p) {
> +				fprintf(stderr, "WARNING: label %s already"
> +					" exists in /%s", l->label,
> +					an->name);
> +				continue;
> +			}
> +
> +			/* insert it */
> +			p = build_property(l->label,
> +				data_copy_mem(node->fullpath,
> +						strlen(node->fullpath) + 1));
> +			add_property(an, p);
> +		}
> +
> +		/* force allocation of a phandle for this node */
> +		if (allocph)
> +			(void)get_node_phandle(dt, node);
> +	}
> +
> +	for_each_child(node, c)
> +		generate_label_tree_internal(dti, an, c, allocph);
> +}
> +
> +static bool any_fixup_tree(struct dt_info *dti, struct node *node)
> +{
> +	struct node *c;
> +	struct property *prop;
> +	struct marker *m;
> +
> +	for_each_property(node, prop) {
> +		m = prop->val.markers;
> +		for_each_marker_of_type(m, REF_PHANDLE) {
> +			if (!get_node_by_ref(dti->dt, m->ref))
> +				return true;
> +		}
> +	}
> +
> +	for_each_child(node, c) {
> +		if (any_fixup_tree(dti, c))
> +			return true;
> +	}
> +
> +	return false;
> +}
> +
> +static void add_fixup_entry(struct dt_info *dti, struct node *fn,
> +			    struct node *node, struct property *prop,
> +			    struct marker *m)
> +{
> +	char *entry;
> +
> +	/* m->ref can only be a REF_PHANDLE, but check anyway */
> +	assert(m->type == REF_PHANDLE);
> +
> +	/* 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);
> +
> +	free(entry);
> +}
> +
> +static void generate_fixups_tree_internal(struct dt_info *dti,
> +					  struct node *fn,
> +					  struct node *node)
> +{
> +	struct node *dt = dti->dt;
> +	struct node *c;
> +	struct property *prop;
> +	struct marker *m;
> +	struct node *refnode;
> +
> +	for_each_property(node, prop) {
> +		m = prop->val.markers;
> +		for_each_marker_of_type(m, REF_PHANDLE) {
> +			refnode = get_node_by_ref(dt, m->ref);
> +			if (!refnode)
> +				add_fixup_entry(dti, fn, node, prop, m);
> +		}
> +	}
> +
> +	for_each_child(node, c)
> +		generate_fixups_tree_internal(dti, fn, c);
> +}
> +
> +static bool any_local_fixup_tree(struct dt_info *dti, struct node *node)
> +{
> +	struct node *c;
> +	struct property *prop;
> +	struct marker *m;
> +
> +	for_each_property(node, prop) {
> +		m = prop->val.markers;
> +		for_each_marker_of_type(m, REF_PHANDLE) {
> +			if (get_node_by_ref(dti->dt, m->ref))
> +				return true;
> +		}
> +	}
> +
> +	for_each_child(node, c) {
> +		if (any_local_fixup_tree(dti, c))
> +			return true;
> +	}
> +
> +	return false;
> +}
> +
> +static void add_local_fixup_entry(struct dt_info *dti,
> +		struct node *lfn, struct node *node,
> +		struct property *prop, struct marker *m,
> +		struct node *refnode)
> +{
> +	struct node *wn, *nwn;	/* local fixup node, walk node, new */
> +	fdt32_t value_32;
> +	char **compp;
> +	int i, depth;
> +
> +	/* walk back retreiving depth */
> +	depth = 0;
> +	for (wn = node; wn; wn = wn->parent)
> +		depth++;
> +
> +	/* allocate name array */
> +	compp = xmalloc(sizeof(*compp) * depth);
> +
> +	/* store names in the array */
> +	for (wn = node, i = depth - 1; wn; wn = wn->parent, i--)
> +		compp[i] = wn->name;
> +
> +	/* 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]);
> +	}
> +
> +	free(compp);
> +
> +	value_32 = cpu_to_fdt32(m->offset);
> +	append_to_property(wn, prop->name, &value_32, sizeof(value_32));
> +}
> +
> +static void generate_local_fixups_tree_internal(struct dt_info *dti,
> +						struct node *lfn,
> +						struct node *node)
> +{
> +	struct node *dt = dti->dt;
> +	struct node *c;
> +	struct property *prop;
> +	struct marker *m;
> +	struct node *refnode;
> +
> +	for_each_property(node, prop) {
> +		m = prop->val.markers;
> +		for_each_marker_of_type(m, REF_PHANDLE) {
> +			refnode = get_node_by_ref(dt, m->ref);
> +			if (refnode)
> +				add_local_fixup_entry(dti, lfn, node, prop, m, refnode);
> +		}
> +	}
> +
> +	for_each_child(node, c)
> +		generate_local_fixups_tree_internal(dti, lfn, c);
> +}
> +
> +void generate_label_tree(struct dt_info *dti, char *name, bool allocph)
> +{
> +	if (!any_label_tree(dti, dti->dt))
> +		return;
> +	generate_label_tree_internal(dti, build_root_node(dti->dt, name),
> +				     dti->dt, allocph);
> +}
> +
> +void generate_fixups_tree(struct dt_info *dti, char *name)
> +{
> +	if (!any_fixup_tree(dti, dti->dt))
> +		return;
> +	generate_fixups_tree_internal(dti, build_root_node(dti->dt, name),
> +				      dti->dt);
> +}
> +
> +void generate_local_fixups_tree(struct dt_info *dti, char *name)
> +{
> +	if (!any_local_fixup_tree(dti, dti->dt))
> +		return;
> +	generate_local_fixups_tree_internal(dti, build_root_node(dti->dt, name),
> +					    dti->dt);
>  }
> diff --git a/scripts/dtc/srcpos.c b/scripts/dtc/srcpos.c
> index f534c22a8..cb6ed0e3e 100644
> --- a/scripts/dtc/srcpos.c
> +++ b/scripts/dtc/srcpos.c
> @@ -209,8 +209,6 @@ struct srcpos srcpos_empty = {
>  	.file = NULL,
>  };
>  
> -#define TAB_SIZE      8
> -
>  void srcpos_update(struct srcpos *pos, const char *text, int len)
>  {
>  	int i;
> @@ -224,9 +222,6 @@ void srcpos_update(struct srcpos *pos, const char *text, int len)
>  		if (text[i] == '\n') {
>  			current_srcfile->lineno++;
>  			current_srcfile->colno = 1;
> -		} else if (text[i] == '\t') {
> -			current_srcfile->colno =
> -				ALIGN(current_srcfile->colno, TAB_SIZE);
>  		} else {
>  			current_srcfile->colno++;
>  		}
> @@ -246,46 +241,27 @@ srcpos_copy(struct srcpos *pos)
>  	return pos_new;
>  }
>  
> -
> -
> -void
> -srcpos_dump(struct srcpos *pos)
> -{
> -	printf("file        : \"%s\"\n",
> -	       pos->file ? (char *) pos->file : "<no file>");
> -	printf("first_line  : %d\n", pos->first_line);
> -	printf("first_column: %d\n", pos->first_column);
> -	printf("last_line   : %d\n", pos->last_line);
> -	printf("last_column : %d\n", pos->last_column);
> -	printf("file        : %s\n", pos->file->name);
> -}
> -
> -
>  char *
>  srcpos_string(struct srcpos *pos)
>  {
>  	const char *fname = "<no-file>";
>  	char *pos_str;
> -	int rc;
>  
> -	if (pos)
> +	if (pos->file && pos->file->name)
>  		fname = pos->file->name;
>  
>  
>  	if (pos->first_line != pos->last_line)
> -		rc = asprintf(&pos_str, "%s:%d.%d-%d.%d", fname,
> -			      pos->first_line, pos->first_column,
> -			      pos->last_line, pos->last_column);
> +		xasprintf(&pos_str, "%s:%d.%d-%d.%d", fname,
> +			  pos->first_line, pos->first_column,
> +			  pos->last_line, pos->last_column);
>  	else if (pos->first_column != pos->last_column)
> -		rc = asprintf(&pos_str, "%s:%d.%d-%d", fname,
> -			      pos->first_line, pos->first_column,
> -			      pos->last_column);
> +		xasprintf(&pos_str, "%s:%d.%d-%d", fname,
> +			  pos->first_line, pos->first_column,
> +			  pos->last_column);
>  	else
> -		rc = asprintf(&pos_str, "%s:%d.%d", fname,
> -			      pos->first_line, pos->first_column);
> -
> -	if (rc == -1)
> -		die("Couldn't allocate in srcpos string");
> +		xasprintf(&pos_str, "%s:%d.%d", fname,
> +			  pos->first_line, pos->first_column);
>  
>  	return pos_str;
>  }
> diff --git a/scripts/dtc/srcpos.h b/scripts/dtc/srcpos.h
> index f81827bd6..9ded12a38 100644
> --- a/scripts/dtc/srcpos.h
> +++ b/scripts/dtc/srcpos.h
> @@ -17,11 +17,12 @@
>   *                                                                   USA
>   */
>  
> -#ifndef _SRCPOS_H_
> -#define _SRCPOS_H_
> +#ifndef SRCPOS_H
> +#define SRCPOS_H
>  
>  #include <stdio.h>
>  #include <stdbool.h>
> +#include "util.h"
>  
>  struct srcfile_state {
>  	FILE *f;
> @@ -105,15 +106,12 @@ 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 char *srcpos_string(struct srcpos *pos);
> -extern void srcpos_dump(struct srcpos *pos);
>  
> -extern void srcpos_verror(struct srcpos *pos, const char *prefix,
> -			  const char *fmt, va_list va)
> -	__attribute__((format(printf, 3, 0)));
> -extern void srcpos_error(struct srcpos *pos, const char *prefix,
> -			 const char *fmt, ...)
> -	__attribute__((format(printf, 3, 4)));
> +extern void PRINTF(3, 0) srcpos_verror(struct srcpos *pos, const char *prefix,
> +					const char *fmt, va_list va);
> +extern void PRINTF(3, 4) srcpos_error(struct srcpos *pos, const char *prefix,
> +				      const char *fmt, ...);
>  
>  extern void srcpos_set_line(char *f, int l);
>  
> -#endif /* _SRCPOS_H_ */
> +#endif /* SRCPOS_H */
> diff --git a/scripts/dtc/treesource.c b/scripts/dtc/treesource.c
> index a55d1d128..2461a3d06 100644
> --- a/scripts/dtc/treesource.c
> +++ b/scripts/dtc/treesource.c
> @@ -25,12 +25,12 @@ extern FILE *yyin;
>  extern int yyparse(void);
>  extern YYLTYPE yylloc;
>  
> -struct boot_info *the_boot_info;
> +struct dt_info *parser_output;
>  bool treesource_error;
>  
> -struct boot_info *dt_from_source(const char *fname)
> +struct dt_info *dt_from_source(const char *fname)
>  {
> -	the_boot_info = NULL;
> +	parser_output = NULL;
>  	treesource_error = false;
>  
>  	srcfile_push(fname);
> @@ -43,7 +43,7 @@ struct boot_info *dt_from_source(const char *fname)
>  	if (treesource_error)
>  		die("Syntax error parsing input tree\n");
>  
> -	return the_boot_info;
> +	return parser_output;
>  }
>  
>  static void write_prefix(FILE *f, int level)
> @@ -137,7 +137,7 @@ static void write_propval_string(FILE *f, struct data val)
>  static void write_propval_cells(FILE *f, struct data val)
>  {
>  	void *propend = val.val + val.len;
> -	cell_t *cp = (cell_t *)val.val;
> +	fdt32_t *cp = (fdt32_t *)val.val;
>  	struct marker *m = val.markers;
>  
>  	fprintf(f, "<");
> @@ -263,22 +263,22 @@ static void write_tree_source_node(FILE *f, struct node *tree, int level)
>  }
>  
>  
> -void dt_to_source(FILE *f, struct boot_info *bi)
> +void dt_to_source(FILE *f, struct dt_info *dti)
>  {
>  	struct reserve_info *re;
>  
>  	fprintf(f, "/dts-v1/;\n\n");
>  
> -	for (re = bi->reservelist; re; re = re->next) {
> +	for (re = dti->reservelist; re; re = re->next) {
>  		struct label *l;
>  
>  		for_each_label(re->labels, l)
>  			fprintf(f, "%s: ", l->label);
>  		fprintf(f, "/memreserve/\t0x%016llx 0x%016llx;\n",
> -			(unsigned long long)re->re.address,
> -			(unsigned long long)re->re.size);
> +			(unsigned long long)re->address,
> +			(unsigned long long)re->size);
>  	}
>  
> -	write_tree_source_node(f, bi->dt, 0);
> +	write_tree_source_node(f, dti->dt, 0);
>  }
>  
> diff --git a/scripts/dtc/update-dtc-source.sh b/scripts/dtc/update-dtc-source.sh
> index 075d1d7af..1a009fd19 100755
> --- a/scripts/dtc/update-dtc-source.sh
> +++ b/scripts/dtc/update-dtc-source.sh
> @@ -1,9 +1,10 @@
>  #!/bin/sh
> +# SPDX-License-Identifier: GPL-2.0
>  # Simple script to update the version of DTC carried by the Linux kernel
>  #
>  # This script assumes that the dtc and the linux git trees are in the
>  # same directory. After building dtc in the dtc directory, it copies the
> -# source files and generated source files into the scripts/dtc directory
> +# source files and generated source file(s) into the scripts/dtc directory
>  # in the kernel and creates a git commit updating them to the new
>  # version.
>  #
> @@ -32,16 +33,24 @@ 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 \
> -		dtc-lexer.l dtc-parser.y fdtdump.c fdtput.c fdtget.c"
> -DTC_LIB="fdt.c fdt.h fdt_addresses.c fdt_empty_tree.c fdt_ro.c fdt_rw.c \
> -		fdt_strerror.c fdt_sw.c fdt_wip.c libfdt.h libfdt_env.h \
> -		libfdt_internal.h"
> -DTC_GENERATED="dtc-lexer.lex.c dtc-parser.tab.c dtc-parser.tab.h"
> +		dtc-lexer.l dtc-parser.y"
> +LIBFDT_SOURCE="Makefile.libfdt 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"
> +
> +get_last_dtc_version() {
> +	git log --oneline scripts/dtc/ | grep 'upstream' | head -1 | sed -e 's/^.* \(.*\)/\1/'
> +}
> +
> +last_dtc_ver=$(get_last_dtc_version)
>  
>  # Build DTC
>  cd $DTC_UPSTREAM_PATH
>  make clean
>  make check
> +dtc_version=$(git describe HEAD)
> +dtc_log=$(git log --oneline ${last_dtc_ver}..)
> +
>  
>  # Copy the files into the Linux tree
>  cd $DTC_LINUX_PATH
> @@ -49,13 +58,22 @@ for f in $DTC_SOURCE; do
>  	cp ${DTC_UPSTREAM_PATH}/${f} ${f}
>  	git add ${f}
>  done
> -for f in $DTC_LIB; do
> -	cp ${DTC_UPSTREAM_PATH}/libfdt/${f} ${f}
> -	git add ${f}
> -done
> -for f in $DTC_GENERATED; do
> -	cp ${DTC_UPSTREAM_PATH}/$f ${f}_shipped
> -	git add ${f}_shipped
> +for f in $LIBFDT_SOURCE; do
> +       cp ${DTC_UPSTREAM_PATH}/libfdt/${f} libfdt/${f}
> +       git add libfdt/${f}
>  done
>  
> -git commit -e -v -m "scripts/dtc: Update to upstream version [CHANGEME]"
> +sed -i -- 's/#include <libfdt_env.h>/#include "libfdt_env.h"/g' ./libfdt/libfdt.h
> +sed -i -- 's/#include <fdt.h>/#include "fdt.h"/g' ./libfdt/libfdt.h
> +git add ./libfdt/libfdt.h
> +
> +commit_msg=$(cat << EOF
> +scripts/dtc: Update to upstream version ${dtc_version}
> +
> +This adds the following commits from upstream:
> +
> +${dtc_log}
> +EOF
> +)
> +
> +git commit -e -v -s -m "${commit_msg}"
> diff --git a/scripts/dtc/util.c b/scripts/dtc/util.c
> index 9d65226df..9953c32a0 100644
> --- a/scripts/dtc/util.c
> +++ b/scripts/dtc/util.c
> @@ -46,6 +46,36 @@ char *xstrdup(const char *s)
>  	return d;
>  }
>  
> +/* based in part from (3) vsnprintf */
> +int xasprintf(char **strp, const char *fmt, ...)
> +{
> +	int n, size = 128;	/* start with 128 bytes */
> +	char *p;
> +	va_list ap;
> +
> +	/* initial pointer is NULL making the fist realloc to be malloc */
> +	p = NULL;
> +	while (1) {
> +		p = xrealloc(p, size);
> +
> +		/* Try to print in the allocated space. */
> +		va_start(ap, fmt);
> +		n = vsnprintf(p, size, fmt, ap);
> +		va_end(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);
> +}
> +
>  char *join_path(const char *path, const char *name)
>  {
>  	int lenp = strlen(path);
> @@ -152,7 +182,6 @@ char get_escape_char(const char *s, int *i)
>  	int	j = *i + 1;
>  	char	val;
>  
> -	assert(c);
>  	switch (c) {
>  	case 'a':
>  		val = '\a';
> @@ -349,7 +378,6 @@ int utilfdt_decode_type(const char *fmt, int *type, int *size)
>  void utilfdt_print_data(const char *data, int len)
>  {
>  	int i;
> -	const char *p = data;
>  	const char *s;
>  
>  	/* no data, don't print */
> @@ -368,7 +396,7 @@ void utilfdt_print_data(const char *data, int len)
>  		} while (s < data + len);
>  
>  	} else if ((len % 4) == 0) {
> -		const uint32_t *cell = (const uint32_t *)data;
> +		const fdt32_t *cell = (const fdt32_t *)data;
>  
>  		printf(" = <");
>  		for (i = 0, len /= 4; i < len; i++)
> @@ -376,6 +404,7 @@ void utilfdt_print_data(const char *data, int len)
>  			       i < (len - 1) ? " " : "");
>  		printf(">");
>  	} else {
> +		const unsigned char *p = (const unsigned char *)data;
>  		printf(" = [");
>  		for (i = 0; i < len; i++)
>  			printf("%02x%s", *p++, i < len - 1 ? " " : "");
> @@ -383,15 +412,16 @@ void utilfdt_print_data(const char *data, int len)
>  	}
>  }
>  
> -void util_version(void)
> +void NORETURN util_version(void)
>  {
>  	printf("Version: %s\n", DTC_VERSION);
>  	exit(0);
>  }
>  
> -void util_usage(const char *errmsg, const char *synopsis,
> -		const char *short_opts, struct option const long_opts[],
> -		const char * const opts_help[])
> +void NORETURN util_usage(const char *errmsg, const char *synopsis,
> +			 const char *short_opts,
> +			 struct option const long_opts[],
> +			 const char * const opts_help[])
>  {
>  	FILE *fp = errmsg ? stderr : stdout;
>  	const char a_arg[] = "<arg>";
> diff --git a/scripts/dtc/util.h b/scripts/dtc/util.h
> index ccfdf4b12..66fba8ea7 100644
> --- a/scripts/dtc/util.h
> +++ b/scripts/dtc/util.h
> @@ -1,5 +1,5 @@
> -#ifndef _UTIL_H
> -#define _UTIL_H
> +#ifndef UTIL_H
> +#define UTIL_H
>  
>  #include <stdarg.h>
>  #include <stdbool.h>
> @@ -25,15 +25,27 @@
>   *                                                                   USA
>   */
>  
> +#ifdef __GNUC__
> +#define PRINTF(i, j)	__attribute__((format (printf, i, j)))
> +#define NORETURN	__attribute__((noreturn))
> +#else
> +#define PRINTF(i, j)
> +#define NORETURN
> +#endif
> +
>  #define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
>  
> -static inline void __attribute__((noreturn)) die(const char *str, ...)
> +#define stringify(s)	stringify_(s)
> +#define stringify_(s)	#s
> +
> +static inline void NORETURN PRINTF(1, 2) die(const char *str, ...)
>  {
>  	va_list ap;
>  
>  	va_start(ap, str);
>  	fprintf(stderr, "FATAL ERROR: ");
>  	vfprintf(stderr, str, ap);
> +	va_end(ap);
>  	exit(1);
>  }
>  
> @@ -52,12 +64,14 @@ static inline void *xrealloc(void *p, size_t len)
>  	void *new = realloc(p, len);
>  
>  	if (!new)
> -		die("realloc() failed (len=%d)\n", len);
> +		die("realloc() failed (len=%zd)\n", len);
>  
>  	return new;
>  }
>  
>  extern char *xstrdup(const char *s);
> +
> +extern int PRINTF(2, 3) xasprintf(char **strp, const char *fmt, ...);
>  extern char *join_path(const char *path, const char *name);
>  
>  /**
> @@ -186,7 +200,7 @@ void utilfdt_print_data(const char *data, int len);
>  /**
>   * Show source version and exit
>   */
> -void util_version(void) __attribute__((noreturn));
> +void NORETURN util_version(void);
>  
>  /**
>   * Show usage and exit
> @@ -200,9 +214,10 @@ void util_version(void) __attribute__((noreturn));
>   * @param long_opts	The structure of long options
>   * @param opts_help	An array of help strings (should align with long_opts)
>   */
> -void util_usage(const char *errmsg, const char *synopsis,
> -		const char *short_opts, struct option const long_opts[],
> -		const char * const opts_help[]) __attribute__((noreturn));
> +void NORETURN util_usage(const char *errmsg, const char *synopsis,
> +			 const char *short_opts,
> +			 struct option const long_opts[],
> +			 const char * const opts_help[]);
>  
>  /**
>   * Show usage and exit
> @@ -248,4 +263,4 @@ void util_usage(const char *errmsg, const char *synopsis,
>  	case 'V': util_version(); \
>  	case '?': usage("unknown option");
>  
> -#endif /* _UTIL_H */
> +#endif /* UTIL_H */
> diff --git a/scripts/dtc/version_gen.h b/scripts/dtc/version_gen.h
> index 607afac1c..89d4e0ad1 100644
> --- a/scripts/dtc/version_gen.h
> +++ b/scripts/dtc/version_gen.h
> @@ -1 +1 @@
> -#define DTC_VERSION "DTC 1.4.1"
> +#define DTC_VERSION "DTC 1.4.6"
> -- 
> 2.17.0
> 
> 
> _______________________________________________
> barebox mailing list
> barebox at lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/barebox
> 

-- 
Pengutronix e.K.                           |                             |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |
Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |



More information about the barebox mailing list