commit 0a5aca98ba104ec4101322ccaf36da45064ad3ce
Author: Josh Boyer <jwboyer@linux.vnet.ibm.com>
Date:   Tue Jun 28 08:47:09 2011 -0400

    dtc: Remove unused check variable
    
    Commit 376ab6f2 removed the old style check functionality from DTC,
    however the check option and variable were not removed.  This leads to
    build failures when -Werror=unused-but-set-variable is specified:
    
    	dtc.c: In function 'main':
    	dtc.c:102:17: error: variable 'check' set but not used [-Werror=unused-but-set-variable]
    	cc1: all warnings being treated as errors
    	make: *** [dtc.o] Error 1
    	make: *** Waiting for unfinished jobs....
    
    Remove the check variable.
    
    Signed-off-by: Josh Boyer <jwboyer@linux.vnet.ibm.com>
    Acked-by: David Gibson <david@gibson.dropbear.id.au>

diff --git a/dtc.c b/dtc.c
index cbc0193..15d2fc2 100644
--- a/dtc.c
+++ b/dtc.c
@@ -99,7 +99,7 @@ int main(int argc, char *argv[])
 	const char *inform = "dts";
 	const char *outform = "dts";
 	const char *outname = "-";
-	int force = 0, check = 0, sort = 0;
+	int force = 0, sort = 0;
 	const char *arg;
 	int opt;
 	FILE *outf = NULL;
@@ -111,7 +111,7 @@ int main(int argc, char *argv[])
 	minsize    = 0;
 	padsize    = 0;
 
-	while ((opt = getopt(argc, argv, "hI:O:o:V:R:S:p:fcqb:vH:s")) != EOF) {
+	while ((opt = getopt(argc, argv, "hI:O:o:V:R:S:p:fqb:vH:s")) != EOF) {
 		switch (opt) {
 		case 'I':
 			inform = optarg;
@@ -137,9 +137,6 @@ int main(int argc, char *argv[])
 		case 'f':
 			force = 1;
 			break;
-		case 'c':
-			check = 1;
-			break;
 		case 'q':
 			quiet++;
 			break;

commit d5b3165023b1cc3914e9943b91964ec9ad4be8b2
Author: Josh Boyer <jwboyer@linux.vnet.ibm.com>
Date:   Tue Jun 28 09:47:11 2011 -0400

    dtc: Remove unused variable in flat_read_mem_reserve
    
    The *p variable is declared and used to save inb->ptr, however p is
    later never used.  This has been the case since commit 6c0f3676 and can
    lead to build failures with -Werror=unused-but-set-variable:
    
    	flattree.c: In function 'flat_read_mem_reserve':
    	flattree.c:700:14: error: variable 'p' set but not used [-Werror=unused-but-set-variable]
    	cc1: all warnings being treated as errors
    	make: *** [flattree.o] Error 1
    
    Remove the variable.
    
    Signed-off-by: Josh Boyer <jwboyer@linux.vnet.ibm.com>
    Acked-by: David Gibson <david@gibson.dropbear.id.au>

diff --git a/flattree.c b/flattree.c
index ead0332..28d0b23 100644
--- a/flattree.c
+++ b/flattree.c
@@ -697,7 +697,6 @@ static struct reserve_info *flat_read_mem_reserve(struct inbuf *inb)
 {
 	struct reserve_info *reservelist = NULL;
 	struct reserve_info *new;
-	const char *p;
 	struct fdt_reserve_entry re;
 
 	/*
@@ -706,7 +705,6 @@ static struct reserve_info *flat_read_mem_reserve(struct inbuf *inb)
 	 *
 	 * First pass, count entries.
 	 */
-	p = inb->ptr;
 	while (1) {
 		flat_read_chunk(inb, &re, sizeof(re));
 		re.address  = fdt64_to_cpu(re.address);

commit 492f9d5de7db74aeb3a905246c4efd7cb29227a8
Author: Simon Glass <sjg@chromium.org>
Date:   Tue Jul 5 12:02:49 2011 -0700

    Split out is_printable_string() into util.c
    
    This useful function is split out so it will be available to programs
    other than ftdump.
    
    Signed-off-by: Simon Glass <sjg@chromium.org>
    Acked-by: David Gibson <david@gibson.dropbear.id.au>

diff --git a/Makefile.ftdump b/Makefile.ftdump
index b70905a..2744a18 100644
--- a/Makefile.ftdump
+++ b/Makefile.ftdump
@@ -5,7 +5,8 @@
 #
 
 FTDUMP_SRCS = \
-	ftdump.c
+	ftdump.c \
+	util.c
 
 FTDUMP_GEN_SRCS =
 
diff --git a/ftdump.c b/ftdump.c
index bce6535..db932e3 100644
--- a/ftdump.c
+++ b/ftdump.c
@@ -11,36 +11,14 @@
 #include <fdt.h>
 #include <libfdt_env.h>
 
+#include "util.h"
+
 #define FTDUMP_BUF_SIZE	65536
 
 #define ALIGN(x, a)	(((x) + ((a) - 1)) & ~((a) - 1))
 #define PALIGN(p, a)	((void *)(ALIGN((unsigned long)(p), (a))))
 #define GET_CELL(p)	(p += 4, *((const uint32_t *)(p-4)))
 
-static int is_printable_string(const void *data, int len)
-{
-	const char *s = data;
-	const char *ss;
-
-	/* zero length is not */
-	if (len == 0)
-		return 0;
-
-	/* must terminate with zero */
-	if (s[len - 1] != '\0')
-		return 0;
-
-	ss = s;
-	while (*s && isprint(*s))
-		s++;
-
-	/* not zero, or not done yet */
-	if (*s != '\0' || (s + 1 - ss) < len)
-		return 0;
-
-	return 1;
-}
-
 static void print_data(const char *data, int len)
 {
 	int i;
@@ -50,7 +28,7 @@ static void print_data(const char *data, int len)
 	if (len == 0)
 		return;
 
-	if (is_printable_string(data, len)) {
+	if (util_is_printable_string(data, len)) {
 		printf(" = \"%s\"", (const char *)data);
 	} else if ((len % 4) == 0) {
 		printf(" = <");
diff --git a/util.c b/util.c
index d7ac27d..994436f 100644
--- a/util.c
+++ b/util.c
@@ -1,6 +1,9 @@
 /*
  * Copyright 2008 Jon Loeliger, Freescale Semiconductor, Inc.
  *
+ * util_is_printable_string contributed by
+ *	Pantelis Antoniou <pantelis.antoniou AT gmail.com>
+ *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License as
  * published by the Free Software Foundation; either version 2 of the
@@ -17,6 +20,7 @@
  *                                                                   USA
  */
 
+#include <ctype.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <stdarg.h>
@@ -57,3 +61,27 @@ char *join_path(const char *path, const char *name)
 	memcpy(str+lenp, name, lenn+1);
 	return str;
 }
+
+int util_is_printable_string(const void *data, int len)
+{
+	const char *s = data;
+	const char *ss;
+
+	/* zero length is not */
+	if (len == 0)
+		return 0;
+
+	/* must terminate with zero */
+	if (s[len - 1] != '\0')
+		return 0;
+
+	ss = s;
+	while (*s && isprint(*s))
+		s++;
+
+	/* not zero, or not done yet */
+	if (*s != '\0' || (s + 1 - ss) < len)
+		return 0;
+
+	return 1;
+}
diff --git a/util.h b/util.h
index 9cead84..cc68933 100644
--- a/util.h
+++ b/util.h
@@ -1,6 +1,8 @@
 #ifndef _UTIL_H
 #define _UTIL_H
 
+#include <stdarg.h>
+
 /*
  * Copyright 2008 Jon Loeliger, Freescale Semiconductor, Inc.
  *
@@ -53,4 +55,13 @@ static inline void *xrealloc(void *p, size_t len)
 extern char *xstrdup(const char *s);
 extern char *join_path(const char *path, const char *name);
 
+/**
+ * Check a string of a given length to see if it is all printable and
+ * has a valid terminator.
+ *
+ * @param data	The string to check
+ * @param len	The string length including terminator
+ * @return 1 if a valid printable string, 0 if not */
+int util_is_printable_string(const void *data, int len);
+
 #endif /* _UTIL_H */

commit ed8fee1a649b5430afc9b551e3bb6746ebe32449
Author: Simon Glass <sjg@chromium.org>
Date:   Tue Jul 5 12:02:52 2011 -0700

    Add missing tests to .gitignore
    
    Signed-off-by: Simon Glass <sjg@chromium.org>
    Acked-by: David Gibson <david@gibson.dropbear.id.au>

diff --git a/tests/.gitignore b/tests/.gitignore
index c4e1205..f4e58b2 100644
--- a/tests/.gitignore
+++ b/tests/.gitignore
@@ -45,3 +45,5 @@
 /sw_tree1
 /truncated_property
 /value-labels
+/dtb_reverse
+/dtbs_equal_unordered

commit b43335a23854b2620140eda6cca2ffae59e8de23
Author: Anton Staaf <robotboy@chromium.org>
Date:   Fri Sep 9 12:16:29 2011 -0700

    dtc: Refactor character literal parsing code
    
    Move the parsing of hex, octal and escaped characters from data.c
    to util.c where it can be used for character literal parsing within
    strings as well as for stand alone C style character literals.
    
    Signed-off-by: Anton Staaf <robotboy@chromium.org>
    Acked-by: David Gibson <david@gibson.dropbear.id.au>

diff --git a/data.c b/data.c
index fe555e8..b5f3066 100644
--- a/data.c
+++ b/data.c
@@ -68,40 +68,6 @@ struct data data_copy_mem(const char *mem, int len)
 	return d;
 }
 
-static char get_oct_char(const char *s, int *i)
-{
-	char x[4];
-	char *endx;
-	long val;
-
-	x[3] = '\0';
-	strncpy(x, s + *i, 3);
-
-	val = strtol(x, &endx, 8);
-
-	assert(endx > x);
-
-	(*i) += endx - x;
-	return val;
-}
-
-static char get_hex_char(const char *s, int *i)
-{
-	char x[3];
-	char *endx;
-	long val;
-
-	x[2] = '\0';
-	strncpy(x, s + *i, 2);
-
-	val = strtol(x, &endx, 16);
-	if (!(endx  > x))
-		die("\\x used with no following hex digits\n");
-
-	(*i) += endx - x;
-	return val;
-}
-
 struct data data_copy_escape_string(const char *s, int len)
 {
 	int i = 0;
@@ -114,53 +80,10 @@ struct data data_copy_escape_string(const char *s, int len)
 	while (i < len) {
 		char c = s[i++];
 
-		if (c != '\\') {
-			q[d.len++] = c;
-			continue;
-		}
-
-		c = s[i++];
-		assert(c);
-		switch (c) {
-		case 'a':
-			q[d.len++] = '\a';
-			break;
-		case 'b':
-			q[d.len++] = '\b';
-			break;
-		case 't':
-			q[d.len++] = '\t';
-			break;
-		case 'n':
-			q[d.len++] = '\n';
-			break;
-		case 'v':
-			q[d.len++] = '\v';
-			break;
-		case 'f':
-			q[d.len++] = '\f';
-			break;
-		case 'r':
-			q[d.len++] = '\r';
-			break;
-		case '0':
-		case '1':
-		case '2':
-		case '3':
-		case '4':
-		case '5':
-		case '6':
-		case '7':
-			i--; /* need to re-read the first digit as
-			      * part of the octal value */
-			q[d.len++] = get_oct_char(s, &i);
-			break;
-		case 'x':
-			q[d.len++] = get_hex_char(s, &i);
-			break;
-		default:
-			q[d.len++] = c;
-		}
+		if (c == '\\')
+			c = get_escape_char(s, &i);
+
+		q[d.len++] = c;
 	}
 
 	q[d.len++] = '\0';
diff --git a/util.c b/util.c
index 994436f..6d07292 100644
--- a/util.c
+++ b/util.c
@@ -25,6 +25,7 @@
 #include <stdlib.h>
 #include <stdarg.h>
 #include <string.h>
+#include <assert.h>
 
 #include "util.h"
 
@@ -85,3 +86,101 @@ int util_is_printable_string(const void *data, int len)
 
 	return 1;
 }
+
+/*
+ * Parse a octal encoded character starting at index i in string s.  The
+ * resulting character will be returned and the index i will be updated to
+ * point at the character directly after the end of the encoding, this may be
+ * the '\0' terminator of the string.
+ */
+static char get_oct_char(const char *s, int *i)
+{
+	char x[4];
+	char *endx;
+	long val;
+
+	x[3] = '\0';
+	strncpy(x, s + *i, 3);
+
+	val = strtol(x, &endx, 8);
+
+	assert(endx > x);
+
+	(*i) += endx - x;
+	return val;
+}
+
+/*
+ * Parse a hexadecimal encoded character starting at index i in string s.  The
+ * resulting character will be returned and the index i will be updated to
+ * point at the character directly after the end of the encoding, this may be
+ * the '\0' terminator of the string.
+ */
+static char get_hex_char(const char *s, int *i)
+{
+	char x[3];
+	char *endx;
+	long val;
+
+	x[2] = '\0';
+	strncpy(x, s + *i, 2);
+
+	val = strtol(x, &endx, 16);
+	if (!(endx  > x))
+		die("\\x used with no following hex digits\n");
+
+	(*i) += endx - x;
+	return val;
+}
+
+char get_escape_char(const char *s, int *i)
+{
+	char	c = s[*i];
+	int	j = *i + 1;
+	char	val;
+
+	assert(c);
+	switch (c) {
+	case 'a':
+		val = '\a';
+		break;
+	case 'b':
+		val = '\b';
+		break;
+	case 't':
+		val = '\t';
+		break;
+	case 'n':
+		val = '\n';
+		break;
+	case 'v':
+		val = '\v';
+		break;
+	case 'f':
+		val = '\f';
+		break;
+	case 'r':
+		val = '\r';
+		break;
+	case '0':
+	case '1':
+	case '2':
+	case '3':
+	case '4':
+	case '5':
+	case '6':
+	case '7':
+		j--; /* need to re-read the first digit as
+		      * part of the octal value */
+		val = get_oct_char(s, &j);
+		break;
+	case 'x':
+		val = get_hex_char(s, &j);
+		break;
+	default:
+		val = c;
+	}
+
+	(*i) = j;
+	return val;
+}
diff --git a/util.h b/util.h
index cc68933..f251480 100644
--- a/util.h
+++ b/util.h
@@ -64,4 +64,12 @@ extern char *join_path(const char *path, const char *name);
  * @return 1 if a valid printable string, 0 if not */
 int util_is_printable_string(const void *data, int len);
 
+/*
+ * Parse an escaped character starting at index i in string s.  The resulting
+ * character will be returned and the index i will be updated to point at the
+ * character directly after the end of the encoding, this may be the '\0'
+ * terminator of the string.
+ */
+char get_escape_char(const char *s, int *i);
+
 #endif /* _UTIL_H */

commit 83df28bd39979b32a75656cac291c36dbd4e5497
Author: David Gibson <david@gibson.dropbear.id.au>
Date:   Mon Sep 12 11:18:43 2011 +1000

    dtc: Remove gcc 4.6 "set but not used" warnings
    
    A number of the dtc testcases trigger the new "variable set but not
    used" warning from gcc 4.6.  That is they have variables which are
    assigned, but then never read after that point.
    
    In a couple of cases this is just because the variables aren't needed,
    so this patch removes them.  In subnode_offset.c, it's because one
    pair of variables we clearly intended to test we don't actually test.
    This patch also adds this missing check.
    
    This patch makes the testsuite compile clean with gcc 4.6.
    
    Signed-off-by: David Gibson <david@gibson.dropbear.id.au>

diff --git a/tests/notfound.c b/tests/notfound.c
index 38918ad..4d55b88 100644
--- a/tests/notfound.c
+++ b/tests/notfound.c
@@ -37,27 +37,25 @@ static void check_error(const char *s, int err)
 
 int main(int argc, char *argv[])
 {
-	const struct fdt_property *prop;
 	void *fdt;
 	int offset;
 	int subnode1_offset;
-	const void *val;
 	int lenerr;
 
 	test_init(argc, argv);
 	fdt = load_blob_arg(argc, argv);
 
-	prop = fdt_get_property(fdt, 0, "nonexistant-property", &lenerr);
+	fdt_get_property(fdt, 0, "nonexistant-property", &lenerr);
 	check_error("fdt_get_property(\"nonexistant-property\")", lenerr);
 
-	val = fdt_getprop(fdt, 0, "nonexistant-property", &lenerr);
+	fdt_getprop(fdt, 0, "nonexistant-property", &lenerr);
 	check_error("fdt_getprop(\"nonexistant-property\"", lenerr);
 
 	subnode1_offset = fdt_subnode_offset(fdt, 0, "subnode@1");
 	if (subnode1_offset < 0)
 		FAIL("Couldn't find subnode1: %s", fdt_strerror(subnode1_offset));
 
-	val = fdt_getprop(fdt, subnode1_offset, "prop-str", &lenerr);
+	fdt_getprop(fdt, subnode1_offset, "prop-str", &lenerr);
 	check_error("fdt_getprop(\"prop-str\")", lenerr);
 
 	offset = fdt_subnode_offset(fdt, 0, "nonexistant-subnode");
diff --git a/tests/path_offset.c b/tests/path_offset.c
index bb092f1..d3e1f8e 100644
--- a/tests/path_offset.c
+++ b/tests/path_offset.c
@@ -104,5 +104,9 @@ int main(int argc, char *argv[])
 		FAIL("Mismatch between subnode_offset (%d) and path_offset (%d)",
 		     subsubnode2_offset, subsubnode2_offset_p);
 
+	if (subsubnode2_offset2 != subsubnode2_offset2_p)
+		FAIL("Mismatch between subnode_offset (%d) and path_offset (%d)",
+		     subsubnode2_offset2, subsubnode2_offset2_p);
+
 	PASS();
 }
diff --git a/tests/subnode_offset.c b/tests/subnode_offset.c
index b961070..e58c192 100644
--- a/tests/subnode_offset.c
+++ b/tests/subnode_offset.c
@@ -60,7 +60,7 @@ int main(int argc, char *argv[])
 	void *fdt;
 	int subnode1_offset, subnode2_offset;
 	int subsubnode1_offset, subsubnode2_offset, subsubnode2_offset2;
-	int ss11_off, ss12_off, ss21_off, ss22_off;
+	int ss12_off, ss21_off;
 
 	test_init(argc, argv);
 	fdt = load_blob_arg(argc, argv);
@@ -85,7 +85,7 @@ int main(int argc, char *argv[])
 	if (subsubnode2_offset != subsubnode2_offset2)
 		FAIL("Different offsets with and without unit address");
 
-	ss11_off = check_subnode(fdt, subnode1_offset, "ss1");
+	check_subnode(fdt, subnode1_offset, "ss1");
 	ss21_off = fdt_subnode_offset(fdt, subnode2_offset, "ss1");
 	if (ss21_off != -FDT_ERR_NOTFOUND)
 		FAIL("Incorrectly found ss1 in subnode2");
@@ -93,7 +93,7 @@ int main(int argc, char *argv[])
 	ss12_off = fdt_subnode_offset(fdt, subnode1_offset, "ss2");
 	if (ss12_off != -FDT_ERR_NOTFOUND)
 		FAIL("Incorrectly found ss2 in subnode1");
-	ss22_off = check_subnode(fdt, subnode2_offset, "ss2");
+	check_subnode(fdt, subnode2_offset, "ss2");
 
 	PASS();
 }

commit a4ea2fa9518ff0f4d7f4a08647599a727faac2e0
Author: Anton Staaf <robotboy@chromium.org>
Date:   Fri Sep 9 12:16:30 2011 -0700

    dtc: Support character literals in cell lists
    
    With this patch the following property assignment:
    
        property = <0x12345678 'a' '\r' 100>;
    
    is equivalent to:
    
        property = <0x12345678 0x00000061 0x0000000D 0x00000064>
    
    Signed-off-by: Anton Staaf <robotboy@chromium.org>
    Acked-by: David Gibson <david@gibson.dropbear.id.au>

diff --git a/Documentation/dts-format.txt b/Documentation/dts-format.txt
index a655b87..eae8b76 100644
--- a/Documentation/dts-format.txt
+++ b/Documentation/dts-format.txt
@@ -33,7 +33,7 @@ Property values may be defined as an array of 32-bit integer cells, as
 NUL-terminated strings, as bytestrings or a combination of these.
 
 * Arrays of cells are represented by angle brackets surrounding a
-  space separated list of C-style integers
+  space separated list of C-style integers or character literals.
 
 	e.g. interrupts = <17 0xc>;
 
diff --git a/dtc-lexer.l b/dtc-lexer.l
index e866ea5..494e342 100644
--- a/dtc-lexer.l
+++ b/dtc-lexer.l
@@ -29,6 +29,7 @@ PROPNODECHAR	[a-zA-Z0-9,._+*#?@-]
 PATHCHAR	({PROPNODECHAR}|[/])
 LABEL		[a-zA-Z_][a-zA-Z0-9_]*
 STRING		\"([^\\"]|\\.)*\"
+CHAR_LITERAL	'([^']|\\')*'
 WS		[[:space:]]
 COMMENT		"/*"([^*]|\*+[^*/])*\*+"/"
 LINECOMMENT	"//".*\n
@@ -109,6 +110,13 @@ static int pop_input_file(void);
 			return DT_LITERAL;
 		}
 
+<*>{CHAR_LITERAL}	{
+			yytext[yyleng-1] = '\0';
+			yylval.literal = xstrdup(yytext+1);
+			DPRINT("Character literal: %s\n", yylval.literal);
+			return DT_CHAR_LITERAL;
+		}
+
 <*>\&{LABEL}	{	/* label reference */
 			DPRINT("Ref: %s\n", yytext+1);
 			yylval.labelref = xstrdup(yytext+1);
diff --git a/dtc-parser.y b/dtc-parser.y
index 5e84a67..554f11a 100644
--- a/dtc-parser.y
+++ b/dtc-parser.y
@@ -34,6 +34,7 @@ extern struct boot_info *the_boot_info;
 extern int treesource_error;
 
 static unsigned long long eval_literal(const char *s, int base, int bits);
+static unsigned char eval_char_literal(const char *s);
 %}
 
 %union {
@@ -57,6 +58,7 @@ static unsigned long long eval_literal(const char *s, int base, int bits);
 %token DT_MEMRESERVE
 %token <propnodename> DT_PROPNODENAME
 %token <literal> DT_LITERAL
+%token <literal> DT_CHAR_LITERAL
 %token <cbase> DT_BASE
 %token <byte> DT_BYTE
 %token <data> DT_STRING
@@ -265,6 +267,10 @@ cellval:
 		{
 			$$ = eval_literal($1, 0, 32);
 		}
+	| DT_CHAR_LITERAL
+		{
+			$$ = eval_char_literal($1);
+		}
 	;
 
 bytestring:
@@ -343,3 +349,29 @@ static unsigned long long eval_literal(const char *s, int base, int bits)
 		print_error("bad literal");
 	return val;
 }
+
+static unsigned char eval_char_literal(const char *s)
+{
+	int i = 1;
+	char c = s[0];
+
+	if (c == '\0')
+	{
+		print_error("empty character literal");
+		return 0;
+	}
+
+	/*
+	 * If the first character in the character literal is a \ then process
+	 * the remaining characters as an escape encoding. If the first
+	 * character is neither an escape or a terminator it should be the only
+	 * character in the literal and will be returned.
+	 */
+	if (c == '\\')
+		c = get_escape_char(s, &i);
+
+	if (s[i] != '\0')
+		print_error("malformed character literal");
+
+	return c;
+}
diff --git a/tests/.gitignore b/tests/.gitignore
index f4e58b2..a3e9bd1 100644
--- a/tests/.gitignore
+++ b/tests/.gitignore
@@ -4,6 +4,7 @@
 /add_subnode_with_nops
 /asm_tree_dump
 /boot-cpuid
+/char_literal
 /del_node
 /del_property
 /dtbs_equal_ordered
diff --git a/tests/Makefile.tests b/tests/Makefile.tests
index c564e72..e718b63 100644
--- a/tests/Makefile.tests
+++ b/tests/Makefile.tests
@@ -5,6 +5,7 @@ LIB_TESTS_L = get_mem_rsv \
 	node_offset_by_prop_value node_offset_by_phandle \
 	node_check_compatible node_offset_by_compatible \
 	get_alias \
+	char_literal \
 	notfound \
 	setprop_inplace nop_property nop_node \
 	sw_tree1 \
diff --git a/tests/char_literal.c b/tests/char_literal.c
new file mode 100644
index 0000000..150f2a0
--- /dev/null
+++ b/tests/char_literal.c
@@ -0,0 +1,50 @@
+/*
+ * libfdt - Flat Device Tree manipulation
+ *	Testcase for character literals in dtc
+ * Copyright (C) 2006 David Gibson, IBM Corporation.
+ * Copyright (C) 2011 The Chromium Authors. All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser 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
+ */
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdint.h>
+
+#include <fdt.h>
+#include <libfdt.h>
+
+#include "tests.h"
+#include "testdata.h"
+
+int main(int argc, char *argv[])
+{
+	void *fdt;
+	uint32_t expected_cells[5];
+
+	expected_cells[0] = cpu_to_fdt32((unsigned char)TEST_CHAR1);
+	expected_cells[1] = cpu_to_fdt32((unsigned char)TEST_CHAR2);
+	expected_cells[2] = cpu_to_fdt32((unsigned char)TEST_CHAR3);
+	expected_cells[3] = cpu_to_fdt32((unsigned char)TEST_CHAR4);
+	expected_cells[4] = cpu_to_fdt32((unsigned char)TEST_CHAR5);
+
+	test_init(argc, argv);
+	fdt = load_blob_arg(argc, argv);
+
+	check_getprop(fdt, 0, "char-literal-cells",
+		      sizeof(expected_cells), expected_cells);
+
+	PASS();
+}
diff --git a/tests/char_literal.dts b/tests/char_literal.dts
new file mode 100644
index 0000000..22e17ed
--- /dev/null
+++ b/tests/char_literal.dts
@@ -0,0 +1,5 @@
+/dts-v1/;
+
+/ {
+	char-literal-cells = <'\r' 'b' '\0' '\'' '\xff'>;
+};
diff --git a/tests/run_tests.sh b/tests/run_tests.sh
index 72dda32..1246df1 100755
--- a/tests/run_tests.sh
+++ b/tests/run_tests.sh
@@ -206,6 +206,9 @@ dtc_tests () {
     run_dtc_test -I dts -O dtb -o dtc_escapes.test.dtb escapes.dts
     run_test string_escapes dtc_escapes.test.dtb
 
+    run_dtc_test -I dts -O dtb -o dtc_char_literal.test.dtb char_literal.dts
+    run_test char_literal dtc_char_literal.test.dtb
+
     run_dtc_test -I dts -O dtb -o dtc_extra-terminating-null.test.dtb extra-terminating-null.dts
     run_test extra-terminating-null dtc_extra-terminating-null.test.dtb
 
diff --git a/tests/testdata.h b/tests/testdata.h
index 5b5a9a3..d4c6759 100644
--- a/tests/testdata.h
+++ b/tests/testdata.h
@@ -19,6 +19,12 @@
 #define TEST_STRING_2	"nastystring: \a\b\t\n\v\f\r\\\""
 #define TEST_STRING_3	"\xde\xad\xbe\xef"
 
+#define TEST_CHAR1	'\r'
+#define TEST_CHAR2	'b'
+#define TEST_CHAR3	'\0'
+#define TEST_CHAR4	'\''
+#define TEST_CHAR5	'\xff'
+
 #ifndef __ASSEMBLY__
 extern struct fdt_header _test_tree1;
 extern struct fdt_header _truncated_property;

commit 9ebd9b4a56e54656431111e5ea7cd74e651910bf
Author: Simon Glass <sjg@chromium.org>
Date:   Wed Sep 21 13:32:44 2011 -0700

    Create Makefile.utils and move ftdump into it
    
    We want to avoid a separate Makefile include for each utility, so this sets
    up a general one for utilities.
    
    Acked-by: David Gibson <david@gibson.dropbear.id.au>
    Signed-off-by: Simon Glass <sjg@chromium.org>

diff --git a/Makefile b/Makefile
index 2172d9a..380a705 100644
--- a/Makefile
+++ b/Makefile
@@ -105,7 +105,7 @@ endef
 
 include Makefile.convert-dtsv0
 include Makefile.dtc
-include Makefile.ftdump
+include Makefile.utils
 
 BIN += convert-dtsv0
 BIN += dtc
diff --git a/Makefile.ftdump b/Makefile.ftdump
deleted file mode 100644
index 2744a18..0000000
--- a/Makefile.ftdump
+++ /dev/null
@@ -1,13 +0,0 @@
-#
-# This is not a complete Makefile of itself.
-# Instead, it is designed to be easily embeddable
-# into other systems of Makefiles.
-#
-
-FTDUMP_SRCS = \
-	ftdump.c \
-	util.c
-
-FTDUMP_GEN_SRCS =
-
-FTDUMP_OBJS = $(FTDUMP_SRCS:%.c=%.o) $(FTDUMP_GEN_SRCS:%.c=%.o)
diff --git a/Makefile.utils b/Makefile.utils
new file mode 100644
index 0000000..0ed9297
--- /dev/null
+++ b/Makefile.utils
@@ -0,0 +1,10 @@
+#
+# This is not a complete Makefile of itself.  Instead, it is designed to
+# be easily embeddable into other systems of Makefiles.
+#
+
+FTDUMP_SRCS = \
+	ftdump.c \
+	util.c
+
+FTDUMP_OBJS = $(FTDUMP_SRCS:%.c=%.o)

commit 36204fdf742cabc074617648a5b2cf62409dc40b
Author: Simon Glass <sjg@chromium.org>
Date:   Thu Sep 22 10:11:02 2011 -0700

    Add fdt read/write utility functions
    
    This adds higher-level libfdt operations for reading/writing an fdt
    blob from/to a file, as well as a function to decode a data type string
    as will be used by fdtget, fdtput.
    
    This also adds a few tests for the simple type argument supported by
    utilfdt_decode_type.
    
    Signed-off-by: Simon Glass <sjg@chromium.org>
    Acked-by: David Gibson <david@gibson.dropbear.id.au>

diff --git a/Makefile b/Makefile
index 380a705..b32409b 100644
--- a/Makefile
+++ b/Makefile
@@ -15,7 +15,7 @@ EXTRAVERSION =
 LOCAL_VERSION =
 CONFIG_LOCALVERSION =
 
-CPPFLAGS = -I libfdt
+CPPFLAGS = -I libfdt -I .
 WARNINGS = -Werror -Wall -Wpointer-arith -Wcast-qual -Wnested-externs \
 	-Wstrict-prototypes -Wmissing-prototypes -Wredundant-decls
 CFLAGS = -g -Os -fPIC -Werror $(WARNINGS)
diff --git a/tests/Makefile.tests b/tests/Makefile.tests
index e718b63..41695df 100644
--- a/tests/Makefile.tests
+++ b/tests/Makefile.tests
@@ -16,7 +16,8 @@ LIB_TESTS_L = get_mem_rsv \
 	extra-terminating-null \
 	dtbs_equal_ordered \
 	dtb_reverse dtbs_equal_unordered \
-	add_subnode_with_nops path_offset_aliases
+	add_subnode_with_nops path_offset_aliases \
+	utilfdt_test
 LIB_TESTS = $(LIB_TESTS_L:%=$(TESTS_PREFIX)%)
 
 LIBTREE_TESTS_L = truncated_property
@@ -42,7 +43,7 @@ TESTS_CLEANFILES = $(TESTS) $(TESTS_CLEANFILES_L:%=$(TESTS_PREFIX)%)
 .PHONY: tests
 tests:	$(TESTS) $(TESTS_TREES)
 
-$(LIB_TESTS): %: $(TESTS_PREFIX)testutils.o $(LIBFDT_archive)
+$(LIB_TESTS): %: $(TESTS_PREFIX)testutils.o util.o $(LIBFDT_archive)
 
 $(DL_LIB_TESTS): %: %.o $(TESTS_PREFIX)testutils.o $(LIBFDT_archive)
 	@$(VECHO) LD [libdl] $@
diff --git a/tests/run_tests.sh b/tests/run_tests.sh
index 1246df1..e2c3046 100755
--- a/tests/run_tests.sh
+++ b/tests/run_tests.sh
@@ -391,6 +391,10 @@ dtbs_equal_tests () {
     cmp_tests test_tree1.dtb $WRONG_TREE1
 }
 
+utilfdt_tests () {
+    run_test utilfdt_test
+}
+
 while getopts "vt:m" ARG ; do
     case $ARG in
 	"v")
@@ -406,7 +410,7 @@ while getopts "vt:m" ARG ; do
 done
 
 if [ -z "$TESTSETS" ]; then
-    TESTSETS="libfdt dtc dtbs_equal"
+    TESTSETS="libfdt utilfdt dtc dtbs_equal"
 fi
 
 # Make sure we don't have stale blobs lying around
@@ -417,6 +421,9 @@ for set in $TESTSETS; do
 	"libfdt")
 	    libfdt_tests
 	    ;;
+	"utilfdt")
+	    utilfdt_tests
+	    ;;
 	"dtc")
 	    dtc_tests
 	    ;;
diff --git a/tests/tests.h b/tests/tests.h
index fcb2b2a..a51556d 100644
--- a/tests/tests.h
+++ b/tests/tests.h
@@ -93,22 +93,6 @@ void cleanup(void);
 		exit(RC_BUG);				\
 	} while (0)
 
-static inline void *xmalloc(size_t size)
-{
-	void *p = malloc(size);
-	if (! p)
-		FAIL("malloc() failure");
-	return p;
-}
-
-static inline void *xrealloc(void *p, size_t size)
-{
-	p = realloc(p, size);
-	if (! p)
-		FAIL("realloc() failure");
-	return p;
-}
-
 void check_mem_rsv(void *fdt, int n, uint64_t addr, uint64_t size);
 
 void check_property(void *fdt, int nodeoffset, const char *name,
@@ -135,4 +119,6 @@ void *load_blob_arg(int argc, char *argv[]);
 void save_blob(const char *filename, void *blob);
 void *open_blob_rw(void *blob);
 
+#include "util.h"
+
 #endif /* _TESTS_H */
diff --git a/tests/utilfdt_test.c b/tests/utilfdt_test.c
new file mode 100644
index 0000000..36b4aa5
--- /dev/null
+++ b/tests/utilfdt_test.c
@@ -0,0 +1,128 @@
+/*
+ * Copyright 2011 The Chromium Authors, All Rights Reserved.
+ *
+ * utilfdt_test - Tests for utilfdt library
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser 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
+ */
+#include <assert.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdint.h>
+#include <stdarg.h>
+
+#include <fdt.h>
+#include <libfdt.h>
+#include <util.h>
+
+#include "tests.h"
+#include "testdata.h"
+
+static void check(const char *fmt, int expect_type, int expect_size)
+{
+	int type;
+	int size;
+
+	if (utilfdt_decode_type(fmt, &type, &size))
+		FAIL("format '%s': valid format string returned failure", fmt);
+	if (expect_type != type)
+		FAIL("format '%s': expected type='%c', got type='%c'", fmt,
+		     expect_type, type);
+	if (expect_size != size)
+		FAIL("format '%s': expected size=%d, got size=%d", fmt,
+		     expect_size, size);
+}
+
+static void checkfail(const char *fmt)
+{
+	int type;
+	int size;
+
+	if (!utilfdt_decode_type(fmt, &type, &size))
+		FAIL("format '%s': invalid format string returned success",
+		     fmt);
+}
+
+/**
+ * Add the given modifier to each of the valid sizes, and check that we get
+ * correct values.
+ *
+ * \param modifier	Modifer string to use as a prefix
+ * \param expected_size	The size (in bytes) that we expect (ignored for
+ *			strings)
+ */
+static void check_sizes(char *modifier, int expected_size)
+{
+	char fmt[10], *ptr;
+
+	/* set up a string with a hole in it for the format character */
+	if (strlen(modifier) + 2 >= sizeof(fmt))
+		FAIL("modifier string '%s' too long", modifier);
+	strcpy(fmt, modifier);
+	ptr = fmt + strlen(fmt);
+	ptr[1] = '\0';
+
+	/* now try each format character in turn */
+	*ptr = 'i';
+	check(fmt, 'i', expected_size);
+
+	*ptr = 'u';
+	check(fmt, 'u', expected_size);
+
+	*ptr = 'x';
+	check(fmt, 'x', expected_size);
+
+	*ptr = 's';
+	check(fmt, 's', -1);
+}
+
+static void test_utilfdt_decode_type(void)
+{
+	char fmt[10];
+	int ch;
+
+	/* check all the valid modifiers and sizes */
+	check_sizes("", -1);
+	check_sizes("b", 1);
+	check_sizes("hh", 1);
+	check_sizes("h", 2);
+	check_sizes("l", 4);
+
+	/* try every other character */
+	checkfail("");
+	for (ch = ' '; ch < 127; ch++) {
+		if (!strchr("iuxs", ch)) {
+			*fmt = ch;
+			fmt[1] = '\0';
+			checkfail(fmt);
+		}
+	}
+
+	/* try a few modifiers at the end */
+	checkfail("sx");
+	checkfail("ihh");
+	checkfail("xb");
+
+	/* and one for the doomsday archives */
+	checkfail("He has all the virtues I dislike and none of the vices "
+			"I admire.");
+}
+
+int main(int argc, char *argv[])
+{
+	test_utilfdt_decode_type();
+	PASS();
+}
diff --git a/util.c b/util.c
index 6d07292..d82d41f 100644
--- a/util.c
+++ b/util.c
@@ -1,4 +1,5 @@
 /*
+ * Copyright 2011 The Chromium Authors, All Rights Reserved.
  * Copyright 2008 Jon Loeliger, Freescale Semiconductor, Inc.
  *
  * util_is_printable_string contributed by
@@ -27,6 +28,11 @@
 #include <string.h>
 #include <assert.h>
 
+#include <errno.h>
+#include <fcntl.h>
+#include <unistd.h>
+
+#include "libfdt.h"
 #include "util.h"
 
 char *xstrdup(const char *s)
@@ -184,3 +190,139 @@ char get_escape_char(const char *s, int *i)
 	(*i) = j;
 	return val;
 }
+
+int utilfdt_read_err(const char *filename, char **buffp)
+{
+	int fd = 0;	/* assume stdin */
+	char *buf = NULL;
+	off_t bufsize = 1024, offset = 0;
+	int ret = 0;
+
+	*buffp = NULL;
+	if (strcmp(filename, "-") != 0) {
+		fd = open(filename, O_RDONLY);
+		if (fd < 0)
+			return errno;
+	}
+
+	/* Loop until we have read everything */
+	buf = malloc(bufsize);
+	do {
+		/* Expand the buffer to hold the next chunk */
+		if (offset == bufsize) {
+			bufsize *= 2;
+			buf = realloc(buf, bufsize);
+			if (!buf) {
+				ret = ENOMEM;
+				break;
+			}
+		}
+
+		ret = read(fd, &buf[offset], bufsize - offset);
+		if (ret < 0) {
+			ret = errno;
+			break;
+		}
+		offset += ret;
+	} while (ret != 0);
+
+	/* Clean up, including closing stdin; return errno on error */
+	close(fd);
+	if (ret)
+		free(buf);
+	else
+		*buffp = buf;
+	return ret;
+}
+
+char *utilfdt_read(const char *filename)
+{
+	char *buff;
+	int ret = utilfdt_read_err(filename, &buff);
+
+	if (ret) {
+		fprintf(stderr, "Couldn't open blob from '%s': %s\n", filename,
+			strerror(ret));
+		return NULL;
+	}
+	/* Successful read */
+	return buff;
+}
+
+int utilfdt_write_err(const char *filename, const void *blob)
+{
+	int fd = 1;	/* assume stdout */
+	int totalsize;
+	int offset;
+	int ret = 0;
+	const char *ptr = blob;
+
+	if (strcmp(filename, "-") != 0) {
+		fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC, 0666);
+		if (fd < 0)
+			return errno;
+	}
+
+	totalsize = fdt_totalsize(blob);
+	offset = 0;
+
+	while (offset < totalsize) {
+		ret = write(fd, ptr + offset, totalsize - offset);
+		if (ret < 0) {
+			ret = -errno;
+			break;
+		}
+		offset += ret;
+	}
+	/* Close the file/stdin; return errno on error */
+	if (fd != 1)
+		close(fd);
+	return ret < 0 ? -ret : 0;
+}
+
+
+int utilfdt_write(const char *filename, const void *blob)
+{
+	int ret = utilfdt_write_err(filename, blob);
+
+	if (ret) {
+		fprintf(stderr, "Couldn't write blob to '%s': %s\n", filename,
+			strerror(ret));
+	}
+	return ret ? -1 : 0;
+}
+
+int utilfdt_decode_type(const char *fmt, int *type, int *size)
+{
+	int qualifier = 0;
+
+	/* get the conversion qualifier */
+	*size = -1;
+	if (strchr("hlLb", *fmt)) {
+		qualifier = *fmt++;
+		if (qualifier == *fmt) {
+			switch (*fmt++) {
+/* TODO:		case 'l': qualifier = 'L'; break;*/
+			case 'h':
+				qualifier = 'b';
+				break;
+			}
+		}
+	}
+
+	/* we should now have a type */
+	if (!strchr("iuxs", *fmt))
+		return -1;
+
+	/* convert qualifier (bhL) to byte size */
+	if (*fmt != 's')
+		*size = qualifier == 'b' ? 1 :
+				qualifier == 'h' ? 2 :
+				qualifier == 'l' ? 4 : -1;
+	*type = *fmt++;
+
+	/* that should be it! */
+	if (*fmt)
+		return -1;
+	return 0;
+}
diff --git a/util.h b/util.h
index f251480..730918e 100644
--- a/util.h
+++ b/util.h
@@ -4,6 +4,7 @@
 #include <stdarg.h>
 
 /*
+ * Copyright 2011 The Chromium Authors, All Rights Reserved.
  * Copyright 2008 Jon Loeliger, Freescale Semiconductor, Inc.
  *
  * This program is free software; you can redistribute it and/or
@@ -72,4 +73,71 @@ int util_is_printable_string(const void *data, int len);
  */
 char get_escape_char(const char *s, int *i);
 
+/**
+ * Read a device tree file into a buffer. This will report any errors on
+ * stderr.
+ *
+ * @param filename	The filename to read, or - for stdin
+ * @return Pointer to allocated buffer containing fdt, or NULL on error
+ */
+char *utilfdt_read(const char *filename);
+
+/**
+ * Read a device tree file into a buffer. Does not report errors, but only
+ * returns them. The value returned can be passed to strerror() to obtain
+ * an error message for the user.
+ *
+ * @param filename	The filename to read, or - for stdin
+ * @param buffp		Returns pointer to buffer containing fdt
+ * @return 0 if ok, else an errno value representing the error
+ */
+int utilfdt_read_err(const char *filename, char **buffp);
+
+
+/**
+ * Write a device tree buffer to a file. This will report any errors on
+ * stderr.
+ *
+ * @param filename	The filename to write, or - for stdout
+ * @param blob		Poiner to buffer containing fdt
+ * @return 0 if ok, -1 on error
+ */
+int utilfdt_write(const char *filename, const void *blob);
+
+/**
+ * Write a device tree buffer to a file. Does not report errors, but only
+ * returns them. The value returned can be passed to strerror() to obtain
+ * an error message for the user.
+ *
+ * @param filename	The filename to write, or - for stdout
+ * @param blob		Poiner to buffer containing fdt
+ * @return 0 if ok, else an errno value representing the error
+ */
+int utilfdt_write_err(const char *filename, const void *blob);
+
+/**
+ * Decode a data type string. The purpose of this string
+ *
+ * The string consists of an optional character followed by the type:
+ *	Modifier characters:
+ *		hh or b	1 byte
+ *		h	2 byte
+ *		l	4 byte, default
+ *
+ *	Type character:
+ *		s	string
+ *		i	signed integer
+ *		u	unsigned integer
+ *		x	hex
+ *
+ * TODO: Implement ll modifier (8 bytes)
+ * TODO: Implement o type (octal)
+ *
+ * @param fmt		Format string to process
+ * @param type		Returns type found(s/d/u/x), or 0 if none
+ * @param size		Returns size found(1,2,4,8) or 4 if none
+ * @return 0 if ok, -1 on error (no type given, or other invalid format)
+ */
+int utilfdt_decode_type(const char *fmt, int *type, int *size);
+
 #endif /* _UTIL_H */

commit 1c25c0d520dee58bfd86626a07036fe9febfebe6
Author: Simon Glass <sjg@chromium.org>
Date:   Thu Sep 22 10:11:03 2011 -0700

    Make testutils use utilfdt
    
    The load_blob() and save_blob() functions are very similar to the utilfdt
    versions. This removes the duplicated code.
    
    Signed-off-by: Simon Glass <sjg@chromium.org>
    Acked-by: David Gibson <david@gibson.dropbear.id.au>

diff --git a/tests/Makefile.tests b/tests/Makefile.tests
index 41695df..cae8390 100644
--- a/tests/Makefile.tests
+++ b/tests/Makefile.tests
@@ -45,11 +45,12 @@ tests:	$(TESTS) $(TESTS_TREES)
 
 $(LIB_TESTS): %: $(TESTS_PREFIX)testutils.o util.o $(LIBFDT_archive)
 
-$(DL_LIB_TESTS): %: %.o $(TESTS_PREFIX)testutils.o $(LIBFDT_archive)
+$(DL_LIB_TESTS): %: %.o $(TESTS_PREFIX)testutils.o util.o $(LIBFDT_archive)
 	@$(VECHO) LD [libdl] $@
 	$(LINK.c) -o $@ $^ -ldl
 
-$(LIBTREE_TESTS): %: $(TESTS_PREFIX)testutils.o $(TESTS_PREFIX)trees.o $(LIBFDT_archive)
+$(LIBTREE_TESTS): %: $(TESTS_PREFIX)testutils.o $(TESTS_PREFIX)trees.o \
+		util.o $(LIBFDT_archive)
 
 $(TESTS_PREFIX)dumptrees: $(TESTS_PREFIX)trees.o
 
diff --git a/tests/testutils.c b/tests/testutils.c
index b0a2230..f185133 100644
--- a/tests/testutils.c
+++ b/tests/testutils.c
@@ -159,33 +159,13 @@ int nodename_eq(const char *s1, const char *s2)
 
 void *load_blob(const char *filename)
 {
-	int fd;
-	int offset = 0;
-	int bufsize = 1024;
-	char *p = NULL;
-	int ret;
-
-	fd = open(filename, O_RDONLY);
-	if (fd < 0)
-		CONFIG("Couldn't open blob from \"%s\": %s", filename,
-		       strerror(errno));
-
-	p = xmalloc(bufsize);
-	do {
-		if (offset == bufsize) {
-			bufsize *= 2;
-			p = xrealloc(p, bufsize);
-		}
-
-		ret = read(fd, &p[offset], bufsize - offset);
-		if (ret < 0)
-			CONFIG("Couldn't read from \"%s\": %s", filename,
-			       strerror(errno));
-
-		offset += ret;
-	} while (ret != 0);
+	char *blob;
+	int ret = utilfdt_read_err(filename, &blob);
 
-	return p;
+	if (ret)
+		CONFIG("Couldn't open blob from \"%s\": %s", filename,
+		       strerror(ret));
+	return blob;
 }
 
 void *load_blob_arg(int argc, char *argv[])
@@ -197,28 +177,11 @@ void *load_blob_arg(int argc, char *argv[])
 
 void save_blob(const char *filename, void *fdt)
 {
-	int fd;
-	int totalsize;
-	int offset;
-	char *p;
-	int ret;
-
-	fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC, 0666);
-	if (fd < 0)
-		CONFIG("Couldn't open \"%s\" to write blob: %s", filename,
-		       strerror(errno));
-
-	totalsize = fdt_totalsize(fdt);
-	offset = 0;
-	p = fdt;
-
-	while (offset < totalsize) {
-		ret = write(fd, p + offset, totalsize - offset);
-		if (ret < 0)
-			CONFIG("Couldn't write to \"%s\": %s", filename,
-			       strerror(errno));
-		offset += ret;
-	}
+	int ret = utilfdt_write_err(filename, fdt);
+
+	if (ret)
+		CONFIG("Couldn't write blob to \"%s\": %s", filename,
+		       strerror(ret));
 }
 
 void *open_blob_rw(void *blob)

commit 07a8691fbbeb2a7e0cff85fb24435e2dc71facaf
Author: Simon Glass <sjg@chromium.org>
Date:   Thu Sep 22 10:11:04 2011 -0700

    ftdump: use utilfdt to read blob
    
    Now that we have utilfdt_read(), ftdump should use it too.
    
    Signed-off-by: Simon Glass <sjg@chromium.org>
    Acked-by: David Gibson <david@gibson.dropbear.id.au>

diff --git a/ftdump.c b/ftdump.c
index db932e3..cc55fe2 100644
--- a/ftdump.c
+++ b/ftdump.c
@@ -13,8 +13,6 @@
 
 #include "util.h"
 
-#define FTDUMP_BUF_SIZE	65536
-
 #define ALIGN(x, a)	(((x) + ((a) - 1)) & ~((a) - 1))
 #define PALIGN(p, a)	((void *)(ALIGN((unsigned long)(p), (a))))
 #define GET_CELL(p)	(p += 4, *((const uint32_t *)(p-4)))
@@ -147,40 +145,18 @@ static void dump_blob(void *blob)
 
 int main(int argc, char *argv[])
 {
-	FILE *fp;
 	char *buf;
-	int size;
 
 	if (argc < 2) {
 		fprintf(stderr, "supply input filename\n");
 		return 5;
 	}
 
-	if (strcmp(argv[1], "-") == 0) {
-		fp = stdin;
-	} else {
-		fp = fopen(argv[1], "rb");
-		if (fp == NULL) {
-			fprintf(stderr, "unable to open %s\n", argv[1]);
-			return 10;
-		}
-	}
-
-	buf = malloc(FTDUMP_BUF_SIZE);
-	if (!buf) {
-		fprintf(stderr, "Couldn't allocate %d byte buffer\n", FTDUMP_BUF_SIZE);
+	buf = utilfdt_read(argv[1]);
+	if (buf)
+		dump_blob(buf);
+	else
 		return 10;
-	}
-
-	size = fread(buf, 1, FTDUMP_BUF_SIZE, fp);
-	if (size == FTDUMP_BUF_SIZE) {
-		fprintf(stderr, "file too large (maximum is %d bytes)\n", FTDUMP_BUF_SIZE);
-		return 10;
-	}
-
-	dump_blob(buf);
-
-	fclose(fp);
 
 	return 0;
 }

commit 2cd4c8d27d6b5ea83723754da4eba5d51aa71b95
Author: Anton Staaf <robotboy@chromium.org>
Date:   Tue Oct 11 10:22:27 2011 -0700

    libfdt: Add fdt16_to_cpu utility function
    
    This utility routine will be used in the variable size cell literal
    append code.  It is a straightforward adaptation of the fdt32_to_cpu
    function.
    
    Signed-off-by: Anton Staaf <robotboy@chromium.org>
    Acked-by: David Gibson <david@gibson.dropbear.id.au>

diff --git a/libfdt/libfdt_env.h b/libfdt/libfdt_env.h
index 449bf60..da952e7 100644
--- a/libfdt/libfdt_env.h
+++ b/libfdt/libfdt_env.h
@@ -6,6 +6,12 @@
 #include <string.h>
 
 #define _B(n)	((unsigned long long)((uint8_t *)&x)[n])
+static inline uint16_t fdt16_to_cpu(uint16_t x)
+{
+	return (_B(0) << 8) | _B(1);
+}
+#define cpu_to_fdt16(x) fdt16_to_cpu(x)
+
 static inline uint32_t fdt32_to_cpu(uint32_t x)
 {
 	return (_B(0) << 24) | (_B(1) << 16) | (_B(2) << 8) | _B(3);

commit a4b515c03804dbc0eff5bbf281bd22438717e773
Author: Anton Staaf <robotboy@chromium.org>
Date:   Tue Oct 11 10:22:28 2011 -0700

    dtc: Add data_append_integer function
    
    This function deals with appending integers of various sizes (8, 16
    32, and 64 bit currently).  It handles endianess conversions.  If the
    integer will not fit in the requested number of bits of storage it
    will have it's high bits ignored.
    
    This patch also rewrites data_append_cell and data_append_addr to use
    data_append_integer.
    
    Signed-off-by: Anton Staaf <robotboy@chromium.org>
    Acked-by: David Gibson <david@gibson.dropbear.id.au>

diff --git a/data.c b/data.c
index b5f3066..4a40c5b 100644
--- a/data.c
+++ b/data.c
@@ -168,11 +168,33 @@ struct data data_merge(struct data d1, struct data d2)
 	return d;
 }
 
-struct data data_append_cell(struct data d, cell_t word)
+struct data data_append_integer(struct data d, uint64_t value, int bits)
 {
-	cell_t beword = cpu_to_fdt32(word);
-
-	return data_append_data(d, &beword, sizeof(beword));
+	uint8_t value_8;
+	uint16_t value_16;
+	uint32_t value_32;
+	uint64_t value_64;
+
+	switch (bits) {
+	case 8:
+		value_8 = value;
+		return data_append_data(d, &value_8, 1);
+
+	case 16:
+		value_16 = cpu_to_fdt16(value);
+		return data_append_data(d, &value_16, 2);
+
+	case 32:
+		value_32 = cpu_to_fdt32(value);
+		return data_append_data(d, &value_32, 4);
+
+	case 64:
+		value_64 = cpu_to_fdt64(value);
+		return data_append_data(d, &value_64, 8);
+
+	default:
+		die("Invalid literal size (%d)\n", bits);
+	}
 }
 
 struct data data_append_re(struct data d, const struct fdt_reserve_entry *re)
@@ -185,11 +207,14 @@ struct data data_append_re(struct data d, const struct fdt_reserve_entry *re)
 	return data_append_data(d, &bere, sizeof(bere));
 }
 
-struct data data_append_addr(struct data d, uint64_t addr)
+struct data data_append_cell(struct data d, cell_t word)
 {
-	uint64_t beaddr = cpu_to_fdt64(addr);
+	return data_append_integer(d, word, sizeof(word) * 8);
+}
 
-	return data_append_data(d, &beaddr, sizeof(beaddr));
+struct data data_append_addr(struct data d, uint64_t addr)
+{
+	return data_append_integer(d, addr, sizeof(addr) * 8);
 }
 
 struct data data_append_byte(struct data d, uint8_t byte)
diff --git a/dtc.h b/dtc.h
index f37c97e..7b4c65b 100644
--- a/dtc.h
+++ b/dtc.h
@@ -109,6 +109,7 @@ struct data data_insert_at_marker(struct data d, struct marker *m,
 				  const void *p, int len);
 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_addr(struct data d, uint64_t addr);
 struct data data_append_byte(struct data d, uint8_t byte);

commit 033089f29099bdfd5c2d6986cdb9fd07b16cfde0
Author: Anton Staaf <robotboy@chromium.org>
Date:   Tue Oct 11 10:22:29 2011 -0700

    dtc: Add support for variable sized elements
    
    Elements of size 8, 16, 32, and 64 bits are supported.  The new
    /bits/ syntax was selected so as to not pollute the reserved
    keyword space with uint8/uint16/... type names.
    
    With this patch the following property assignment:
    
        property = /bits/ 16 <0x1234 0x5678 0x0 0xffff>;
    
    is equivalent to:
    
        property = <0x12345678 0x0000ffff>;
    
    It is now also possible to directly specify a 64 bit literal in a
    cell list, also known as an array using:
    
        property = /bits/ 64 <0xdeadbeef00000000>;
    
    It is an error to attempt to store a literal into an element that is
    too small to hold the literal, and the compiler will generate an
    error when it detects this.  For instance:
    
        property = /bits/ 8 <256>;
    
    Will fail to compile.  It is also an error to attempt to place a
    reference in a non 32-bit element.
    
    The documentation has been changed to reflect that the cell list
    is now an array of elements that can be of sizes other than the
    default 32-bit cell size.
    
    The sized_cells test tests the creation and access of 8, 16, 32,
    and 64-bit sized elements.  It also tests that the creation of two
    properties, one with 16 bit elements and one with 32 bit elements
    result in the same property contents.
    
    Signed-off-by: Anton Staaf <robotboy@chromium.org>
    Acked-by: David Gibson <david@gibson.dropbear.id.au>

diff --git a/Documentation/dts-format.txt b/Documentation/dts-format.txt
index eae8b76..41741df 100644
--- a/Documentation/dts-format.txt
+++ b/Documentation/dts-format.txt
@@ -29,18 +29,28 @@ except for properties with empty (zero length) value which have the
 form:
 	[label:] property-name;
 
-Property values may be defined as an array of 32-bit integer cells, as
-NUL-terminated strings, as bytestrings or a combination of these.
+Property values may be defined as an array of 8, 16, 32, or 64-bit integer
+elements, as NUL-terminated strings, as bytestrings or a combination of these.
 
-* Arrays of cells are represented by angle brackets surrounding a
-  space separated list of C-style integers or character literals.
+* Arrays are represented by angle brackets surrounding a space separated list
+  of C-style integers or character literals.  Array elements default to 32-bits
+  in size.  An array of 32-bit elements is also known as a cell list or a list
+  of cells.  A cell being an unsigned 32-bit integer.
 
 	e.g. interrupts = <17 0xc>;
 
-* A 64-bit value is represented with two 32-bit cells.
+* A 64-bit value can be represented with two 32-bit elements.
 
 	e.g. clock-frequency = <0x00000001 0x00000000>;
 
+* The storage size of an element can be changed using the /bits/ prefix.  The
+  /bits/ prefix allows for the creation of 8, 16, 32, and 64-bit elements.
+  The resulting array will not be padded to a multiple of the default 32-bit
+  element size.
+
+	e.g. interrupts = /bits/ 8 <17 0xc>;
+	e.g. clock-frequency = /bits/ 64 <0x0000000100000000>;
+
 * A NUL-terminated string value is represented using double quotes
   (the property value is considered to include the terminating NUL
   character).
@@ -59,19 +69,20 @@ NUL-terminated strings, as bytestrings or a combination of these.
 	e.g. compatible = "ns16550", "ns8250";
 	     example = <0xf00f0000 19>, "a strange property format";
 
-* In a cell array a reference to another node will be expanded to that
-  node's phandle.  References may by '&' followed by a node's label:
+* In an array a reference to another node will be expanded to that node's
+  phandle.  References may by '&' followed by a node's label:
 	e.g. interrupt-parent = < &mpic >;
   or they may be '&' followed by a node's full path in braces:
 	e.g. interrupt-parent = < &{/soc/interrupt-controller@40000} >;
+  References are only permitted in arrays that have an element size of
+  32-bits.
 
-* Outside a cell array, a reference to another node will be expanded
-  to that node's full path.
+* Outside an array, a reference to another node will be expanded to that
+  node's full path.
 	e.g. ethernet0 = &EMAC0;
 
 * Labels may also appear before or after any component of a property
-  value, or between cells of a cell array, or between bytes of a
-  bytestring.
+  value, or between elements of an array, or between bytes of a bytestring.
 	e.g. reg = reglabel: <0 sizelabel: 0x1000000>;
 	e.g. prop = [ab cd ef byte4: 00 ff fe];
 	e.g. str = start: "string value" end: ;
@@ -108,3 +119,4 @@ Version 1 DTS files have the overall layout:
 
 	-- David Gibson <david@gibson.dropbear.id.au>
 	-- Yoder Stuart <stuart.yoder@freescale.com>
+	-- Anton Staaf <robotboy@chromium.org>
diff --git a/dtc-lexer.l b/dtc-lexer.l
index 494e342..73d190c 100644
--- a/dtc-lexer.l
+++ b/dtc-lexer.l
@@ -97,6 +97,12 @@ static int pop_input_file(void);
 			return DT_MEMRESERVE;
 		}
 
+<*>"/bits/"	{
+			DPRINT("Keyword: /bits/\n");
+			BEGIN_DEFAULT();
+			return DT_BITS;
+		}
+
 <*>{LABEL}:	{
 			DPRINT("Label: %s\n", yytext);
 			yylval.labelref = xstrdup(yytext);
diff --git a/dtc-parser.y b/dtc-parser.y
index 554f11a..348616b 100644
--- a/dtc-parser.y
+++ b/dtc-parser.y
@@ -45,8 +45,12 @@ static unsigned char eval_char_literal(const char *s);
 	uint8_t byte;
 	struct data data;
 
+	struct {
+		struct data	data;
+		int		bits;
+	} array;
+
 	uint64_t addr;
-	cell_t cell;
 	struct property *prop;
 	struct property *proplist;
 	struct node *node;
@@ -56,6 +60,7 @@ static unsigned char eval_char_literal(const char *s);
 
 %token DT_V1
 %token DT_MEMRESERVE
+%token DT_BITS
 %token <propnodename> DT_PROPNODENAME
 %token <literal> DT_LITERAL
 %token <literal> DT_CHAR_LITERAL
@@ -71,8 +76,7 @@ static unsigned char eval_char_literal(const char *s);
 %type <re> memreserve
 %type <re> memreserves
 %type <addr> addr
-%type <data> celllist
-%type <cell> cellval
+%type <array> arrayprefix
 %type <data> bytestring
 %type <prop> propdef
 %type <proplist> proplist
@@ -182,9 +186,9 @@ propdata:
 		{
 			$$ = data_merge($1, $2);
 		}
-	| propdataprefix '<' celllist '>'
+	| propdataprefix arrayprefix '>'
 		{
-			$$ = data_merge($1, $3);
+			$$ = data_merge($1, $2.data);
 		}
 	| propdataprefix '[' bytestring ']'
 		{
@@ -242,34 +246,56 @@ propdataprefix:
 		}
 	;
 
-celllist:
-	  /* empty */
+arrayprefix:
+	DT_BITS DT_LITERAL '<'
 		{
-			$$ = empty_data;
+			$$.data = empty_data;
+			$$.bits = eval_literal($2, 0, 7);
+
+			if (($$.bits !=  8) &&
+			    ($$.bits != 16) &&
+			    ($$.bits != 32) &&
+			    ($$.bits != 64))
+			{
+				print_error("Only 8, 16, 32 and 64-bit elements"
+					    " are currently supported");
+				$$.bits = 32;
+			}
 		}
-	| celllist cellval
+	| '<'
 		{
-			$$ = data_append_cell($1, $2);
+			$$.data = empty_data;
+			$$.bits = 32;
 		}
-	| celllist DT_REF
+	| arrayprefix DT_LITERAL
 		{
-			$$ = data_append_cell(data_add_marker($1, REF_PHANDLE,
-							      $2), -1);
+			uint64_t val = eval_literal($2, 0, $1.bits);
+
+			$$.data = data_append_integer($1.data, val, $1.bits);
 		}
-	| celllist DT_LABEL
+	| arrayprefix DT_CHAR_LITERAL
 		{
-			$$ = data_add_marker($1, LABEL, $2);
-		}
-	;
+			uint64_t val = eval_char_literal($2);
 
-cellval:
-	  DT_LITERAL
+			$$.data = data_append_integer($1.data, val, $1.bits);
+		}
+	| arrayprefix DT_REF
 		{
-			$$ = eval_literal($1, 0, 32);
+			uint64_t val = ~0ULL >> (64 - $1.bits);
+
+			if ($1.bits == 32)
+				$1.data = data_add_marker($1.data,
+							  REF_PHANDLE,
+							  $2);
+			else
+				print_error("References are only allowed in "
+					    "arrays with 32-bit elements.");
+
+			$$.data = data_append_integer($1.data, val, $1.bits);
 		}
-	| DT_CHAR_LITERAL
+	| arrayprefix DT_LABEL
 		{
-			$$ = eval_char_literal($1);
+			$$.data = data_add_marker($1.data, LABEL, $2);
 		}
 	;
 
diff --git a/tests/.gitignore b/tests/.gitignore
index a3e9bd1..9e062c3 100644
--- a/tests/.gitignore
+++ b/tests/.gitignore
@@ -40,6 +40,7 @@
 /set_name
 /setprop
 /setprop_inplace
+/sized_cells
 /string_escapes
 /subnode_offset
 /supernode_atdepth_offset
diff --git a/tests/Makefile.tests b/tests/Makefile.tests
index cae8390..215a8c5 100644
--- a/tests/Makefile.tests
+++ b/tests/Makefile.tests
@@ -6,6 +6,7 @@ LIB_TESTS_L = get_mem_rsv \
 	node_check_compatible node_offset_by_compatible \
 	get_alias \
 	char_literal \
+	sized_cells \
 	notfound \
 	setprop_inplace nop_property nop_node \
 	sw_tree1 \
diff --git a/tests/run_tests.sh b/tests/run_tests.sh
index e2c3046..da6f970 100755
--- a/tests/run_tests.sh
+++ b/tests/run_tests.sh
@@ -209,6 +209,9 @@ dtc_tests () {
     run_dtc_test -I dts -O dtb -o dtc_char_literal.test.dtb char_literal.dts
     run_test char_literal dtc_char_literal.test.dtb
 
+    run_dtc_test -I dts -O dtb -o dtc_sized_cells.test.dtb sized_cells.dts
+    run_test sized_cells dtc_sized_cells.test.dtb
+
     run_dtc_test -I dts -O dtb -o dtc_extra-terminating-null.test.dtb extra-terminating-null.dts
     run_test extra-terminating-null dtc_extra-terminating-null.test.dtb
 
diff --git a/tests/sized_cells.c b/tests/sized_cells.c
new file mode 100644
index 0000000..847ec96
--- /dev/null
+++ b/tests/sized_cells.c
@@ -0,0 +1,84 @@
+/*
+ * libfdt - Flat Device Tree manipulation
+ *	Testcase for variable sized cells in dtc
+ * Copyright (C) 2006 David Gibson, IBM Corporation.
+ * Copyright (C) 2011 The Chromium Authors. All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser 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
+ */
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdint.h>
+
+#include <fdt.h>
+#include <libfdt.h>
+
+#include "tests.h"
+#include "testdata.h"
+
+static void check_compare_properties(void *fdt,
+				     char const *name_one,
+				     char const *name_two)
+{
+	const void *propval;
+	int proplen;
+
+	propval = fdt_getprop(fdt, 0, name_one, &proplen);
+
+	if (!propval)
+		FAIL("fdt_getprop(\"%s\"): %s",
+		     name_one,
+		     fdt_strerror(proplen));
+
+	check_getprop(fdt, 0, name_two, proplen, propval);
+}
+
+int main(int argc, char *argv[])
+{
+	void *fdt;
+	uint8_t expected_8[6] = {TEST_CHAR1,
+				 TEST_CHAR2,
+				 TEST_CHAR3,
+				 TEST_CHAR4,
+				 TEST_CHAR5,
+				 TEST_VALUE_1 >> 24};
+	uint16_t expected_16[6];
+	uint32_t expected_32[6];
+	uint64_t expected_64[6];
+	int i;
+
+	for (i = 0; i < 5; ++i) {
+		expected_16[i] = cpu_to_fdt16(expected_8[i]);
+		expected_32[i] = cpu_to_fdt32(expected_8[i]);
+		expected_64[i] = cpu_to_fdt64(expected_8[i]);
+	}
+
+	expected_16[5] = cpu_to_fdt16(TEST_VALUE_1 >> 16);
+	expected_32[5] = cpu_to_fdt32(TEST_VALUE_1);
+	expected_64[5] = cpu_to_fdt64(TEST_ADDR_1);
+
+	test_init(argc, argv);
+	fdt = load_blob_arg(argc, argv);
+
+	check_getprop(fdt, 0, "cells-8b", sizeof(expected_8), expected_8);
+	check_getprop(fdt, 0, "cells-16b", sizeof(expected_16), expected_16);
+	check_getprop(fdt, 0, "cells-32b", sizeof(expected_32), expected_32);
+	check_getprop(fdt, 0, "cells-64b", sizeof(expected_64), expected_64);
+
+	check_compare_properties(fdt, "cells-one-16b", "cells-one-32b");
+
+	PASS();
+}
diff --git a/tests/sized_cells.dts b/tests/sized_cells.dts
new file mode 100644
index 0000000..efea9f5
--- /dev/null
+++ b/tests/sized_cells.dts
@@ -0,0 +1,11 @@
+/dts-v1/;
+
+/ {
+	cells-8b = /bits/ 8 <'\r' 'b' '\0' '\'' '\xff' 0xde>;
+	cells-16b = /bits/ 16 <'\r' 'b' '\0' '\'' '\xff' 0xdead>;
+	cells-32b = /bits/ 32 <'\r' 'b' '\0' '\'' '\xff' 0xdeadbeef>;
+	cells-64b = /bits/ 64 <'\r' 'b' '\0' '\'' '\xff' 0xdeadbeef00000000>;
+
+	cells-one-16b = /bits/ 16 <0x1234 0x5678 0x0 0xffff>;
+	cells-one-32b = <0x12345678 0x0000ffff>;
+};

commit 8f459c5d72673e1a3a119ac58a7eee56236fca73
Author: Mike Frysinger <vapier@gentoo.org>
Date:   Tue Oct 25 17:29:24 2011 -0400

    fdtdump: rename from ftdump
    
    The freetype package already installs a binary named "ftdump", so the dtc
    package conflicts with that.  So rename the newer dtc tool to "fdtdump".
    This even makes a bit more sense:
    	ftdump: [F]lat device [T]ree [dump]
    	fdtdump: [F]lat [D]evice [T]ree [dump]
    
    Signed-off-by: Mike Frysinger <vapier@gentoo.org>
    Acked-by: David Gibson <david@gibson.dropbear.id.au>

diff --git a/.gitignore b/.gitignore
index ae7a46a..74714cd 100644
--- a/.gitignore
+++ b/.gitignore
@@ -7,6 +7,6 @@
 lex.yy.c
 *.lex.c
 /dtc
-/ftdump
+/fdtdump
 /convert-dtsv0
 /version_gen.h
diff --git a/Documentation/manual.txt b/Documentation/manual.txt
index f8a8a7b..14508f3 100644
--- a/Documentation/manual.txt
+++ b/Documentation/manual.txt
@@ -21,7 +21,7 @@ III - libfdt
 
 IV - Utility Tools
     1) convert-dtsv0 -- Conversion to Version 1
-    1) ftdump
+    1) fdtdump
 
 
 I - "dtc", the device tree compiler
@@ -643,10 +643,10 @@ a new file with a "v1" appended the filename.
 Comments, empty lines, etc. are preserved.
 
 
-2) ftdump -- Flat Tree dumping utility
+2) fdtdump -- Flat Device Tree dumping utility
 
-The ftdump program prints a readable version of a flat device tree file.
+The fdtdump program prints a readable version of a flat device tree file.
 
-The syntax of the ftdump command line is:
+The syntax of the fdtdump command line is:
 
-    ftdump <DTB-file-name>
+    fdtdump <DTB-file-name>
diff --git a/Makefile b/Makefile
index b32409b..4582f5d 100644
--- a/Makefile
+++ b/Makefile
@@ -109,7 +109,7 @@ include Makefile.utils
 
 BIN += convert-dtsv0
 BIN += dtc
-BIN += ftdump
+BIN += fdtdump
 
 SCRIPTS = dtdiff
 
@@ -119,7 +119,7 @@ all: $(BIN) libfdt
 ifneq ($(DEPTARGETS),)
 -include $(DTC_OBJS:%.o=%.d)
 -include $(CONVERT_OBJS:%.o=%.d)
--include $(FTDUMP_OBJS:%.o=%.d)
+-include $(FDTDUMP_OBJS:%.o=%.d)
 endif
 
 
@@ -178,7 +178,7 @@ convert-dtsv0: $(CONVERT_OBJS)
 	@$(VECHO) LD $@
 	$(LINK.c) -o $@ $^
 
-ftdump:	$(FTDUMP_OBJS)
+fdtdump:	$(FDTDUMP_OBJS)
 
 
 #
diff --git a/Makefile.utils b/Makefile.utils
index 0ed9297..fae5b00 100644
--- a/Makefile.utils
+++ b/Makefile.utils
@@ -3,8 +3,8 @@
 # be easily embeddable into other systems of Makefiles.
 #
 
-FTDUMP_SRCS = \
-	ftdump.c \
+FDTDUMP_SRCS = \
+	fdtdump.c \
 	util.c
 
-FTDUMP_OBJS = $(FTDUMP_SRCS:%.c=%.o)
+FDTDUMP_OBJS = $(FDTDUMP_SRCS:%.c=%.o)
diff --git a/fdtdump.c b/fdtdump.c
new file mode 100644
index 0000000..207a46d
--- /dev/null
+++ b/fdtdump.c
@@ -0,0 +1,162 @@
+/*
+ * fdtdump.c - Contributed by Pantelis Antoniou <pantelis.antoniou AT gmail.com>
+ */
+
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+
+#include <fdt.h>
+#include <libfdt_env.h>
+
+#include "util.h"
+
+#define ALIGN(x, a)	(((x) + ((a) - 1)) & ~((a) - 1))
+#define PALIGN(p, a)	((void *)(ALIGN((unsigned long)(p), (a))))
+#define GET_CELL(p)	(p += 4, *((const uint32_t *)(p-4)))
+
+static void print_data(const char *data, int len)
+{
+	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("]");
+	}
+}
+
+static void dump_blob(void *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);
+	uint32_t off_str = fdt32_to_cpu(bph->off_dt_strings);
+	struct fdt_reserve_entry *p_rsvmap =
+		(struct fdt_reserve_entry *)((char *)blob + off_mem_rsvmap);
+	const char *p_struct = (const char *)blob + off_dt;
+	const char *p_strings = (const char *)blob + off_str;
+	uint32_t version = fdt32_to_cpu(bph->version);
+	uint32_t totalsize = fdt32_to_cpu(bph->totalsize);
+	uint32_t tag;
+	const char *p, *s, *t;
+	int depth, sz, shift;
+	int i;
+	uint64_t addr, size;
+
+	depth = 0;
+	shift = 4;
+
+	printf("/dts-v1/;\n");
+	printf("// magic:\t\t0x%x\n", fdt32_to_cpu(bph->magic));
+	printf("// totalsize:\t\t0x%x (%d)\n", totalsize, totalsize);
+	printf("// off_dt_struct:\t0x%x\n", off_dt);
+	printf("// off_dt_strings:\t0x%x\n", off_str);
+	printf("// off_mem_rsvmap:\t0x%x\n", off_mem_rsvmap);
+	printf("// version:\t\t%d\n", version);
+	printf("// last_comp_version:\t%d\n",
+	       fdt32_to_cpu(bph->last_comp_version));
+	if (version >= 2)
+		printf("// boot_cpuid_phys:\t0x%x\n",
+		       fdt32_to_cpu(bph->boot_cpuid_phys));
+
+	if (version >= 3)
+		printf("// size_dt_strings:\t0x%x\n",
+		       fdt32_to_cpu(bph->size_dt_strings));
+	if (version >= 17)
+		printf("// size_dt_struct:\t0x%x\n",
+		       fdt32_to_cpu(bph->size_dt_struct));
+	printf("\n");
+
+	for (i = 0; ; i++) {
+		addr = fdt64_to_cpu(p_rsvmap[i].address);
+		size = fdt64_to_cpu(p_rsvmap[i].size);
+		if (addr == 0 && size == 0)
+			break;
+
+		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) {
+
+		/* printf("tag: 0x%08x (%d)\n", tag, p - p_struct); */
+
+		if (tag == FDT_BEGIN_NODE) {
+			s = p;
+			p = PALIGN(p + strlen(s) + 1, 4);
+
+			if (*s == '\0')
+				s = "/";
+
+			printf("%*s%s {\n", depth * shift, "", s);
+
+			depth++;
+			continue;
+		}
+
+		if (tag == FDT_END_NODE) {
+			depth--;
+
+			printf("%*s};\n", depth * shift, "");
+			continue;
+		}
+
+		if (tag == FDT_NOP) {
+			printf("%*s// [NOP]\n", depth * shift, "");
+			continue;
+		}
+
+		if (tag != FDT_PROP) {
+			fprintf(stderr, "%*s ** Unknown tag 0x%08x\n", depth * shift, "", tag);
+			break;
+		}
+		sz = fdt32_to_cpu(GET_CELL(p));
+		s = p_strings + fdt32_to_cpu(GET_CELL(p));
+		if (version < 16 && sz >= 8)
+			p = PALIGN(p, 8);
+		t = p;
+
+		p = PALIGN(p + sz, 4);
+
+		printf("%*s%s", depth * shift, "", s);
+		print_data(t, sz);
+		printf(";\n");
+	}
+}
+
+
+int main(int argc, char *argv[])
+{
+	char *buf;
+
+	if (argc < 2) {
+		fprintf(stderr, "supply input filename\n");
+		return 5;
+	}
+
+	buf = utilfdt_read(argv[1]);
+	if (buf)
+		dump_blob(buf);
+	else
+		return 10;
+
+	return 0;
+}
diff --git a/ftdump.c b/ftdump.c
deleted file mode 100644
index cc55fe2..0000000
--- a/ftdump.c
+++ /dev/null
@@ -1,162 +0,0 @@
-/*
- * ftdump.c - Contributed by Pantelis Antoniou <pantelis.antoniou AT gmail.com>
- */
-
-#include <stdint.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <ctype.h>
-
-#include <fdt.h>
-#include <libfdt_env.h>
-
-#include "util.h"
-
-#define ALIGN(x, a)	(((x) + ((a) - 1)) & ~((a) - 1))
-#define PALIGN(p, a)	((void *)(ALIGN((unsigned long)(p), (a))))
-#define GET_CELL(p)	(p += 4, *((const uint32_t *)(p-4)))
-
-static void print_data(const char *data, int len)
-{
-	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("]");
-	}
-}
-
-static void dump_blob(void *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);
-	uint32_t off_str = fdt32_to_cpu(bph->off_dt_strings);
-	struct fdt_reserve_entry *p_rsvmap =
-		(struct fdt_reserve_entry *)((char *)blob + off_mem_rsvmap);
-	const char *p_struct = (const char *)blob + off_dt;
-	const char *p_strings = (const char *)blob + off_str;
-	uint32_t version = fdt32_to_cpu(bph->version);
-	uint32_t totalsize = fdt32_to_cpu(bph->totalsize);
-	uint32_t tag;
-	const char *p, *s, *t;
-	int depth, sz, shift;
-	int i;
-	uint64_t addr, size;
-
-	depth = 0;
-	shift = 4;
-
-	printf("/dts-v1/;\n");
-	printf("// magic:\t\t0x%x\n", fdt32_to_cpu(bph->magic));
-	printf("// totalsize:\t\t0x%x (%d)\n", totalsize, totalsize);
-	printf("// off_dt_struct:\t0x%x\n", off_dt);
-	printf("// off_dt_strings:\t0x%x\n", off_str);
-	printf("// off_mem_rsvmap:\t0x%x\n", off_mem_rsvmap);
-	printf("// version:\t\t%d\n", version);
-	printf("// last_comp_version:\t%d\n",
-	       fdt32_to_cpu(bph->last_comp_version));
-	if (version >= 2)
-		printf("// boot_cpuid_phys:\t0x%x\n",
-		       fdt32_to_cpu(bph->boot_cpuid_phys));
-
-	if (version >= 3)
-		printf("// size_dt_strings:\t0x%x\n",
-		       fdt32_to_cpu(bph->size_dt_strings));
-	if (version >= 17)
-		printf("// size_dt_struct:\t0x%x\n",
-		       fdt32_to_cpu(bph->size_dt_struct));
-	printf("\n");
-
-	for (i = 0; ; i++) {
-		addr = fdt64_to_cpu(p_rsvmap[i].address);
-		size = fdt64_to_cpu(p_rsvmap[i].size);
-		if (addr == 0 && size == 0)
-			break;
-
-		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) {
-
-		/* printf("tag: 0x%08x (%d)\n", tag, p - p_struct); */
-
-		if (tag == FDT_BEGIN_NODE) {
-			s = p;
-			p = PALIGN(p + strlen(s) + 1, 4);
-
-			if (*s == '\0')
-				s = "/";
-
-			printf("%*s%s {\n", depth * shift, "", s);
-
-			depth++;
-			continue;
-		}
-
-		if (tag == FDT_END_NODE) {
-			depth--;
-
-			printf("%*s};\n", depth * shift, "");
-			continue;
-		}
-
-		if (tag == FDT_NOP) {
-			printf("%*s// [NOP]\n", depth * shift, "");
-			continue;
-		}
-
-		if (tag != FDT_PROP) {
-			fprintf(stderr, "%*s ** Unknown tag 0x%08x\n", depth * shift, "", tag);
-			break;
-		}
-		sz = fdt32_to_cpu(GET_CELL(p));
-		s = p_strings + fdt32_to_cpu(GET_CELL(p));
-		if (version < 16 && sz >= 8)
-			p = PALIGN(p, 8);
-		t = p;
-
-		p = PALIGN(p + sz, 4);
-
-		printf("%*s%s", depth * shift, "", s);
-		print_data(t, sz);
-		printf(";\n");
-	}
-}
-
-
-int main(int argc, char *argv[])
-{
-	char *buf;
-
-	if (argc < 2) {
-		fprintf(stderr, "supply input filename\n");
-		return 5;
-	}
-
-	buf = utilfdt_read(argv[1]);
-	if (buf)
-		dump_blob(buf);
-	else
-		return 10;
-
-	return 0;
-}

commit a31e3ef83bfce62d07695355e5f06cd4d0e44b86
Author: Minghuan Lian <Minghuan.Lian@freescale.com>
Date:   Mon Dec 5 12:22:07 2011 +1100

    libfdt: Add support for appending the values to a existing property
    
    Some properties may contain multiple values, these values may need
    to be added to the property respectively. this patch provides this
    functionality. The main purpose of fdt_append_prop() is to append
    the values to a existing property, or create a new property if it
    dose not exist.
    
    Signed-off-by: Minghuan Lian <Minghuan.Lian@freescale.com>
    Signed-off-by: David Gibson <david@gibson.dropbear.id.au>

diff --git a/libfdt/fdt_rw.c b/libfdt/fdt_rw.c
index 994037b..24437df 100644
--- a/libfdt/fdt_rw.c
+++ b/libfdt/fdt_rw.c
@@ -289,6 +289,33 @@ int fdt_setprop(void *fdt, int nodeoffset, const char *name,
 	return 0;
 }
 
+int fdt_appendprop(void *fdt, int nodeoffset, const char *name,
+		   const void *val, int len)
+{
+	struct fdt_property *prop;
+	int err, oldlen, newlen;
+
+	FDT_RW_CHECK_HEADER(fdt);
+
+	prop = fdt_get_property_w(fdt, nodeoffset, name, &oldlen);
+	if (prop) {
+		newlen = len + oldlen;
+		err = _fdt_splice_struct(fdt, prop->data,
+					 FDT_TAGALIGN(oldlen),
+					 FDT_TAGALIGN(newlen));
+		if (err)
+			return err;
+		prop->len = cpu_to_fdt32(newlen);
+		memcpy(prop->data + oldlen, val, len);
+	} else {
+		err = _fdt_add_property(fdt, nodeoffset, name, len, &prop);
+		if (err)
+			return err;
+		memcpy(prop->data, val, len);
+	}
+	return 0;
+}
+
 int fdt_delprop(void *fdt, int nodeoffset, const char *name)
 {
 	struct fdt_property *prop;
diff --git a/libfdt/libfdt.h b/libfdt/libfdt.h
index 55f3eb3..060479e 100644
--- a/libfdt/libfdt.h
+++ b/libfdt/libfdt.h
@@ -1134,6 +1134,101 @@ static inline int fdt_setprop_cell(void *fdt, int nodeoffset, const char *name,
 	fdt_setprop((fdt), (nodeoffset), (name), (str), strlen(str)+1)
 
 /**
+ * fdt_appendprop - append to or create a property
+ * @fdt: pointer to the device tree blob
+ * @nodeoffset: offset of the node whose property to change
+ * @name: name of the property to append to
+ * @val: pointer to data to append to the property value
+ * @len: length of the data to append to the property value
+ *
+ * fdt_appendprop() appends the value to the named property in the
+ * given node, creating the property if it does not already exist.
+ *
+ * This function may insert data into 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_appendprop(void *fdt, int nodeoffset, const char *name,
+		   const void *val, int len);
+
+/**
+ * fdt_appendprop_cell - append a single cell value to a property
+ * @fdt: pointer to the device tree blob
+ * @nodeoffset: offset of the node whose property to change
+ * @name: name of the property to change
+ * @val: 32-bit integer value to append to the property (native endian)
+ *
+ * fdt_appendprop_cell() appends the given cell value (converting to
+ * big-endian if necessary) to the value of the named property in the
+ * given node, or creates a new property with that value if it does
+ * not already exist.
+ *
+ * This function may insert data into 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
+ */
+static inline int fdt_appendprop_cell(void *fdt, int nodeoffset,
+				      const char *name, uint32_t val)
+{
+	val = cpu_to_fdt32(val);
+	return fdt_appendprop(fdt, nodeoffset, name, &val, sizeof(val));
+}
+
+/**
+ * fdt_appendprop_string - append a string to a property
+ * @fdt: pointer to the device tree blob
+ * @nodeoffset: offset of the node whose property to change
+ * @name: name of the property to change
+ * @str: string value to append to the property
+ *
+ * fdt_appendprop_string() appends the given string to the value of
+ * the named property in the given node, or creates a new property
+ * with that value if it does not already exist.
+ *
+ * This function may insert data into 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_appendprop_string(fdt, nodeoffset, name, str) \
+	fdt_appendprop((fdt), (nodeoffset), (name), (str), strlen(str)+1)
+
+/**
  * fdt_delprop - delete a property
  * @fdt: pointer to the device tree blob
  * @nodeoffset: offset of the node whose property to nop
diff --git a/tests/appendprop.dts b/tests/appendprop.dts
new file mode 100644
index 0000000..6e3a3eb
--- /dev/null
+++ b/tests/appendprop.dts
@@ -0,0 +1,7 @@
+/dts-v1/;
+
+/ {
+	prop-str = "hello world", "nastystring: \a\b\t\n\v\f\r\\\"";
+	prop-int = <0xdeadbeef 123456789>;
+	prop-bytes = [00010203040001020304];
+};
diff --git a/tests/appendprop1.c b/tests/appendprop1.c
new file mode 100644
index 0000000..180d296
--- /dev/null
+++ b/tests/appendprop1.c
@@ -0,0 +1,70 @@
+/*
+ * libfdt - Flat Device Tree manipulation
+ *	Testcase for fdt_appendprop()
+ * Copyright (C) 2006 David Gibson, IBM Corporation.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser 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
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <ctype.h>
+#include <stdint.h>
+
+#include <fdt.h>
+#include <libfdt.h>
+
+#include "tests.h"
+#include "testdata.h"
+
+#define SPACE		65536
+
+#define CHECK(code) \
+	{ \
+		err = (code); \
+		if (err) \
+			FAIL(#code ": %s", fdt_strerror(err)); \
+	}
+
+int main(int argc, char *argv[])
+{
+	void *fdt;
+	int err;
+	uint8_t bytes[] = {0x00, 0x01, 0x02, 0x03, 0x04};
+
+	test_init(argc, argv);
+
+	/* Create an empty tree first */
+	fdt = xmalloc(SPACE);
+	CHECK(fdt_create(fdt, SPACE));
+	CHECK(fdt_finish_reservemap(fdt));
+	CHECK(fdt_begin_node(fdt, ""));
+	CHECK(fdt_end_node(fdt));
+	CHECK(fdt_finish(fdt));
+
+	/* Now use appendprop to add properties */
+	CHECK(fdt_open_into(fdt, fdt, SPACE));
+
+	CHECK(fdt_appendprop(fdt, 0, "prop-bytes", bytes, sizeof(bytes)));
+	CHECK(fdt_appendprop_cell(fdt, 0, "prop-int", TEST_VALUE_1));
+	CHECK(fdt_appendprop_string(fdt, 0, "prop-str", TEST_STRING_1));
+
+	CHECK(fdt_pack(fdt));
+
+	save_blob("appendprop1.test.dtb", fdt);
+
+	PASS();
+}
diff --git a/tests/appendprop2.c b/tests/appendprop2.c
new file mode 100644
index 0000000..d651a89
--- /dev/null
+++ b/tests/appendprop2.c
@@ -0,0 +1,64 @@
+/*
+ * libfdt - Flat Device Tree manipulation
+ *	Testcase for fdt_appendprop()
+ * Copyright (C) 2006 David Gibson, IBM Corporation.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser 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
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <ctype.h>
+#include <stdint.h>
+
+#include <fdt.h>
+#include <libfdt.h>
+
+#include "tests.h"
+#include "testdata.h"
+
+#define SPACE		65536
+
+#define CHECK(code) \
+	{ \
+		err = (code); \
+		if (err) \
+			FAIL(#code ": %s", fdt_strerror(err)); \
+	}
+
+int main(int argc, char *argv[])
+{
+	void *fdt, *buf;
+	int err;
+	uint8_t bytes[] = {0x00, 0x01, 0x02, 0x03, 0x04};
+
+	test_init(argc, argv);
+	fdt = load_blob_arg(argc, argv);
+
+	buf = xmalloc(SPACE);
+	CHECK(fdt_open_into(fdt, buf, SPACE));
+	fdt = buf;
+
+	CHECK(fdt_appendprop(fdt, 0, "prop-bytes", bytes, sizeof(bytes)));
+	CHECK(fdt_appendprop_cell(fdt, 0, "prop-int", TEST_VALUE_2));
+	CHECK(fdt_appendprop_string(fdt, 0, "prop-str", TEST_STRING_2));
+
+	CHECK(fdt_pack(fdt));
+
+	save_blob("appendprop2.test.dtb", fdt);
+
+	PASS();
+}

commit 97b909f852039daaae267a66f5df2c90ed05b586
Author: David Gibson <david@gibson.dropbear.id.au>
Date:   Wed Jan 11 23:41:32 2012 +1100

    libfdt: Activate testcase for appending properties
    
    Commit a31e3ef83bfce62d07695355e5f06cd4d0e44b86 introduced new libfdt
    functions to append to existing properties.  It also included a test case
    for this, but neglected to update the Makefile and run_tests.sh script
    to actually build and execute this testcase.
    
    This patch corrects the oversight.
    
    Signed-off-by: David Gibson <david@gibson.dropbear.id.au>

diff --git a/tests/Makefile.tests b/tests/Makefile.tests
index 215a8c5..3f92074 100644
--- a/tests/Makefile.tests
+++ b/tests/Makefile.tests
@@ -12,6 +12,7 @@ LIB_TESTS_L = get_mem_rsv \
 	sw_tree1 \
 	move_and_save mangle-layout nopulate \
 	open_pack rw_tree1 set_name setprop del_property del_node \
+	appendprop1 appendprop2 \
 	string_escapes references path-references phandle_format \
 	boot-cpuid incbin \
 	extra-terminating-null \
diff --git a/tests/run_tests.sh b/tests/run_tests.sh
index da6f970..c72b9d2 100755
--- a/tests/run_tests.sh
+++ b/tests/run_tests.sh
@@ -178,6 +178,10 @@ libfdt_tests () {
     run_test rw_tree1
     tree1_tests rw_tree1.test.dtb
     tree1_tests_rw rw_tree1.test.dtb
+    run_test appendprop1
+    run_test appendprop2 appendprop1.test.dtb
+    run_dtc_test -I dts -O dtb -o appendprop.test.dtb appendprop.dts
+    run_test dtbs_equal_ordered appendprop2.test.dtb appendprop.test.dtb
 
     for basetree in test_tree1.dtb sw_tree1.test.dtb rw_tree1.test.dtb; do
 	run_test nopulate $basetree

commit 69df9f0de25db1c37970850115cdf48335d41802
Author: Stephen Warren <swarren@nvidia.com>
Date:   Thu Jan 12 11:31:00 2012 -0700

    dtc: Implement -d option to write out a dependency file
    
    This will allow callers to rebuild .dtb files when any of the /include/d
    .dtsi files are modified, not just the top-level .dts file.
    
    Signed-off-by: Stephen Warren <swarren@nvidia.com>
    Acked-by: David Gibson <david@gibson.dropbear.id.au>

diff --git a/Documentation/manual.txt b/Documentation/manual.txt
index 14508f3..989c589 100644
--- a/Documentation/manual.txt
+++ b/Documentation/manual.txt
@@ -106,6 +106,9 @@ Options:
     -O <output_format>
 	The generated output format, as listed above.
 
+    -d <dependency_filename>
+	Generate a dependency file during compilation.
+
     -q
 	Quiet: -q suppress warnings, -qq errors, -qqq all
 
diff --git a/dtc.c b/dtc.c
index 15d2fc2..7a0c605 100644
--- a/dtc.c
+++ b/dtc.c
@@ -71,6 +71,7 @@ static void  __attribute__ ((noreturn)) usage(void)
 	fprintf(stderr, "\t\t\tasm - assembler source\n");
 	fprintf(stderr, "\t-V <output version>\n");
 	fprintf(stderr, "\t\tBlob version to produce, defaults to %d (relevant for dtb\n\t\tand asm output only)\n", DEFAULT_FDT_VERSION);
+	fprintf(stderr, "\t-d <output dependency file>\n");
 	fprintf(stderr, "\t-R <number>\n");
 	fprintf(stderr, "\t\tMake space for <number> reserve map entries (relevant for \n\t\tdtb and asm output only)\n");
 	fprintf(stderr, "\t-S <bytes>\n");
@@ -99,6 +100,7 @@ int main(int argc, char *argv[])
 	const char *inform = "dts";
 	const char *outform = "dts";
 	const char *outname = "-";
+	const char *depname = NULL;
 	int force = 0, sort = 0;
 	const char *arg;
 	int opt;
@@ -111,7 +113,7 @@ int main(int argc, char *argv[])
 	minsize    = 0;
 	padsize    = 0;
 
-	while ((opt = getopt(argc, argv, "hI:O:o:V:R:S:p:fqb:vH:s")) != EOF) {
+	while ((opt = getopt(argc, argv, "hI:O:o:V:d:R:S:p:fqb:vH:s")) != EOF) {
 		switch (opt) {
 		case 'I':
 			inform = optarg;
@@ -125,6 +127,9 @@ int main(int argc, char *argv[])
 		case 'V':
 			outversion = strtol(optarg, NULL, 0);
 			break;
+		case 'd':
+			depname = optarg;
+			break;
 		case 'R':
 			reservenum = strtol(optarg, NULL, 0);
 			break;
@@ -185,6 +190,14 @@ int main(int argc, char *argv[])
 	fprintf(stderr, "DTC: %s->%s  on file \"%s\"\n",
 		inform, outform, arg);
 
+	if (depname) {
+		depfile = fopen(depname, "w");
+		if (!depfile)
+			die("Couldn't open dependency file %s: %s\n", depname,
+			    strerror(errno));
+		fprintf(depfile, "%s:", outname);
+	}
+
 	if (streq(inform, "dts"))
 		bi = dt_from_source(arg);
 	else if (streq(inform, "fs"))
@@ -194,6 +207,11 @@ int main(int argc, char *argv[])
 	else
 		die("Unknown input format \"%s\"\n", inform);
 
+	if (depfile) {
+		fputc('\n', depfile);
+		fclose(depfile);
+	}
+
 	if (cmdline_boot_cpuid != -1)
 		bi->boot_cpuid_phys = cmdline_boot_cpuid;
 
diff --git a/srcpos.c b/srcpos.c
index 2dbc874..36a38e9 100644
--- a/srcpos.c
+++ b/srcpos.c
@@ -40,6 +40,7 @@ static char *dirname(const char *path)
 	return NULL;
 }
 
+FILE *depfile; /* = NULL */
 struct srcfile_state *current_srcfile; /* = NULL */
 
 /* Detect infinite include recursion. */
@@ -67,6 +68,9 @@ FILE *srcfile_relative_open(const char *fname, char **fullnamep)
 			    strerror(errno));
 	}
 
+	if (depfile)
+		fprintf(depfile, " %s", fullname);
+
 	if (fullnamep)
 		*fullnamep = fullname;
 	else
diff --git a/srcpos.h b/srcpos.h
index bd7966e..ce980ca 100644
--- a/srcpos.h
+++ b/srcpos.h
@@ -30,6 +30,7 @@ struct srcfile_state {
 	struct srcfile_state *prev;
 };
 
+extern FILE *depfile; /* = NULL */
 extern struct srcfile_state *current_srcfile; /* = NULL */
 
 FILE *srcfile_relative_open(const char *fname, char **fullnamep);
diff --git a/tests/dependencies.cmp b/tests/dependencies.cmp
new file mode 100644
index 0000000..bcd9432
--- /dev/null
+++ b/tests/dependencies.cmp
@@ -0,0 +1 @@
+dependencies.test.dtb: dependencies.dts deps_inc1.dtsi deps_inc2.dtsi
diff --git a/tests/dependencies.dts b/tests/dependencies.dts
new file mode 100644
index 0000000..2cfe31b
--- /dev/null
+++ b/tests/dependencies.dts
@@ -0,0 +1,6 @@
+/dts-v1/;
+
+/include/ "deps_inc1.dtsi"
+
+/ {
+};
diff --git a/tests/deps_inc1.dtsi b/tests/deps_inc1.dtsi
new file mode 100644
index 0000000..5c607dc
--- /dev/null
+++ b/tests/deps_inc1.dtsi
@@ -0,0 +1 @@
+/include/ "deps_inc2.dtsi"
diff --git a/tests/deps_inc2.dtsi b/tests/deps_inc2.dtsi
new file mode 100644
index 0000000..710cecc
--- /dev/null
+++ b/tests/deps_inc2.dtsi
@@ -0,0 +1 @@
+/* Empty */
diff --git a/tests/run_tests.sh b/tests/run_tests.sh
index c72b9d2..e42154b 100755
--- a/tests/run_tests.sh
+++ b/tests/run_tests.sh
@@ -357,6 +357,10 @@ dtc_tests () {
     run_sh_test dtc-fatal.sh -I dts -O dtb nosuchfile.dts
     run_sh_test dtc-fatal.sh -I dtb -O dtb nosuchfile.dtb
     run_sh_test dtc-fatal.sh -I fs -O dtb nosuchfile
+
+    # Dependencies
+    run_dtc_test -I dts -O dtb -o dependencies.test.dtb -d dependencies.test.d dependencies.dts
+    run_wrap_test cmp dependencies.test.d dependencies.cmp
 }
 
 cmp_tests () {

commit 68d057f20d7c3a93b441d2892c4749392bc83b45
Author: Simon Glass <sjg@chromium.org>
Date:   Sat Jan 21 10:14:47 2012 -0800

    Add fdtget utility to read property values from a device tree
    
    This simply utility makes it easy for scripts to read values from the device
    tree. It is written in C and uses the same libfdt as the rest of the dtc
    package.
    
    What is it for:
    - Reading fdt values from scripts
    - Extracting fdt information within build systems
    - Looking at particular values without having to dump the entire tree
    
    To use it, specify the fdt binary file on command line followed by a list of
    node, property pairs. The utility then looks up each node, finds the property
    and displays the value.
    
    Each value is printed on a new line.
    
    fdtget tries to guess the type of each property based on its contents. This
    is not always reliable, so you can use the -t option to force fdtget to decode
    the value as a string, or byte, etc.
    
    To read from stdin, use - as the file.
    
    Usage:
    	fdtget <options> <dt file> [<node> <property>]...
    Options:
    	-t <type>	Type of data
    	-h		Print this help
    
    <type>	s=string, i=int, u=unsigned, x=hex
    	Optional modifier prefix:
    		hh or b=byte, h=2 byte, l=4 byte (default)
    
    Signed-off-by: Simon Glass <sjg@chromium.org>

diff --git a/.gitignore b/.gitignore
index 74714cd..2d82b71 100644
--- a/.gitignore
+++ b/.gitignore
@@ -10,3 +10,4 @@ lex.yy.c
 /fdtdump
 /convert-dtsv0
 /version_gen.h
+/fdtget
diff --git a/Makefile b/Makefile
index 4582f5d..a54a209 100644
--- a/Makefile
+++ b/Makefile
@@ -110,6 +110,7 @@ include Makefile.utils
 BIN += convert-dtsv0
 BIN += dtc
 BIN += fdtdump
+BIN += fdtget
 
 SCRIPTS = dtdiff
 
@@ -120,6 +121,7 @@ ifneq ($(DEPTARGETS),)
 -include $(DTC_OBJS:%.o=%.d)
 -include $(CONVERT_OBJS:%.o=%.d)
 -include $(FDTDUMP_OBJS:%.o=%.d)
+-include $(FDTGET_OBJS:%.o=%.d)
 endif
 
 
@@ -180,6 +182,8 @@ convert-dtsv0: $(CONVERT_OBJS)
 
 fdtdump:	$(FDTDUMP_OBJS)
 
+fdtget:	$(FDTGET_OBJS) $(LIBFDT_archive)
+
 
 #
 # Testsuite rules
diff --git a/Makefile.utils b/Makefile.utils
index fae5b00..38efa3c 100644
--- a/Makefile.utils
+++ b/Makefile.utils
@@ -8,3 +8,10 @@ FDTDUMP_SRCS = \
 	util.c
 
 FDTDUMP_OBJS = $(FDTDUMP_SRCS:%.c=%.o)
+
+
+FDTGET_SRCS = \
+	fdtget.c \
+	util.c
+
+FDTGET_OBJS = $(FDTGET_SRCS:%.c=%.o)
diff --git a/fdtget.c b/fdtget.c
new file mode 100644
index 0000000..48ab615
--- /dev/null
+++ b/fdtget.c
@@ -0,0 +1,226 @@
+/*
+ * Copyright (c) 2011 The Chromium OS Authors. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <ctype.h>
+#include <getopt.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <libfdt.h>
+
+#include "util.h"
+
+/* Holds information which controls our output and options */
+struct display_info {
+	int type;		/* data type (s/i/u/x or 0 for default) */
+	int size;		/* data size (1/2/4) */
+};
+
+static void report_error(const char *where, int err)
+{
+	fprintf(stderr, "Error at '%s': %s\n", where, fdt_strerror(err));
+}
+
+/**
+ * Displays data of a given length according to selected options
+ *
+ * If a specific data type is provided in disp, then this is used. Otherwise
+ * we try to guess the data type / size from the contents.
+ *
+ * @param disp		Display information / options
+ * @param data		Data to display
+ * @param len		Maximum length of buffer
+ * @return 0 if ok, -1 if data does not match format
+ */
+static int show_data(struct display_info *disp, const char *data, int len)
+{
+	int i, size;
+	const uint8_t *p = (const uint8_t *)data;
+	const char *s;
+	int value;
+	int is_string;
+	char fmt[3];
+
+	/* no data, don't print */
+	if (len == 0)
+		return 0;
+
+	is_string = (disp->type) == 's' ||
+		(!disp->type && util_is_printable_string(data, len));
+	if (is_string) {
+		if (data[len - 1] != '\0') {
+			fprintf(stderr, "Unterminated string\n");
+			return -1;
+		}
+		for (s = data; s - data < len; s += strlen(s) + 1) {
+			if (s != data)
+				printf(" ");
+			printf("%s", (const char *)s);
+		}
+		return 0;
+	}
+	size = disp->size;
+	if (size == -1)
+		size = (len % 4) == 0 ? 4 : 1;
+	else if (len % size) {
+		fprintf(stderr, "Property length must be a multiple of "
+				"selected data size\n");
+		return -1;
+	}
+	fmt[0] = '%';
+	fmt[1] = disp->type ? disp->type : 'd';
+	fmt[2] = '\0';
+	for (i = 0; i < len; i += size, p += size) {
+		if (i)
+			printf(" ");
+		value = size == 4 ? fdt32_to_cpu(*(const uint32_t *)p) :
+			size == 2 ? (*p << 8) | p[1] : *p;
+		printf(fmt, value);
+	}
+	return 0;
+}
+
+/**
+ * Show the data for a given node (and perhaps property) according to the
+ * display option provided.
+ *
+ * @param blob		FDT blob
+ * @param disp		Display information / options
+ * @param node		Node to display
+ * @param property	Name of property to display, or NULL if none
+ * @return 0 if ok, -ve on error
+ */
+static int show_data_for_item(const void *blob, struct display_info *disp,
+		int node, const char *property)
+{
+	const void *value = NULL;
+	int len, err = 0;
+
+	value = fdt_getprop(blob, node, property, &len);
+	if (value) {
+		if (show_data(disp, value, len))
+			err = -1;
+		else
+			printf("\n");
+	} else {
+		report_error(property, len);
+		err = -1;
+	}
+	return err;
+}
+
+/**
+ * Run the main fdtget operation, given a filename and valid arguments
+ *
+ * @param disp		Display information / options
+ * @param filename	Filename of blob file
+ * @param arg		List of arguments to process
+ * @param arg_count	Number of arguments
+ * @param return 0 if ok, -ve on error
+ */
+static int do_fdtget(struct display_info *disp, const char *filename,
+		     char **arg, int arg_count)
+{
+	char *blob;
+	int i, node;
+
+	blob = utilfdt_read(filename);
+	if (!blob)
+		return -1;
+
+	for (i = 0; i + 2 <= arg_count; i += 2) {
+		node = fdt_path_offset(blob, arg[0]);
+		if (node < 0) {
+			report_error(arg[0], node);
+			return -1;
+		}
+
+		if (show_data_for_item(blob, disp, node, arg[1]))
+			return -1;
+	}
+	return 0;
+}
+
+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"
+	"Options:\n"
+	"\t-t <type>\tType of data\n"
+	"\t-h\t\tPrint this help\n\n"
+	USAGE_TYPE_MSG;
+
+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[])
+{
+	char *filename = NULL;
+	struct display_info disp;
+
+	/* set defaults */
+	memset(&disp, '\0', sizeof(disp));
+	disp.size = -1;
+	for (;;) {
+		int c = getopt(argc, argv, "ht:");
+		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");
+			break;
+		}
+	}
+
+	if (optind < argc)
+		filename = argv[optind++];
+	if (!filename)
+		usage("Missing filename");
+
+	argv += optind;
+	argc -= optind;
+
+	/* Allow no arguments, and silently succeed */
+	if (!argc)
+		return 0;
+
+	/* Check for node, property arguments */
+	if (argc % 2)
+		usage("Must have an even number of arguments");
+
+	if (do_fdtget(&disp, filename, argv, argc))
+		return 1;
+	return 0;
+}
diff --git a/tests/fdtget-runtest.sh b/tests/fdtget-runtest.sh
new file mode 100755
index 0000000..f38184f
--- /dev/null
+++ b/tests/fdtget-runtest.sh
@@ -0,0 +1,35 @@
+#! /bin/sh
+
+. ./tests.sh
+
+LOG="tmp.log.$$"
+EXPECT="tmp.expect.$$"
+
+rm -f $TMPFILE $LOG
+
+expect="$1"
+echo "$expect" >$EXPECT
+shift
+
+verbose_run_log "$LOG" $VALGRIND "$DTGET" "$@"
+ret="$?"
+
+if [ "$ret" -ne 0 -a "$expect" = "ERR" ]; then
+	PASS
+fi
+
+if [ "$ret" -gt 127 ]; then
+    signame=$(kill -l $[ret - 128])
+    FAIL "Killed by SIG$signame"
+fi
+
+diff $EXPECT $LOG
+ret="$?"
+
+rm -f $LOG $EXPECT
+
+if [ "$ret" -eq 0 ]; then
+	PASS
+else
+	FAIL
+fi
diff --git a/tests/run_tests.sh b/tests/run_tests.sh
index e42154b..e6184df 100755
--- a/tests/run_tests.sh
+++ b/tests/run_tests.sh
@@ -83,6 +83,13 @@ asm_to_so_test () {
     run_wrap_test asm_to_so "$@"
 }
 
+run_fdtget_test () {
+    # run_fdtget_test name expected_output dtb_file args...
+    echo -n "$1:	"
+    shift
+    base_run_test sh fdtget-runtest.sh "$@"
+}
+
 tree1_tests () {
     TREE=$1
 
@@ -402,6 +409,37 @@ dtbs_equal_tests () {
     cmp_tests test_tree1.dtb $WRONG_TREE1
 }
 
+fdtget_tests () {
+    file=label01.dtb
+    $DTC -O dtb -o $file ${file%.dtb}.dts 2>/dev/null
+
+    # run_fdtget_test <test-name> <expected-result> <args>...
+    run_fdtget_test "Simple string" "MyBoardName" $file / model
+    run_fdtget_test "Multiple string i" "77 121 66 111 \
+97 114 100 78 97 109 101 0 77 121 66 111 97 114 100 70 97 109 105 \
+108 121 78 97 109 101 0" $file / compatible
+    run_fdtget_test "Multiple string s" "MyBoardName MyBoardFamilyName" \
+	-t s $file / compatible
+    run_fdtget_test "Integer" "32768" $file /cpus/PowerPC,970@1 d-cache-size
+    run_fdtget_test "Integer hex" "8000" -tx $file \
+	/cpus/PowerPC,970@1 d-cache-size
+    run_fdtget_test "Integer list" "61 62 63 0" -tbx $file \
+	/randomnode tricky1
+    run_fdtget_test "Byte list short" "a b c d de ea ad be ef" -tbx \
+	$file /randomnode blob
+
+    # Here the property size is not a multiple of 4 bytes, so it should fail
+    run_fdtget_test "Integer list invalid" ERR -tlx \
+	$file /randomnode mixed
+    run_fdtget_test "Integer list halfword" "6162 6300 1234 0 a 0 b 0 c" -thx \
+	$file /randomnode mixed
+    run_fdtget_test "Integer list byte" \
+	"61 62 63 0 12 34 0 0 0 a 0 0 0 b 0 0 0 c" -thhx \
+	$file /randomnode mixed
+    run_fdtget_test "Missing property" ERR -ts \
+	$file /randomnode doctor-who
+}
+
 utilfdt_tests () {
     run_test utilfdt_test
 }
@@ -421,7 +459,7 @@ while getopts "vt:m" ARG ; do
 done
 
 if [ -z "$TESTSETS" ]; then
-    TESTSETS="libfdt utilfdt dtc dtbs_equal"
+    TESTSETS="libfdt utilfdt dtc dtbs_equal fdtget"
 fi
 
 # Make sure we don't have stale blobs lying around
@@ -441,6 +479,9 @@ for set in $TESTSETS; do
 	"dtbs_equal")
 	    dtbs_equal_tests
 	    ;;
+	"fdtget")
+	    fdtget_tests
+	    ;;
     esac
 done
 
diff --git a/tests/tests.sh b/tests/tests.sh
index 30ffead..d9a0524 100644
--- a/tests/tests.sh
+++ b/tests/tests.sh
@@ -11,6 +11,7 @@ FAIL () {
 }
 
 DTC=../dtc
+DTGET=../fdtget
 
 verbose_run () {
     if [ -z "$QUIET_TEST" ]; then
diff --git a/util.h b/util.h
index 730918e..c8eb45d 100644
--- a/util.h
+++ b/util.h
@@ -140,4 +140,14 @@ int utilfdt_write_err(const char *filename, const void *blob);
  */
 int utilfdt_decode_type(const char *fmt, int *type, int *size);
 
+/*
+ * This is a usage message fragment for the -t option. It is the format
+ * supported by utilfdt_decode_type.
+ */
+
+#define USAGE_TYPE_MSG \
+	"<type>\ts=string, i=int, u=unsigned, x=hex\n" \
+	"\tOptional modifier prefix:\n" \
+	"\t\thh or b=byte, h=2 byte, l=4 byte (default)\n";
+
 #endif /* _UTIL_H */

commit 1ede50c3559bbfca79fadcbfd8acb9388f4aac87
Author: Simon Glass <sjg@chromium.org>
Date:   Sat Jan 21 10:14:48 2012 -0800

    Add fdtput utility to write property values to a device tree
    
    This simple utility allows writing of values into a device tree from the
    command line. It aimes to be the opposite of fdtget.
    
    What is it for:
    - Updating fdt values when a binary blob already exists
       (even though source may be available it might be easier to use this
        utility rather than sed, etc.)
    - Writing machine-specific fdt values within a build system
    
    To use it, specify the fdt binary file on command line followed by the node
    and property to set. Then, provide a list of values to put into that
    property. Often there will be just one, but fdtput also supports arrays and
    string lists.
    
    fdtput does not try to guess the type of the property based on looking at
    the arguments. Instead it always assumes that an integer is provided. To
    indicate that you want to write a string, use -ts. You can also provide
    hex values with -tx.
    
    The command line arguments are joined together into a single value. For
    strings, a nul terminator is placed between each string when it is packed
    into the property. To avoid this, pass the string as a single argument.
    
    Usage:
    	fdtput <options> <dt file> <<node> <property> [<value>...]
    Options:
    	-t <type>	Type of data
    	-v		Verbose: display each value decoded from command line
    	-h		Print this help
    
    <type>	s=string, i=int, u=unsigned, x=hex
    	Optional modifier prefix:
    		hh or b=byte, h=2 byte, l=4 byte (default)
    
    To read from stdin and write to stdout, use - as the file. So you can do:
    
    cat somefile.dtb | fdtput -ts - /node prop "My string value" > newfile.dtb
    
    This commit also adds basic tests to verify the major features.
    
    Signed-off-by: Simon Glass <sjg@chromium.org>

diff --git a/.gitignore b/.gitignore
index 2d82b71..5074980 100644
--- a/.gitignore
+++ b/.gitignore
@@ -11,3 +11,4 @@ lex.yy.c
 /convert-dtsv0
 /version_gen.h
 /fdtget
+/fdtput
diff --git a/Makefile b/Makefile
index a54a209..510caa6 100644
--- a/Makefile
+++ b/Makefile
@@ -111,6 +111,7 @@ BIN += convert-dtsv0
 BIN += dtc
 BIN += fdtdump
 BIN += fdtget
+BIN += fdtput
 
 SCRIPTS = dtdiff
 
@@ -122,6 +123,7 @@ ifneq ($(DEPTARGETS),)
 -include $(CONVERT_OBJS:%.o=%.d)
 -include $(FDTDUMP_OBJS:%.o=%.d)
 -include $(FDTGET_OBJS:%.o=%.d)
+-include $(FDTPUT_OBJS:%.o=%.d)
 endif
 
 
@@ -184,6 +186,8 @@ fdtdump:	$(FDTDUMP_OBJS)
 
 fdtget:	$(FDTGET_OBJS) $(LIBFDT_archive)
 
+fdtput:	$(FDTPUT_OBJS) $(LIBFDT_archive)
+
 
 #
 # Testsuite rules
diff --git a/Makefile.utils b/Makefile.utils
index 38efa3c..48ece49 100644
--- a/Makefile.utils
+++ b/Makefile.utils
@@ -15,3 +15,10 @@ FDTGET_SRCS = \
 	util.c
 
 FDTGET_OBJS = $(FDTGET_SRCS:%.c=%.o)
+
+
+FDTPUT_SRCS = \
+	fdtput.c \
+	util.c
+
+FDTPUT_OBJS = $(FDTPUT_SRCS:%.c=%.o)
diff --git a/fdtput.c b/fdtput.c
new file mode 100644
index 0000000..f6ebd24
--- /dev/null
+++ b/fdtput.c
@@ -0,0 +1,235 @@
+/*
+ * Copyright (c) 2011 The Chromium OS Authors. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <assert.h>
+#include <ctype.h>
+#include <getopt.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <libfdt.h>
+
+#include "util.h"
+
+struct display_info {
+	int type;		/* data type (s/i/u/x or 0 for default) */
+	int size;		/* data size (1/2/4) */
+	int verbose;		/* verbose output */
+};
+
+static void report_error(const char *where, int err)
+{
+	fprintf(stderr, "Error at '%s': %s\n", where, fdt_strerror(err));
+}
+
+/**
+ * Encode a series of arguments in a property value.
+ *
+ * @param disp		Display information / options
+ * @param arg		List of arguments from command line
+ * @param arg_count	Number of arguments (may be 0)
+ * @param valuep	Returns buffer containing value
+ * @param *value_len	Returns length of value encoded
+ */
+static int encode_value(struct display_info *disp, char **arg, int arg_count,
+			char **valuep, int *value_len)
+{
+	char *value = NULL;	/* holding area for value */
+	int value_size = 0;	/* size of holding area */
+	char *ptr;		/* pointer to current value position */
+	int len;		/* length of this cell/string/byte */
+	int ival;
+	int upto;	/* the number of bytes we have written to buf */
+	char fmt[3];
+
+	upto = 0;
+
+	if (disp->verbose)
+		fprintf(stderr, "Decoding value:\n");
+
+	fmt[0] = '%';
+	fmt[1] = disp->type ? disp->type : 'd';
+	fmt[2] = '\0';
+	for (; arg_count > 0; arg++, arg_count--, upto += len) {
+		/* assume integer unless told otherwise */
+		if (disp->type == 's')
+			len = strlen(*arg) + 1;
+		else
+			len = disp->size == -1 ? 4 : disp->size;
+
+		/* enlarge our value buffer by a suitable margin if needed */
+		if (upto + len > value_size) {
+			value_size = (upto + len) + 500;
+			value = realloc(value, value_size);
+			if (!value) {
+				fprintf(stderr, "Out of mmory: cannot alloc "
+					"%d bytes\n", value_size);
+				return -1;
+			}
+		}
+
+		ptr = value + upto;
+		if (disp->type == 's') {
+			memcpy(ptr, *arg, len);
+			if (disp->verbose)
+				fprintf(stderr, "\tstring: '%s'\n", ptr);
+		} else {
+			int *iptr = (int *)ptr;
+			sscanf(*arg, fmt, &ival);
+			if (len == 4)
+				*iptr = cpu_to_fdt32(ival);
+			else
+				*ptr = (uint8_t)ival;
+			if (disp->verbose) {
+				fprintf(stderr, "\t%s: %d\n",
+					disp->size == 1 ? "byte" :
+					disp->size == 2 ? "short" : "int",
+					ival);
+			}
+		}
+	}
+	*value_len = upto;
+	*valuep = value;
+	if (disp->verbose)
+		fprintf(stderr, "Value size %d\n", upto);
+	return 0;
+}
+
+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);
+	if (node < 0) {
+		report_error(node_name, node);
+		return -1;
+	}
+
+	err = fdt_setprop(blob, node, property, buf, len);
+	if (err) {
+		report_error(property, err);
+		return -1;
+	}
+	return 0;
+}
+
+static int do_fdtput(struct display_info *disp, const char *filename,
+		    char **arg, int arg_count)
+{
+	char *value;
+	char *blob;
+	int len, ret = 0;
+
+	blob = utilfdt_read(filename);
+	if (!blob)
+		return -1;
+
+	/* convert the arguments into a single binary value, then store */
+	assert(arg_count >= 2);
+	if (encode_value(disp, arg + 2, arg_count - 2, &value, &len) ||
+		store_key_value(blob, *arg, arg[1], value, len))
+		ret = -1;
+
+	if (!ret)
+		ret = utilfdt_write(filename, blob);
+
+	free(blob);
+	return ret;
+}
+
+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"
+	"Options:\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 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[])
+{
+	struct display_info disp;
+	char *filename = NULL;
+
+	memset(&disp, '\0', sizeof(disp));
+	disp.size = -1;
+	for (;;) {
+		int c = getopt(argc, argv, "ht:v");
+		if (c == -1)
+			break;
+
+		/*
+		 * TODO: add options to:
+		 * - delete property
+		 * - delete node (optionally recursively)
+		 * - rename node
+		 * - pack fdt before writing
+		 * - set amount of free space when writing
+		 * - expand fdt if value doesn't fit
+		 */
+		switch (c) {
+		case 'h':
+		case '?':
+			usage(NULL);
+
+		case 't':
+			if (utilfdt_decode_type(optarg, &disp.type,
+					&disp.size))
+				usage("Invalid type string");
+			break;
+
+		case 'v':
+			disp.verbose = 1;
+			break;
+		}
+	}
+
+	if (optind < argc)
+		filename = argv[optind++];
+	if (!filename)
+		usage("Missing filename");
+
+	argv += optind;
+	argc -= optind;
+
+	if (argc < 1)
+		usage("Missing node");
+	if (argc < 2)
+		usage("Missing property");
+
+	if (do_fdtput(&disp, filename, argv, argc))
+		return 1;
+	return 0;
+}
diff --git a/tests/fdtput-runtest.sh b/tests/fdtput-runtest.sh
new file mode 100644
index 0000000..ea51569
--- /dev/null
+++ b/tests/fdtput-runtest.sh
@@ -0,0 +1,55 @@
+#! /bin/sh
+
+# Run script for fdtput tests
+# We run fdtput to update the device tree, thn fdtget to check it
+
+# Usage
+#    fdtput-runtest.sh name expected_output dtb_file node property flags value
+
+. ./tests.sh
+
+LOG="tmp.log.$$"
+EXPECT="tmp.expect.$$"
+
+rm -f $TMPFILE $LOG
+
+expect="$1"
+echo "$expect" >$EXPECT
+dtb="$2"
+node="$3"
+property="$4"
+flags="$5"
+shift 5
+value="$@"
+
+# First run fdtput
+verbose_run $VALGRIND "$DTPUT" "$dtb" "$node" "$property" $value $flags
+ret="$?"
+
+if [ "$ret" -ne 0 -a "$expect" = "ERR" ]; then
+	PASS
+fi
+if [ "$ret" -gt 127 ]; then
+    signame=$(kill -l $[ret - 128])
+    FAIL "Killed by SIG$signame"
+fi
+
+# Now fdtget to read the value
+verbose_run_log "$LOG" $VALGRIND "$DTGET" "$dtb" "$node" "$property" $flags
+ret="$?"
+
+if [ "$ret" -gt 127 ]; then
+    signame=$(kill -l $[ret - 128])
+    FAIL "Killed by SIG$signame"
+fi
+
+diff $EXPECT $LOG
+ret="$?"
+
+rm -f $LOG $EXPECT
+
+if [ "$ret" -eq 0 ]; then
+	PASS
+else
+	FAIL
+fi
diff --git a/tests/run_tests.sh b/tests/run_tests.sh
index e6184df..2650559 100755
--- a/tests/run_tests.sh
+++ b/tests/run_tests.sh
@@ -90,6 +90,21 @@ run_fdtget_test () {
     base_run_test sh fdtget-runtest.sh "$@"
 }
 
+run_fdtput_test () {
+    # run_fdtput_test name expected_output dtb_file node property flags value...
+    echo -n "$1:	"
+    shift
+    output="$1"
+    dtb="$2"
+    node="$3"
+    property="$4"
+    flags="$5"
+    shift 5
+    base_run_test sh fdtput-runtest.sh "$output" "$dtb" "$node" "$property" \
+		"$flags" $@
+#     base_run_test sh fdtput-runtest.sh "$@"
+}
+
 tree1_tests () {
     TREE=$1
 
@@ -440,6 +455,59 @@ fdtget_tests () {
 	$file /randomnode doctor-who
 }
 
+fdtput_tests () {
+    file=label01.dtb
+    src=label01.dts
+
+    # Create some test files containing useful strings
+    base=tmp.test0
+    file1=tmp.test1
+    file2=tmp.test2
+    bigfile1=tmp.test3
+    bigfile2=tmp.test4
+
+    # Filter out anything the shell might not like
+    cat $src | tr -d "'\"\n\;/\.\*{}\-" | tr -s "[:blank:]" " " >$base
+
+    # Make two small files
+    head -5 $base >$file1
+    cat $file1 | tr a-z A-Z | cut -c10-30 | sort -r >$file2
+
+    # and two larger ones
+    cat $base > $bigfile1
+    tac $base | tr a-z A-Z | sort -r >$bigfile2
+
+    # Allow just enough space for both file1 and file2
+    (( space = $(stat -c %s $file1) + $(stat -c %s $file2) ))
+    $DTC -O dtb -p $space -o $file ${file%.dtb}.dts 2>/dev/null
+
+    # run_fdtput_test <test-name> <expected-result> <file> <key> <flags>
+    #		<args>...
+    run_fdtput_test "Simple string" "a_model" $file / model -ts "a_model"
+    run_fdtput_test "Multiple string s" "board1 board2" \
+	$file / compatible -ts board1 board2
+    run_fdtput_test "Single string with spaces" "board1 board2" \
+	$file / compatible -ts "board1 board2"
+    run_fdtput_test "Integer" "32768" \
+	$file /cpus/PowerPC,970@1 d-cache-size "" "32768"
+    run_fdtput_test "Integer hex" "8001" \
+	$file /cpus/PowerPC,970@1 d-cache-size -tx 0x8001
+    run_fdtput_test "Integer list" "2 3 12" \
+	$file /randomnode tricky1 -tbi "02 003 12"
+    run_fdtput_test "Byte list short" "a b c ea ad be ef" \
+	$file /randomnode blob -tbx "a b c ea ad be ef"
+    run_fdtput_test "Integer list short" "a0b0c0d deeaae ef000000" \
+	$file /randomnode blob -tx "a0b0c0d deeaae ef000000"
+    run_fdtput_test "Large string list" "`cat $file1 $file2`" \
+	$file /randomnode blob -ts "`cat $file1`" "`cat $file2`"
+
+    # This should be larger than available space in the fdt ($space)
+    run_fdtput_test "Enormous string list" ERR \
+	$file /randomnode blob -ts "`cat $bigfile1`" "`cat $bigfile2`"
+
+    # TODO: Add tests for verbose mode?
+}
+
 utilfdt_tests () {
     run_test utilfdt_test
 }
@@ -459,7 +527,7 @@ while getopts "vt:m" ARG ; do
 done
 
 if [ -z "$TESTSETS" ]; then
-    TESTSETS="libfdt utilfdt dtc dtbs_equal fdtget"
+    TESTSETS="libfdt utilfdt dtc dtbs_equal fdtget fdtput"
 fi
 
 # Make sure we don't have stale blobs lying around
@@ -482,6 +550,9 @@ for set in $TESTSETS; do
 	"fdtget")
 	    fdtget_tests
 	    ;;
+	"fdtput")
+	    fdtput_tests
+	    ;;
     esac
 done
 
diff --git a/tests/tests.sh b/tests/tests.sh
index d9a0524..6e5e76a 100644
--- a/tests/tests.sh
+++ b/tests/tests.sh
@@ -12,6 +12,7 @@ FAIL () {
 
 DTC=../dtc
 DTGET=../fdtget
+DTPUT=../fdtput
 
 verbose_run () {
     if [ -z "$QUIET_TEST" ]; then

commit 1456da7e2d3054882b20c120d817096bea21571e
Author: Jon Loeliger <jdl@jdl.com>
Date:   Sat Jan 21 15:24:51 2012 -0600

    Introduce ${TESTS_BIN} in Makefiles to identify tested executables.

diff --git a/Makefile b/Makefile
index 510caa6..1169e6c 100644
--- a/Makefile
+++ b/Makefile
@@ -193,6 +193,12 @@ fdtput:	$(FDTPUT_OBJS) $(LIBFDT_archive)
 # Testsuite rules
 #
 TESTS_PREFIX=tests/
+
+TESTS_BIN += dtc
+TESTS_BIN += convert-dtsv0
+TESTS_BIN += fdtput
+TESTS_BIN += fdtget
+
 include tests/Makefile.tests
 
 #
diff --git a/tests/Makefile.tests b/tests/Makefile.tests
index 3f92074..2eee708 100644
--- a/tests/Makefile.tests
+++ b/tests/Makefile.tests
@@ -65,13 +65,13 @@ tests_clean:
 	rm -f $(STD_CLEANFILES:%=$(TESTS_PREFIX)%)
 	rm -f $(TESTS_CLEANFILES)
 
-check:	tests dtc convert-dtsv0
+check:	tests ${TESTS_BIN}
 	cd $(TESTS_PREFIX); ./run_tests.sh
 
-checkm: tests dtc convert-dtsv0
+checkm: tests ${TESTS_BIN}
 	cd $(TESTS_PREFIX); ./run_tests.sh -m 2>&1 | tee vglog.$$$$
 
-checkv:	tests dtc convert-dtsv0
+checkv:	tests ${TESTS_BIN}
 	cd $(TESTS_PREFIX); ./run_tests.sh -v
 
 ifneq ($(DEPTARGETS),)

commit 81f11f4f109cc16e1ec31a85c222a1caabea5654
Author: David Gibson <david@gibson.dropbear.id.au>
Date:   Fri Feb 3 16:12:00 2012 +1100

    Update .gitignore for tests
    
    We've add some test (generated) binaries that aren't currently listed in
    .gitignore, in addition more scripts now generate various tmp.* files
    during operation.  This adds them all to .gitignore.
    
    Signed-off-by: David Gibson <david@gibson.dropbear.id.au>

diff --git a/tests/.gitignore b/tests/.gitignore
index 9e062c3..0b71bcf 100644
--- a/tests/.gitignore
+++ b/tests/.gitignore
@@ -1,7 +1,9 @@
 *.dtb
 *.dtb.test.dts
 *.dts.test.s
+tmp.*
 /add_subnode_with_nops
+/appendprop[12]
 /asm_tree_dump
 /boot-cpuid
 /char_literal
@@ -46,6 +48,7 @@
 /supernode_atdepth_offset
 /sw_tree1
 /truncated_property
+/utilfdt_test
 /value-labels
 /dtb_reverse
 /dtbs_equal_unordered

commit 9cf26ffa4a9dfa477971f989dcd7392bedbaaaed
Author: David Gibson <david@gibson.dropbear.id.au>
Date:   Fri Feb 3 16:12:01 2012 +1100

    Add quilt files to .gitignore
    
    For the benefit of quilt users (such as myself, sometimes) have git
    ignore the quilt control and patches files.
    
    Signed-off-by: David Gibson <david@gibson.dropbear.id.au>

diff --git a/.gitignore b/.gitignore
index 5074980..7cabc49 100644
--- a/.gitignore
+++ b/.gitignore
@@ -12,3 +12,5 @@ lex.yy.c
 /version_gen.h
 /fdtget
 /fdtput
+/patches
+/.pc

commit 53d6ca639d1e95d0d62e84b25f3d22d721d1f4a3
Author: David Gibson <david@gibson.dropbear.id.au>
Date:   Fri Feb 3 16:12:02 2012 +1100

    Trivial style fixup
    
    Having braces on an if branch but not the else branch, or vice
    versa is ugly and can trick you when reading the code.
    
    Signed-off-by: David Gibson <david@gibson.dropbear.id.au>

diff --git a/fdtget.c b/fdtget.c
index 48ab615..2c384b6 100644
--- a/fdtget.c
+++ b/fdtget.c
@@ -77,9 +77,9 @@ static int show_data(struct display_info *disp, const char *data, int len)
 		return 0;
 	}
 	size = disp->size;
-	if (size == -1)
+	if (size == -1) {
 		size = (len % 4) == 0 ? 4 : 1;
-	else if (len % size) {
+	} else if (len % size) {
 		fprintf(stderr, "Property length must be a multiple of "
 				"selected data size\n");
 		return -1;

commit 9a50d82c4e3a44ca004ada288f7c37004da0b0cc
Author: David Gibson <david@gibson.dropbear.id.au>
Date:   Fri Feb 3 16:12:03 2012 +1100

    Remove unused variable from test scripts
    
    Several of the test scripts remove $TMPFILE, without ever having set
    the TMPFILE variable. This patch fixes it.
    
    Signed-off-by: David Gibson <david@gibson.dropbear.id.au>

diff --git a/tests/dtc-checkfails.sh b/tests/dtc-checkfails.sh
index c58694f..e7aa25e 100755
--- a/tests/dtc-checkfails.sh
+++ b/tests/dtc-checkfails.sh
@@ -12,7 +12,7 @@ done
 
 LOG="tmp.log.$$"
 
-rm -f $TMPFILE $LOG
+rm -f $LOG
 
 verbose_run_log "$LOG" $VALGRIND "$DTC" -o /dev/null "$@"
 ret="$?"
diff --git a/tests/fdtget-runtest.sh b/tests/fdtget-runtest.sh
index f38184f..c17c8f9 100755
--- a/tests/fdtget-runtest.sh
+++ b/tests/fdtget-runtest.sh
@@ -5,7 +5,7 @@
 LOG="tmp.log.$$"
 EXPECT="tmp.expect.$$"
 
-rm -f $TMPFILE $LOG
+rm -f $LOG
 
 expect="$1"
 echo "$expect" >$EXPECT
diff --git a/tests/fdtput-runtest.sh b/tests/fdtput-runtest.sh
index ea51569..8e4cd95 100644
--- a/tests/fdtput-runtest.sh
+++ b/tests/fdtput-runtest.sh
@@ -11,7 +11,7 @@
 LOG="tmp.log.$$"
 EXPECT="tmp.expect.$$"
 
-rm -f $TMPFILE $LOG
+rm -f $LOG
 
 expect="$1"
 echo "$expect" >$EXPECT

commit 2ca83614e78f32e68202100e94668b0bb62f1ba6
Author: David Gibson <david@gibson.dropbear.id.au>
Date:   Fri Feb 3 16:12:04 2012 +1100

    Use 'trap' builtin to clean up temporaries in test scripts
    
    Some of the test scripts create temporary files, which we remove at the
    end.  Except that we usually forgot to remove them on some exit paths. To
    avoid this problem in future, this modifies the scripts to use the shell's
    trap 0 functionality to automatically remove the temporaries on any exit.
    
    Signed-off-by: David Gibson <david@gibson.dropbear.id.au>

diff --git a/tests/dtc-checkfails.sh b/tests/dtc-checkfails.sh
index e7aa25e..87992a0 100755
--- a/tests/dtc-checkfails.sh
+++ b/tests/dtc-checkfails.sh
@@ -10,9 +10,9 @@ for x; do
     CHECKS="$CHECKS $x"
 done
 
-LOG="tmp.log.$$"
-
+LOG=tmp.log.$$
 rm -f $LOG
+trap "rm -f $LOG" 0
 
 verbose_run_log "$LOG" $VALGRIND "$DTC" -o /dev/null "$@"
 ret="$?"
@@ -28,6 +28,4 @@ for c in $CHECKS; do
     fi
 done
 
-rm -f $LOG
-
 PASS
diff --git a/tests/fdtget-runtest.sh b/tests/fdtget-runtest.sh
index c17c8f9..44c3529 100755
--- a/tests/fdtget-runtest.sh
+++ b/tests/fdtget-runtest.sh
@@ -2,10 +2,10 @@
 
 . ./tests.sh
 
-LOG="tmp.log.$$"
-EXPECT="tmp.expect.$$"
-
-rm -f $LOG
+LOG=tmp.log.$$
+EXPECT=tmp.expect.$$
+rm -f $LOG $EXPECT
+trap "rm -f $LOG $EXPECT" 0
 
 expect="$1"
 echo "$expect" >$EXPECT
@@ -26,8 +26,6 @@ fi
 diff $EXPECT $LOG
 ret="$?"
 
-rm -f $LOG $EXPECT
-
 if [ "$ret" -eq 0 ]; then
 	PASS
 else
diff --git a/tests/fdtput-runtest.sh b/tests/fdtput-runtest.sh
index 8e4cd95..c4b2135 100644
--- a/tests/fdtput-runtest.sh
+++ b/tests/fdtput-runtest.sh
@@ -8,10 +8,10 @@
 
 . ./tests.sh
 
-LOG="tmp.log.$$"
-EXPECT="tmp.expect.$$"
-
-rm -f $LOG
+LOG=tmp.log.$$
+EXPECT=tmp.expect.$$
+rm -f $LOG $EXPECT
+trap "rm -f $LOG $EXPECT" 0
 
 expect="$1"
 echo "$expect" >$EXPECT
@@ -46,8 +46,6 @@ fi
 diff $EXPECT $LOG
 ret="$?"
 
-rm -f $LOG $EXPECT
-
 if [ "$ret" -eq 0 ]; then
 	PASS
 else

commit a90b5b149197a8b38bd569c6a8abc9fc0363fa4b
Author: David Gibson <david@gibson.dropbear.id.au>
Date:   Fri Feb 3 16:12:05 2012 +1100

    Remove bashism from run_tests.sh
    
    The patches introducing fdtget and fdtput inserted a peculiar bashism to
    run_tests.sh using non-portable assignment within an (( )) expression.
    This patch fixes it.
    
    Signed-off-by: David Gibson <david@gibson.dropbear.id.au>

diff --git a/tests/run_tests.sh b/tests/run_tests.sh
index 2650559..37c173c 100755
--- a/tests/run_tests.sh
+++ b/tests/run_tests.sh
@@ -478,7 +478,7 @@ fdtput_tests () {
     tac $base | tr a-z A-Z | sort -r >$bigfile2
 
     # Allow just enough space for both file1 and file2
-    (( space = $(stat -c %s $file1) + $(stat -c %s $file2) ))
+    space=$(( $(stat -c %s $file1) + $(stat -c %s $file2) ))
     $DTC -O dtb -p $space -o $file ${file%.dtb}.dts 2>/dev/null
 
     # run_fdtput_test <test-name> <expected-result> <file> <key> <flags>

commit c879a8a28b168b3b448ca8a107e3386eda6829c7
Author: David Gibson <david@gibson.dropbear.id.au>
Date:   Fri Feb 3 16:12:06 2012 +1100

    Factor signal checks out of test scripts
    
    Several test scripts now have some code to check for a program returning
    a signal, and reporting a suitable failure.  This patch moves this
    duplicated code into a helper function in tests.sh.  At the same time we
    remove a bashism found in the current copies (using the non portablr $[ ]
    construct for arithmetic).
    
    Signed-off-by: David Gibson <david@gibson.dropbear.id.au>

diff --git a/tests/dtc-checkfails.sh b/tests/dtc-checkfails.sh
index 87992a0..3f77b13 100755
--- a/tests/dtc-checkfails.sh
+++ b/tests/dtc-checkfails.sh
@@ -17,10 +17,7 @@ trap "rm -f $LOG" 0
 verbose_run_log "$LOG" $VALGRIND "$DTC" -o /dev/null "$@"
 ret="$?"
 
-if [ "$ret" -gt 127 ]; then
-    signame=$(kill -l $[ret - 128])
-    FAIL "Killed by SIG$signame"
-fi
+FAIL_IF_SIGNAL $ret
 
 for c in $CHECKS; do
     if ! grep -E "^(ERROR)|(Warning) \($c\):" $LOG > /dev/null; then
diff --git a/tests/fdtget-runtest.sh b/tests/fdtget-runtest.sh
index 44c3529..42dc00c 100755
--- a/tests/fdtget-runtest.sh
+++ b/tests/fdtget-runtest.sh
@@ -18,10 +18,7 @@ if [ "$ret" -ne 0 -a "$expect" = "ERR" ]; then
 	PASS
 fi
 
-if [ "$ret" -gt 127 ]; then
-    signame=$(kill -l $[ret - 128])
-    FAIL "Killed by SIG$signame"
-fi
+FAIL_IF_SIGNAL $ret
 
 diff $EXPECT $LOG
 ret="$?"
diff --git a/tests/fdtput-runtest.sh b/tests/fdtput-runtest.sh
index c4b2135..9178d2f 100644
--- a/tests/fdtput-runtest.sh
+++ b/tests/fdtput-runtest.sh
@@ -29,19 +29,14 @@ ret="$?"
 if [ "$ret" -ne 0 -a "$expect" = "ERR" ]; then
 	PASS
 fi
-if [ "$ret" -gt 127 ]; then
-    signame=$(kill -l $[ret - 128])
-    FAIL "Killed by SIG$signame"
-fi
+
+FAIL_IF_SIGNAL $ret
 
 # Now fdtget to read the value
 verbose_run_log "$LOG" $VALGRIND "$DTGET" "$dtb" "$node" "$property" $flags
 ret="$?"
 
-if [ "$ret" -gt 127 ]; then
-    signame=$(kill -l $[ret - 128])
-    FAIL "Killed by SIG$signame"
-fi
+FAIL_IF_SIGNAL $ret
 
 diff $EXPECT $LOG
 ret="$?"
diff --git a/tests/tests.sh b/tests/tests.sh
index 6e5e76a..3b7c6c8 100644
--- a/tests/tests.sh
+++ b/tests/tests.sh
@@ -10,6 +10,14 @@ FAIL () {
     exit 2
 }
 
+FAIL_IF_SIGNAL () {
+    ret="$1"
+    if [ "$ret" -gt 127 ]; then
+	signame=$(kill -l $((ret - 128)))
+	FAIL "Killed by SIG$signame"
+    fi
+}
+
 DTC=../dtc
 DTGET=../fdtget
 DTPUT=../fdtput

commit 15b23d21a62b5a0295ee08b54d0842889ce94c92
Author: David Gibson <david@gibson.dropbear.id.au>
Date:   Fri Feb 3 16:12:07 2012 +1100

    Clean up invocation of fdt{get,put} tests
    
    This patch cleans up how the fdtget and fdtput tests are invoked.
    Specifically we no longer hide the full command lines with a wrapper
    function - this makes it possible to distinguish fdtget from similar
    fdtput tests and makes it easier to work out how to manually invoke an
    individual failing test.
    
    In addition, we remove the testing for errors from the
    fdt{get,put}-runtest.sh script, instead using an internal wrapper
    analagous to run_wrap_test which can test for any program invocation
    that's expected to return an error.
    
    For a couple of the fdtput tests this would result in printing out
    ludicrously large command lines.  Therefore we introduce a new
    mechanism to cut those down to something reasonable.
    
    Signed-off-by: David Gibson <david@gibson.dropbear.id.au>

diff --git a/tests/fdtget-runtest.sh b/tests/fdtget-runtest.sh
index 42dc00c..75e7503 100755
--- a/tests/fdtget-runtest.sh
+++ b/tests/fdtget-runtest.sh
@@ -8,17 +8,10 @@ rm -f $LOG $EXPECT
 trap "rm -f $LOG $EXPECT" 0
 
 expect="$1"
-echo "$expect" >$EXPECT
+echo $expect >$EXPECT
 shift
 
-verbose_run_log "$LOG" $VALGRIND "$DTGET" "$@"
-ret="$?"
-
-if [ "$ret" -ne 0 -a "$expect" = "ERR" ]; then
-	PASS
-fi
-
-FAIL_IF_SIGNAL $ret
+verbose_run_log_check "$LOG" $VALGRIND $DTGET "$@"
 
 diff $EXPECT $LOG
 ret="$?"
diff --git a/tests/fdtput-runtest.sh b/tests/fdtput-runtest.sh
index 9178d2f..dbd9c0d 100644
--- a/tests/fdtput-runtest.sh
+++ b/tests/fdtput-runtest.sh
@@ -14,7 +14,7 @@ rm -f $LOG $EXPECT
 trap "rm -f $LOG $EXPECT" 0
 
 expect="$1"
-echo "$expect" >$EXPECT
+echo $expect >$EXPECT
 dtb="$2"
 node="$3"
 property="$4"
@@ -23,20 +23,10 @@ shift 5
 value="$@"
 
 # First run fdtput
-verbose_run $VALGRIND "$DTPUT" "$dtb" "$node" "$property" $value $flags
-ret="$?"
-
-if [ "$ret" -ne 0 -a "$expect" = "ERR" ]; then
-	PASS
-fi
-
-FAIL_IF_SIGNAL $ret
+verbose_run_check $VALGRIND "$DTPUT" "$dtb" "$node" "$property" $value $flags
 
 # Now fdtget to read the value
-verbose_run_log "$LOG" $VALGRIND "$DTGET" "$dtb" "$node" "$property" $flags
-ret="$?"
-
-FAIL_IF_SIGNAL $ret
+verbose_run_log_check "$LOG" $VALGRIND "$DTGET" "$dtb" "$node" "$property" $flags
 
 diff $EXPECT $LOG
 ret="$?"
diff --git a/tests/run_tests.sh b/tests/run_tests.sh
index 37c173c..999c882 100755
--- a/tests/run_tests.sh
+++ b/tests/run_tests.sh
@@ -36,6 +36,20 @@ base_run_test() {
     fi
 }
 
+shorten_echo () {
+    limit=32
+    echo -n "$1"
+    shift
+    for x; do
+	if [ ${#x} -le $limit ]; then
+	    echo -n " $x"
+	else
+	    short=$(echo "$x" | head -c$limit)
+	    echo -n " \"$short\"...<${#x} bytes>"
+	fi
+    done
+}
+
 run_test () {
     echo -n "$@:	"
     if [ -n "$VALGRIND" -a -f $1.supp ]; then
@@ -70,6 +84,28 @@ run_wrap_test () {
     base_run_test wrap_test "$@"
 }
 
+wrap_error () {
+    (
+	if verbose_run "$@"; then
+	    FAIL "Expected non-zero return code"
+	else
+	    ret="$?"
+	    if [ "$ret" -gt 127 ]; then
+		signame=$(kill -l $((ret - 128)))
+		FAIL "Killed by SIG$signame"
+	    else
+		PASS
+	    fi
+	fi
+    )
+}
+
+run_wrap_error_test () {
+    shorten_echo "$@"
+    echo -n " {!= 0}:	"
+    base_run_test wrap_error "$@"
+}
+
 run_dtc_test () {
     echo -n "dtc $@:	"
     base_run_test wrap_test $VALGRIND $DTC "$@"
@@ -84,25 +120,18 @@ asm_to_so_test () {
 }
 
 run_fdtget_test () {
-    # run_fdtget_test name expected_output dtb_file args...
-    echo -n "$1:	"
+    expect="$1"
     shift
-    base_run_test sh fdtget-runtest.sh "$@"
+    echo -n "fdtget-runtest.sh "$expect" $@:	"
+    base_run_test sh fdtget-runtest.sh "$expect" "$@"
 }
 
 run_fdtput_test () {
-    # run_fdtput_test name expected_output dtb_file node property flags value...
-    echo -n "$1:	"
+    expect="$1"
     shift
-    output="$1"
-    dtb="$2"
-    node="$3"
-    property="$4"
-    flags="$5"
-    shift 5
-    base_run_test sh fdtput-runtest.sh "$output" "$dtb" "$node" "$property" \
-		"$flags" $@
-#     base_run_test sh fdtput-runtest.sh "$@"
+    shorten_echo fdtput-runtest.sh "$expect" "$@"
+    echo -n ":	"
+    base_run_test sh fdtput-runtest.sh "$expect" "$@"
 }
 
 tree1_tests () {
@@ -425,39 +454,32 @@ dtbs_equal_tests () {
 }
 
 fdtget_tests () {
-    file=label01.dtb
-    $DTC -O dtb -o $file ${file%.dtb}.dts 2>/dev/null
+    dts=label01.dts
+    dtb=$dts.fdtget.test.dtb
+    run_dtc_test -O dtb -o $dtb $dts
 
-    # run_fdtget_test <test-name> <expected-result> <args>...
-    run_fdtget_test "Simple string" "MyBoardName" $file / model
-    run_fdtget_test "Multiple string i" "77 121 66 111 \
+    # run_fdtget_test <expected-result> [<flags>] <file> <node> <property>
+    run_fdtget_test "MyBoardName" $dtb / model
+    run_fdtget_test "77 121 66 111 \
 97 114 100 78 97 109 101 0 77 121 66 111 97 114 100 70 97 109 105 \
-108 121 78 97 109 101 0" $file / compatible
-    run_fdtget_test "Multiple string s" "MyBoardName MyBoardFamilyName" \
-	-t s $file / compatible
-    run_fdtget_test "Integer" "32768" $file /cpus/PowerPC,970@1 d-cache-size
-    run_fdtget_test "Integer hex" "8000" -tx $file \
-	/cpus/PowerPC,970@1 d-cache-size
-    run_fdtget_test "Integer list" "61 62 63 0" -tbx $file \
-	/randomnode tricky1
-    run_fdtget_test "Byte list short" "a b c d de ea ad be ef" -tbx \
-	$file /randomnode blob
+108 121 78 97 109 101 0" $dtb / compatible
+    run_fdtget_test "MyBoardName MyBoardFamilyName" -t s $dtb / compatible
+    run_fdtget_test 32768 $dtb /cpus/PowerPC,970@1 d-cache-size
+    run_fdtget_test 8000 -tx $dtb /cpus/PowerPC,970@1 d-cache-size
+    run_fdtget_test "61 62 63 0" -tbx $dtb /randomnode tricky1
+    run_fdtget_test "a b c d de ea ad be ef" -tbx $dtb /randomnode blob
 
     # Here the property size is not a multiple of 4 bytes, so it should fail
-    run_fdtget_test "Integer list invalid" ERR -tlx \
-	$file /randomnode mixed
-    run_fdtget_test "Integer list halfword" "6162 6300 1234 0 a 0 b 0 c" -thx \
-	$file /randomnode mixed
-    run_fdtget_test "Integer list byte" \
-	"61 62 63 0 12 34 0 0 0 a 0 0 0 b 0 0 0 c" -thhx \
-	$file /randomnode mixed
-    run_fdtget_test "Missing property" ERR -ts \
-	$file /randomnode doctor-who
+    run_wrap_error_test $DTGET -tlx $dtb /randomnode mixed
+    run_fdtget_test "6162 6300 1234 0 a 0 b 0 c" -thx $dtb /randomnode mixed
+    run_fdtget_test "61 62 63 0 12 34 0 0 0 a 0 0 0 b 0 0 0 c" \
+	-thhx $dtb /randomnode mixed
+    run_wrap_error_test $DTGET -ts $dtb /randomnode doctor-who
 }
 
 fdtput_tests () {
-    file=label01.dtb
-    src=label01.dts
+    dts=label01.dts
+    dtb=$dts.fdtput.test.dtb
 
     # Create some test files containing useful strings
     base=tmp.test0
@@ -467,7 +489,7 @@ fdtput_tests () {
     bigfile2=tmp.test4
 
     # Filter out anything the shell might not like
-    cat $src | tr -d "'\"\n\;/\.\*{}\-" | tr -s "[:blank:]" " " >$base
+    cat $dts | tr -d "'\"\n\;/\.\*{}\-" | tr -s "[:blank:]" " " >$base
 
     # Make two small files
     head -5 $base >$file1
@@ -479,31 +501,25 @@ fdtput_tests () {
 
     # Allow just enough space for both file1 and file2
     space=$(( $(stat -c %s $file1) + $(stat -c %s $file2) ))
-    $DTC -O dtb -p $space -o $file ${file%.dtb}.dts 2>/dev/null
-
-    # run_fdtput_test <test-name> <expected-result> <file> <key> <flags>
-    #		<args>...
-    run_fdtput_test "Simple string" "a_model" $file / model -ts "a_model"
-    run_fdtput_test "Multiple string s" "board1 board2" \
-	$file / compatible -ts board1 board2
-    run_fdtput_test "Single string with spaces" "board1 board2" \
-	$file / compatible -ts "board1 board2"
-    run_fdtput_test "Integer" "32768" \
-	$file /cpus/PowerPC,970@1 d-cache-size "" "32768"
-    run_fdtput_test "Integer hex" "8001" \
-	$file /cpus/PowerPC,970@1 d-cache-size -tx 0x8001
-    run_fdtput_test "Integer list" "2 3 12" \
-	$file /randomnode tricky1 -tbi "02 003 12"
-    run_fdtput_test "Byte list short" "a b c ea ad be ef" \
-	$file /randomnode blob -tbx "a b c ea ad be ef"
-    run_fdtput_test "Integer list short" "a0b0c0d deeaae ef000000" \
-	$file /randomnode blob -tx "a0b0c0d deeaae ef000000"
-    run_fdtput_test "Large string list" "`cat $file1 $file2`" \
-	$file /randomnode blob -ts "`cat $file1`" "`cat $file2`"
+    run_dtc_test -O dtb -p $space -o $dtb $dts
+
+    # run_fdtput_test <expected-result> <file> <node> <property> <flags> <value>
+    run_fdtput_test "a_model" $dtb / model -ts "a_model"
+    run_fdtput_test "board1 board2" $dtb / compatible -ts board1 board2
+    run_fdtput_test "board1 board2" $dtb / compatible -ts "board1 board2"
+    run_fdtput_test "32768" $dtb /cpus/PowerPC,970@1 d-cache-size "" "32768"
+    run_fdtput_test "8001" $dtb /cpus/PowerPC,970@1 d-cache-size -tx 0x8001
+    run_fdtput_test "2 3 12" $dtb /randomnode tricky1 -tbi "02 003 12"
+    run_fdtput_test "a b c ea ad be ef" $dtb /randomnode blob \
+	-tbx "a b c ea ad be ef"
+    run_fdtput_test "a0b0c0d deeaae ef000000" $dtb /randomnode blob \
+	-tx "a0b0c0d deeaae ef000000"
+    run_fdtput_test "`cat $file1 $file2`" $dtb /randomnode blob \
+	-ts "`cat $file1`" "`cat $file2`"
 
     # This should be larger than available space in the fdt ($space)
-    run_fdtput_test "Enormous string list" ERR \
-	$file /randomnode blob -ts "`cat $bigfile1`" "`cat $bigfile2`"
+    run_wrap_error_test $DTPUT $dtb /randomnode blob \
+	-ts "`cat $bigfile1`" "`cat $bigfile2`"
 
     # TODO: Add tests for verbose mode?
 }
diff --git a/tests/tests.sh b/tests/tests.sh
index 3b7c6c8..31530d5 100644
--- a/tests/tests.sh
+++ b/tests/tests.sh
@@ -30,6 +30,15 @@ verbose_run () {
     fi
 }
 
+verbose_run_check () {
+    verbose_run "$@"
+    ret="$?"
+    FAIL_IF_SIGNAL $ret
+    if [ $ret != 0 ]; then
+	FAIL "Returned error code $ret"
+    fi
+}
+
 verbose_run_log () {
     LOG="$1"
     shift
@@ -40,3 +49,13 @@ verbose_run_log () {
     fi
     return $ret
 }
+
+verbose_run_log_check () {
+    verbose_run_log "$@"
+    ret="$?"
+    FAIL_IF_SIGNAL $ret
+    if [ $ret != 0 ]; then
+	FAIL "Returned error code $ret"
+    fi
+}
+

commit c34e88354a07099dbc15a41621c81f71325d25fd
Author: David Gibson <david@gibson.dropbear.id.au>
Date:   Fri Feb 3 16:12:08 2012 +1100

    Don't use diff to check fdt{get,put} results
    
    Currently the fdt{get,put}-runtest.sh scripts invoke diff to check if
    fdt{get,put} did the right thing.  This isn't great though: it's not
    obvious from the diff output which is the expected and which is the
    actual result; diff's line by line behaviour is useless here, since all
    the results are a single line and finally, when there is a difference
    it always prints information even when the tests are supposed to be
    running in quiet mode.
    
    This patch uses cmp instead, and explicitly prints the expected results,
    when running in verbose mode (the invocation of fdtget itself will have
    already displayed the actual results in this mode.
    
    Signed-off-by: David Gibson <david@gibson.dropbear.id.au>

diff --git a/tests/fdtget-runtest.sh b/tests/fdtget-runtest.sh
index 75e7503..dac7f9a 100755
--- a/tests/fdtget-runtest.sh
+++ b/tests/fdtget-runtest.sh
@@ -13,11 +13,12 @@ shift
 
 verbose_run_log_check "$LOG" $VALGRIND $DTGET "$@"
 
-diff $EXPECT $LOG
-ret="$?"
-
-if [ "$ret" -eq 0 ]; then
-	PASS
+if cmp $EXPECT $LOG>/dev/null; then
+    PASS
 else
-	FAIL
+    if [ -z "$QUIET_TEST" ]; then
+	echo "EXPECTED :-:"
+	cat $EXPECT
+    fi
+    FAIL "Results differ from expected"
 fi
diff --git a/tests/fdtput-runtest.sh b/tests/fdtput-runtest.sh
index dbd9c0d..527a968 100644
--- a/tests/fdtput-runtest.sh
+++ b/tests/fdtput-runtest.sh
@@ -28,11 +28,12 @@ verbose_run_check $VALGRIND "$DTPUT" "$dtb" "$node" "$property" $value $flags
 # Now fdtget to read the value
 verbose_run_log_check "$LOG" $VALGRIND "$DTGET" "$dtb" "$node" "$property" $flags
 
-diff $EXPECT $LOG
-ret="$?"
-
-if [ "$ret" -eq 0 ]; then
-	PASS
+if cmp $EXPECT $LOG >/dev/null; then
+    PASS
 else
-	FAIL
+    if [ -z "$QUIET_TEST" ]; then
+	echo "EXPECTED :-:"
+	cat $EXPECT
+    fi
+    FAIL "Results differ from expected"
 fi

commit 0b3b46e019f546a24927bb7ca009670762c00107
Author: David Gibson <david@gibson.dropbear.id.au>
Date:   Fri Feb 3 16:12:09 2012 +1100

    Generate test data for fdtput more sensibly
    
    Currently run_tests.sh generates several files of text test data.  The
    procedure it uses for this is somewhat torturous and has several problems:
     * Since the test data is derived from a dts file, a cursory glance at the
    test output suggests something is wrong with the processing of that dts.
    This is misleading since in fact it's just being used as an arbirary
    string.
     * Since the base input has linefeeds removed, the head and sort commands
    used later have no effect.
     * Although an attempt is made to get rid of characters which the shell
    will mangle, it's not thorough enough.  Specifically it leaves in \ which
    means that some string escapes found in the input data can get expanded
    somewhere along the line in some shells.
    
    This patch, therefore, replaces this generation of test data with a
    pre-canned "Lorem ipsum" of approximately 2k.  On my system, where /bin/sh
    is dash, this fixes a test failure due to the aforementioned string
    escapes being evaluated on one but not the other of the two comparison
    paths (I haven't tracked down exactly where the expansion is happening).
    
    Signed-off-by: David Gibson <david@gibson.dropbear.id.au>

diff --git a/tests/lorem.txt b/tests/lorem.txt
new file mode 100644
index 0000000..acff698
--- /dev/null
+++ b/tests/lorem.txt
@@ -0,0 +1,35 @@
+Lorem ipsum dolor sit amet, consectetur adipiscing elit. Mauris eros
+arcu, egestas non pellentesque non, euismod eu nibh. Proin arcu metus,
+dapibus vitae sodales rhoncus, suscipit vel nulla. Etiam lorem est,
+aliquam ut fringilla sit amet, condimentum et quam. Duis eu arcu odio,
+at pulvinar nisi. Morbi condimentum eros ut turpis rhoncus
+pharetra. Pellentesque habitant morbi tristique senectus et netus et
+malesuada fames ac turpis egestas. Nam et nulla enim. Etiam fringilla
+eleifend neque, at posuere ante lacinia a. Duis orci tortor, dictum ac
+gravida ac, euismod eu leo. Sed eget dolor tortor. Pellentesque
+venenatis, lectus eu vulputate porta, libero ipsum convallis mi, sit
+amet vehicula arcu elit sit amet odio.
+
+Fusce iaculis massa metus, id sagittis diam. Praesent molestie ante
+vel odio tincidunt auctor. Cum sociis natoque penatibus et magnis dis
+parturient montes, nascetur ridiculus mus. Duis rutrum vehicula nisl
+eget condimentum. In in justo nisl. Nullam id arcu at nisl eleifend
+pretium. Nulla interdum ligula id elit mollis dictum a sit amet
+quam. Nullam iaculis laoreet ipsum at tempus. Vestibulum in cursus
+dui. Curabitur porta lectus eget urna bibendum congue eget elementum
+nisi. Proin sit amet lectus ut neque iaculis consectetur eu sit amet
+nibh. Maecenas rhoncus dolor ac nunc gravida blandit. Fusce sem felis,
+aliquam a porttitor a, porta quis odio.
+
+Nunc purus lorem, sollicitudin non ultricies id, porta vitae
+enim. Nulla tristique gravida leo ut suscipit. Phasellus vitae turpis
+libero. Proin ac purus dolor, in suscipit magna. Sed et enim
+arcu. Morbi semper aliquet suscipit. Aenean laoreet condimentum massa,
+eu pharetra magna fermentum ut. Morbi euismod convallis tortor, eget
+fringilla lacus sagittis non. Nullam bibendum posuere feugiat.
+
+In at pulvinar massa. Mauris nunc lectus, mollis et malesuada
+pharetra, cursus sed lacus. Integer dolor urna, interdum a mollis at,
+vestibulum non nisl. Sed in urna tortor. Mauris arcu felis, volutpat
+quis euismod vel, congue sit amet ipsum. Morbi in aliquet purus. Duis
+cras amet.
diff --git a/tests/run_tests.sh b/tests/run_tests.sh
index 999c882..a561433 100755
--- a/tests/run_tests.sh
+++ b/tests/run_tests.sh
@@ -480,28 +480,10 @@ fdtget_tests () {
 fdtput_tests () {
     dts=label01.dts
     dtb=$dts.fdtput.test.dtb
+    text=lorem.txt
 
-    # Create some test files containing useful strings
-    base=tmp.test0
-    file1=tmp.test1
-    file2=tmp.test2
-    bigfile1=tmp.test3
-    bigfile2=tmp.test4
-
-    # Filter out anything the shell might not like
-    cat $dts | tr -d "'\"\n\;/\.\*{}\-" | tr -s "[:blank:]" " " >$base
-
-    # Make two small files
-    head -5 $base >$file1
-    cat $file1 | tr a-z A-Z | cut -c10-30 | sort -r >$file2
-
-    # and two larger ones
-    cat $base > $bigfile1
-    tac $base | tr a-z A-Z | sort -r >$bigfile2
-
-    # Allow just enough space for both file1 and file2
-    space=$(( $(stat -c %s $file1) + $(stat -c %s $file2) ))
-    run_dtc_test -O dtb -p $space -o $dtb $dts
+    # Allow just enough space for $text
+    run_dtc_test -O dtb -p $(stat -c %s $text) -o $dtb $dts
 
     # run_fdtput_test <expected-result> <file> <node> <property> <flags> <value>
     run_fdtput_test "a_model" $dtb / model -ts "a_model"
@@ -514,12 +496,10 @@ fdtput_tests () {
 	-tbx "a b c ea ad be ef"
     run_fdtput_test "a0b0c0d deeaae ef000000" $dtb /randomnode blob \
 	-tx "a0b0c0d deeaae ef000000"
-    run_fdtput_test "`cat $file1 $file2`" $dtb /randomnode blob \
-	-ts "`cat $file1`" "`cat $file2`"
+    run_fdtput_test "$(cat $text)" $dtb /randomnode blob -ts "$(cat $text)"
 
-    # This should be larger than available space in the fdt ($space)
-    run_wrap_error_test $DTPUT $dtb /randomnode blob \
-	-ts "`cat $bigfile1`" "`cat $bigfile2`"
+    # This should be larger than available space in the fdt
+    run_wrap_error_test $DTPUT $dtb /randomnode blob -ts "$(cat $text $text)"
 
     # TODO: Add tests for verbose mode?
 }

commit e280442e08fcbe8431dc85d836ff3ecc489932fb
Author: David Gibson <david@gibson.dropbear.id.au>
Date:   Fri Feb 3 17:06:12 2012 +1100

    Fix uninitialized access bug in utilfdt_decode_type
    
    I just found this little bug with valgrind.  strchr() will return true
    if the given character is '\0'.  This meant that utilfdt_decode_type()
    could take a path which accesses uninitialized data when given the
    (invalid) format string "L".
    
    Signed-off-by: David Gibson <david@gibson.dropbear.id.au>

diff --git a/util.c b/util.c
index d82d41f..2422c34 100644
--- a/util.c
+++ b/util.c
@@ -296,6 +296,9 @@ int utilfdt_decode_type(const char *fmt, int *type, int *size)
 {
 	int qualifier = 0;
 
+	if (!*fmt)
+		return -1;
+
 	/* get the conversion qualifier */
 	*size = -1;
 	if (strchr("hlLb", *fmt)) {
@@ -311,7 +314,7 @@ int utilfdt_decode_type(const char *fmt, int *type, int *size)
 	}
 
 	/* we should now have a type */
-	if (!strchr("iuxs", *fmt))
+	if ((*fmt == '\0') || !strchr("iuxs", *fmt))
 		return -1;
 
 	/* convert qualifier (bhL) to byte size */

commit a6e6c60e3a97a6b3a033cd052bb3740fd53cbf4c
Author: Horst Kronstorfer <hkronsto@frequentis.com>
Date:   Tue Feb 7 10:02:53 2012 +0100

    dtc: Fix zero-length input segfault
    
    This patch fixes a segmentation fault caused by dereferencing a NULL
    pointer (pos->file aka yylloc.file) in srcpos_string when the input
    length is 0 (fe 'dtc </dev/null'.) Reason: yylloc.file is initialized
    with 0 and the tokenizer, which updates yylloc.file via srcpos_update
    doesn't get a chance to run on zero-length input.
    
    Signed-off-by: Horst Kronstorfer <hkronsto@frequentis.com>

diff --git a/treesource.c b/treesource.c
index c09aafa..33eeba5 100644
--- a/treesource.c
+++ b/treesource.c
@@ -23,6 +23,7 @@
 
 extern FILE *yyin;
 extern int yyparse(void);
+extern YYLTYPE yylloc;
 
 struct boot_info *the_boot_info;
 int treesource_error;
@@ -34,6 +35,7 @@ struct boot_info *dt_from_source(const char *fname)
 
 	srcfile_push(fname);
 	yyin = current_srcfile->f;
+	yylloc.file = current_srcfile;
 
 	if (yyparse() != 0)
 		die("Unable to parse input tree\n");

commit 097ec97c1a35685957210adb93692c3e210bc82c
Author: Simon Glass <sjg@chromium.org>
Date:   Fri Mar 2 17:12:07 2012 -0800

    fdtget: Fix multiple arg bug and add test for it
    
    There is a rather unfortunate bug in fdtget in that if multiple argument
    sets are provided, it just repeats displaying the first set ones for
    each set.
    
    Fix this bug and add a test for it.
    
    Signed-off-by: Simon Glass <sjg@chromium.org>
    Acked-by: David Gibson <david@gibson.dropbear.id.au>

diff --git a/fdtget.c b/fdtget.c
index 2c384b6..9783e04 100644
--- a/fdtget.c
+++ b/fdtget.c
@@ -146,13 +146,13 @@ static int do_fdtget(struct display_info *disp, const char *filename,
 		return -1;
 
 	for (i = 0; i + 2 <= arg_count; i += 2) {
-		node = fdt_path_offset(blob, arg[0]);
+		node = fdt_path_offset(blob, arg[i]);
 		if (node < 0) {
-			report_error(arg[0], node);
+			report_error(arg[i], node);
 			return -1;
 		}
 
-		if (show_data_for_item(blob, disp, node, arg[1]))
+		if (show_data_for_item(blob, disp, node, arg[i + 1]))
 			return -1;
 	}
 	return 0;
diff --git a/tests/fdtget-runtest.sh b/tests/fdtget-runtest.sh
index dac7f9a..982fbe1 100755
--- a/tests/fdtget-runtest.sh
+++ b/tests/fdtget-runtest.sh
@@ -8,7 +8,7 @@ rm -f $LOG $EXPECT
 trap "rm -f $LOG $EXPECT" 0
 
 expect="$1"
-echo $expect >$EXPECT
+echo -e $expect >$EXPECT
 shift
 
 verbose_run_log_check "$LOG" $VALGRIND $DTGET "$@"
diff --git a/tests/run_tests.sh b/tests/run_tests.sh
index a561433..ac6fa17 100755
--- a/tests/run_tests.sh
+++ b/tests/run_tests.sh
@@ -475,6 +475,9 @@ fdtget_tests () {
     run_fdtget_test "61 62 63 0 12 34 0 0 0 a 0 0 0 b 0 0 0 c" \
 	-thhx $dtb /randomnode mixed
     run_wrap_error_test $DTGET -ts $dtb /randomnode doctor-who
+
+    # Test multiple arguments
+    run_fdtget_test "MyBoardName\nmemory" -ts $dtb / model /memory device_type
 }
 
 fdtput_tests () {

commit 30eb201adae2132c36874c89d4c6cf3195659d71
Author: Simon Glass <sjg@chromium.org>
Date:   Fri Mar 2 17:12:08 2012 -0800

    fdtget: Add -p to list the properties of a node
    
    This option lists the properties of each node given as a parameter, one
    property per line.
    
    Signed-off-by: Simon Glass <sjg@chromium.org>
    Acked-by: David Gibson <david@gibson.dropbear.id.au>

diff --git a/fdtget.c b/fdtget.c
index 9783e04..874bcbf 100644
--- a/fdtget.c
+++ b/fdtget.c
@@ -1,6 +1,12 @@
 /*
  * Copyright (c) 2011 The Chromium OS Authors. All rights reserved.
  *
+ * Portions from U-Boot cmd_fdt.c (C) Copyright 2007
+ * Gerald Van Baren, Custom IDEAS, vanbaren@cideas.com
+ * Based on code written by:
+ *   Pantelis Antoniou <pantelis.antoniou@gmail.com> and
+ *   Matthew McClintock <msm@freescale.com>
+ *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License as
  * published by the Free Software Foundation; either version 2 of
@@ -17,6 +23,7 @@
  * MA 02111-1307 USA
  */
 
+#include <assert.h>
 #include <ctype.h>
 #include <getopt.h>
 #include <stdio.h>
@@ -27,10 +34,16 @@
 
 #include "util.h"
 
+enum display_mode {
+	MODE_SHOW_VALUE,	/* show values for node properties */
+	MODE_LIST_PROPS,	/* list the properties for a node */
+};
+
 /* Holds information which controls our output and options */
 struct display_info {
 	int type;		/* data type (s/i/u/x or 0 for default) */
 	int size;		/* data size (1/2/4) */
+	enum display_mode mode;	/* display mode that we are using */
 };
 
 static void report_error(const char *where, int err)
@@ -98,6 +111,32 @@ static int show_data(struct display_info *disp, const char *data, int len)
 }
 
 /**
+ * List all properties in a node, one per line.
+ *
+ * @param blob		FDT blob
+ * @param node		Node to display
+ * @return 0 if ok, or FDT_ERR... if not.
+ */
+static int list_properties(const void *blob, int node)
+{
+	const struct fdt_property *data;
+	const char *name;
+	int prop;
+
+	prop = fdt_first_property_offset(blob, node);
+	do {
+		/* Stop silently when there are no more properties */
+		if (prop < 0)
+			return prop == -FDT_ERR_NOTFOUND ? 0 : prop;
+		data = fdt_get_property_by_offset(blob, prop, NULL);
+		name = fdt_string(blob, fdt32_to_cpu(data->nameoff));
+		if (name)
+			puts(name);
+		prop = fdt_next_property_offset(blob, prop);
+	} while (1);
+}
+
+/**
  * Show the data for a given node (and perhaps property) according to the
  * display option provided.
  *
@@ -113,6 +152,10 @@ static int show_data_for_item(const void *blob, struct display_info *disp,
 	const void *value = NULL;
 	int len, err = 0;
 
+	if (disp->mode == MODE_LIST_PROPS)
+		return list_properties(blob, node);
+
+	assert(property);
 	value = fdt_getprop(blob, node, property, &len);
 	if (value) {
 		if (show_data(disp, value, len))
@@ -136,23 +179,25 @@ static int show_data_for_item(const void *blob, struct display_info *disp,
  * @param return 0 if ok, -ve on error
  */
 static int do_fdtget(struct display_info *disp, const char *filename,
-		     char **arg, int arg_count)
+		     char **arg, int arg_count, int args_per_step)
 {
 	char *blob;
+	const char *prop;
 	int i, node;
 
 	blob = utilfdt_read(filename);
 	if (!blob)
 		return -1;
 
-	for (i = 0; i + 2 <= arg_count; i += 2) {
+	for (i = 0; i + args_per_step <= arg_count; i += args_per_step) {
 		node = fdt_path_offset(blob, arg[i]);
 		if (node < 0) {
 			report_error(arg[i], node);
 			return -1;
 		}
+		prop = args_per_step == 1 ? NULL : arg[i + 1];
 
-		if (show_data_for_item(blob, disp, node, arg[i + 1]))
+		if (show_data_for_item(blob, disp, node, prop))
 			return -1;
 	}
 	return 0;
@@ -164,8 +209,10 @@ static const char *usage_msg =
 	"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"
 	"Options:\n"
 	"\t-t <type>\tType of data\n"
+	"\t-p\t\tList properties for each node\n"
 	"\t-h\t\tPrint this help\n\n"
 	USAGE_TYPE_MSG;
 
@@ -182,12 +229,14 @@ int main(int argc, char *argv[])
 {
 	char *filename = NULL;
 	struct display_info disp;
+	int args_per_step = 2;
 
 	/* set defaults */
 	memset(&disp, '\0', sizeof(disp));
 	disp.size = -1;
+	disp.mode = MODE_SHOW_VALUE;
 	for (;;) {
-		int c = getopt(argc, argv, "ht:");
+		int c = getopt(argc, argv, "hpt:");
 		if (c == -1)
 			break;
 
@@ -201,6 +250,11 @@ int main(int argc, char *argv[])
 					&disp.size))
 				usage("Invalid type string");
 			break;
+
+		case 'p':
+			disp.mode = MODE_LIST_PROPS;
+			args_per_step = 1;
+			break;
 		}
 	}
 
@@ -217,10 +271,10 @@ int main(int argc, char *argv[])
 		return 0;
 
 	/* Check for node, property arguments */
-	if (argc % 2)
+	if (args_per_step == 2 && (argc % 2))
 		usage("Must have an even number of arguments");
 
-	if (do_fdtget(&disp, filename, argv, argc))
+	if (do_fdtget(&disp, filename, argv, argc, args_per_step))
 		return 1;
 	return 0;
 }

commit 16c99ee8e3e60fb47b5eaa1778996fe6ef11c611
Author: Simon Glass <sjg@chromium.org>
Date:   Tue Mar 6 16:41:46 2012 -0800

    fdtget: Add -l to list the subnodes of a node
    
    This option lists the subnodes of each node given as a parameter, one
    subnode per line.
    
    Signed-off-by: Simon Glass <sjg@chromium.org>
    Acked-by: David Gibson <david@gibson.dropbear.id.au>

diff --git a/fdtget.c b/fdtget.c
index 874bcbf..2c7d238 100644
--- a/fdtget.c
+++ b/fdtget.c
@@ -37,6 +37,7 @@
 enum display_mode {
 	MODE_SHOW_VALUE,	/* show values for node properties */
 	MODE_LIST_PROPS,	/* list the properties for a node */
+	MODE_LIST_SUBNODES,	/* list the subnodes of a node */
 };
 
 /* Holds information which controls our output and options */
@@ -136,6 +137,61 @@ static int list_properties(const void *blob, int node)
 	} while (1);
 }
 
+#define MAX_LEVEL	32		/* how deeply nested we will go */
+
+/**
+ * List all subnodes in a node, one per line
+ *
+ * @param blob		FDT blob
+ * @param node		Node to display
+ * @return 0 if ok, or FDT_ERR... if not.
+ */
+static int list_subnodes(const void *blob, int node)
+{
+	int nextoffset;		/* next node offset from libfdt */
+	uint32_t tag;		/* current tag */
+	int level = 0;		/* keep track of nesting level */
+	const char *pathp;
+	int depth = 1;		/* the assumed depth of this node */
+
+	while (level >= 0) {
+		tag = fdt_next_tag(blob, node, &nextoffset);
+		switch (tag) {
+		case FDT_BEGIN_NODE:
+			pathp = fdt_get_name(blob, node, NULL);
+			if (level <= depth) {
+				if (pathp == NULL)
+					pathp = "/* NULL pointer error */";
+				if (*pathp == '\0')
+					pathp = "/";	/* root is nameless */
+				if (level == 1)
+					puts(pathp);
+			}
+			level++;
+			if (level >= MAX_LEVEL) {
+				printf("Nested too deep, aborting.\n");
+				return 1;
+			}
+			break;
+		case FDT_END_NODE:
+			level--;
+			if (level == 0)
+				level = -1;		/* exit the loop */
+			break;
+		case FDT_END:
+			return 1;
+		case FDT_PROP:
+			break;
+		default:
+			if (level <= depth)
+				printf("Unknown tag 0x%08X\n", tag);
+			return 1;
+		}
+		node = nextoffset;
+	}
+	return 0;
+}
+
 /**
  * Show the data for a given node (and perhaps property) according to the
  * display option provided.
@@ -152,20 +208,30 @@ static int show_data_for_item(const void *blob, struct display_info *disp,
 	const void *value = NULL;
 	int len, err = 0;
 
-	if (disp->mode == MODE_LIST_PROPS)
-		return list_properties(blob, node);
+	switch (disp->mode) {
+	case MODE_LIST_PROPS:
+		err = list_properties(blob, node);
+		break;
+
+	case MODE_LIST_SUBNODES:
+		err = list_subnodes(blob, node);
+		break;
 
-	assert(property);
-	value = fdt_getprop(blob, node, property, &len);
-	if (value) {
-		if (show_data(disp, value, len))
+	default:
+		assert(property);
+		value = fdt_getprop(blob, node, property, &len);
+		if (value) {
+			if (show_data(disp, value, len))
+				err = -1;
+			else
+				printf("\n");
+		} else {
+			report_error(property, len);
 			err = -1;
-		else
-			printf("\n");
-	} else {
-		report_error(property, len);
-		err = -1;
+		}
+		break;
 	}
+
 	return err;
 }
 
@@ -213,6 +279,7 @@ static const char *usage_msg =
 	"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-h\t\tPrint this help\n\n"
 	USAGE_TYPE_MSG;
 
@@ -236,7 +303,7 @@ int main(int argc, char *argv[])
 	disp.size = -1;
 	disp.mode = MODE_SHOW_VALUE;
 	for (;;) {
-		int c = getopt(argc, argv, "hpt:");
+		int c = getopt(argc, argv, "hlpt:");
 		if (c == -1)
 			break;
 
@@ -255,6 +322,11 @@ int main(int argc, char *argv[])
 			disp.mode = MODE_LIST_PROPS;
 			args_per_step = 1;
 			break;
+
+		case 'l':
+			disp.mode = MODE_LIST_SUBNODES;
+			args_per_step = 1;
+			break;
 		}
 	}
 

commit 7fcbef275741793064268cf0a1bdcd59144a9a10
Author: Simon Glass <sjg@chromium.org>
Date:   Tue Mar 6 16:41:47 2012 -0800

    fdtget: Add -d to provide a default value
    
    Sometimes the requested node or property is not present in the device
    tree. This option provides a way of reporting a default value in this
    case, rather than halting with an error.
    
    Signed-off-by: Simon Glass <sjg@chromium.org>
    Acked-by: David Gibson <david@gibson.dropbear.id.au>

diff --git a/fdtget.c b/fdtget.c
index 2c7d238..c2fbab2 100644
--- a/fdtget.c
+++ b/fdtget.c
@@ -45,6 +45,7 @@ struct display_info {
 	int type;		/* data type (s/i/u/x or 0 for default) */
 	int size;		/* data size (1/2/4) */
 	enum display_mode mode;	/* display mode that we are using */
+	const char *default_val; /* default value if node/property not found */
 };
 
 static void report_error(const char *where, int err)
@@ -225,6 +226,8 @@ static int show_data_for_item(const void *blob, struct display_info *disp,
 				err = -1;
 			else
 				printf("\n");
+		} else if (disp->default_val) {
+			puts(disp->default_val);
 		} else {
 			report_error(property, len);
 			err = -1;
@@ -258,8 +261,13 @@ static int do_fdtget(struct display_info *disp, const char *filename,
 	for (i = 0; i + args_per_step <= arg_count; i += args_per_step) {
 		node = fdt_path_offset(blob, arg[i]);
 		if (node < 0) {
-			report_error(arg[i], node);
-			return -1;
+			if (disp->default_val) {
+				puts(disp->default_val);
+				continue;
+			} else {
+				report_error(arg[i], node);
+				return -1;
+			}
 		}
 		prop = args_per_step == 1 ? NULL : arg[i + 1];
 
@@ -280,6 +288,8 @@ static const char *usage_msg =
 	"\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;
 
@@ -303,7 +313,7 @@ int main(int argc, char *argv[])
 	disp.size = -1;
 	disp.mode = MODE_SHOW_VALUE;
 	for (;;) {
-		int c = getopt(argc, argv, "hlpt:");
+		int c = getopt(argc, argv, "d:hlpt:");
 		if (c == -1)
 			break;
 
@@ -327,6 +337,10 @@ int main(int argc, char *argv[])
 			disp.mode = MODE_LIST_SUBNODES;
 			args_per_step = 1;
 			break;
+
+		case 'd':
+			disp.default_val = optarg;
+			break;
 		}
 	}
 
diff --git a/tests/run_tests.sh b/tests/run_tests.sh
index ac6fa17..deffae3 100755
--- a/tests/run_tests.sh
+++ b/tests/run_tests.sh
@@ -478,6 +478,12 @@ fdtget_tests () {
 
     # Test multiple arguments
     run_fdtget_test "MyBoardName\nmemory" -ts $dtb / model /memory device_type
+
+    # Test defaults
+    run_wrap_error_test $DTGET -tx $dtb /randomnode doctor-who
+    run_fdtget_test "<the dead silence>" -tx \
+	-d "<the dead silence>" $dtb /randomnode doctor-who
+    run_fdtget_test "<blink>" -tx -d "<blink>" $dtb /memory doctor-who
 }
 
 fdtput_tests () {

commit de6b76240e91b9288cdce63ab81e51a7232d0927
Author: Simon Glass <sjg@chromium.org>
Date:   Wed Mar 14 20:04:13 2012 -0700

    dtc: Add -i option to support search paths
    
    It is often inconvenient to place device tree files in the same directory
    as their includes, or to specify the full path to include files.
    
    An example of this is in U-Boot where we have a .dtsi file for each SOC
    type, and this is included by the board .dts file. We need to either use
    a mechanism like:
    
    /include/ ARCH_CPU_DTS
    
    with sed or cpp to perform the replacement with the correct path, or
    we must specify the full path in the file:
    
    /include/ "../../arch/arm/dts/tegra20.dtsi"
    
    The first option is not desirable since it requires anyone compiling the
    file to first pre-process it. The second is not desirable since it
    introduces a path which is project-specific into a file which is supposed
    to be a hardware description. For example Linux and U-Boot are unlikely to
    put these include files in the same place.
    
    It is much more convenient to specify the search patch on the command line
    as is done with C pre-processors, for example.
    
    Introduce a -i option to add to the list of search paths used to find
    source and include files.
    
    We cannot use -I as it is already in use. Other suggestions welcome.
    
    Signed-off-by: Simon Glass <sjg@chromium.org>

diff --git a/dtc.c b/dtc.c
index 7a0c605..83aef32 100644
--- a/dtc.c
+++ b/dtc.c
@@ -82,6 +82,8 @@ static void  __attribute__ ((noreturn)) usage(void)
 	fprintf(stderr, "\t\tSet the physical boot cpu\n");
 	fprintf(stderr, "\t-f\n");
 	fprintf(stderr, "\t\tForce - try to produce output even if the input tree has errors\n");
+	fprintf(stderr, "\t-i\n");
+	fprintf(stderr, "\t\tAdd a path to search for include files\n");
 	fprintf(stderr, "\t-s\n");
 	fprintf(stderr, "\t\tSort nodes and properties before outputting (only useful for\n\t\tcomparing trees)\n");
 	fprintf(stderr, "\t-v\n");
@@ -113,7 +115,8 @@ int main(int argc, char *argv[])
 	minsize    = 0;
 	padsize    = 0;
 
-	while ((opt = getopt(argc, argv, "hI:O:o:V:d:R:S:p:fqb:vH:s")) != EOF) {
+	while ((opt = getopt(argc, argv, "hI:O:o:V:d:R:S:p:fqb:i:vH:s"))
+			!= EOF) {
 		switch (opt) {
 		case 'I':
 			inform = optarg;
@@ -148,6 +151,9 @@ int main(int argc, char *argv[])
 		case 'b':
 			cmdline_boot_cpuid = strtoll(optarg, NULL, 0);
 			break;
+		case 'i':
+			srcfile_add_search_path(optarg);
+			break;
 		case 'v':
 			printf("Version: %s\n", DTC_VERSION);
 			exit(0);
diff --git a/srcpos.c b/srcpos.c
index 36a38e9..3ee523d 100644
--- a/srcpos.c
+++ b/srcpos.c
@@ -24,6 +24,15 @@
 #include "dtc.h"
 #include "srcpos.h"
 
+/* A node in our list of directories to search for source/include files */
+struct search_path {
+	struct search_path *next;	/* next node in list, NULL for end */
+	const char *dirname;		/* name of directory to search */
+};
+
+/* This is the list of directories that we search for source files */
+static struct search_path *search_path_head, **search_path_tail;
+
 
 static char *dirname(const char *path)
 {
@@ -47,6 +56,64 @@ struct srcfile_state *current_srcfile; /* = NULL */
 #define MAX_SRCFILE_DEPTH     (100)
 static int srcfile_depth; /* = 0 */
 
+
+/**
+ * Try to open a file in a given directory.
+ *
+ * If the filename is an absolute path, then dirname is ignored. If it is a
+ * relative path, then we look in that directory for the file.
+ *
+ * @param dirname	Directory to look in, or NULL for none
+ * @param fname		Filename to look for
+ * @param fp		Set to NULL if file did not open
+ * @return allocated filename on success (caller must free), NULL on failure
+ */
+static char *try_open(const char *dirname, const char *fname, FILE **fp)
+{
+	char *fullname;
+
+	if (!dirname || fname[0] == '/')
+		fullname = xstrdup(fname);
+	else
+		fullname = join_path(dirname, fname);
+
+	*fp = fopen(fullname, "r");
+	if (!*fp) {
+		free(fullname);
+		fullname = NULL;
+	}
+
+	return fullname;
+}
+
+/**
+ * Open a file for read access
+ *
+ * If it is a relative filename, we search the full search path for it.
+ *
+ * @param fname	Filename to open
+ * @param fp	Returns pointer to opened FILE, or NULL on failure
+ * @return pointer to allocated filename, which caller must free
+ */
+static char *fopen_any_on_path(const char *fname, FILE **fp)
+{
+	const char *cur_dir = NULL;
+	struct search_path *node;
+	char *fullname;
+
+	/* Try current directory first */
+	assert(fp);
+	if (current_srcfile)
+		cur_dir = current_srcfile->dir;
+	fullname = try_open(cur_dir, fname, fp);
+
+	/* Failing that, try each search path in turn */
+	for (node = search_path_head; !*fp && node; node = node->next)
+		fullname = try_open(node->dirname, fname, fp);
+
+	return fullname;
+}
+
 FILE *srcfile_relative_open(const char *fname, char **fullnamep)
 {
 	FILE *f;
@@ -56,13 +123,7 @@ FILE *srcfile_relative_open(const char *fname, char **fullnamep)
 		f = stdin;
 		fullname = xstrdup("<stdin>");
 	} else {
-		if (!current_srcfile || !current_srcfile->dir
-		    || (fname[0] == '/'))
-			fullname = xstrdup(fname);
-		else
-			fullname = join_path(current_srcfile->dir, fname);
-
-		f = fopen(fullname, "r");
+		fullname = fopen_any_on_path(fname, &f);
 		if (!f)
 			die("Couldn't open \"%s\": %s\n", fname,
 			    strerror(errno));
@@ -119,6 +180,23 @@ int srcfile_pop(void)
 	return current_srcfile ? 1 : 0;
 }
 
+void srcfile_add_search_path(const char *dirname)
+{
+	struct search_path *node;
+
+	/* Create the node */
+	node = xmalloc(sizeof(*node));
+	node->next = NULL;
+	node->dirname = xstrdup(dirname);
+
+	/* Add to the end of our list */
+	if (search_path_tail)
+		*search_path_tail = node;
+	else
+		search_path_head = node;
+	search_path_tail = &node->next;
+}
+
 /*
  * The empty source position.
  */
diff --git a/srcpos.h b/srcpos.h
index ce980ca..5617916 100644
--- a/srcpos.h
+++ b/srcpos.h
@@ -33,10 +33,39 @@ struct srcfile_state {
 extern FILE *depfile; /* = NULL */
 extern struct srcfile_state *current_srcfile; /* = NULL */
 
+/**
+ * Open a source file.
+ *
+ * If the source file is a relative pathname, then it is searched for in the
+ * current directory (the directory of the last source file read) and after
+ * that in the search path.
+ *
+ * We work through the search path in order from the first path specified to
+ * the last.
+ *
+ * If the file is not found, then this function does not return, but calls
+ * die().
+ *
+ * @param fname		Filename to search
+ * @param fullnamep	If non-NULL, it is set to the allocated filename of the
+ *			file that was opened. The caller is then responsible
+ *			for freeing the pointer.
+ * @return pointer to opened FILE
+ */
 FILE *srcfile_relative_open(const char *fname, char **fullnamep);
+
 void srcfile_push(const char *fname);
 int srcfile_pop(void);
 
+/**
+ * Add a new directory to the search path for input files
+ *
+ * The new path is added at the end of the list.
+ *
+ * @param dirname	Directory to add
+ */
+void srcfile_add_search_path(const char *dirname);
+
 struct srcpos {
     int first_line;
     int first_column;
diff --git a/tests/run_tests.sh b/tests/run_tests.sh
index deffae3..e470b82 100755
--- a/tests/run_tests.sh
+++ b/tests/run_tests.sh
@@ -412,6 +412,17 @@ dtc_tests () {
     # Dependencies
     run_dtc_test -I dts -O dtb -o dependencies.test.dtb -d dependencies.test.d dependencies.dts
     run_wrap_test cmp dependencies.test.d dependencies.cmp
+
+    # Search paths
+    run_wrap_error_test $DTC -I dts -O dtb -o search_paths.dtb search_paths.dts
+    run_dtc_test -i search_dir -I dts -O dtb -o search_paths.dtb \
+	search_paths.dts
+    run_wrap_error_test $DTC -i search_dir_b -I dts -O dtb \
+	-o search_paths_b.dtb search_paths_b.dts
+    run_dtc_test -i search_dir_b -i search_dir -I dts -O dtb \
+	-o search_paths_b.dtb search_paths_b.dts
+    run_dtc_test -I dts -O dtb -o search_paths_subdir.dtb \
+	search_dir_b/search_paths_subdir.dts
 }
 
 cmp_tests () {
diff --git a/tests/search_dir/search_test.dtsi b/tests/search_dir/search_test.dtsi
new file mode 100644
index 0000000..217fb80
--- /dev/null
+++ b/tests/search_dir/search_test.dtsi
@@ -0,0 +1,4 @@
+/include/ "search_test2.dtsi"
+
+/ {
+};
diff --git a/tests/search_dir/search_test2.dtsi b/tests/search_dir/search_test2.dtsi
new file mode 100644
index 0000000..7b9099e
--- /dev/null
+++ b/tests/search_dir/search_test2.dtsi
@@ -0,0 +1,3 @@
+
+/ {
+};
diff --git a/tests/search_dir_b/search_paths_subdir.dts b/tests/search_dir_b/search_paths_subdir.dts
new file mode 100644
index 0000000..5c5c962
--- /dev/null
+++ b/tests/search_dir_b/search_paths_subdir.dts
@@ -0,0 +1,6 @@
+/dts-v1/;
+
+/include/ "search_test_c.dtsi"
+
+/ {
+};
diff --git a/tests/search_dir_b/search_test_b.dtsi b/tests/search_dir_b/search_test_b.dtsi
new file mode 100644
index 0000000..b06a7d6
--- /dev/null
+++ b/tests/search_dir_b/search_test_b.dtsi
@@ -0,0 +1,4 @@
+/include/ "search_test_b2.dtsi"
+
+/ {
+};
diff --git a/tests/search_dir_b/search_test_b2.dtsi b/tests/search_dir_b/search_test_b2.dtsi
new file mode 100644
index 0000000..2526b43
--- /dev/null
+++ b/tests/search_dir_b/search_test_b2.dtsi
@@ -0,0 +1,5 @@
+
+/include/ "search_test.dtsi"
+
+/ {
+};
diff --git a/tests/search_dir_b/search_test_c.dtsi b/tests/search_dir_b/search_test_c.dtsi
new file mode 100644
index 0000000..336d7a2
--- /dev/null
+++ b/tests/search_dir_b/search_test_c.dtsi
@@ -0,0 +1,2 @@
+/ {
+};
diff --git a/tests/search_paths.dts b/tests/search_paths.dts
new file mode 100644
index 0000000..a2bf179
--- /dev/null
+++ b/tests/search_paths.dts
@@ -0,0 +1,6 @@
+/dts-v1/;
+
+/include/ "search_test.dtsi"
+
+/ {
+};
diff --git a/tests/search_paths_b.dts b/tests/search_paths_b.dts
new file mode 100644
index 0000000..6ace6e2
--- /dev/null
+++ b/tests/search_paths_b.dts
@@ -0,0 +1,6 @@
+/dts-v1/;
+
+/include/ "search_test_b.dtsi"
+
+/ {
+};

commit eaec1dbc5946d5fd01a9ef7120f8461c74d759a0
Author: Stephen Warren <swarren@wwwdotorg.org>
Date:   Tue Mar 20 20:23:46 2012 -0600

    fdtget-runtest.sh: Fix failures when /bin/sh isn't bash
    
    On Ubuntu, /bin/sh is dash (at least by default), and dash's echo doesn't
    accept the -e option. This means that fdtget-runtest.sh's EXPECT file will
    contain "-e foo" rather than just "foo", which causes a test failure.
    
    To work around this, run /bin/echo instead of (builtin) echo, which has
    more chance of supporting the -e option.
    
    Another possible fix is to change all the #! lines to /bin/bash rather
    than /bin/sh, and change run_tests.sh to invoke sub-scripts using $SHELL
    instead of just "sh". However, that would require bash specifically, which
    may not be desirable.
    
    Signed-off-by: Stephen Warren <swarren@wwwdotorg.org>
    Acked-by: David Gibson <david@gibson.dropbear.id.au>

diff --git a/tests/fdtget-runtest.sh b/tests/fdtget-runtest.sh
index 982fbe1..c3a3559 100755
--- a/tests/fdtget-runtest.sh
+++ b/tests/fdtget-runtest.sh
@@ -8,7 +8,7 @@ rm -f $LOG $EXPECT
 trap "rm -f $LOG $EXPECT" 0
 
 expect="$1"
-echo -e $expect >$EXPECT
+/bin/echo -e $expect >$EXPECT
 shift
 
 verbose_run_log_check "$LOG" $VALGRIND $DTGET "$@"

commit 5f0c3b2d6235dec65fff1628a97f45e21680b36d
Author: Stephen Warren <swarren@wwwdotorg.org>
Date:   Tue Apr 3 20:56:00 2012 -0600

    dtc: Basic integer expressions
    
    Written by David Gibson <david@gibson.dropbear.id.au>. Additions by me:
    * Ported to ToT dtc.
    * Renamed cell to integer throughout.
    * Implemented value range checks.
    * Allow U/L/UL/LL/ULL suffix on literals.
    * Enabled the commented test.
    
    Signed-off-by: Stephen Warren <swarren@wwwdotorg.org>

diff --git a/dtc-lexer.l b/dtc-lexer.l
index 73d190c..4715f31 100644
--- a/dtc-lexer.l
+++ b/dtc-lexer.l
@@ -110,7 +110,7 @@ static int pop_input_file(void);
 			return DT_LABEL;
 		}
 
-<V1>[0-9]+|0[xX][0-9a-fA-F]+      {
+<V1>([0-9]+|0[xX][0-9a-fA-F]+)(U|L|UL|LL|ULL)? {
 			yylval.literal = xstrdup(yytext);
 			DPRINT("Literal: '%s'\n", yylval.literal);
 			return DT_LITERAL;
@@ -164,6 +164,15 @@ static int pop_input_file(void);
 <*>{COMMENT}+	/* eat C-style comments */
 <*>{LINECOMMENT}+ /* eat C++-style comments */
 
+<*>"<<"		{ return DT_LSHIFT; };
+<*>">>"		{ return DT_RSHIFT; };
+<*>"<="		{ return DT_LE; };
+<*>">="		{ return DT_GE; };
+<*>"=="		{ return DT_EQ; };
+<*>"!="		{ return DT_NE; };
+<*>"&&"		{ return DT_AND; };
+<*>"||"		{ return DT_OR; };
+
 <*>.		{
 			DPRINT("Char: %c (\\x%02x)\n", yytext[0],
 				(unsigned)yytext[0]);
diff --git a/dtc-parser.y b/dtc-parser.y
index 348616b..6d5c2c2 100644
--- a/dtc-parser.y
+++ b/dtc-parser.y
@@ -50,16 +50,17 @@ static unsigned char eval_char_literal(const char *s);
 		int		bits;
 	} array;
 
-	uint64_t addr;
 	struct property *prop;
 	struct property *proplist;
 	struct node *node;
 	struct node *nodelist;
 	struct reserve_info *re;
+	uint64_t integer;
 }
 
 %token DT_V1
 %token DT_MEMRESERVE
+%token DT_LSHIFT DT_RSHIFT DT_LE DT_GE DT_EQ DT_NE DT_AND DT_OR
 %token DT_BITS
 %token <propnodename> DT_PROPNODENAME
 %token <literal> DT_LITERAL
@@ -75,7 +76,6 @@ static unsigned char eval_char_literal(const char *s);
 %type <data> propdataprefix
 %type <re> memreserve
 %type <re> memreserves
-%type <addr> addr
 %type <array> arrayprefix
 %type <data> bytestring
 %type <prop> propdef
@@ -86,6 +86,21 @@ static unsigned char eval_char_literal(const char *s);
 %type <node> subnode
 %type <nodelist> subnodes
 
+%type <integer> integer_prim
+%type <integer> integer_unary
+%type <integer> integer_mul
+%type <integer> integer_add
+%type <integer> integer_shift
+%type <integer> integer_rela
+%type <integer> integer_eq
+%type <integer> integer_bitand
+%type <integer> integer_bitxor
+%type <integer> integer_bitor
+%type <integer> integer_and
+%type <integer> integer_or
+%type <integer> integer_trinary
+%type <integer> integer_expr
+
 %%
 
 sourcefile:
@@ -108,7 +123,7 @@ memreserves:
 	;
 
 memreserve:
-	  DT_MEMRESERVE addr addr ';'
+	  DT_MEMRESERVE integer_prim integer_prim ';'
 		{
 			$$ = build_reserve_entry($2, $3);
 		}
@@ -119,13 +134,6 @@ memreserve:
 		}
 	;
 
-addr:
-	  DT_LITERAL
-		{
-			$$ = eval_literal($1, 0, 64);
-		}
-	  ;
-
 devicetree:
 	  '/' nodedef
 		{
@@ -198,7 +206,7 @@ propdata:
 		{
 			$$ = data_add_marker($1, REF_PATH, $2);
 		}
-	| propdataprefix DT_INCBIN '(' DT_STRING ',' addr ',' addr ')'
+	| propdataprefix DT_INCBIN '(' DT_STRING ',' integer_prim ',' integer_prim ')'
 		{
 			FILE *f = srcfile_relative_open($4.val, NULL);
 			struct data d;
@@ -267,17 +275,25 @@ arrayprefix:
 			$$.data = empty_data;
 			$$.bits = 32;
 		}
-	| arrayprefix DT_LITERAL
-		{
-			uint64_t val = eval_literal($2, 0, $1.bits);
-
-			$$.data = data_append_integer($1.data, val, $1.bits);
-		}
-	| arrayprefix DT_CHAR_LITERAL
-		{
-			uint64_t val = eval_char_literal($2);
+	| arrayprefix integer_prim
+		{
+			if ($1.bits < 64) {
+				uint64_t mask = (1ULL << $1.bits) - 1;
+				/*
+				 * Bits above mask must either be all zero
+				 * (positive within range of mask) or all one
+				 * (negative and sign-extended). The second
+				 * condition is true if when we set all bits
+				 * within the mask to one (i.e. | in the
+				 * mask), all bits are one.
+				 */
+				if (($2 > mask) && (($2 | mask) != -1ULL))
+					print_error(
+						"integer value out of range "
+						"%016lx (%d bits)", $1.bits);
+			}
 
-			$$.data = data_append_integer($1.data, val, $1.bits);
+			$$.data = data_append_integer($1.data, $2, $1.bits);
 		}
 	| arrayprefix DT_REF
 		{
@@ -299,6 +315,95 @@ arrayprefix:
 		}
 	;
 
+integer_prim:
+	  DT_LITERAL
+		{
+			$$ = eval_literal($1, 0, 64);
+		}
+	| DT_CHAR_LITERAL
+		{
+			$$ = eval_char_literal($1);
+		}
+	| '(' integer_expr ')'
+		{
+			$$ = $2;
+		}
+	;
+
+integer_expr:
+	integer_trinary
+	;
+
+integer_trinary:
+	  integer_or
+	| integer_or '?' integer_expr ':' integer_trinary { $$ = $1 ? $3 : $5; }
+	;
+
+integer_or:
+	  integer_and
+	| integer_or DT_OR integer_and { $$ = $1 || $3; }
+	;
+
+integer_and:
+	  integer_bitor
+	| integer_and DT_AND integer_bitor { $$ = $1 && $3; }
+	;
+
+integer_bitor:
+	  integer_bitxor
+	| integer_bitor '|' integer_bitxor { $$ = $1 | $3; }
+	;
+
+integer_bitxor:
+	  integer_bitand
+	| integer_bitxor '^' integer_bitand { $$ = $1 ^ $3; }
+	;
+
+integer_bitand:
+	  integer_eq
+	| integer_bitand '&' integer_eq { $$ = $1 & $3; }
+	;
+
+integer_eq:
+	  integer_rela
+	| integer_eq DT_EQ integer_rela { $$ = $1 == $3; }
+	| integer_eq DT_NE integer_rela { $$ = $1 != $3; }
+	;
+
+integer_rela:
+	  integer_shift
+	| integer_rela '<' integer_shift { $$ = $1 < $3; }
+	| integer_rela '>' integer_shift { $$ = $1 > $3; }
+	| integer_rela DT_LE integer_shift { $$ = $1 <= $3; }
+	| integer_rela DT_GE integer_shift { $$ = $1 >= $3; }
+	;
+
+integer_shift:
+	  integer_shift DT_LSHIFT integer_add { $$ = $1 << $3; }
+	| integer_shift DT_RSHIFT integer_add { $$ = $1 >> $3; }
+	| integer_add
+	;
+
+integer_add:
+	  integer_add '+' integer_mul { $$ = $1 + $3; }
+	| integer_add '-' integer_mul { $$ = $1 - $3; }
+	| integer_mul
+	;
+
+integer_mul:
+	  integer_mul '*' integer_unary { $$ = $1 * $3; }
+	| integer_mul '/' integer_unary { $$ = $1 / $3; }
+	| integer_mul '%' integer_unary { $$ = $1 % $3; }
+	| integer_unary
+	;
+
+integer_unary:
+	  integer_prim
+	| '-' integer_unary { $$ = -$2; }
+	| '~' integer_unary { $$ = ~$2; }
+	| '!' integer_unary { $$ = !$2; }
+	;
+
 bytestring:
 	  /* empty */
 		{
@@ -366,9 +471,12 @@ static unsigned long long eval_literal(const char *s, int base, int bits)
 
 	errno = 0;
 	val = strtoull(s, &e, base);
-	if (*e)
-		print_error("bad characters in literal");
-	else if ((errno == ERANGE)
+	if (*e) {
+		size_t uls = strspn(e, "UL");
+		if (e[uls])
+			print_error("bad characters in literal");
+	}
+	if ((errno == ERANGE)
 		 || ((bits < 64) && (val >= (1ULL << bits))))
 		print_error("literal out of range");
 	else if (errno != 0)
diff --git a/tests/Makefile.tests b/tests/Makefile.tests
index 2eee708..1795466 100644
--- a/tests/Makefile.tests
+++ b/tests/Makefile.tests
@@ -19,7 +19,8 @@ LIB_TESTS_L = get_mem_rsv \
 	dtbs_equal_ordered \
 	dtb_reverse dtbs_equal_unordered \
 	add_subnode_with_nops path_offset_aliases \
-	utilfdt_test
+	utilfdt_test \
+	integer-expressions
 LIB_TESTS = $(LIB_TESTS_L:%=$(TESTS_PREFIX)%)
 
 LIBTREE_TESTS_L = truncated_property
diff --git a/tests/integer-expressions.c b/tests/integer-expressions.c
new file mode 100644
index 0000000..5ba1566
--- /dev/null
+++ b/tests/integer-expressions.c
@@ -0,0 +1,117 @@
+/*
+ * Testcase for dtc expression support
+ *
+ * Copyright (C) 2008 David Gibson, IBM Corporation.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser 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
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdint.h>
+#include <errno.h>
+
+
+#include <fdt.h>
+#include <libfdt.h>
+
+#include "tests.h"
+#include "testdata.h"
+
+struct test_expr {
+	const char *expr;
+	uint32_t result;
+} expr_table[] = {
+#define TE(expr)	{ #expr, (expr) }
+	TE(0xdeadbeef),
+	TE(-0x21524111),
+	TE(1+1),
+	TE(2*3),
+	TE(4/2),
+	TE(10/3),
+	TE(19%4),
+	TE(1 << 13),
+	TE(0x1000 >> 4),
+	TE(3*2+1), TE(3*(2+1)),
+	TE(1+2*3), TE((1+2)*3),
+	TE(1 < 2), TE(2 < 1), TE(1 < 1),
+	TE(1 <= 2), TE(2 <= 1), TE(1 <= 1),
+	TE(1 > 2), TE(2 > 1), TE(1 > 1),
+	TE(1 >= 2), TE(2 >= 1), TE(1 >= 1),
+	TE(1 == 1), TE(1 == 2),
+	TE(1 != 1), TE(1 != 2),
+	TE(0xabcdabcd & 0xffff0000),
+	TE(0xdead4110 ^ 0xf0f0f0f0),
+	TE(0xabcd0000 | 0x0000abcd),
+	TE(~0x21524110),
+	TE(~~0xdeadbeef),
+	TE(0 && 0), TE(17 && 0), TE(0 && 17), TE(17 && 17),
+	TE(0 || 0), TE(17 || 0), TE(0 || 17), TE(17 || 17),
+	TE(!0), TE(!1), TE(!17), TE(!!0), TE(!!17),
+	TE(0 ? 17 : 39), TE(1 ? 17 : 39), TE(17 ? 0xdeadbeef : 0xabcd1234),
+	TE(11 * 257 * 1321517ULL),
+	TE(123456790 - 4/2 + 17%4),
+};
+
+#define ARRAY_SIZE(x)	(sizeof(x) / sizeof((x)[0]))
+
+int main(int argc, char *argv[])
+{
+	void *fdt;
+	const uint32_t *res;
+	int reslen;
+	int i;
+
+	test_init(argc, argv);
+
+	if ((argc == 3) && (strcmp(argv[1], "-g") == 0)) {
+		FILE *f = fopen(argv[2], "w");
+
+		if (!f)
+			FAIL("Couldn't open \"%s\" for output: %s\n",
+			     argv[2], strerror(errno));
+
+		fprintf(f, "/dts-v1/;\n");
+		fprintf(f, "/ {\n");
+		fprintf(f, "\texpressions = <\n");
+		for (i = 0; i < ARRAY_SIZE(expr_table); i++)
+			fprintf(f, "\t\t(%s)\n", expr_table[i].expr);
+		fprintf(f, "\t>;\n");
+		fprintf(f, "};\n");
+		fclose(f);
+	} else {
+		fdt = load_blob_arg(argc, argv);
+
+		res = fdt_getprop(fdt, 0, "expressions", &reslen);
+
+		if (!res)
+			FAIL("Error retreiving expression results: %s\n",
+		     fdt_strerror(reslen));
+
+		if (reslen != (ARRAY_SIZE(expr_table) * sizeof(uint32_t)))
+			FAIL("Unexpected length of results %d instead of %zd\n",
+			     reslen, ARRAY_SIZE(expr_table) * sizeof(uint32_t));
+
+		for (i = 0; i < ARRAY_SIZE(expr_table); i++)
+			if (fdt32_to_cpu(res[i]) != expr_table[i].result)
+				FAIL("Incorrect result for expression \"%s\","
+				     " 0x%x instead of 0x%x\n",
+				     expr_table[i].expr, fdt32_to_cpu(res[i]),
+				     expr_table[i].result);
+	}
+
+	PASS();
+}
diff --git a/tests/run_tests.sh b/tests/run_tests.sh
index e470b82..ab8133c 100755
--- a/tests/run_tests.sh
+++ b/tests/run_tests.sh
@@ -404,6 +404,11 @@ dtc_tests () {
     run_dtc_test -I dtb -O dts -o stdin_odts_test_tree1.dtb.test.dts - < test_tree1.dtb
     run_wrap_test cmp stdin_odts_test_tree1.dtb.test.dts odts_test_tree1.dtb.test.dts
 
+    # Check integer expresisons
+    run_test integer-expressions -g integer-expressions.test.dts
+    run_dtc_test -I dts -O dtb -o integer-expressions.test.dtb integer-expressions.test.dts
+    run_test integer-expressions integer-expressions.test.dtb
+
     # Check for graceful failure in some error conditions
     run_sh_test dtc-fatal.sh -I dts -O dtb nosuchfile.dts
     run_sh_test dtc-fatal.sh -I dtb -O dtb nosuchfile.dtb

commit 37b167f68afa21fbecb3077839f9c037a1459701
Author: Bert Kenward <bert.kenward@broadcom.com>
Date:   Tue Apr 10 08:00:15 2012 -0700

    Remove invalid macro starting with _ from libfdt_env.h
    
    libfdt_env.h in the device tree compiler currently defines a _B() macro. This is in the
    namespace reserved for the implementation, and Cygwin's ctype.h actually defines a macro
    with this name. This renames _B to EXTRACT_BYTE.
    
    Signed-off-by: Bert Kenward <bert.kenward@broadcom.com>

diff --git a/libfdt/libfdt_env.h b/libfdt/libfdt_env.h
index da952e7..213d7fb 100644
--- a/libfdt/libfdt_env.h
+++ b/libfdt/libfdt_env.h
@@ -5,25 +5,25 @@
 #include <stdint.h>
 #include <string.h>
 
-#define _B(n)	((unsigned long long)((uint8_t *)&x)[n])
+#define EXTRACT_BYTE(n)	((unsigned long long)((uint8_t *)&x)[n])
 static inline uint16_t fdt16_to_cpu(uint16_t x)
 {
-	return (_B(0) << 8) | _B(1);
+	return (EXTRACT_BYTE(0) << 8) | EXTRACT_BYTE(1);
 }
 #define cpu_to_fdt16(x) fdt16_to_cpu(x)
 
 static inline uint32_t fdt32_to_cpu(uint32_t x)
 {
-	return (_B(0) << 24) | (_B(1) << 16) | (_B(2) << 8) | _B(3);
+	return (EXTRACT_BYTE(0) << 24) | (EXTRACT_BYTE(1) << 16) | (EXTRACT_BYTE(2) << 8) | EXTRACT_BYTE(3);
 }
 #define cpu_to_fdt32(x) fdt32_to_cpu(x)
 
 static inline uint64_t fdt64_to_cpu(uint64_t x)
 {
-	return (_B(0) << 56) | (_B(1) << 48) | (_B(2) << 40) | (_B(3) << 32)
-		| (_B(4) << 24) | (_B(5) << 16) | (_B(6) << 8) | _B(7);
+	return (EXTRACT_BYTE(0) << 56) | (EXTRACT_BYTE(1) << 48) | (EXTRACT_BYTE(2) << 40) | (EXTRACT_BYTE(3) << 32)
+		| (EXTRACT_BYTE(4) << 24) | (EXTRACT_BYTE(5) << 16) | (EXTRACT_BYTE(6) << 8) | EXTRACT_BYTE(7);
 }
 #define cpu_to_fdt64(x) fdt64_to_cpu(x)
-#undef _B
+#undef EXTRACT_BYTE
 
 #endif /* _LIBFDT_ENV_H */

commit 3cbf82987425f0bfcdd898a24db9647b35ee7351
Author: Simon Glass <sjg@chromium.org>
Date:   Wed Apr 11 16:32:26 2012 -0700

    dtc: Remove spurious output on stderr
    
    Outputing to stderr is best avoided unless there is an error or warning to
    display. At present dtc always displays the name of the file it is compiling
    and the input/output formats. For example:
    
    DTC: dts->dts  on file "-"
    
    This can cause problems in some build systems. For example, U-Boot shows
    build errors for any boards which use dtc at present. It is typically the
    only message output during such a build. The C compiler does not output
    anything in general. The current dtc behaviour makes it difficult to
    provide a silent build in the normal case where nothing went wrong.
    
    Remove the message entirely.
    
    Signed-off-by: Simon Glass <sjg@chromium.org>
    Acked-by: David Gibson <david@gibson.dropbear.id.au>

diff --git a/dtc.c b/dtc.c
index 83aef32..bee5085 100644
--- a/dtc.c
+++ b/dtc.c
@@ -193,9 +193,6 @@ int main(int argc, char *argv[])
 	if (minsize)
 		fprintf(stderr, "DTC: Use of \"-S\" is deprecated; it will be removed soon, use \"-p\" instead\n");
 
-	fprintf(stderr, "DTC: %s->%s  on file \"%s\"\n",
-		inform, outform, arg);
-
 	if (depname) {
 		depfile = fopen(depname, "w");
 		if (!depfile)

commit 84a94f6ffcab762f44e44cba3409b7bc5fa46a89
Author: Simon Glass <sjg@chromium.org>
Date:   Thu Apr 19 09:33:35 2012 -0700

    dtc: Adjust .gitignore to be in alphabetical order
    
    This is the intent, so correct it.
    
    Signed-off-by: Simon Glass <sjg@chromium.org>

diff --git a/tests/.gitignore b/tests/.gitignore
index 0b71bcf..cca3dbc 100644
--- a/tests/.gitignore
+++ b/tests/.gitignore
@@ -10,6 +10,8 @@ tmp.*
 /del_node
 /del_property
 /dtbs_equal_ordered
+/dtbs_equal_unordered
+/dtb_reverse
 /dumptrees
 /extra-terminating-null
 /find_property
@@ -50,5 +52,3 @@ tmp.*
 /truncated_property
 /utilfdt_test
 /value-labels
-/dtb_reverse
-/dtbs_equal_unordered

commit 3ec9cb570333769295774e4fd0e2000d35cf6eda
Author: Simon Glass <sjg@chromium.org>
Date:   Thu Apr 19 09:33:36 2012 -0700

    Add integer expressions files to .gitignore
    
    Several files were added, and should be in .gitignore. The *.test.dts
    pattern should catch future source files which are generated by tests.
    It also subsumes the old *.dtb.test.dts pattern.
    
    Signed-off-by: Simon Glass <sjg@chromium.org>

diff --git a/tests/.gitignore b/tests/.gitignore
index cca3dbc..f8e1af0 100644
--- a/tests/.gitignore
+++ b/tests/.gitignore
@@ -1,6 +1,6 @@
 *.dtb
-*.dtb.test.dts
 *.dts.test.s
+*.test.dts
 tmp.*
 /add_subnode_with_nops
 /appendprop[12]
@@ -22,6 +22,7 @@ tmp.*
 /get_phandle
 /getprop
 /incbin
+/integer-expressions
 /mangle-layout
 /move_and_save
 /node_check_compatible

commit 4adbb5336b0eed99f30c852d9dcf3cd125cae921
Author: David Gibson <david@gibson.dropbear.id.au>
Date:   Fri Jun 1 14:12:36 2012 +1000

    Remove test_tree1_dts0 testcases
    
    The testcases based on test_tree1_dts0.dts were added purely to test dtc's
    backwards compatibility handling of the old dts-v0 format.  Since that
    support has been removed, the dts has been updated to use the current
    dts-v1 syntax, which makes the testcases pass, but be completely useless.
    
    This patch removes the now obsolete testcases.
    
    Signed-off-by: David Gibson <david@gibson.dropbear.id.au>

diff --git a/tests/run_tests.sh b/tests/run_tests.sh
index ab8133c..9a2a7d9 100755
--- a/tests/run_tests.sh
+++ b/tests/run_tests.sh
@@ -254,10 +254,6 @@ dtc_tests () {
     tree1_tests_rw dtc_tree1.test.dtb
     run_test dtbs_equal_ordered dtc_tree1.test.dtb test_tree1.dtb
 
-    run_dtc_test -I dts -O dtb -o dtc_tree1_dts0.test.dtb test_tree1_dts0.dts
-    tree1_tests dtc_tree1_dts0.test.dtb
-    tree1_tests_rw dtc_tree1_dts0.test.dtb
-
     run_dtc_test -I dts -O dtb -o dtc_escapes.test.dtb escapes.dts
     run_test string_escapes dtc_escapes.test.dtb
 
diff --git a/tests/test_tree1_dts0.dts b/tests/test_tree1_dts0.dts
deleted file mode 100644
index 032d540..0000000
--- a/tests/test_tree1_dts0.dts
+++ /dev/null
@@ -1,37 +0,0 @@
-/dts-v1/;
-
-/memreserve/ 0xdeadbeef00000000 0x0000000000100000;
-/memreserve/ 0x00000000075bcd15 0x0000000000001000;
-
-/ {
-	compatible = "test_tree1";
-	prop-int = <0xdeadbeef>;
-	prop-str = "hello world";
-
-	subnode@1 {
-		compatible = "subnode1";
-		prop-int = [deadbeef];
-
-		subsubnode {
-			compatible = "subsubnode1", "subsubnode";
-			prop-int = < 0xdeadbeef>;
-		};
-
-		ss1 {
-		};
-	};
-
-	subnode@2 {
-		linux,phandle = <0x2000>;
-		prop-int = < 123456789>;
-
-		subsubnode@0 {
-			linux,phandle = <0x2001>;
-			compatible = "subsubnode2", "subsubnode";
-			prop-int = < 0726746425>;
-		};
-
-		ss2 {
-		};
-	};
-};

commit cbf1410eab4b7ce7be1b15f985ef71bfc1f5886d
Author: David Gibson <david@gibson.dropbear.id.au>
Date:   Fri Jun 1 14:12:37 2012 +1000

    libfdt: Add helpers for 64-bit integer properties
    
    In device trees in the world, properties consisting of a single 64-bit
    integer are not as common as those consisting of a single 32-bit, cell
    sized integer, but they're common enough that they're worth including
    convenience functions for.
    
    This patch adds helper wrappers of fdt_setprop_inplace(), fdt_setprop() and
    fdt_appendprop() for handling 64-bit integer quantities in properties.  For
    better consistency with the names of these new *_u64() functions we also
    add *_u32() functions as alternative names for the existing *_cell()
    functions handling 32-bit integers.
    
    Signed-off-by: David Gibson <david@gibson.dropbear.id.au>

diff --git a/libfdt/libfdt.h b/libfdt/libfdt.h
index 060479e..35d78b8 100644
--- a/libfdt/libfdt.h
+++ b/libfdt/libfdt.h
@@ -852,17 +852,17 @@ int fdt_setprop_inplace(void *fdt, int nodeoffset, const char *name,
 			const void *val, int len);
 
 /**
- * fdt_setprop_inplace_cell - change the value of a single-cell property
+ * fdt_setprop_inplace_u32 - change the value of a 32-bit integer property
  * @fdt: pointer to the device tree blob
  * @nodeoffset: offset of the node whose property to change
  * @name: name of the property to change
- * @val: cell (32-bit integer) value to replace the property with
+ * @val: 32-bit integer value to replace the property with
  *
- * fdt_setprop_inplace_cell() replaces the value of a given property
- * with the 32-bit integer cell value in val, converting val to
- * big-endian if necessary.  This function cannot change the size of a
- * property, and so will only work if the property already exists and
- * has length 4.
+ * fdt_setprop_inplace_u32() replaces the value of a given property
+ * with the 32-bit integer value in val, converting val to big-endian
+ * if necessary.  This function cannot change the size of a property,
+ * and so will only work if the property already exists and has length
+ * 4.
  *
  * This function will alter only the bytes in the blob which contain
  * the given property value, and will not alter or move any other part
@@ -871,7 +871,7 @@ int fdt_setprop_inplace(void *fdt, int nodeoffset, const char *name,
  * returns:
  *	0, on success
  *	-FDT_ERR_NOSPACE, if the property's length is not equal to 4
-  *	-FDT_ERR_NOTFOUND, node does not have the named property
+ *	-FDT_ERR_NOTFOUND, node does not have the named property
  *	-FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag
  *	-FDT_ERR_BADMAGIC,
  *	-FDT_ERR_BADVERSION,
@@ -879,14 +879,60 @@ int fdt_setprop_inplace(void *fdt, int nodeoffset, const char *name,
  *	-FDT_ERR_BADSTRUCTURE,
  *	-FDT_ERR_TRUNCATED, standard meanings
  */
-static inline int fdt_setprop_inplace_cell(void *fdt, int nodeoffset,
-					   const char *name, uint32_t val)
+static inline int fdt_setprop_inplace_u32(void *fdt, int nodeoffset,
+					  const char *name, uint32_t val)
 {
 	val = cpu_to_fdt32(val);
 	return fdt_setprop_inplace(fdt, nodeoffset, name, &val, sizeof(val));
 }
 
 /**
+ * fdt_setprop_inplace_u64 - change the value of a 64-bit integer property
+ * @fdt: pointer to the device tree blob
+ * @nodeoffset: offset of the node whose property to change
+ * @name: name of the property to change
+ * @val: 64-bit integer value to replace the property with
+ *
+ * fdt_setprop_inplace_u64() replaces the value of a given property
+ * with the 64-bit integer value in val, converting val to big-endian
+ * if necessary.  This function cannot change the size of a property,
+ * and so will only work if the property already exists and has length
+ * 8.
+ *
+ * This function will alter only the bytes in the blob which contain
+ * the given property value, and will not alter or move any other part
+ * of the tree.
+ *
+ * returns:
+ *	0, on success
+ *	-FDT_ERR_NOSPACE, if the property's length is not equal to 8
+ *	-FDT_ERR_NOTFOUND, node does not have the named property
+ *	-FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag
+ *	-FDT_ERR_BADMAGIC,
+ *	-FDT_ERR_BADVERSION,
+ *	-FDT_ERR_BADSTATE,
+ *	-FDT_ERR_BADSTRUCTURE,
+ *	-FDT_ERR_TRUNCATED, standard meanings
+ */
+static inline int fdt_setprop_inplace_u64(void *fdt, int nodeoffset,
+					  const char *name, uint64_t val)
+{
+	val = cpu_to_fdt64(val);
+	return fdt_setprop_inplace(fdt, nodeoffset, name, &val, sizeof(val));
+}
+
+/**
+ * fdt_setprop_inplace_cell - change the value of a single-cell property
+ *
+ * This is an alternative name for fdt_setprop_inplace_u32()
+ */
+static inline int fdt_setprop_inplace_cell(void *fdt, int nodeoffset,
+					   const char *name, uint32_t val)
+{
+	return fdt_setprop_inplace_u32(fdt, nodeoffset, name, val);
+}
+
+/**
  * fdt_nop_property - replace a property with nop tags
  * @fdt: pointer to the device tree blob
  * @nodeoffset: offset of the node whose property to nop
@@ -945,11 +991,20 @@ int fdt_add_reservemap_entry(void *fdt, uint64_t addr, uint64_t size);
 int fdt_finish_reservemap(void *fdt);
 int fdt_begin_node(void *fdt, const char *name);
 int fdt_property(void *fdt, const char *name, const void *val, int len);
-static inline int fdt_property_cell(void *fdt, const char *name, uint32_t val)
+static inline int fdt_property_u32(void *fdt, const char *name, uint32_t val)
 {
 	val = cpu_to_fdt32(val);
 	return fdt_property(fdt, name, &val, sizeof(val));
 }
+static inline int fdt_property_u64(void *fdt, const char *name, uint64_t val)
+{
+	val = cpu_to_fdt64(val);
+	return fdt_property(fdt, name, &val, sizeof(val));
+}
+static inline int fdt_property_cell(void *fdt, const char *name, uint32_t val)
+{
+	return fdt_property_u32(fdt, name, val);
+}
 #define fdt_property_string(fdt, name, str) \
 	fdt_property(fdt, name, str, strlen(str)+1)
 int fdt_end_node(void *fdt);
@@ -1068,14 +1123,14 @@ int fdt_setprop(void *fdt, int nodeoffset, const char *name,
 		const void *val, int len);
 
 /**
- * fdt_setprop_cell - set a property to a single cell value
+ * fdt_setprop_u32 - set a property to a 32-bit integer
  * @fdt: pointer to the device tree blob
  * @nodeoffset: offset of the node whose property to change
  * @name: name of the property to change
  * @val: 32-bit integer value for the property (native endian)
  *
- * fdt_setprop_cell() sets the value of the named property in the
- * given node to the given cell value (converting to big-endian if
+ * fdt_setprop_u32() sets the value of the named property in the given
+ * node to the given 32-bit integer value (converting to big-endian if
  * necessary), or creates a new property with that value if it does
  * not already exist.
  *
@@ -1095,14 +1150,60 @@ int fdt_setprop(void *fdt, int nodeoffset, const char *name,
  *	-FDT_ERR_BADLAYOUT,
  *	-FDT_ERR_TRUNCATED, standard meanings
  */
-static inline int fdt_setprop_cell(void *fdt, int nodeoffset, const char *name,
-				   uint32_t val)
+static inline int fdt_setprop_u32(void *fdt, int nodeoffset, const char *name,
+				  uint32_t val)
 {
 	val = cpu_to_fdt32(val);
 	return fdt_setprop(fdt, nodeoffset, name, &val, sizeof(val));
 }
 
 /**
+ * fdt_setprop_u64 - set a property to a 64-bit integer
+ * @fdt: pointer to the device tree blob
+ * @nodeoffset: offset of the node whose property to change
+ * @name: name of the property to change
+ * @val: 64-bit integer value for the property (native endian)
+ *
+ * fdt_setprop_u64() sets the value of the named property in the given
+ * node to the given 64-bit integer value (converting to big-endian if
+ * necessary), or creates a new property with that value if it does
+ * not already exist.
+ *
+ * This function may insert or delete data from the blob, and will
+ * therefore change the offsets of some existing nodes.
+ *
+ * returns:
+ *	0, on success
+ *	-FDT_ERR_NOSPACE, there is insufficient free space in the blob to
+ *		contain the new property value
+ *	-FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag
+ *	-FDT_ERR_BADLAYOUT,
+ *	-FDT_ERR_BADMAGIC,
+ *	-FDT_ERR_BADVERSION,
+ *	-FDT_ERR_BADSTATE,
+ *	-FDT_ERR_BADSTRUCTURE,
+ *	-FDT_ERR_BADLAYOUT,
+ *	-FDT_ERR_TRUNCATED, standard meanings
+ */
+static inline int fdt_setprop_u64(void *fdt, int nodeoffset, const char *name,
+				  uint64_t val)
+{
+	val = cpu_to_fdt64(val);
+	return fdt_setprop(fdt, nodeoffset, name, &val, sizeof(val));
+}
+
+/**
+ * fdt_setprop_cell - set a property to a single cell value
+ *
+ * This is an alternative name for fdt_setprop_u32()
+ */
+static inline int fdt_setprop_cell(void *fdt, int nodeoffset, const char *name,
+				   uint32_t val)
+{
+	return fdt_setprop_u32(fdt, nodeoffset, name, val);
+}
+
+/**
  * fdt_setprop_string - set a property to a string value
  * @fdt: pointer to the device tree blob
  * @nodeoffset: offset of the node whose property to change
@@ -1164,16 +1265,16 @@ int fdt_appendprop(void *fdt, int nodeoffset, const char *name,
 		   const void *val, int len);
 
 /**
- * fdt_appendprop_cell - append a single cell value to a property
+ * fdt_appendprop_u32 - append a 32-bit integer value to a property
  * @fdt: pointer to the device tree blob
  * @nodeoffset: offset of the node whose property to change
  * @name: name of the property to change
  * @val: 32-bit integer value to append to the property (native endian)
  *
- * fdt_appendprop_cell() appends the given cell value (converting to
- * big-endian if necessary) to the value of the named property in the
- * given node, or creates a new property with that value if it does
- * not already exist.
+ * fdt_appendprop_u32() appends the given 32-bit integer value
+ * (converting to big-endian if necessary) to the value of the named
+ * property in the given node, or creates a new property with that
+ * value if it does not already exist.
  *
  * This function may insert data into the blob, and will therefore
  * change the offsets of some existing nodes.
@@ -1191,14 +1292,60 @@ int fdt_appendprop(void *fdt, int nodeoffset, const char *name,
  *	-FDT_ERR_BADLAYOUT,
  *	-FDT_ERR_TRUNCATED, standard meanings
  */
-static inline int fdt_appendprop_cell(void *fdt, int nodeoffset,
-				      const char *name, uint32_t val)
+static inline int fdt_appendprop_u32(void *fdt, int nodeoffset,
+				     const char *name, uint32_t val)
 {
 	val = cpu_to_fdt32(val);
 	return fdt_appendprop(fdt, nodeoffset, name, &val, sizeof(val));
 }
 
 /**
+ * fdt_appendprop_u64 - append a 64-bit integer value to a property
+ * @fdt: pointer to the device tree blob
+ * @nodeoffset: offset of the node whose property to change
+ * @name: name of the property to change
+ * @val: 64-bit integer value to append to the property (native endian)
+ *
+ * fdt_appendprop_u64() appends the given 64-bit integer value
+ * (converting to big-endian if necessary) to the value of the named
+ * property in the given node, or creates a new property with that
+ * value if it does not already exist.
+ *
+ * This function may insert data into 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
+ */
+static inline int fdt_appendprop_u64(void *fdt, int nodeoffset,
+				     const char *name, uint64_t val)
+{
+	val = cpu_to_fdt64(val);
+	return fdt_appendprop(fdt, nodeoffset, name, &val, sizeof(val));
+}
+
+/**
+ * fdt_appendprop_cell - append a single cell value to a property
+ *
+ * This is an alternative name for fdt_appendprop_u32()
+ */
+static inline int fdt_appendprop_cell(void *fdt, int nodeoffset,
+				      const char *name, uint32_t val)
+{
+	return fdt_appendprop_u32(fdt, nodeoffset, name, val);
+}
+
+/**
  * fdt_appendprop_string - append a string to a property
  * @fdt: pointer to the device tree blob
  * @nodeoffset: offset of the node whose property to change
diff --git a/tests/appendprop.dts b/tests/appendprop.dts
index 6e3a3eb..f4bc730 100644
--- a/tests/appendprop.dts
+++ b/tests/appendprop.dts
@@ -2,6 +2,7 @@
 
 / {
 	prop-str = "hello world", "nastystring: \a\b\t\n\v\f\r\\\"";
+	prop-int64 = /bits/ 64 <0xdeadbeef01abcdef 0xdeadbeef01abcdef>;
 	prop-int = <0xdeadbeef 123456789>;
 	prop-bytes = [00010203040001020304];
 };
diff --git a/tests/appendprop1.c b/tests/appendprop1.c
index 180d296..d716f7a 100644
--- a/tests/appendprop1.c
+++ b/tests/appendprop1.c
@@ -60,6 +60,7 @@ int main(int argc, char *argv[])
 
 	CHECK(fdt_appendprop(fdt, 0, "prop-bytes", bytes, sizeof(bytes)));
 	CHECK(fdt_appendprop_cell(fdt, 0, "prop-int", TEST_VALUE_1));
+	CHECK(fdt_appendprop_u64(fdt, 0, "prop-int64", TEST_VALUE64_1));
 	CHECK(fdt_appendprop_string(fdt, 0, "prop-str", TEST_STRING_1));
 
 	CHECK(fdt_pack(fdt));
diff --git a/tests/appendprop2.c b/tests/appendprop2.c
index d651a89..7eb243d 100644
--- a/tests/appendprop2.c
+++ b/tests/appendprop2.c
@@ -54,6 +54,7 @@ int main(int argc, char *argv[])
 
 	CHECK(fdt_appendprop(fdt, 0, "prop-bytes", bytes, sizeof(bytes)));
 	CHECK(fdt_appendprop_cell(fdt, 0, "prop-int", TEST_VALUE_2));
+	CHECK(fdt_appendprop_u64(fdt, 0, "prop-int64", TEST_VALUE64_1));
 	CHECK(fdt_appendprop_string(fdt, 0, "prop-str", TEST_STRING_2));
 
 	CHECK(fdt_pack(fdt));
diff --git a/tests/include1.dts b/tests/include1.dts
index 5d59d83..893aaff 100644
--- a/tests/include1.dts
+++ b/tests/include1.dts
@@ -6,6 +6,7 @@
 / {
 	/include/ "include4.dts"
 	/include/ "include5.dts" = <0xdeadbeef>;
+	prop-int64 /include/ "include5a.dts";
 	prop-str = /include/ "include6.dts";
 
 	/include/ "include7.dts"
diff --git a/tests/include5a.dts b/tests/include5a.dts
new file mode 100644
index 0000000..39ddba4
--- /dev/null
+++ b/tests/include5a.dts
@@ -0,0 +1 @@
+= /bits/ 64 <0xdeadbeef01abcdef>
\ No newline at end of file
diff --git a/tests/rw_tree1.c b/tests/rw_tree1.c
index f0bce88..f4965ec 100644
--- a/tests/rw_tree1.c
+++ b/tests/rw_tree1.c
@@ -73,7 +73,8 @@ int main(int argc, char *argv[])
 	CHECK(fdt_add_mem_rsv(fdt, TEST_ADDR_2, TEST_SIZE_2));
 
 	CHECK(fdt_setprop_string(fdt, 0, "compatible", "test_tree1"));
-	CHECK(fdt_setprop_cell(fdt, 0, "prop-int", TEST_VALUE_1));
+	CHECK(fdt_setprop_u32(fdt, 0, "prop-int", TEST_VALUE_1));
+	CHECK(fdt_setprop_u64(fdt, 0, "prop-int64", TEST_VALUE64_1));
 	CHECK(fdt_setprop_string(fdt, 0, "prop-str", TEST_STRING_1));
 
 	OFF_CHECK(offset, fdt_add_subnode(fdt, 0, "subnode@1"));
diff --git a/tests/setprop.c b/tests/setprop.c
index 386b87b..9f2bc88 100644
--- a/tests/setprop.c
+++ b/tests/setprop.c
@@ -74,5 +74,23 @@ int main(int argc, char *argv[])
 
 	check_getprop(fdt, 0, "prop-str", 0, NULL);
 
+	err = fdt_setprop_u32(fdt, 0, "prop-u32", TEST_VALUE_2);
+	if (err)
+		FAIL("Failed to set \"prop-u32\" to 0x%08x: %s",
+		     TEST_VALUE_2, fdt_strerror(err));
+	check_getprop_cell(fdt, 0, "prop-u32", TEST_VALUE_2);
+
+	err = fdt_setprop_cell(fdt, 0, "prop-cell", TEST_VALUE_2);
+	if (err)
+		FAIL("Failed to set \"prop-cell\" to 0x%08x: %s",
+		     TEST_VALUE_2, fdt_strerror(err));
+	check_getprop_cell(fdt, 0, "prop-cell", TEST_VALUE_2);
+
+	err = fdt_setprop_u64(fdt, 0, "prop-u64", TEST_VALUE64_1);
+	if (err)
+		FAIL("Failed to set \"prop-u64\" to 0x%016llx: %s",
+		     TEST_VALUE64_1, fdt_strerror(err));
+	check_getprop_64(fdt, 0, "prop-u64", TEST_VALUE64_1);
+	
 	PASS();
 }
diff --git a/tests/setprop_inplace.c b/tests/setprop_inplace.c
index aa0cd96..30a1cf3 100644
--- a/tests/setprop_inplace.c
+++ b/tests/setprop_inplace.c
@@ -34,6 +34,7 @@ int main(int argc, char *argv[])
 {
 	void *fdt;
 	const uint32_t *intp;
+	const uint64_t *int64p;
 	const char *strp;
 	char *xstr;
 	int xlen, i;
@@ -55,6 +56,20 @@ int main(int argc, char *argv[])
 	strp = check_getprop(fdt, 0, "prop-str", strlen(TEST_STRING_1)+1,
 			     TEST_STRING_1);
 
+
+	int64p = check_getprop_64(fdt, 0, "prop-int64", TEST_VALUE64_1);
+
+	verbose_printf("Old int64 value was 0x%016llx\n", *int64p);
+	err = fdt_setprop_inplace_u64(fdt, 0, "prop-int64", ~TEST_VALUE64_1);
+	if (err)
+		FAIL("Failed to set \"prop-int64\" to 0x016%llx: %s",
+		     ~TEST_VALUE64_1, fdt_strerror(err));
+	int64p = check_getprop_64(fdt, 0, "prop-int64", ~TEST_VALUE64_1);
+	verbose_printf("New int64 value is 0x%016llx\n", *int64p);
+
+	strp = check_getprop(fdt, 0, "prop-str", strlen(TEST_STRING_1)+1,
+			     TEST_STRING_1);
+
 	verbose_printf("Old string value was \"%s\"\n", strp);
 	xstr = strdup(strp);
 	xlen = strlen(xstr);
diff --git a/tests/sw_tree1.c b/tests/sw_tree1.c
index f2c430a..5c71414 100644
--- a/tests/sw_tree1.c
+++ b/tests/sw_tree1.c
@@ -55,7 +55,8 @@ int main(int argc, char *argv[])
 
 	CHECK(fdt_begin_node(fdt, ""));
 	CHECK(fdt_property_string(fdt, "compatible", "test_tree1"));
-	CHECK(fdt_property_cell(fdt, "prop-int", TEST_VALUE_1));
+	CHECK(fdt_property_u32(fdt, "prop-int", TEST_VALUE_1));
+	CHECK(fdt_property_u64(fdt, "prop-int64", TEST_VALUE64_1));
 	CHECK(fdt_property_string(fdt, "prop-str", TEST_STRING_1));
 
 	CHECK(fdt_begin_node(fdt, "subnode@1"));
diff --git a/tests/test_tree1.dts b/tests/test_tree1.dts
index 4f0ce45..cf530ce 100644
--- a/tests/test_tree1.dts
+++ b/tests/test_tree1.dts
@@ -6,6 +6,7 @@
 / {
 	compatible = "test_tree1";
 	prop-int = <0xdeadbeef>;
+	prop-int64 = /bits/ 64 <0xdeadbeef01abcdef>;
 	prop-str = "hello world";
 
 	subnode@1 {
diff --git a/tests/test_tree1_merge.dts b/tests/test_tree1_merge.dts
index fc191fd..ded08d8 100644
--- a/tests/test_tree1_merge.dts
+++ b/tests/test_tree1_merge.dts
@@ -30,6 +30,7 @@
 
 / {
 	prop-int = <0xdeadbeef>;
+	prop-int64 = /bits/ 64 <0xdeadbeef01abcdef>;
 	subnode@1 {
 		prop-int = [deadbeef];
 	};
diff --git a/tests/test_tree1_merge_labelled.dts b/tests/test_tree1_merge_labelled.dts
index 46a6840..29953b0 100644
--- a/tests/test_tree1_merge_labelled.dts
+++ b/tests/test_tree1_merge_labelled.dts
@@ -6,6 +6,7 @@
 / {
 	compatible = "test_tree1";
 	prop-int = <0xdeadbeef>;
+	prop-int64 = /bits/ 64 <0xdeadbeef01abcdef>;
 	prop-str = "hello world";
 
 	subnode@1 {
diff --git a/tests/test_tree1_merge_path.dts b/tests/test_tree1_merge_path.dts
index d68713b..168d066 100644
--- a/tests/test_tree1_merge_path.dts
+++ b/tests/test_tree1_merge_path.dts
@@ -6,6 +6,7 @@
 / {
 	compatible = "test_tree1";
 	prop-int = <0xdeadbeef>;
+	prop-int64 = /bits/ 64 <0xdeadbeef01abcdef>;
 	prop-str = "hello world";
 
 	subnode@1 {
diff --git a/tests/testdata.h b/tests/testdata.h
index d4c6759..ce715e4 100644
--- a/tests/testdata.h
+++ b/tests/testdata.h
@@ -12,6 +12,8 @@
 #define TEST_VALUE_1	0xdeadbeef
 #define TEST_VALUE_2	123456789
 
+#define TEST_VALUE64_1	ASM_CONST_LL(0xdeadbeef01abcdef)
+
 #define PHANDLE_1	0x2000
 #define PHANDLE_2	0x2001
 
diff --git a/tests/tests.h b/tests/tests.h
index a51556d..56a843c 100644
--- a/tests/tests.h
+++ b/tests/tests.h
@@ -111,6 +111,11 @@ const void *check_getprop(void *fdt, int nodeoffset, const char *name,
 		uint32_t x = cpu_to_fdt32(val);			     \
 		check_getprop(fdt, nodeoffset, name, sizeof(x), &x); \
 	})
+#define check_getprop_64(fdt, nodeoffset, name, val) \
+	({ \
+		uint64_t x = cpu_to_fdt64(val);			     \
+		check_getprop(fdt, nodeoffset, name, sizeof(x), &x); \
+	})
 #define check_getprop_string(fdt, nodeoffset, name, s) \
 	check_getprop((fdt), (nodeoffset), (name), strlen(s)+1, (s))
 int nodename_eq(const char *s1, const char *s2);
diff --git a/tests/trees.S b/tests/trees.S
index 66adf3f..cae0187 100644
--- a/tests/trees.S
+++ b/tests/trees.S
@@ -52,6 +52,10 @@ tree##_rsvmap_end:		;
 	PROPHDR(tree, name, 4) \
 	FDTLONG(val)		;
 
+#define PROP_INT64(tree, name, val) \
+	PROPHDR(tree, name, 8) \
+	FDTQUAD(val)		;
+
 #define PROP_STR(tree, name, str) \
 	PROPHDR(tree, name, 55f - 54f) \
 54:	\
@@ -86,6 +90,7 @@ test_tree1_struct:
 	BEGIN_NODE("")
 	PROP_STR(test_tree1, compatible, "test_tree1")
 	PROP_INT(test_tree1, prop_int, TEST_VALUE_1)
+	PROP_INT64(test_tree1, prop_int64, TEST_VALUE64_1)
 	PROP_STR(test_tree1, prop_str, TEST_STRING_1)
 
 	BEGIN_NODE("subnode@1")
@@ -124,6 +129,7 @@ test_tree1_struct_end:
 test_tree1_strings:
 	STRING(test_tree1, compatible, "compatible")
 	STRING(test_tree1, prop_int, "prop-int")
+	STRING(test_tree1, prop_int64, "prop-int64")
 	STRING(test_tree1, prop_str, "prop-str")
 	STRING(test_tree1, linux_phandle, "linux,phandle")
 	STRING(test_tree1, phandle, "phandle")

commit be6026838e45b67800ac803f4ad8cca3cde57d6d
Author: David Gibson <david@gibson.dropbear.id.au>
Date:   Fri Jun 1 14:12:38 2012 +1000

    libfdt: Add helper function to create a trivial, empty tree
    
    The libfdt read/write functions are now usable enough that it's become a
    moderately common pattern to use them to build and manipulate a device
    tree from scratch.  For example, we do so ourself in our rw_tree1 testcase,
    and qemu is starting to use this model when building device trees for some
    targets such as e500.
    
    However, the read/write functions require some sort of valid tree to begin
    with, so this necessitates either having a trivial canned dtb to begin with
    or, more commonly, creating an empty tree using the serial-write functions
    first.
    
    This patch adds a helper function which uses the serial-write functions to
    create a trivial, empty but complete and valid tree in a supplied buffer,
    ready for manipulation with the read/write functions.
    
    Signed-off-by: David Gibson <david@gibson.dropbear.id.au>

diff --git a/libfdt/Makefile.libfdt b/libfdt/Makefile.libfdt
index d55a6f8..4366627 100644
--- a/libfdt/Makefile.libfdt
+++ b/libfdt/Makefile.libfdt
@@ -6,5 +6,5 @@
 LIBFDT_soname = libfdt.$(SHAREDLIB_EXT).1
 LIBFDT_INCLUDES = fdt.h libfdt.h
 LIBFDT_VERSION = version.lds
-LIBFDT_SRCS = fdt.c fdt_ro.c fdt_wip.c fdt_sw.c fdt_rw.c fdt_strerror.c
+LIBFDT_SRCS = fdt.c fdt_ro.c fdt_wip.c fdt_sw.c fdt_rw.c fdt_strerror.c fdt_empty_tree.c
 LIBFDT_OBJS = $(LIBFDT_SRCS:%.c=%.o)
diff --git a/libfdt/fdt_empty_tree.c b/libfdt/fdt_empty_tree.c
new file mode 100644
index 0000000..f72d13b
--- /dev/null
+++ b/libfdt/fdt_empty_tree.c
@@ -0,0 +1,84 @@
+/*
+ * libfdt - Flat Device Tree manipulation
+ * Copyright (C) 2012 David Gibson, IBM Corporation.
+ *
+ * libfdt is dual licensed: you can use it either under the terms of
+ * the GPL, or the BSD license, at your option.
+ *
+ *  a) This library is free software; you can redistribute it and/or
+ *     modify it under the terms of the GNU General Public License as
+ *     published by the Free Software Foundation; either version 2 of the
+ *     License, or (at your option) any later version.
+ *
+ *     This library is distributed in the hope that it will be useful,
+ *     but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *     GNU General Public License for more details.
+ *
+ *     You should have received a copy of the GNU General Public
+ *     License along with this library; if not, write to the Free
+ *     Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
+ *     MA 02110-1301 USA
+ *
+ * Alternatively,
+ *
+ *  b) Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *     1. Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *     2. Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ *     THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+ *     CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ *     INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ *     MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ *     DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ *     CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *     SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ *     NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ *     LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ *     HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ *     CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ *     OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+ *     EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#include "libfdt_env.h"
+
+#include <fdt.h>
+#include <libfdt.h>
+
+#include "libfdt_internal.h"
+
+int fdt_create_empty_tree(void *buf, int bufsize)
+{
+	int err;
+
+	err = fdt_create(buf, bufsize);
+	if (err)
+		return err;
+
+	err = fdt_finish_reservemap(buf);
+	if (err)
+		return err;
+
+	err = fdt_begin_node(buf, "");
+	if (err)
+		return err;
+
+	err =  fdt_end_node(buf);
+	if (err)
+		return err;
+
+	err = fdt_finish(buf);
+	if (err)
+		return err;
+
+	return fdt_open_into(buf, buf, bufsize);
+}
+
diff --git a/libfdt/libfdt.h b/libfdt/libfdt.h
index 35d78b8..73f4975 100644
--- a/libfdt/libfdt.h
+++ b/libfdt/libfdt.h
@@ -1014,6 +1014,7 @@ int fdt_finish(void *fdt);
 /* Read-write functions                                               */
 /**********************************************************************/
 
+int fdt_create_empty_tree(void *buf, int bufsize);
 int fdt_open_into(const void *fdt, void *buf, int bufsize);
 int fdt_pack(void *fdt);
 
diff --git a/tests/rw_tree1.c b/tests/rw_tree1.c
index f4965ec..103a24d 100644
--- a/tests/rw_tree1.c
+++ b/tests/rw_tree1.c
@@ -57,17 +57,7 @@ int main(int argc, char *argv[])
 	fdt = xmalloc(SPACE);
 
 	/* First create empty tree with SW */
-	CHECK(fdt_create(fdt, SPACE));
-
-	CHECK(fdt_finish_reservemap(fdt));
-	CHECK(fdt_begin_node(fdt, ""));
-	CHECK(fdt_end_node(fdt));
-	CHECK(fdt_finish(fdt));
-
-	verbose_printf("Built empty tree, totalsize = %d\n",
-		       fdt_totalsize(fdt));
-
-	CHECK(fdt_open_into(fdt, fdt, SPACE));
+	CHECK(fdt_create_empty_tree(fdt, SPACE));
 
 	CHECK(fdt_add_mem_rsv(fdt, TEST_ADDR_1, TEST_SIZE_1));
 	CHECK(fdt_add_mem_rsv(fdt, TEST_ADDR_2, TEST_SIZE_2));

commit 942b3c065fb1c8788d2317977945c7283f1db7e2
Author: Stephen Warren <swarren@nvidia.com>
Date:   Tue Jun 12 14:48:12 2012 -0600

    Fix compilation warning/error in setprop_inplace.c
    
    When compiling the current code-base with gcc 4.6.1, the following warning
    is raised, which is interpreted as an error:
    
    cc1: warnings being treated as errors
    tests/setprop_inplace.c: In function ‘main’:
    tests/setprop_inplace.c:62: error: format ‘%016llx’ expects type ‘long long unsigned int’, but argument 2 has type ‘uint64_t’
    tests/setprop_inplace.c:68: error: format ‘%016llx’ expects type ‘long long unsigned int’, but argument 2 has type ‘uint64_t’
    
    Use printf format specifiers from <inttypes.h> to solve this.
    
    Signed-off-by: Stephen Warren <swarren@nvidia.com>
    Acked-by: David Gibson <david@gibson.dropbear.id.au>

diff --git a/tests/setprop_inplace.c b/tests/setprop_inplace.c
index 30a1cf3..82d8951 100644
--- a/tests/setprop_inplace.c
+++ b/tests/setprop_inplace.c
@@ -18,6 +18,7 @@
  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
  */
 
+#include <inttypes.h>
 #include <stdlib.h>
 #include <stdio.h>
 #include <string.h>
@@ -48,7 +49,7 @@ int main(int argc, char *argv[])
 	verbose_printf("Old int value was 0x%08x\n", *intp);
 	err = fdt_setprop_inplace_cell(fdt, 0, "prop-int", ~TEST_VALUE_1);
 	if (err)
-		FAIL("Failed to set \"prop-int\" to 0x08%x: %s",
+		FAIL("Failed to set \"prop-int\" to 0x%08x: %s",
 		     ~TEST_VALUE_1, fdt_strerror(err));
 	intp = check_getprop_cell(fdt, 0, "prop-int", ~TEST_VALUE_1);
 	verbose_printf("New int value is 0x%08x\n", *intp);
@@ -59,13 +60,13 @@ int main(int argc, char *argv[])
 
 	int64p = check_getprop_64(fdt, 0, "prop-int64", TEST_VALUE64_1);
 
-	verbose_printf("Old int64 value was 0x%016llx\n", *int64p);
+	verbose_printf("Old int64 value was 0x%016" PRIx64 "\n", *int64p);
 	err = fdt_setprop_inplace_u64(fdt, 0, "prop-int64", ~TEST_VALUE64_1);
 	if (err)
-		FAIL("Failed to set \"prop-int64\" to 0x016%llx: %s",
+		FAIL("Failed to set \"prop-int64\" to 0x%016llx: %s",
 		     ~TEST_VALUE64_1, fdt_strerror(err));
 	int64p = check_getprop_64(fdt, 0, "prop-int64", ~TEST_VALUE64_1);
-	verbose_printf("New int64 value is 0x%016llx\n", *int64p);
+	verbose_printf("New int64 value is 0x%016" PRIx64 "\n", *int64p);
 
 	strp = check_getprop(fdt, 0, "prop-str", strlen(TEST_STRING_1)+1,
 			     TEST_STRING_1);

commit f67dfe845930b32ea14df6ff18d69799828a5909
Author: Stephen Warren <swarren@nvidia.com>
Date:   Tue Jul 3 14:09:30 2012 -0600

    Add test for re-defining an identical label
    
    When merging one device tree over the top of a previous tree, it is
    possible to define a duplicate label that has the same name and points
    to the same property or node. This is currently allowed by the duplicate
    label checking code. However, alternative duplicate label checking
    algorithms might not allow this. Add an explicit test to ensure this
    capability is maintained.
    
    Signed-off-by: Stephen Warren <swarren@nvidia.com>
    Acked-by: David Gibson <david@gibson.dropbear.id.au>

diff --git a/tests/label_repeated.dts b/tests/label_repeated.dts
new file mode 100644
index 0000000..34225d3
--- /dev/null
+++ b/tests/label_repeated.dts
@@ -0,0 +1,15 @@
+/dts-v1/;
+
+/ {
+	l0: prop = "foo";
+
+	l1: node {
+	};
+};
+
+/ {
+	l0: prop = "foo";
+
+	l1: node {
+	};
+};
diff --git a/tests/run_tests.sh b/tests/run_tests.sh
index 9a2a7d9..e0299e3 100755
--- a/tests/run_tests.sh
+++ b/tests/run_tests.sh
@@ -281,6 +281,8 @@ dtc_tests () {
     run_dtc_test -I dts -O dtb -o multilabel.test.dtb multilabel.dts
     run_test references multilabel.test.dtb
 
+    run_dtc_test -I dts -O dtb -o label_repeated.test.dtb label_repeated.dts
+
     run_dtc_test -I dts -O dtb -o dtc_comments.test.dtb comments.dts
     run_dtc_test -I dts -O dtb -o dtc_comments-cmp.test.dtb comments-cmp.dts
     run_test dtbs_equal_ordered dtc_comments.test.dtb dtc_comments-cmp.test.dtb

commit 511dedd40f0372cd7c85e3d4c66553f5829142b7
Author: David Gibson <david@gibson.dropbear.id.au>
Date:   Sun Jul 8 23:25:21 2012 +1000

    Re-work level setting on checks code
    
    Currently each of the semantic checks in checks.c has a "level" between
    IGNORE and ERROR.  This single level makes it awkward to implement the
    semantics we want for toggling the checks on the command line.
    
    This patch reworks the code to instead have separate boolean flags for
    warning and error.  At present having both flags set will have the same
    effect as having just the error flag set, but this can change in the
    future.
    
    Signed-off-by: David Gibson <david@gibson.dropbear.id.au>

diff --git a/checks.c b/checks.c
index a662a00..3080439 100644
--- a/checks.c
+++ b/checks.c
@@ -31,12 +31,6 @@
 #define TRACE(c, fmt, ...)	do { } while (0)
 #endif
 
-enum checklevel {
-	IGNORE = 0,
-	WARN = 1,
-	ERROR = 2,
-};
-
 enum checkstatus {
 	UNCHECKED = 0,
 	PREREQ,
@@ -57,14 +51,14 @@ struct check {
 	node_check_fn node_fn;
 	prop_check_fn prop_fn;
 	void *data;
-	enum checklevel level;
+	bool warn, error;
 	enum checkstatus status;
 	int inprogress;
 	int num_prereqs;
 	struct check **prereq;
 };
 
-#define CHECK(nm, tfn, nfn, pfn, d, lvl, ...) \
+#define CHECK(nm, tfn, nfn, pfn, d, w, e, ...)	       \
 	static struct check *nm##_prereqs[] = { __VA_ARGS__ }; \
 	static struct check nm = { \
 		.name = #nm, \
@@ -72,20 +66,29 @@ struct check {
 		.node_fn = (nfn), \
 		.prop_fn = (pfn), \
 		.data = (d), \
-		.level = (lvl), \
+		.warn = (w), \
+		.error = (e), \
 		.status = UNCHECKED, \
 		.num_prereqs = ARRAY_SIZE(nm##_prereqs), \
 		.prereq = nm##_prereqs, \
 	};
-
-#define TREE_CHECK(nm, d, lvl, ...) \
-	CHECK(nm, check_##nm, NULL, NULL, d, lvl, __VA_ARGS__)
-#define NODE_CHECK(nm, d, lvl, ...) \
-	CHECK(nm, NULL, check_##nm, NULL, d, lvl, __VA_ARGS__)
-#define PROP_CHECK(nm, d, lvl, ...) \
-	CHECK(nm, NULL, NULL, check_##nm, d, lvl, __VA_ARGS__)
-#define BATCH_CHECK(nm, lvl, ...) \
-	CHECK(nm, NULL, NULL, NULL, NULL, lvl, __VA_ARGS__)
+#define WARNING(nm, tfn, nfn, pfn, d, ...) \
+	CHECK(nm, tfn, nfn, pfn, d, true, false, __VA_ARGS__)
+#define ERROR(nm, tfn, nfn, pfn, d, ...) \
+	CHECK(nm, tfn, nfn, pfn, d, false, true, __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 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 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__)
 
 #ifdef __GNUC__
 static inline void check_msg(struct check *c, const char *fmt, ...) __attribute__((format (printf, 2, 3)));
@@ -95,13 +98,13 @@ static inline void check_msg(struct check *c, const char *fmt, ...)
 	va_list ap;
 	va_start(ap, fmt);
 
-	if ((c->level < WARN) || (c->level <= quiet))
-		return; /* Suppress message */
-
-	fprintf(stderr, "%s (%s): ",
-		(c->level == ERROR) ? "ERROR" : "Warning", c->name);
-	vfprintf(stderr, fmt, ap);
-	fprintf(stderr, "\n");
+	if ((c->warn && (quiet < 1))
+	    || (c->error && (quiet < 2))) {
+		fprintf(stderr, "%s (%s): ",
+			(c->error) ? "ERROR" : "Warning", c->name);
+		vfprintf(stderr, fmt, ap);
+		fprintf(stderr, "\n");
+	}
 }
 
 #define FAIL(c, ...) \
@@ -167,7 +170,7 @@ static int run_check(struct check *c, struct node *dt)
 
 out:
 	c->inprogress = 0;
-	if ((c->status != PASSED) && (c->level == ERROR))
+	if ((c->status != PASSED) && (c->error))
 		error = 1;
 	return error;
 }
@@ -190,8 +193,10 @@ static void check_is_string(struct check *c, struct node *root,
 		FAIL(c, "\"%s\" property in %s is not a string",
 		     propname, node->fullpath);
 }
-#define CHECK_IS_STRING(nm, propname, lvl) \
-	CHECK(nm, NULL, check_is_string, NULL, (propname), (lvl))
+#define WARNING_IF_NOT_STRING(nm, propname) \
+	WARNING(nm, NULL, check_is_string, NULL, (propname))
+#define ERROR_IF_NOT_STRING(nm, propname) \
+	ERROR(nm, NULL, check_is_string, NULL, (propname))
 
 static void check_is_cell(struct check *c, struct node *root,
 			  struct node *node)
@@ -207,8 +212,10 @@ static void check_is_cell(struct check *c, struct node *root,
 		FAIL(c, "\"%s\" property in %s is not a single cell",
 		     propname, node->fullpath);
 }
-#define CHECK_IS_CELL(nm, propname, lvl) \
-	CHECK(nm, NULL, check_is_cell, NULL, (propname), (lvl))
+#define WARNING_IF_NOT_CELL(nm, propname) \
+	WARNING(nm, NULL, check_is_cell, NULL, (propname))
+#define ERROR_IF_NOT_CELL(nm, propname) \
+	ERROR(nm, NULL, check_is_cell, NULL, (propname))
 
 /*
  * Structural check functions
@@ -227,7 +234,7 @@ static void check_duplicate_node_names(struct check *c, struct node *dt,
 				FAIL(c, "Duplicate node name %s",
 				     child->fullpath);
 }
-NODE_CHECK(duplicate_node_names, NULL, ERROR);
+NODE_ERROR(duplicate_node_names, NULL);
 
 static void check_duplicate_property_names(struct check *c, struct node *dt,
 					   struct node *node)
@@ -240,7 +247,7 @@ static void check_duplicate_property_names(struct check *c, struct node *dt,
 				FAIL(c, "Duplicate property name %s in %s",
 				     prop->name, node->fullpath);
 }
-NODE_CHECK(duplicate_property_names, NULL, ERROR);
+NODE_ERROR(duplicate_property_names, NULL);
 
 #define LOWERCASE	"abcdefghijklmnopqrstuvwxyz"
 #define UPPERCASE	"ABCDEFGHIJKLMNOPQRSTUVWXYZ"
@@ -256,7 +263,7 @@ static void check_node_name_chars(struct check *c, struct node *dt,
 		FAIL(c, "Bad character '%c' in node %s",
 		     node->name[n], node->fullpath);
 }
-NODE_CHECK(node_name_chars, PROPNODECHARS "@", ERROR);
+NODE_ERROR(node_name_chars, PROPNODECHARS "@");
 
 static void check_node_name_format(struct check *c, struct node *dt,
 				   struct node *node)
@@ -265,7 +272,7 @@ static void check_node_name_format(struct check *c, struct node *dt,
 		FAIL(c, "Node %s has multiple '@' characters in name",
 		     node->fullpath);
 }
-NODE_CHECK(node_name_format, NULL, ERROR, &node_name_chars);
+NODE_ERROR(node_name_format, NULL, &node_name_chars);
 
 static void check_property_name_chars(struct check *c, struct node *dt,
 				      struct node *node, struct property *prop)
@@ -276,7 +283,7 @@ static void check_property_name_chars(struct check *c, struct node *dt,
 		FAIL(c, "Bad character '%c' in property name \"%s\", node %s",
 		     prop->name[n], prop->name, node->fullpath);
 }
-PROP_CHECK(property_name_chars, PROPNODECHARS, ERROR);
+PROP_ERROR(property_name_chars, PROPNODECHARS);
 
 #define DESCLABEL_FMT	"%s%s%s%s%s"
 #define DESCLABEL_ARGS(node,prop,mark)		\
@@ -331,8 +338,8 @@ static void check_duplicate_label_prop(struct check *c, struct node *dt,
 	for_each_marker_of_type(m, LABEL)
 		check_duplicate_label(c, dt, m->ref, node, prop, m);
 }
-CHECK(duplicate_label, NULL, check_duplicate_label_node,
-      check_duplicate_label_prop, NULL, ERROR);
+ERROR(duplicate_label, NULL, check_duplicate_label_node,
+      check_duplicate_label_prop, NULL);
 
 static void check_explicit_phandles(struct check *c, struct node *root,
 				    struct node *node, struct property *prop)
@@ -391,7 +398,7 @@ static void check_explicit_phandles(struct check *c, struct node *root,
 
 	node->phandle = phandle;
 }
-PROP_CHECK(explicit_phandles, NULL, ERROR);
+PROP_ERROR(explicit_phandles, NULL);
 
 static void check_name_properties(struct check *c, struct node *root,
 				  struct node *node)
@@ -420,8 +427,8 @@ static void check_name_properties(struct check *c, struct node *root,
 		free(prop);
 	}
 }
-CHECK_IS_STRING(name_is_string, "name", ERROR);
-NODE_CHECK(name_properties, NULL, ERROR, &name_is_string);
+ERROR_IF_NOT_STRING(name_is_string, "name");
+NODE_ERROR(name_properties, NULL, &name_is_string);
 
 /*
  * Reference fixup functions
@@ -448,7 +455,7 @@ static void fixup_phandle_references(struct check *c, struct node *dt,
 		*((cell_t *)(prop->val.val + m->offset)) = cpu_to_fdt32(phandle);
 	}
 }
-CHECK(phandle_references, NULL, NULL, fixup_phandle_references, NULL, ERROR,
+ERROR(phandle_references, NULL, NULL, fixup_phandle_references, NULL,
       &duplicate_node_names, &explicit_phandles);
 
 static void fixup_path_references(struct check *c, struct node *dt,
@@ -473,19 +480,19 @@ static void fixup_path_references(struct check *c, struct node *dt,
 						  strlen(path) + 1);
 	}
 }
-CHECK(path_references, NULL, NULL, fixup_path_references, NULL, ERROR,
+ERROR(path_references, NULL, NULL, fixup_path_references, NULL,
       &duplicate_node_names);
 
 /*
  * Semantic checks
  */
-CHECK_IS_CELL(address_cells_is_cell, "#address-cells", WARN);
-CHECK_IS_CELL(size_cells_is_cell, "#size-cells", WARN);
-CHECK_IS_CELL(interrupt_cells_is_cell, "#interrupt-cells", WARN);
+WARNING_IF_NOT_CELL(address_cells_is_cell, "#address-cells");
+WARNING_IF_NOT_CELL(size_cells_is_cell, "#size-cells");
+WARNING_IF_NOT_CELL(interrupt_cells_is_cell, "#interrupt-cells");
 
-CHECK_IS_STRING(device_type_is_string, "device_type", WARN);
-CHECK_IS_STRING(model_is_string, "model", WARN);
-CHECK_IS_STRING(status_is_string, "status", WARN);
+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");
 
 static void fixup_addr_size_cells(struct check *c, struct node *dt,
 				  struct node *node)
@@ -503,8 +510,8 @@ static void fixup_addr_size_cells(struct check *c, struct node *dt,
 	if (prop)
 		node->size_cells = propval_cell(prop);
 }
-CHECK(addr_size_cells, NULL, fixup_addr_size_cells, NULL, NULL, WARN,
-      &address_cells_is_cell, &size_cells_is_cell);
+WARNING(addr_size_cells, NULL, fixup_addr_size_cells, NULL, NULL,
+	&address_cells_is_cell, &size_cells_is_cell);
 
 #define node_addr_cells(n) \
 	(((n)->addr_cells == -1) ? 2 : (n)->addr_cells)
@@ -538,7 +545,7 @@ static void check_reg_format(struct check *c, struct node *dt,
 		     "(#address-cells == %d, #size-cells == %d)",
 		     node->fullpath, prop->val.len, addr_cells, size_cells);
 }
-NODE_CHECK(reg_format, NULL, WARN, &addr_size_cells);
+NODE_WARNING(reg_format, NULL, &addr_size_cells);
 
 static void check_ranges_format(struct check *c, struct node *dt,
 				struct node *node)
@@ -579,7 +586,7 @@ static void check_ranges_format(struct check *c, struct node *dt,
 		     p_addr_cells, c_addr_cells, c_size_cells);
 	}
 }
-NODE_CHECK(ranges_format, NULL, WARN, &addr_size_cells);
+NODE_WARNING(ranges_format, NULL, &addr_size_cells);
 
 /*
  * Style checks
@@ -606,7 +613,7 @@ static void check_avoid_default_addr_size(struct check *c, struct node *dt,
 		FAIL(c, "Relying on default #size-cells value for %s",
 		     node->fullpath);
 }
-NODE_CHECK(avoid_default_addr_size, NULL, WARN, &addr_size_cells);
+NODE_WARNING(avoid_default_addr_size, NULL, &addr_size_cells);
 
 static void check_obsolete_chosen_interrupt_controller(struct check *c,
 						       struct node *dt)
@@ -623,7 +630,7 @@ static void check_obsolete_chosen_interrupt_controller(struct check *c,
 		FAIL(c, "/chosen has obsolete \"interrupt-controller\" "
 		     "property");
 }
-TREE_CHECK(obsolete_chosen_interrupt_controller, NULL, WARN);
+TREE_WARNING(obsolete_chosen_interrupt_controller, NULL);
 
 static struct check *check_table[] = {
 	&duplicate_node_names, &duplicate_property_names,
@@ -653,7 +660,7 @@ void process_checks(int force, struct boot_info *bi)
 	for (i = 0; i < ARRAY_SIZE(check_table); i++) {
 		struct check *c = check_table[i];
 
-		if (c->level != IGNORE)
+		if (c->warn || c->error)
 			error = error || run_check(c, dt);
 	}
 
diff --git a/dtc.h b/dtc.h
index 7b4c65b..d57fbfc 100644
--- a/dtc.h
+++ b/dtc.h
@@ -25,6 +25,7 @@
 #include <string.h>
 #include <stdlib.h>
 #include <stdint.h>
+#include <stdbool.h>
 #include <stdarg.h>
 #include <assert.h>
 #include <ctype.h>

commit d5399197e9e0d8bad13de5c41df3b93804c0558a
Author: David Gibson <david@gibson.dropbear.id.au>
Date:   Sun Jul 8 23:25:22 2012 +1000

    Allow toggling of semantic checks
    
    This patch adds -W and -E options to dtc which allow toggling on and off
    of the various built in semantic checks on the tree.
    
    Signed-off-by: David Gibson <david@gibson.dropbear.id.au>

diff --git a/checks.c b/checks.c
index 3080439..9061237 100644
--- a/checks.c
+++ b/checks.c
@@ -58,7 +58,7 @@ struct check {
 	struct check **prereq;
 };
 
-#define CHECK(nm, tfn, nfn, pfn, d, w, e, ...)	       \
+#define CHECK_ENTRY(nm, tfn, nfn, pfn, d, w, e, ...)	       \
 	static struct check *nm##_prereqs[] = { __VA_ARGS__ }; \
 	static struct check nm = { \
 		.name = #nm, \
@@ -73,22 +73,30 @@ struct check {
 		.prereq = nm##_prereqs, \
 	};
 #define WARNING(nm, tfn, nfn, pfn, d, ...) \
-	CHECK(nm, tfn, nfn, pfn, d, true, false, __VA_ARGS__)
+	CHECK_ENTRY(nm, tfn, nfn, pfn, d, true, false, __VA_ARGS__)
 #define ERROR(nm, tfn, nfn, pfn, d, ...) \
-	CHECK(nm, tfn, nfn, pfn, d, false, true, __VA_ARGS__)
+	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)));
@@ -179,6 +187,13 @@ out:
  * Utility check functions
  */
 
+/* A check which always fails, for testing purposes only */
+static inline void check_always_fail(struct check *c, struct node *dt)
+{
+	FAIL(c, "always_fail check");
+}
+TREE_CHECK(always_fail, NULL);
+
 static void check_is_string(struct check *c, struct node *root,
 			    struct node *node)
 {
@@ -649,8 +664,71 @@ static struct check *check_table[] = {
 
 	&avoid_default_addr_size,
 	&obsolete_chosen_interrupt_controller,
+
+	&always_fail,
 };
 
+static void enable_warning_error(struct check *c, bool warn, bool error)
+{
+	int i;
+
+	/* Raising level, also raise it for prereqs */
+	if ((warn && !c->warn) || (error && !c->error))
+		for (i = 0; i < c->num_prereqs; i++)
+			enable_warning_error(c->prereq[i], warn, error);
+
+	c->warn = c->warn || warn;
+	c->error = c->error || error;
+}
+
+static void disable_warning_error(struct check *c, bool warn, bool error)
+{
+	int i;
+
+	/* Lowering level, also lower it for things this is the prereq
+	 * for */
+	if ((warn && c->warn) || (error && c->error)) {
+		for (i = 0; i < ARRAY_SIZE(check_table); i++) {
+			struct check *cc = check_table[i];
+			int j;
+
+			for (j = 0; j < cc->num_prereqs; j++)
+				if (cc->prereq[j] == c)
+					disable_warning_error(cc, warn, error);
+		}
+	}
+
+	c->warn = c->warn && !warn;
+	c->error = c->error && !error;
+}
+
+void parse_checks_option(bool warn, bool error, const char *optarg)
+{
+	int i;
+	const char *name = optarg;
+	bool enable = true;
+
+	if ((strncmp(optarg, "no-", 3) == 0)
+	    || (strncmp(optarg, "no_", 3) == 0)) {
+		name = optarg + 3;
+		enable = false;
+	}
+
+	for (i = 0; i < ARRAY_SIZE(check_table); i++) {
+		struct check *c = check_table[i];
+
+		if (streq(c->name, name)) {
+			if (enable)
+				enable_warning_error(c, warn, error);
+			else
+				disable_warning_error(c, warn, error);
+			return;
+		}
+	}
+
+	die("Unrecognized check name \"%s\"\n", name);
+}
+
 void process_checks(int force, struct boot_info *bi)
 {
 	struct node *dt = bi->dt;
diff --git a/dtc.c b/dtc.c
index bee5085..a375683 100644
--- a/dtc.c
+++ b/dtc.c
@@ -93,6 +93,9 @@ static void  __attribute__ ((noreturn)) usage(void)
 	fprintf(stderr, "\t\t\tlegacy - \"linux,phandle\" properties only\n");
 	fprintf(stderr, "\t\t\tepapr - \"phandle\" properties only\n");
 	fprintf(stderr, "\t\t\tboth - Both \"linux,phandle\" and \"phandle\" properties\n");
+	fprintf(stderr, "\t-W [no-]<checkname>\n");
+	fprintf(stderr, "\t-E [no-]<checkname>\n");
+	fprintf(stderr, "\t\t\tenable or disable warnings and errors\n");
 	exit(3);
 }
 
@@ -115,7 +118,7 @@ int main(int argc, char *argv[])
 	minsize    = 0;
 	padsize    = 0;
 
-	while ((opt = getopt(argc, argv, "hI:O:o:V:d:R:S:p:fqb:i:vH:s"))
+	while ((opt = getopt(argc, argv, "hI:O:o:V:d:R:S:p:fqb:i:vH:sW:E:"))
 			!= EOF) {
 		switch (opt) {
 		case 'I':
@@ -173,6 +176,14 @@ int main(int argc, char *argv[])
 			sort = 1;
 			break;
 
+		case 'W':
+			parse_checks_option(true, false, optarg);
+			break;
+
+		case 'E':
+			parse_checks_option(false, true, optarg);
+			break;
+
 		case 'h':
 		default:
 			usage();
diff --git a/dtc.h b/dtc.h
index d57fbfc..7ee2d54 100644
--- a/dtc.h
+++ b/dtc.h
@@ -226,6 +226,7 @@ void sort_tree(struct boot_info *bi);
 
 /* Checks */
 
+void parse_checks_option(bool warn, bool error, const char *optarg);
 void process_checks(int force, struct boot_info *bi);
 
 /* Flattened trees */
diff --git a/tests/dtc-checkfails.sh b/tests/dtc-checkfails.sh
index 3f77b13..76ded15 100755
--- a/tests/dtc-checkfails.sh
+++ b/tests/dtc-checkfails.sh
@@ -4,10 +4,20 @@
 
 for x; do
     shift
+    if [ "$x" = "-n" ]; then
+	for x; do
+	    shift
+	    if [ "$x" = "--" ]; then
+		break;
+	    fi
+	    NOCHECKS="$NOCHECKS $x"
+	done
+	break;
+    fi
     if [ "$x" = "--" ]; then
 	break;
     fi
-    CHECKS="$CHECKS $x"
+    YESCHECKS="$YESCHECKS $x"
 done
 
 LOG=tmp.log.$$
@@ -19,10 +29,16 @@ ret="$?"
 
 FAIL_IF_SIGNAL $ret
 
-for c in $CHECKS; do
+for c in $YESCHECKS; do
     if ! grep -E "^(ERROR)|(Warning) \($c\):" $LOG > /dev/null; then
 	FAIL "Failed to trigger check \"$c\""
     fi
 done
 
+for c in $NOCHECKS; do
+    if grep -E "^(ERROR)|(Warning) \($c\):" $LOG > /dev/null; then
+	FAIL "Incorrectly triggered check \"$c\""
+    fi
+done
+
 PASS
diff --git a/tests/dtc-fails.sh b/tests/dtc-fails.sh
new file mode 100755
index 0000000..4ddcb27
--- /dev/null
+++ b/tests/dtc-fails.sh
@@ -0,0 +1,30 @@
+#! /bin/sh
+
+. ./tests.sh
+
+if [ "$1" = "-n" ]; then
+    NEG="$1"
+    shift
+fi
+
+OUTPUT="$1"
+shift
+
+verbose_run $VALGRIND "$DTC" -o "$OUTPUT" "$@"
+ret="$?"
+
+FAIL_IF_SIGNAL $ret
+
+if [ -n "$NEG" ]; then
+    if [ ! -e "$OUTPUT" ]; then
+	FAIL "Produced no output"
+    fi
+else
+    if [ -e "$OUTPUT" ]; then
+	FAIL "Incorrectly produced output"
+    fi
+fi
+
+rm -f "$OUTPUT"
+
+PASS
diff --git a/tests/run_tests.sh b/tests/run_tests.sh
index e0299e3..169a829 100755
--- a/tests/run_tests.sh
+++ b/tests/run_tests.sh
@@ -396,6 +396,18 @@ dtc_tests () {
     run_sh_test dtc-checkfails.sh duplicate_label -- -I dts -O dtb reuse-label5.dts
     run_sh_test dtc-checkfails.sh duplicate_label -- -I dts -O dtb reuse-label6.dts
 
+    # Check warning options
+    run_sh_test dtc-checkfails.sh address_cells_is_cell interrupt_cells_is_cell -n size_cells_is_cell -- -Wno_size_cells_is_cell -I dts -O dtb bad-ncells.dts
+    run_sh_test dtc-fails.sh -n test-warn-output.test.dtb -I dts -O dtb bad-ncells.dts
+    run_sh_test dtc-fails.sh test-error-output.test.dtb -I dts -O dtb bad-ncells.dts -Esize_cells_is_cell
+    run_sh_test dtc-checkfails.sh always_fail -- -Walways_fail -I dts -O dtb test_tree1.dts
+    run_sh_test dtc-checkfails.sh -n always_fail -- -Walways_fail -Wno_always_fail -I dts -O dtb test_tree1.dts
+    run_sh_test dtc-fails.sh test-negation-1.test.dtb -Ealways_fail -I dts -O dtb test_tree1.dts
+    run_sh_test dtc-fails.sh -n test-negation-2.test.dtb -Ealways_fail -Eno_always_fail -I dts -O dtb test_tree1.dts
+    run_sh_test dtc-fails.sh test-negation-3.test.dtb -Ealways_fail -Wno_always_fail -I dts -O dtb test_tree1.dts
+    run_sh_test dtc-fails.sh -n test-negation-4.test.dtb -Esize_cells_is_cell -Eno_size_cells_is_cell -I dts -O dtb bad-ncells.dts
+    run_sh_test dtc-checkfails.sh size_cells_is_cell -- -Esize_cells_is_cell -Eno_size_cells_is_cell -I dts -O dtb bad-ncells.dts
+
     # Check for proper behaviour reading from stdin
     run_dtc_test -I dts -O dtb -o stdin_dtc_tree1.test.dtb - < test_tree1.dts
     run_wrap_test cmp stdin_dtc_tree1.test.dtb dtc_tree1.test.dtb

commit bb21f0a766056114e4d9336324b4c294f640d9d1
Author: Simon Glass <sjg@chromium.org>
Date:   Tue Jul 10 05:56:44 2012 -0700

    fdtput: Fix nit in help message
    
    There was an extra < in the help message, so fix it.
    
    Signed-off-by: Simon Glass <sjg@chromium.org>
    Acked-by: David Gibson <david@gibson.dropbear.id.au>

diff --git a/fdtput.c b/fdtput.c
index f6ebd24..244d1f1 100644
--- a/fdtput.c
+++ b/fdtput.c
@@ -162,7 +162,7 @@ static const char *usage_msg =
 	"The command line arguments are joined together into a single value.\n"
 	"\n"
 	"Usage:\n"
-	"	fdtput <options> <dt file> <<node> <property> [<value>...]\n"
+	"	fdtput <options> <dt file> <node> <property> [<value>...]\n"
 	"Options:\n"
 	"\t-t <type>\tType of data\n"
 	"\t-v\t\tVerbose: display each value decoded from command line\n"

commit f58dff50407c0ee56b372ab201469c18dc042f56
Author: Simon Glass <sjg@chromium.org>
Date:   Thu Jul 12 08:52:48 2012 -0700

    fdtput: Prepare to support multiple operations
    
    We want to add new options to this tool. In preparation for this, add
    the concept of a current operation.
    
    Signed-off-by: Simon Glass <sjg@chromium.org>

diff --git a/fdtput.c b/fdtput.c
index 244d1f1..da63539 100644
--- a/fdtput.c
+++ b/fdtput.c
@@ -28,7 +28,13 @@
 
 #include "util.h"
 
+/* These are the operations we support */
+enum oper_type {
+	OPER_WRITE_PROP,		/* Write a property in a node */
+};
+
 struct display_info {
+	enum oper_type oper;	/* operation to perform */
 	int type;		/* data type (s/i/u/x or 0 for default) */
 	int size;		/* data size (1/2/4) */
 	int verbose;		/* verbose output */
@@ -143,13 +149,19 @@ static int do_fdtput(struct display_info *disp, const char *filename,
 	if (!blob)
 		return -1;
 
-	/* convert the arguments into a single binary value, then store */
-	assert(arg_count >= 2);
-	if (encode_value(disp, arg + 2, arg_count - 2, &value, &len) ||
-		store_key_value(blob, *arg, arg[1], value, len))
-		ret = -1;
-
-	if (!ret)
+	switch (disp->oper) {
+	case OPER_WRITE_PROP:
+		/*
+		 * Convert the arguments into a single binary value, then
+		 * store them into the property.
+		 */
+		assert(arg_count >= 2);
+		if (encode_value(disp, arg + 2, arg_count - 2, &value, &len) ||
+			store_key_value(blob, *arg, arg[1], value, len))
+			ret = -1;
+		break;
+	}
+	if (ret >= 0)
 		ret = utilfdt_write(filename, blob);
 
 	free(blob);
@@ -185,6 +197,7 @@ int main(int argc, char *argv[])
 
 	memset(&disp, '\0', sizeof(disp));
 	disp.size = -1;
+	disp.oper = OPER_WRITE_PROP;
 	for (;;) {
 		int c = getopt(argc, argv, "ht:v");
 		if (c == -1)
@@ -224,10 +237,12 @@ int main(int argc, char *argv[])
 	argv += optind;
 	argc -= optind;
 
-	if (argc < 1)
-		usage("Missing node");
-	if (argc < 2)
-		usage("Missing property");
+	if (disp.oper == OPER_WRITE_PROP) {
+		if (argc < 1)
+			usage("Missing node");
+		if (argc < 2)
+			usage("Missing property");
+	}
 
 	if (do_fdtput(&disp, filename, argv, argc))
 		return 1;

commit d46c2de5700fd8d43de67ca3709c276beba39b39
Author: Simon Glass <sjg@chromium.org>
Date:   Thu Jul 12 08:52:49 2012 -0700

    fdtput: Add -c option to create nodes
    
    This option allows the creation of new nodes in a dtb file. The syntax
    is:
    
       fdtput -c <dtb_file> <node_path>
    
    The node_path contains the path of the node to be created. All path
    components up to the final one must exist already. The final one must
    not exist already.
    
    Signed-off-by: Simon Glass <sjg@chromium.org>
    Acked-by: David Gibson <david@gibson.dropbear.id.au>

diff --git a/fdtput.c b/fdtput.c
index da63539..a414fe9 100644
--- a/fdtput.c
+++ b/fdtput.c
@@ -31,6 +31,7 @@
 /* These are the operations we support */
 enum oper_type {
 	OPER_WRITE_PROP,		/* Write a property in a node */
+	OPER_CREATE_NODE,		/* Create a new node */
 };
 
 struct display_info {
@@ -138,6 +139,46 @@ static int store_key_value(void *blob, const char *node_name,
 	return 0;
 }
 
+/**
+ * Create a new node in the fdt.
+ *
+ * This will overwrite the node_name string. Any error is reported.
+ *
+ * TODO: Perhaps create fdt_path_offset_namelen() so we don't need to do this.
+ *
+ * @param blob		FDT blob to write into
+ * @param node_name	Name of node to create
+ * @return new node offset if found, or -1 on failure
+ */
+static int create_node(void *blob, const char *node_name)
+{
+	int node = 0;
+	char *p;
+
+	p = strrchr(node_name, '/');
+	if (!p) {
+		report_error(node_name, -FDT_ERR_BADPATH);
+		return -1;
+	}
+	*p = '\0';
+
+	if (p > node_name) {
+		node = fdt_path_offset(blob, node_name);
+		if (node < 0) {
+			report_error(node_name, node);
+			return -1;
+		}
+	}
+
+	node = fdt_add_subnode(blob, node, p + 1);
+	if (node < 0) {
+		report_error(p + 1, node);
+		return -1;
+	}
+
+	return 0;
+}
+
 static int do_fdtput(struct display_info *disp, const char *filename,
 		    char **arg, int arg_count)
 {
@@ -160,6 +201,10 @@ static int do_fdtput(struct display_info *disp, const char *filename,
 			store_key_value(blob, *arg, arg[1], value, len))
 			ret = -1;
 		break;
+	case OPER_CREATE_NODE:
+		for (; ret >= 0 && arg_count--; arg++)
+			ret = create_node(blob, *arg);
+		break;
 	}
 	if (ret >= 0)
 		ret = utilfdt_write(filename, blob);
@@ -175,7 +220,9 @@ static const char *usage_msg =
 	"\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-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"
@@ -199,7 +246,7 @@ int main(int argc, char *argv[])
 	disp.size = -1;
 	disp.oper = OPER_WRITE_PROP;
 	for (;;) {
-		int c = getopt(argc, argv, "ht:v");
+		int c = getopt(argc, argv, "cht:v");
 		if (c == -1)
 			break;
 
@@ -213,6 +260,9 @@ int main(int argc, char *argv[])
 		 * - expand fdt if value doesn't fit
 		 */
 		switch (c) {
+		case 'c':
+			disp.oper = OPER_CREATE_NODE;
+			break;
 		case 'h':
 		case '?':
 			usage(NULL);
diff --git a/tests/run_tests.sh b/tests/run_tests.sh
index 169a829..617372d 100755
--- a/tests/run_tests.sh
+++ b/tests/run_tests.sh
@@ -536,6 +536,19 @@ fdtput_tests () {
     # This should be larger than available space in the fdt
     run_wrap_error_test $DTPUT $dtb /randomnode blob -ts "$(cat $text $text)"
 
+    # Start again with a fresh dtb
+    run_dtc_test -O dtb -p $(stat -c %s $text) -o $dtb $dts
+
+    # Node creation
+    run_wrap_error_test $DTPUT $dtb -c /baldrick sod
+    run_wrap_test $DTPUT $dtb -c /chosen/son /chosen/daughter
+    run_fdtput_test "eva" $dtb /chosen/daughter name "" -ts "eva"
+    run_fdtput_test "adam" $dtb /chosen/son name "" -ts "adam"
+
+    # Not allowed to create an existing node
+    run_wrap_error_test $DTPUT $dtb -c /chosen
+    run_wrap_error_test $DTPUT $dtb -c /chosen/son
+
     # TODO: Add tests for verbose mode?
 }
 

commit 3553dfac224435233f2c0d33169194098e979c88
Author: Simon Glass <sjg@chromium.org>
Date:   Tue Jul 10 05:56:47 2012 -0700

    fdtput: Adjust report_error() to use name, namelen params
    
    As with many fdt functions, report_error() should permit a namelen to
    be specified, thus obviating the need for nul termination in strings
    passed to it.
    
    Signed-off-by: Simon Glass <sjg@chromium.org>
    Acked-by: David Gibson <david@gibson.dropbear.id.au>

diff --git a/fdtput.c b/fdtput.c
index a414fe9..1f048a8 100644
--- a/fdtput.c
+++ b/fdtput.c
@@ -41,9 +41,20 @@ struct display_info {
 	int verbose;		/* verbose output */
 };
 
-static void report_error(const char *where, int err)
+
+/**
+ * Report an error with a particular node.
+ *
+ * @param name		Node name to report error on
+ * @param namelen	Length of node name, or -1 to use entire string
+ * @param err		Error number to report (-FDT_ERR_...)
+ */
+static void report_error(const char *name, int namelen, int err)
 {
-	fprintf(stderr, "Error at '%s': %s\n", where, fdt_strerror(err));
+	if (namelen == -1)
+		namelen = strlen(name);
+	fprintf(stderr, "Error at '%1.*s': %s\n", namelen, name,
+		fdt_strerror(err));
 }
 
 /**
@@ -127,13 +138,13 @@ static int store_key_value(void *blob, const char *node_name,
 
 	node = fdt_path_offset(blob, node_name);
 	if (node < 0) {
-		report_error(node_name, node);
+		report_error(node_name, -1, node);
 		return -1;
 	}
 
 	err = fdt_setprop(blob, node, property, buf, len);
 	if (err) {
-		report_error(property, err);
+		report_error(property, -1, err);
 		return -1;
 	}
 	return 0;
@@ -157,7 +168,7 @@ static int create_node(void *blob, const char *node_name)
 
 	p = strrchr(node_name, '/');
 	if (!p) {
-		report_error(node_name, -FDT_ERR_BADPATH);
+		report_error(node_name, -1, -FDT_ERR_BADPATH);
 		return -1;
 	}
 	*p = '\0';
@@ -165,14 +176,14 @@ static int create_node(void *blob, const char *node_name)
 	if (p > node_name) {
 		node = fdt_path_offset(blob, node_name);
 		if (node < 0) {
-			report_error(node_name, node);
+			report_error(node_name, -1, node);
 			return -1;
 		}
 	}
 
 	node = fdt_add_subnode(blob, node, p + 1);
 	if (node < 0) {
-		report_error(p + 1, node);
+		report_error(p + 1, -1, node);
 		return -1;
 	}
 

commit f807af192828222dee7a5c9f94d999673bb4d8a1
Author: Simon Glass <sjg@chromium.org>
Date:   Thu Jul 12 08:52:51 2012 -0700

    fdtput: Add -p option to create subnodes along entire path
    
    This option mimics mkdir's -p option. It automatically creates nodes
    as needed along the path provided. If the node already exists, no
    error is given.
    
    Signed-off-by: Simon Glass <sjg@chromium.org>

diff --git a/fdtput.c b/fdtput.c
index 1f048a8..f2197f5 100644
--- a/fdtput.c
+++ b/fdtput.c
@@ -39,6 +39,7 @@ struct display_info {
 	int type;		/* data type (s/i/u/x or 0 for default) */
 	int size;		/* data size (1/2/4) */
 	int verbose;		/* verbose output */
+	int auto_path;		/* automatically create all path components */
 };
 
 
@@ -151,6 +152,47 @@ static int store_key_value(void *blob, const char *node_name,
 }
 
 /**
+ * Create paths as needed for all components of a path
+ *
+ * Any components of the path that do not exist are created. Errors are
+ * reported.
+ *
+ * @param blob		FDT blob to write into
+ * @param in_path	Path to process
+ * @return 0 if ok, -1 on error
+ */
+static int create_paths(void *blob, const char *in_path)
+{
+	const char *path = in_path;
+	const char *sep;
+	int node, offset = 0;
+
+	/* skip leading '/' */
+	while (*path == '/')
+		path++;
+
+	for (sep = path; *sep; path = sep + 1, offset = node) {
+		/* equivalent to strchrnul(), but it requires _GNU_SOURCE */
+		sep = strchr(path, '/');
+		if (!sep)
+			sep = path + strlen(path);
+
+		node = fdt_subnode_offset_namelen(blob, offset, path,
+				sep - path);
+		if (node == -FDT_ERR_NOTFOUND) {
+			node = fdt_add_subnode_namelen(blob, offset, path,
+						       sep - path);
+		}
+		if (node < 0) {
+			report_error(path, sep - path, node);
+			return -1;
+		}
+	}
+
+	return 0;
+}
+
+/**
  * Create a new node in the fdt.
  *
  * This will overwrite the node_name string. Any error is reported.
@@ -208,13 +250,19 @@ 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))
+			return -1;
 		if (encode_value(disp, arg + 2, arg_count - 2, &value, &len) ||
 			store_key_value(blob, *arg, arg[1], value, len))
 			ret = -1;
 		break;
 	case OPER_CREATE_NODE:
-		for (; ret >= 0 && arg_count--; arg++)
-			ret = create_node(blob, *arg);
+		for (; ret >= 0 && arg_count--; arg++) {
+			if (disp->auto_path)
+				ret = create_paths(blob, *arg);
+			else
+				ret = create_node(blob, *arg);
+		}
 		break;
 	}
 	if (ret >= 0)
@@ -234,6 +282,7 @@ static const char *usage_msg =
 	"	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"
@@ -257,7 +306,7 @@ int main(int argc, char *argv[])
 	disp.size = -1;
 	disp.oper = OPER_WRITE_PROP;
 	for (;;) {
-		int c = getopt(argc, argv, "cht:v");
+		int c = getopt(argc, argv, "chpt:v");
 		if (c == -1)
 			break;
 
@@ -277,7 +326,9 @@ int main(int argc, char *argv[])
 		case 'h':
 		case '?':
 			usage(NULL);
-
+		case 'p':
+			disp.auto_path = 1;
+			break;
 		case 't':
 			if (utilfdt_decode_type(optarg, &disp.type,
 					&disp.size))
diff --git a/tests/run_tests.sh b/tests/run_tests.sh
index 617372d..f5eebd6 100755
--- a/tests/run_tests.sh
+++ b/tests/run_tests.sh
@@ -549,6 +549,19 @@ fdtput_tests () {
     run_wrap_error_test $DTPUT $dtb -c /chosen
     run_wrap_error_test $DTPUT $dtb -c /chosen/son
 
+    # Automatic node creation
+    run_wrap_test $DTPUT $dtb -cp /blackadder/the-second/turnip \
+	/blackadder/the-second/potato
+    run_fdtput_test 1000 $dtb /blackadder/the-second/turnip cost "" 1000
+    run_fdtput_test "fine wine" $dtb /blackadder/the-second/potato drink \
+	"-ts" "fine wine"
+    run_wrap_test $DTPUT $dtb -p /you/are/drunk/sir/winston slurp -ts twice
+    run_wrap_error_test $DTPUT $dtb -cp "$(cat $text $text)/longish"
+
+    # Allowed to create an existing node with -p
+    run_wrap_test $DTPUT $dtb -cp /chosen
+    run_wrap_test $DTPUT $dtb -cp /chosen/son
+
     # TODO: Add tests for verbose mode?
 }
 

commit 8716901d2215a314504b7df6282aedfcf89da1ea
Author: Yann E. MORIN <yann.morin.1998@anciens.enib.fr>
Date:   Wed Aug 22 01:48:17 2012 +0200

    dtc/libfdt: install missing header
    
    Previously, only two headers were installed: libfdt.h and fdt.h.
    But libfdt.h also #includes libfdt_env.h, which was not installed.
    
    Install this missing header too.
    
    Signed-off-by: "Yann E. MORIN" <yann.morin.1998@free.fr>
    Acked-by: David Gibson <david@gibson.dropbear.id.au>

diff --git a/libfdt/Makefile.libfdt b/libfdt/Makefile.libfdt
index 4366627..91126c0 100644
--- a/libfdt/Makefile.libfdt
+++ b/libfdt/Makefile.libfdt
@@ -4,7 +4,7 @@
 # be easily embeddable into other systems of Makefiles.
 #
 LIBFDT_soname = libfdt.$(SHAREDLIB_EXT).1
-LIBFDT_INCLUDES = fdt.h libfdt.h
+LIBFDT_INCLUDES = fdt.h libfdt.h libfdt_env.h
 LIBFDT_VERSION = version.lds
 LIBFDT_SRCS = fdt.c fdt_ro.c fdt_wip.c fdt_sw.c fdt_rw.c fdt_strerror.c fdt_empty_tree.c
 LIBFDT_OBJS = $(LIBFDT_SRCS:%.c=%.o)

commit 45013d86197fea96810a7ae1b920d22b4c887688
Author: Stephen Warren <swarren@nvidia.com>
Date:   Tue Aug 7 22:50:15 2012 -0600

    dtc: Add ability to delete nodes and properties
    
    dtc currently allows the contents of properties to be changed, and the
    contents of nodes to be added to. There are situations where removing
    properties or nodes may be useful. This change implements the following
    syntax to do that:
    
        / {
            /delete-property/ propname;
            /delete-node/ nodename;
        };
    
    or:
    
        /delete-node/ &noderef;
    
    Signed-off-by: Stephen Warren <swarren@nvidia.com>
    Acked-by: David Gibson <david@gibson.dropbear.id.au>

diff --git a/checks.c b/checks.c
index 9061237..ee96a25 100644
--- a/checks.c
+++ b/checks.c
@@ -256,11 +256,15 @@ static void check_duplicate_property_names(struct check *c, struct node *dt,
 {
 	struct property *prop, *prop2;
 
-	for_each_property(node, prop)
-		for (prop2 = prop->next; prop2; prop2 = prop2->next)
+	for_each_property(node, prop) {
+		for (prop2 = prop->next; prop2; prop2 = prop2->next) {
+			if (prop2->deleted)
+				continue;
 			if (streq(prop->name, prop2->name))
 				FAIL(c, "Duplicate property name %s in %s",
 				     prop->name, node->fullpath);
+		}
+	}
 }
 NODE_ERROR(duplicate_property_names, NULL);
 
diff --git a/dtc-lexer.l b/dtc-lexer.l
index 4715f31..91c4930 100644
--- a/dtc-lexer.l
+++ b/dtc-lexer.l
@@ -103,6 +103,20 @@ static int pop_input_file(void);
 			return DT_BITS;
 		}
 
+<*>"/delete-property/"	{
+			DPRINT("Keyword: /delete-property/\n");
+			DPRINT("<PROPNODENAME>\n");
+			BEGIN(PROPNODENAME);
+			return DT_DEL_PROP;
+		}
+
+<*>"/delete-node/"	{
+			DPRINT("Keyword: /delete-node/\n");
+			DPRINT("<PROPNODENAME>\n");
+			BEGIN(PROPNODENAME);
+			return DT_DEL_NODE;
+		}
+
 <*>{LABEL}:	{
 			DPRINT("Label: %s\n", yytext);
 			yylval.labelref = xstrdup(yytext);
diff --git a/dtc-parser.y b/dtc-parser.y
index 6d5c2c2..f412460 100644
--- a/dtc-parser.y
+++ b/dtc-parser.y
@@ -62,6 +62,8 @@ static unsigned char eval_char_literal(const char *s);
 %token DT_MEMRESERVE
 %token DT_LSHIFT DT_RSHIFT DT_LE DT_GE DT_EQ DT_NE DT_AND DT_OR
 %token DT_BITS
+%token DT_DEL_PROP
+%token DT_DEL_NODE
 %token <propnodename> DT_PROPNODENAME
 %token <literal> DT_LITERAL
 %token <literal> DT_CHAR_LITERAL
@@ -153,6 +155,17 @@ devicetree:
 				print_error("label or path, '%s', not found", $2);
 			$$ = $1;
 		}
+	| devicetree DT_DEL_NODE DT_REF ';'
+		{
+			struct node *target = get_node_by_ref($1, $3);
+
+			if (!target)
+				print_error("label or path, '%s', not found", $3);
+			else
+				delete_node(target);
+
+			$$ = $1;
+		}
 	;
 
 nodedef:
@@ -182,6 +195,10 @@ propdef:
 		{
 			$$ = build_property($1, empty_data);
 		}
+	| DT_DEL_PROP DT_PROPNODENAME ';'
+		{
+			$$ = build_property_delete($2);
+		}
 	| DT_LABEL propdef
 		{
 			add_label(&$2->labels, $1);
@@ -440,6 +457,10 @@ subnode:
 		{
 			$$ = name_node($2, $1);
 		}
+	| DT_DEL_NODE DT_PROPNODENAME ';'
+		{
+			$$ = name_node(build_node_delete(), $2);
+		}
 	| DT_LABEL subnode
 		{
 			add_label(&$2->labels, $1);
diff --git a/dtc.h b/dtc.h
index 7ee2d54..d501c86 100644
--- a/dtc.h
+++ b/dtc.h
@@ -128,11 +128,13 @@ int data_is_one_string(struct data d);
 
 /* Live trees */
 struct label {
+	int deleted;
 	char *label;
 	struct label *next;
 };
 
 struct property {
+	int deleted;
 	char *name;
 	struct data val;
 
@@ -142,6 +144,7 @@ struct property {
 };
 
 struct node {
+	int deleted;
 	char *name;
 	struct property *proplist;
 	struct node *children;
@@ -158,28 +161,71 @@ struct node {
 	struct label *labels;
 };
 
+static inline struct label *for_each_label_next(struct label *l)
+{
+	do {
+		l = l->next;
+	} while (l && l->deleted);
+
+	return l;
+}
+
 #define for_each_label(l0, l) \
+	for ((l) = (l0); (l); (l) = for_each_label_next(l))
+
+#define for_each_label_withdel(l0, l) \
 	for ((l) = (l0); (l); (l) = (l)->next)
 
+static inline struct property *for_each_property_next(struct property *p)
+{
+	do {
+		p = p->next;
+	} while (p && p->deleted);
+
+	return p;
+}
+
 #define for_each_property(n, p) \
+	for ((p) = (n)->proplist; (p); (p) = for_each_property_next(p))
+
+#define for_each_property_withdel(n, p) \
 	for ((p) = (n)->proplist; (p); (p) = (p)->next)
 
-#define for_each_child(n, c)	\
+static inline struct node *for_each_child_next(struct node *c)
+{
+	do {
+		c = c->next_sibling;
+	} while (c && c->deleted);
+
+	return c;
+}
+
+#define for_each_child(n, c) \
+	for ((c) = (n)->children; (c); (c) = for_each_child_next(c))
+
+#define for_each_child_withdel(n, c) \
 	for ((c) = (n)->children; (c); (c) = (c)->next_sibling)
 
 void add_label(struct label **labels, char *label);
+void delete_labels(struct label **labels);
 
 struct property *build_property(char *name, struct data val);
+struct property *build_property_delete(char *name);
 struct property *chain_property(struct property *first, struct property *list);
 struct property *reverse_properties(struct property *first);
 
 struct node *build_node(struct property *proplist, struct node *children);
+struct node *build_node_delete(void);
 struct node *name_node(struct node *node, char *name);
 struct node *chain_node(struct node *first, struct node *list);
 struct node *merge_nodes(struct node *old_node, struct node *new_node);
 
 void add_property(struct node *node, struct property *prop);
+void delete_property_by_name(struct node *node, char *name);
+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);
 
 const char *get_unitname(struct node *node);
 struct property *get_property(struct node *node, const char *propname);
diff --git a/flattree.c b/flattree.c
index 28d0b23..665dad7 100644
--- a/flattree.c
+++ b/flattree.c
@@ -263,6 +263,9 @@ static void flatten_tree(struct node *tree, struct emitter *emit,
 	struct node *child;
 	int seen_name_prop = 0;
 
+	if (tree->deleted)
+		return;
+
 	emit->beginnode(etarget, tree->labels);
 
 	if (vi->flags & FTF_FULLPATH)
diff --git a/livetree.c b/livetree.c
index c9209d5..e856662 100644
--- a/livetree.c
+++ b/livetree.c
@@ -29,9 +29,11 @@ void add_label(struct label **labels, char *label)
 	struct label *new;
 
 	/* Make sure the label isn't already there */
-	for_each_label(*labels, new)
-		if (streq(new->label, label))
+	for_each_label_withdel(*labels, new)
+		if (streq(new->label, label)) {
+			new->deleted = 0;
 			return;
+		}
 
 	new = xmalloc(sizeof(*new));
 	new->label = label;
@@ -39,6 +41,14 @@ void add_label(struct label **labels, char *label)
 	*labels = new;
 }
 
+void delete_labels(struct label **labels)
+{
+	struct label *label;
+
+	for_each_label(*labels, label)
+		label->deleted = 1;
+}
+
 struct property *build_property(char *name, struct data val)
 {
 	struct property *new = xmalloc(sizeof(*new));
@@ -51,6 +61,18 @@ struct property *build_property(char *name, struct data val)
 	return new;
 }
 
+struct property *build_property_delete(char *name)
+{
+	struct property *new = xmalloc(sizeof(*new));
+
+	memset(new, 0, sizeof(*new));
+
+	new->name = name;
+	new->deleted = 1;
+
+	return new;
+}
+
 struct property *chain_property(struct property *first, struct property *list)
 {
 	assert(first->next == NULL);
@@ -91,6 +113,17 @@ struct node *build_node(struct property *proplist, struct node *children)
 	return new;
 }
 
+struct node *build_node_delete(void)
+{
+	struct node *new = xmalloc(sizeof(*new));
+
+	memset(new, 0, sizeof(*new));
+
+	new->deleted = 1;
+
+	return new;
+}
+
 struct node *name_node(struct node *node, char *name)
 {
 	assert(node->name == NULL);
@@ -106,8 +139,10 @@ struct node *merge_nodes(struct node *old_node, struct node *new_node)
 	struct node *new_child, *old_child;
 	struct label *l;
 
+	old_node->deleted = 0;
+
 	/* Add new node labels to old node */
-	for_each_label(new_node->labels, l)
+	for_each_label_withdel(new_node->labels, l)
 		add_label(&old_node->labels, l->label);
 
 	/* Move properties from the new node to the old node.  If there
@@ -118,14 +153,21 @@ struct node *merge_nodes(struct node *old_node, struct node *new_node)
 		new_node->proplist = new_prop->next;
 		new_prop->next = NULL;
 
+		if (new_prop->deleted) {
+			delete_property_by_name(old_node, new_prop->name);
+			free(new_prop);
+			continue;
+		}
+
 		/* Look for a collision, set new value if there is */
-		for_each_property(old_node, old_prop) {
+		for_each_property_withdel(old_node, old_prop) {
 			if (streq(old_prop->name, new_prop->name)) {
 				/* Add new labels to old property */
-				for_each_label(new_prop->labels, l)
+				for_each_label_withdel(new_prop->labels, l)
 					add_label(&old_prop->labels, l->label);
 
 				old_prop->val = new_prop->val;
+				old_prop->deleted = 0;
 				free(new_prop);
 				new_prop = NULL;
 				break;
@@ -146,8 +188,14 @@ struct node *merge_nodes(struct node *old_node, struct node *new_node)
 		new_child->parent = NULL;
 		new_child->next_sibling = NULL;
 
+		if (new_child->deleted) {
+			delete_node_by_name(old_node, new_child->name);
+			free(new_child);
+			continue;
+		}
+
 		/* Search for a collision.  Merge if there is */
-		for_each_child(old_node, old_child) {
+		for_each_child_withdel(old_node, old_child) {
 			if (streq(old_child->name, new_child->name)) {
 				merge_nodes(old_child, new_child);
 				new_child = NULL;
@@ -188,6 +236,25 @@ void add_property(struct node *node, struct property *prop)
 	*p = prop;
 }
 
+void delete_property_by_name(struct node *node, char *name)
+{
+	struct property *prop = node->proplist;
+
+	while (prop) {
+		if (!strcmp(prop->name, name)) {
+			delete_property(prop);
+			return;
+		}
+		prop = prop->next;
+	}
+}
+
+void delete_property(struct property *prop)
+{
+	prop->deleted = 1;
+	delete_labels(&prop->labels);
+}
+
 void add_child(struct node *parent, struct node *child)
 {
 	struct node **p;
@@ -202,6 +269,32 @@ void add_child(struct node *parent, struct node *child)
 	*p = child;
 }
 
+void delete_node_by_name(struct node *parent, char *name)
+{
+	struct node *node = parent->children;
+
+	while (node) {
+		if (!strcmp(node->name, name)) {
+			delete_node(node);
+			return;
+		}
+		node = node->next_sibling;
+	}
+}
+
+void delete_node(struct node *node)
+{
+	struct property *prop;
+	struct node *child;
+
+	node->deleted = 1;
+	for_each_child(node, child)
+		delete_node(child);
+	for_each_property(node, prop)
+		delete_property(prop);
+	delete_labels(&node->labels);
+}
+
 struct reserve_info *build_reserve_entry(uint64_t address, uint64_t size)
 {
 	struct reserve_info *new = xmalloc(sizeof(*new));
@@ -353,8 +446,11 @@ struct node *get_node_by_path(struct node *tree, const char *path)
 	const char *p;
 	struct node *child;
 
-	if (!path || ! (*path))
+	if (!path || ! (*path)) {
+		if (tree->deleted)
+			return NULL;
 		return tree;
+	}
 
 	while (path[0] == '/')
 		path++;
@@ -397,8 +493,11 @@ struct node *get_node_by_phandle(struct node *tree, cell_t phandle)
 
 	assert((phandle != 0) && (phandle != -1));
 
-	if (tree->phandle == phandle)
+	if (tree->phandle == phandle) {
+		if (tree->deleted)
+			return NULL;
 		return tree;
+	}
 
 	for_each_child(tree, child) {
 		node = get_node_by_phandle(child, phandle);
@@ -535,7 +634,7 @@ static void sort_properties(struct node *node)
 	int n = 0, i = 0;
 	struct property *prop, **tbl;
 
-	for_each_property(node, prop)
+	for_each_property_withdel(node, prop)
 		n++;
 
 	if (n == 0)
@@ -543,7 +642,7 @@ static void sort_properties(struct node *node)
 
 	tbl = xmalloc(n * sizeof(*tbl));
 
-	for_each_property(node, prop)
+	for_each_property_withdel(node, prop)
 		tbl[i++] = prop;
 
 	qsort(tbl, n, sizeof(*tbl), cmp_prop);
@@ -571,7 +670,7 @@ static void sort_subnodes(struct node *node)
 	int n = 0, i = 0;
 	struct node *subnode, **tbl;
 
-	for_each_child(node, subnode)
+	for_each_child_withdel(node, subnode)
 		n++;
 
 	if (n == 0)
@@ -579,7 +678,7 @@ static void sort_subnodes(struct node *node)
 
 	tbl = xmalloc(n * sizeof(*tbl));
 
-	for_each_child(node, subnode)
+	for_each_child_withdel(node, subnode)
 		tbl[i++] = subnode;
 
 	qsort(tbl, n, sizeof(*tbl), cmp_subnode);
@@ -598,7 +697,7 @@ static void sort_node(struct node *node)
 
 	sort_properties(node);
 	sort_subnodes(node);
-	for_each_child(node, c)
+	for_each_child_withdel(node, c)
 		sort_node(c);
 }
 
diff --git a/tests/run_tests.sh b/tests/run_tests.sh
index f5eebd6..e2158f7 100755
--- a/tests/run_tests.sh
+++ b/tests/run_tests.sh
@@ -367,6 +367,10 @@ dtc_tests () {
     run_dtc_test -I dts -O dtb -o dtc_tree1_merge_path.test.dtb test_tree1_merge_path.dts
     tree1_tests dtc_tree1_merge_path.test.dtb test_tree1.dtb
 
+    # Check prop/node delete functionality
+    run_dtc_test -I dts -O dtb -o dtc_tree1_delete.test.dtb test_tree1_delete.dts
+    tree1_tests dtc_tree1_delete.test.dtb
+
     # Check some checks
     check_tests dup-nodename.dts duplicate_node_names
     check_tests dup-propname.dts duplicate_property_names
diff --git a/tests/test_tree1.dts b/tests/test_tree1.dts
index cf530ce..c7b170c 100644
--- a/tests/test_tree1.dts
+++ b/tests/test_tree1.dts
@@ -1,38 +1,3 @@
 /dts-v1/;
 
-/memreserve/ 0xdeadbeef00000000 0x100000;
-/memreserve/ 123456789 010000;
-
-/ {
-	compatible = "test_tree1";
-	prop-int = <0xdeadbeef>;
-	prop-int64 = /bits/ 64 <0xdeadbeef01abcdef>;
-	prop-str = "hello world";
-
-	subnode@1 {
-		compatible = "subnode1";
-		prop-int = [deadbeef];
-
-		subsubnode {
-			compatible = "subsubnode1", "subsubnode";
-			prop-int = <0xdeadbeef>;
-		};
-
-		ss1 {
-		};
-	};
-
-	subnode@2 {
-		linux,phandle = <0x2000>;
-		prop-int = <123456789>;
-
-		ssn0: subsubnode@0 {
-			phandle = <0x2001>;
-			compatible = "subsubnode2", "subsubnode";
-			prop-int = <0726746425>;
-		};
-
-		ss2 {
-		};
-	};
-};
+/include/ "test_tree1_body.dtsi"
diff --git a/tests/test_tree1_body.dtsi b/tests/test_tree1_body.dtsi
new file mode 100644
index 0000000..1446191
--- /dev/null
+++ b/tests/test_tree1_body.dtsi
@@ -0,0 +1,36 @@
+/memreserve/ 0xdeadbeef00000000 0x100000;
+/memreserve/ 123456789 010000;
+
+/ {
+	compatible = "test_tree1";
+	prop-int = <0xdeadbeef>;
+	prop-int64 = /bits/ 64 <0xdeadbeef01abcdef>;
+	prop-str = "hello world";
+
+	subnode@1 {
+		compatible = "subnode1";
+		prop-int = [deadbeef];
+
+		subsubnode {
+			compatible = "subsubnode1", "subsubnode";
+			prop-int = <0xdeadbeef>;
+		};
+
+		ss1 {
+		};
+	};
+
+	subnode@2 {
+		linux,phandle = <0x2000>;
+		prop-int = <123456789>;
+
+		ssn0: subsubnode@0 {
+			phandle = <0x2001>;
+			compatible = "subsubnode2", "subsubnode";
+			prop-int = <0726746425>;
+		};
+
+		ss2 {
+		};
+	};
+};
diff --git a/tests/test_tree1_delete.dts b/tests/test_tree1_delete.dts
new file mode 100644
index 0000000..a2f1bfd
--- /dev/null
+++ b/tests/test_tree1_delete.dts
@@ -0,0 +1,68 @@
+/dts-v1/;
+
+/include/ "test_tree1_body.dtsi"
+
+/ {
+	nonexistant-property = <0xdeadbeef>;
+
+	nonexistant-subnode {
+		prop-int = <1>;
+	};
+
+	dellabel: deleted-by-label {
+		prop-int = <1>;
+	};
+
+	subnode@1 {
+		delete-this-str = "deadbeef";
+	};
+
+};
+
+/ {
+	/delete-property/ nonexistant-property;
+
+	/delete-node/ nonexistant-subnode;
+
+	subnode@1 {
+		/delete-property/ delete-this-str;
+	};
+};
+
+/delete-node/ &dellabel;
+
+/ {
+	/delete-property/ prop-str;
+};
+
+/ {
+	prop-str = "hello world";
+};
+
+/ {
+	subnode@1 {
+		/delete-node/ ss1;
+	};
+};
+
+/ {
+	subnode@1 {
+		ss1 {
+		};
+	};
+};
+
+/{
+	duplabel1: foo1 = "bar";
+	duplabel2: foo2 = "bar";
+};
+
+/{
+	duplabel1: baz1 = "qux";
+	duplabel2: baz2 = "qux";
+};
+
+/{
+	/delete-property/ foo1;
+	/delete-property/ baz2;
+};

commit 1ff3d3f8de701ed107e908030b5c1fed9d17125a
Author: Stephen Warren <swarren@nvidia.com>
Date:   Thu Sep 27 17:11:04 2012 -0600

    dtc: cpp co-existence: allow names starting with # to be escaped
    
    The device tree language as currently defined conflicts with the C pre-
    processor in one aspect - when a property or node name begins with a #
    character, a pre-processor would attempt to interpret it as a directive,
    fail, and most likely error out.
    
    This change allows a property/node name to be prefixed with \. This
    prevents a pre-processor from seeing # as the first non-whitespace
    character on the line, and hence prevents the conflict. \ was previously
    an illegal character in property/node names, so this change is
    backwards compatible. The \ is stripped from the name during parsing
    by dtc.
    
    Signed-off-by: Stephen Warren <swarren@nvidia.com>
    Acked-by: David Gibson <david@gibson.dropbear.id.au>

diff --git a/dtc-lexer.l b/dtc-lexer.l
index 91c4930..edbeb86 100644
--- a/dtc-lexer.l
+++ b/dtc-lexer.l
@@ -162,9 +162,10 @@ static int pop_input_file(void);
 			return ']';
 		}
 
-<PROPNODENAME>{PROPNODECHAR}+ {
+<PROPNODENAME>\\?{PROPNODECHAR}+ {
 			DPRINT("PropNodeName: %s\n", yytext);
-			yylval.propnodename = xstrdup(yytext);
+			yylval.propnodename = xstrdup((yytext[0] == '\\') ?
+							yytext + 1 : yytext);
 			BEGIN_DEFAULT();
 			return DT_PROPNODENAME;
 		}
diff --git a/tests/.gitignore b/tests/.gitignore
index f8e1af0..e2aa24a 100644
--- a/tests/.gitignore
+++ b/tests/.gitignore
@@ -39,6 +39,7 @@ tmp.*
 /path_offset
 /path_offset_aliases
 /phandle_format
+/propname_escapes
 /references
 /root_node
 /rw_tree1
diff --git a/tests/Makefile.tests b/tests/Makefile.tests
index 1795466..d59bff8 100644
--- a/tests/Makefile.tests
+++ b/tests/Makefile.tests
@@ -12,7 +12,7 @@ LIB_TESTS_L = get_mem_rsv \
 	sw_tree1 \
 	move_and_save mangle-layout nopulate \
 	open_pack rw_tree1 set_name setprop del_property del_node \
-	appendprop1 appendprop2 \
+	appendprop1 appendprop2 propname_escapes \
 	string_escapes references path-references phandle_format \
 	boot-cpuid incbin \
 	extra-terminating-null \
diff --git a/tests/propname_escapes.c b/tests/propname_escapes.c
new file mode 100644
index 0000000..3aec28f
--- /dev/null
+++ b/tests/propname_escapes.c
@@ -0,0 +1,43 @@
+/*
+ * libfdt - Flat Device Tree manipulation
+ *	Testcase for fdt_getprop()
+ * Copyright (C) 2006 David Gibson, IBM Corporation.
+ * Copyright (C) 2012 NVIDIA CORPORATION. All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser 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
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdint.h>
+
+#include <fdt.h>
+#include <libfdt.h>
+
+#include "tests.h"
+
+int main(int argc, char *argv[])
+{
+	void *fdt;
+
+	test_init(argc, argv);
+	fdt = load_blob_arg(argc, argv);
+
+	check_getprop_cell(fdt, 0, "#address-cells", 1);
+	check_getprop_cell(fdt, 0, "#gpio-cells", 2);
+
+	PASS();
+}
diff --git a/tests/propname_escapes.dts b/tests/propname_escapes.dts
new file mode 100644
index 0000000..9f70618
--- /dev/null
+++ b/tests/propname_escapes.dts
@@ -0,0 +1,6 @@
+/dts-v1/;
+
+/ {
+	#address-cells = <1>;
+	\#gpio-cells = <2>;
+};
diff --git a/tests/run_tests.sh b/tests/run_tests.sh
index e2158f7..7d7a5f7 100755
--- a/tests/run_tests.sh
+++ b/tests/run_tests.sh
@@ -254,6 +254,9 @@ dtc_tests () {
     tree1_tests_rw dtc_tree1.test.dtb
     run_test dtbs_equal_ordered dtc_tree1.test.dtb test_tree1.dtb
 
+    run_dtc_test -I dts -O dtb -o dtc_escapes.test.dtb propname_escapes.dts
+    run_test propname_escapes dtc_escapes.test.dtb
+
     run_dtc_test -I dts -O dtb -o dtc_escapes.test.dtb escapes.dts
     run_test string_escapes dtc_escapes.test.dtb
 

commit 1b6d1941dc5b589632c254ee6e960404d7cef5f2
Author: Stephen Warren <swarren@nvidia.com>
Date:   Thu Sep 27 17:11:05 2012 -0600

    dtc: cpp co-existence: add support for #line directives
    
    Line control directives of the following formats are supported:
        #line LINE "FILE"
        # LINE "FILE" [FLAGS]
    
    This allows dtc to consume the output of pre-processors, and to provide
    error messages that refer to the original filename, including taking
    into account any #include directives that the pre-processor may have
    performed.
    
    Signed-off-by: Stephen Warren <swarren@nvidia.com>
    Acked-by: David Gibson <david@gibson.dropbear.id.au>

diff --git a/dtc-lexer.l b/dtc-lexer.l
index edbeb86..254d5af 100644
--- a/dtc-lexer.l
+++ b/dtc-lexer.l
@@ -71,6 +71,27 @@ static int pop_input_file(void);
 			push_input_file(name);
 		}
 
+<*>^"#"(line)?{WS}+[0-9]+{WS}+{STRING}({WS}+[0-9]+)? {
+			char *line, *tmp, *fn;
+			/* skip text before line # */
+			line = yytext;
+			while (!isdigit(*line))
+				line++;
+			/* skip digits in line # */
+			tmp = line;
+			while (!isspace(*tmp))
+				tmp++;
+			/* "NULL"-terminate line # */
+			*tmp = '\0';
+			/* start of filename */
+			fn = strchr(tmp + 1, '"') + 1;
+			/* strip trailing " from filename */
+			tmp = strchr(fn, '"');
+			*tmp = 0;
+			/* -1 since #line is the number of the next line */
+			srcpos_set_line(xstrdup(fn), atoi(line) - 1);
+		}
+
 <*><<EOF>>		{
 			if (!pop_input_file()) {
 				yyterminate();
diff --git a/srcpos.c b/srcpos.c
index 3ee523d..246ab4b 100644
--- a/srcpos.c
+++ b/srcpos.c
@@ -328,3 +328,9 @@ srcpos_warn(struct srcpos *pos, char const *fmt, ...)
 
 	va_end(va);
 }
+
+void srcpos_set_line(char *f, int l)
+{
+	current_srcfile->name = f;
+	current_srcfile->lineno = l;
+}
diff --git a/srcpos.h b/srcpos.h
index 5617916..93a2712 100644
--- a/srcpos.h
+++ b/srcpos.h
@@ -113,4 +113,6 @@ extern void srcpos_error(struct srcpos *pos, char const *, ...)
 extern void srcpos_warn(struct srcpos *pos, char const *, ...)
      __attribute__((format(printf, 2, 3)));
 
+extern void srcpos_set_line(char *f, int l);
+
 #endif /* _SRCPOS_H_ */
diff --git a/tests/line_directives.dts b/tests/line_directives.dts
new file mode 100644
index 0000000..e9d0800
--- /dev/null
+++ b/tests/line_directives.dts
@@ -0,0 +1,11 @@
+/dts-v1/;
+
+/* common format */
+#line 3 "foo.dts"
+/* newer gcc format */
+# 9 "baz.dts" 1
+/* flags are optional */
+# 6 "bar.dts"
+
+/ {
+};
diff --git a/tests/run_tests.sh b/tests/run_tests.sh
index 7d7a5f7..9ca45c9 100755
--- a/tests/run_tests.sh
+++ b/tests/run_tests.sh
@@ -257,6 +257,8 @@ dtc_tests () {
     run_dtc_test -I dts -O dtb -o dtc_escapes.test.dtb propname_escapes.dts
     run_test propname_escapes dtc_escapes.test.dtb
 
+    run_dtc_test -I dts -O dtb -o line_directives.test.dtb line_directives.dts
+
     run_dtc_test -I dts -O dtb -o dtc_escapes.test.dtb escapes.dts
     run_test string_escapes dtc_escapes.test.dtb
 

commit 317a5d92bc357aba2c993ee78b4c089b7539fcc6
Author: Stephen Warren <swarren@nvidia.com>
Date:   Fri Sep 28 12:39:22 2012 -0600

    dtc: zero out new label objects
    
    Without this, new->deleted may be left set to some random value, which
    may then cause future label references to fail to locate the label. The
    code that allocates properties and nodes already contains the equivalent
    memset().
    
    Signed-off-by: Stephen Warren <swarren@nvidia.com>

diff --git a/livetree.c b/livetree.c
index e856662..b61465f 100644
--- a/livetree.c
+++ b/livetree.c
@@ -36,6 +36,7 @@ void add_label(struct label **labels, char *label)
 		}
 
 	new = xmalloc(sizeof(*new));
+	memset(new, 0, sizeof(*new));
 	new->label = label;
 	new->next = *labels;
 	*labels = new;

commit c6fb1d239191daa3323fb6caeff56d48c4777793
Author: Anders Hedlund <anders.hedlund@windriver.com>
Date:   Mon Sep 10 13:50:56 2012 +0200

    libfdt: Added missing functions to shared library
    
    Some API function symbols were set as 'local' causing linking errors,
    now they are set as global (external).
    
    Signed-off-by: Anders Hedlund <anders.hedlund@windriver.com>
    Acked-by: David Gibson <david@gibson.dropbear.id.au>

diff --git a/libfdt/version.lds b/libfdt/version.lds
index 3c3994e..80b322b 100644
--- a/libfdt/version.lds
+++ b/libfdt/version.lds
@@ -48,6 +48,12 @@ LIBFDT_1.2 {
 		fdt_strerror;
 		fdt_offset_ptr;
 		fdt_next_tag;
+		fdt_appendprop;
+		fdt_create_empty_tree;
+		fdt_first_property_offset;
+		fdt_get_property_by_offset;
+		fdt_getprop_by_offset;
+		fdt_next_property_offset;
 
 	local:
 		*;

commit 1762ab42ef77db7ab2776d0d6cba3515150f518a
Author: Stephen Warren <swarren@nvidia.com>
Date:   Fri Oct 5 09:57:41 2012 -0600

    dtc: fix for_each_*() to skip first object if deleted
    
    The previous definition of for_each_*() would always include the very
    first object within the list, irrespective of whether it was marked
    deleted, since the deleted flag was not checked on the first object,
    but only on any "next" object.
    
    Fix for_each_*() to check the deleted flag in the loop body every
    iteration to correct this.
    
    Incidentally, this change is why commit 45013d8 dtc: "Add ability to
    delete nodes and properties" only caused two "make checkm" failures;
    only two tests actually use multiple labels on the same property or
    node. With this current change applied, but commit 317a5d9 "dtc: zero
    out new label objects" reverted, "make checkm" fails 29 times; i.e.
    for every test that uses any labels at all.
    
    Signed-off-by: Stephen Warren <swarren@nvidia.com>
    Acked-by: David Gibson <david@gibson.dropbear.id.au>

diff --git a/dtc.h b/dtc.h
index d501c86..3e42a07 100644
--- a/dtc.h
+++ b/dtc.h
@@ -161,51 +161,27 @@ struct node {
 	struct label *labels;
 };
 
-static inline struct label *for_each_label_next(struct label *l)
-{
-	do {
-		l = l->next;
-	} while (l && l->deleted);
-
-	return l;
-}
-
-#define for_each_label(l0, l) \
-	for ((l) = (l0); (l); (l) = for_each_label_next(l))
-
 #define for_each_label_withdel(l0, l) \
 	for ((l) = (l0); (l); (l) = (l)->next)
 
-static inline struct property *for_each_property_next(struct property *p)
-{
-	do {
-		p = p->next;
-	} while (p && p->deleted);
-
-	return p;
-}
-
-#define for_each_property(n, p) \
-	for ((p) = (n)->proplist; (p); (p) = for_each_property_next(p))
+#define for_each_label(l0, l) \
+	for_each_label_withdel(l0, l) \
+		if (!(l)->deleted)
 
 #define for_each_property_withdel(n, p) \
 	for ((p) = (n)->proplist; (p); (p) = (p)->next)
 
-static inline struct node *for_each_child_next(struct node *c)
-{
-	do {
-		c = c->next_sibling;
-	} while (c && c->deleted);
-
-	return c;
-}
-
-#define for_each_child(n, c) \
-	for ((c) = (n)->children; (c); (c) = for_each_child_next(c))
+#define for_each_property(n, p) \
+	for_each_property_withdel(n, p) \
+		if (!(p)->deleted)
 
 #define for_each_child_withdel(n, c) \
 	for ((c) = (n)->children; (c); (c) = (c)->next_sibling)
 
+#define for_each_child(n, c) \
+	for_each_child_withdel(n, c) \
+		if (!(c)->deleted)
+
 void add_label(struct label **labels, char *label);
 void delete_labels(struct label **labels);
 
diff --git a/tests/delete_reinstate_multilabel.dts b/tests/delete_reinstate_multilabel.dts
new file mode 100644
index 0000000..281a6b2
--- /dev/null
+++ b/tests/delete_reinstate_multilabel.dts
@@ -0,0 +1,37 @@
+/dts-v1/;
+
+/* Create some nodes and properties with multiple labels */
+
+/ {
+	label1: label2: prop = "value";
+
+	label3: label4: node {
+		label5: label6: prop = "value";
+	};
+};
+
+/* Delete them, and everything that's part of them, i.e. the labels */
+
+/ {
+	/delete-property/ prop;
+	/delete-node/ node;
+};
+
+/*
+ * Re-instate them. None of the old labels should come back
+ *
+ * Note: Do not add any new/extra labels here. As of the time of writing,
+ * when dtc adds labels to an object, they are added to the head of the list
+ * of labels, and this test is specifically about ensuring the correct
+ * handling of lists of labels where the first label in the list is marked as
+ * deleted. Failure to observe this note may result in the test passing when
+ * it should not.
+ */
+
+/ {
+	prop = "value";
+
+	node {
+		prop = "value";
+	};
+};
diff --git a/tests/delete_reinstate_multilabel_ref.dts b/tests/delete_reinstate_multilabel_ref.dts
new file mode 100644
index 0000000..28fa117
--- /dev/null
+++ b/tests/delete_reinstate_multilabel_ref.dts
@@ -0,0 +1,9 @@
+/dts-v1/;
+
+/ {
+	prop = "value";
+
+	node {
+		prop = "value";
+	};
+};
diff --git a/tests/run_tests.sh b/tests/run_tests.sh
index 9ca45c9..dd7f217 100755
--- a/tests/run_tests.sh
+++ b/tests/run_tests.sh
@@ -376,6 +376,9 @@ dtc_tests () {
     run_dtc_test -I dts -O dtb -o dtc_tree1_delete.test.dtb test_tree1_delete.dts
     tree1_tests dtc_tree1_delete.test.dtb
 
+    run_dtc_test -I dts -O dts -o delete_reinstate_multilabel.dts.test.dts delete_reinstate_multilabel.dts
+    run_wrap_test cmp delete_reinstate_multilabel.dts.test.dts delete_reinstate_multilabel_ref.dts
+
     # Check some checks
     check_tests dup-nodename.dts duplicate_node_names
     check_tests dup-propname.dts duplicate_property_names

commit 8dec4d86ad3f44ef5011f86394d8f3061a09237a
Author: Michael Ellerman <michael@ellerman.id.au>
Date:   Tue Oct 16 17:58:56 2012 +1100

    dtc: srcpos_verror() should print to stderr
    
    Errors should go to stderr.
    
    Signed-off-by: Michael Ellerman <michael@ellerman.id.au>
    Acked-by: David Gibson <david@gibson.dropbear.id.au>

diff --git a/srcpos.c b/srcpos.c
index 246ab4b..c20bc53 100644
--- a/srcpos.c
+++ b/srcpos.c
@@ -297,9 +297,9 @@ srcpos_verror(struct srcpos *pos, char const *fmt, va_list va)
 
        srcstr = srcpos_string(pos);
 
-       fprintf(stdout, "Error: %s ", srcstr);
-       vfprintf(stdout, fmt, va);
-       fprintf(stdout, "\n");
+       fprintf(stderr, "Error: %s ", srcstr);
+       vfprintf(stderr, fmt, va);
+       fprintf(stderr, "\n");
 }
 
 void

commit e4b497f367a3b2ae99cc52089a14a221b13a76ef
Author: Michael Ellerman <michael@ellerman.id.au>
Date:   Tue Oct 16 18:04:20 2012 +1100

    Add documentation on how to submit patches
    
    Signed-off-by: Michael Ellerman <michael@ellerman.id.au>
    Acked-by: David Gibson <david@gibson.dropbear.id.au>

diff --git a/Documentation/manual.txt b/Documentation/manual.txt
index 989c589..65c8540 100644
--- a/Documentation/manual.txt
+++ b/Documentation/manual.txt
@@ -3,6 +3,7 @@ Device Tree Compiler Manual
 
 I - "dtc", the device tree compiler
     1) Obtaining Sources
+    1.1) Submitting Patches
     2) Description
     3) Command Line
     4) Source File
@@ -44,6 +45,10 @@ Tarballs of the 1.0.0 and latest releases are here:
     http://www.jdl.com/software/dtc-v1.2.0.tgz
     http://www.jdl.com/software/dtc-latest.tgz
 
+1.1) Submitting Patches
+
+Patches should be sent to jdl@jdl.com, and CC'ed to
+devicetree-discuss@lists.ozlabs.org.
 
 2) Description
 

commit 94a4799b200451d4037ec9219023becfe8c45ef1
Author: Pantelis Antoniou <panto@antoniou-consulting.com>
Date:   Fri Jan 4 21:12:46 2013 +0200

    fdtdump: properly handle multi-string properties
    
    Device tree can store multiple strings in a single property.
    We didn't handle that case properly.
    
    Signed-off-by: Pantelis Antoniou <panto@antoniou-consulting.com>
    Acked-by: David Gibson <david@gibson.dropbear.id.au>

diff --git a/fdtdump.c b/fdtdump.c
index 207a46d..d4fa6d7 100644
--- a/fdtdump.c
+++ b/fdtdump.c
@@ -21,13 +21,23 @@ static void print_data(const char *data, int len)
 {
 	int i;
 	const char *p = data;
+	const char *s;
 
 	/* no data, don't print */
 	if (len == 0)
 		return;
 
 	if (util_is_printable_string(data, len)) {
-		printf(" = \"%s\"", (const char *)data);
+		printf(" = ");
+
+		s = data;
+		do {
+			printf("\"%s\"", s);
+			s += strlen(s) + 1;
+			if (s < data + len)
+				printf(", ");
+		} while (s < data + len);
+
 	} else if ((len % 4) == 0) {
 		printf(" = <");
 		for (i = 0; i < len; i += 4)

commit 1c1efd69545a101d7181fc8e5df2b9a3545a58e8
Author: Pantelis Antoniou <panto@antoniou-consulting.com>
Date:   Fri Jan 4 21:12:58 2013 +0200

    Fix util_is_printable_string
    
    The method used did not account for multi-part strings.
    
    Signed-off-by: Pantelis Antoniou <panto@antoniou-consulting.com>
    Acked-by: David Gibson <david@gibson.dropbear.id.au>

diff --git a/util.c b/util.c
index 2422c34..45f186b 100644
--- a/util.c
+++ b/util.c
@@ -72,7 +72,7 @@ char *join_path(const char *path, const char *name)
 int util_is_printable_string(const void *data, int len)
 {
 	const char *s = data;
-	const char *ss;
+	const char *ss, *se;
 
 	/* zero length is not */
 	if (len == 0)
@@ -82,13 +82,19 @@ int util_is_printable_string(const void *data, int len)
 	if (s[len - 1] != '\0')
 		return 0;
 
-	ss = s;
-	while (*s && isprint(*s))
-		s++;
+	se = s + len;
 
-	/* not zero, or not done yet */
-	if (*s != '\0' || (s + 1 - ss) < len)
-		return 0;
+	while (s < se) {
+		ss = s;
+		while (s < se && *s && isprint(*s))
+			s++;
+
+		/* not zero, or not done yet */
+		if (*s != '\0' || s == ss)
+			return 0;
+
+		s++;
+	}
 
 	return 1;
 }

commit 38ad79d33946590c862567c7cbdf25b5a46d8149
Author: Kim Phillips <kim.phillips@freescale.com>
Date:   Tue Nov 13 18:34:01 2012 -0600

    dtc/tests: don't include fdt.h prior to libfdt.h
    
    tests will need fdt type definitions provided in a subsequent patch
    to libfdt_env.h.  Since libfdt.h includes libfdt_env.h in the right
    order anyway, just remove the fdt.h include.
    
    Signed-off-by: Kim Phillips <kim.phillips@freescale.com>
    Acked-by: David Gibson <david@gibson.dropbear.id.au>

diff --git a/tests/add_subnode_with_nops.c b/tests/add_subnode_with_nops.c
index 4fb8f02..95ddf6a 100644
--- a/tests/add_subnode_with_nops.c
+++ b/tests/add_subnode_with_nops.c
@@ -24,7 +24,6 @@
 #include <ctype.h>
 #include <stdint.h>
 
-#include <fdt.h>
 #include <libfdt.h>
 
 #include "tests.h"
diff --git a/tests/appendprop1.c b/tests/appendprop1.c
index d716f7a..9d6b3ad 100644
--- a/tests/appendprop1.c
+++ b/tests/appendprop1.c
@@ -24,7 +24,6 @@
 #include <ctype.h>
 #include <stdint.h>
 
-#include <fdt.h>
 #include <libfdt.h>
 
 #include "tests.h"
diff --git a/tests/appendprop2.c b/tests/appendprop2.c
index 7eb243d..ca1446c 100644
--- a/tests/appendprop2.c
+++ b/tests/appendprop2.c
@@ -24,7 +24,6 @@
 #include <ctype.h>
 #include <stdint.h>
 
-#include <fdt.h>
 #include <libfdt.h>
 
 #include "tests.h"
diff --git a/tests/asm_tree_dump.c b/tests/asm_tree_dump.c
index 5ff5087..bd12eda 100644
--- a/tests/asm_tree_dump.c
+++ b/tests/asm_tree_dump.c
@@ -26,7 +26,6 @@
 
 #include <dlfcn.h>
 
-#include <fdt.h>
 #include <libfdt.h>
 
 #include "tests.h"
diff --git a/tests/boot-cpuid.c b/tests/boot-cpuid.c
index 7b5433d..ca39f4b 100644
--- a/tests/boot-cpuid.c
+++ b/tests/boot-cpuid.c
@@ -21,7 +21,6 @@
 #include <string.h>
 #include <stdint.h>
 
-#include <fdt.h>
 #include <libfdt.h>
 
 #include "tests.h"
diff --git a/tests/char_literal.c b/tests/char_literal.c
index 150f2a0..d7a4773 100644
--- a/tests/char_literal.c
+++ b/tests/char_literal.c
@@ -23,7 +23,6 @@
 #include <string.h>
 #include <stdint.h>
 
-#include <fdt.h>
 #include <libfdt.h>
 
 #include "tests.h"
diff --git a/tests/del_node.c b/tests/del_node.c
index afad502..45cb060 100644
--- a/tests/del_node.c
+++ b/tests/del_node.c
@@ -24,7 +24,6 @@
 #include <ctype.h>
 #include <stdint.h>
 
-#include <fdt.h>
 #include <libfdt.h>
 
 #include "tests.h"
diff --git a/tests/del_property.c b/tests/del_property.c
index 449eca6..42fd7cb 100644
--- a/tests/del_property.c
+++ b/tests/del_property.c
@@ -24,7 +24,6 @@
 #include <ctype.h>
 #include <stdint.h>
 
-#include <fdt.h>
 #include <libfdt.h>
 
 #include "tests.h"
diff --git a/tests/dtb_reverse.c b/tests/dtb_reverse.c
index 25e1eef..527fd71 100644
--- a/tests/dtb_reverse.c
+++ b/tests/dtb_reverse.c
@@ -24,7 +24,6 @@
 #include <stdint.h>
 #include <limits.h>
 
-#include <fdt.h>
 #include <libfdt.h>
 
 #include "tests.h"
diff --git a/tests/dtbs_equal_ordered.c b/tests/dtbs_equal_ordered.c
index 1db25f4..12495de 100644
--- a/tests/dtbs_equal_ordered.c
+++ b/tests/dtbs_equal_ordered.c
@@ -23,7 +23,6 @@
 #include <string.h>
 #include <stdint.h>
 
-#include <fdt.h>
 #include <libfdt.h>
 
 #include "tests.h"
diff --git a/tests/dtbs_equal_unordered.c b/tests/dtbs_equal_unordered.c
index df53318..20b4356 100644
--- a/tests/dtbs_equal_unordered.c
+++ b/tests/dtbs_equal_unordered.c
@@ -24,7 +24,6 @@
 #include <stdint.h>
 #include <limits.h>
 
-#include <fdt.h>
 #include <libfdt.h>
 
 #include "tests.h"
diff --git a/tests/dumptrees.c b/tests/dumptrees.c
index fa1f563..bebf553 100644
--- a/tests/dumptrees.c
+++ b/tests/dumptrees.c
@@ -25,9 +25,7 @@
 #include <fcntl.h>
 #include <stdint.h>
 
-#include <fdt.h>
 #include <libfdt.h>
-#include <libfdt_env.h>
 
 #include "testdata.h"
 
diff --git a/tests/extra-terminating-null.c b/tests/extra-terminating-null.c
index 8a2043f..dc1fe89 100644
--- a/tests/extra-terminating-null.c
+++ b/tests/extra-terminating-null.c
@@ -22,7 +22,6 @@
 #include <string.h>
 #include <stdint.h>
 
-#include <fdt.h>
 #include <libfdt.h>
 
 #include "tests.h"
diff --git a/tests/find_property.c b/tests/find_property.c
index 74a6965..4dc3030 100644
--- a/tests/find_property.c
+++ b/tests/find_property.c
@@ -22,7 +22,6 @@
 #include <string.h>
 #include <stdint.h>
 
-#include <fdt.h>
 #include <libfdt.h>
 
 #include "tests.h"
diff --git a/tests/get_alias.c b/tests/get_alias.c
index 1e0faf4..5060795 100644
--- a/tests/get_alias.c
+++ b/tests/get_alias.c
@@ -23,7 +23,6 @@
 #include <string.h>
 #include <stdint.h>
 
-#include <fdt.h>
 #include <libfdt.h>
 
 #include "tests.h"
diff --git a/tests/get_mem_rsv.c b/tests/get_mem_rsv.c
index 554c788..1812639 100644
--- a/tests/get_mem_rsv.c
+++ b/tests/get_mem_rsv.c
@@ -23,7 +23,6 @@
 #include <string.h>
 #include <stdint.h>
 
-#include <fdt.h>
 #include <libfdt.h>
 
 #include "tests.h"
diff --git a/tests/get_name.c b/tests/get_name.c
index 0262a12..c6ca9f9 100644
--- a/tests/get_name.c
+++ b/tests/get_name.c
@@ -22,7 +22,6 @@
 #include <string.h>
 #include <stdint.h>
 
-#include <fdt.h>
 #include <libfdt.h>
 
 #include "tests.h"
diff --git a/tests/get_path.c b/tests/get_path.c
index 1e05f7c..7352976 100644
--- a/tests/get_path.c
+++ b/tests/get_path.c
@@ -22,7 +22,6 @@
 #include <string.h>
 #include <stdint.h>
 
-#include <fdt.h>
 #include <libfdt.h>
 
 #include "tests.h"
diff --git a/tests/get_phandle.c b/tests/get_phandle.c
index 5735733..2079591 100644
--- a/tests/get_phandle.c
+++ b/tests/get_phandle.c
@@ -22,7 +22,6 @@
 #include <string.h>
 #include <stdint.h>
 
-#include <fdt.h>
 #include <libfdt.h>
 
 #include "tests.h"
diff --git a/tests/getprop.c b/tests/getprop.c
index 239856e..6255bad 100644
--- a/tests/getprop.c
+++ b/tests/getprop.c
@@ -23,7 +23,6 @@
 #include <string.h>
 #include <stdint.h>
 
-#include <fdt.h>
 #include <libfdt.h>
 
 #include "tests.h"
diff --git a/tests/incbin.c b/tests/incbin.c
index 76d8626..4100ba0 100644
--- a/tests/incbin.c
+++ b/tests/incbin.c
@@ -23,7 +23,6 @@
 #include <stdint.h>
 #include <errno.h>
 
-#include <fdt.h>
 #include <libfdt.h>
 
 #include "tests.h"
diff --git a/tests/integer-expressions.c b/tests/integer-expressions.c
index 5ba1566..57e2ff6 100644
--- a/tests/integer-expressions.c
+++ b/tests/integer-expressions.c
@@ -25,7 +25,6 @@
 #include <errno.h>
 
 
-#include <fdt.h>
 #include <libfdt.h>
 
 #include "tests.h"
diff --git a/tests/mangle-layout.c b/tests/mangle-layout.c
index 3b19788..a76e51e 100644
--- a/tests/mangle-layout.c
+++ b/tests/mangle-layout.c
@@ -24,7 +24,6 @@
 #include <limits.h>
 #include <stdint.h>
 
-#include <fdt.h>
 #include <libfdt.h>
 
 #include "tests.h"
diff --git a/tests/move_and_save.c b/tests/move_and_save.c
index 410ccb3..393b60a 100644
--- a/tests/move_and_save.c
+++ b/tests/move_and_save.c
@@ -24,7 +24,6 @@
 #include <limits.h>
 #include <stdint.h>
 
-#include <fdt.h>
 #include <libfdt.h>
 
 #include "tests.h"
diff --git a/tests/node_check_compatible.c b/tests/node_check_compatible.c
index 23abbf5..4bdf091 100644
--- a/tests/node_check_compatible.c
+++ b/tests/node_check_compatible.c
@@ -23,7 +23,6 @@
 #include <string.h>
 #include <stdint.h>
 
-#include <fdt.h>
 #include <libfdt.h>
 
 #include "tests.h"
diff --git a/tests/node_offset_by_compatible.c b/tests/node_offset_by_compatible.c
index 2317930..f62b591 100644
--- a/tests/node_offset_by_compatible.c
+++ b/tests/node_offset_by_compatible.c
@@ -23,7 +23,6 @@
 #include <stdint.h>
 #include <stdarg.h>
 
-#include <fdt.h>
 #include <libfdt.h>
 
 #include "tests.h"
diff --git a/tests/node_offset_by_phandle.c b/tests/node_offset_by_phandle.c
index a8442f1..becff0f 100644
--- a/tests/node_offset_by_phandle.c
+++ b/tests/node_offset_by_phandle.c
@@ -23,7 +23,6 @@
 #include <stdint.h>
 #include <stdarg.h>
 
-#include <fdt.h>
 #include <libfdt.h>
 
 #include "tests.h"
diff --git a/tests/node_offset_by_prop_value.c b/tests/node_offset_by_prop_value.c
index 0f2a345..9212a4e 100644
--- a/tests/node_offset_by_prop_value.c
+++ b/tests/node_offset_by_prop_value.c
@@ -23,7 +23,6 @@
 #include <stdint.h>
 #include <stdarg.h>
 
-#include <fdt.h>
 #include <libfdt.h>
 
 #include "tests.h"
diff --git a/tests/nop_node.c b/tests/nop_node.c
index ea3a18f..c316444 100644
--- a/tests/nop_node.c
+++ b/tests/nop_node.c
@@ -24,7 +24,6 @@
 #include <ctype.h>
 #include <stdint.h>
 
-#include <fdt.h>
 #include <libfdt.h>
 
 #include "tests.h"
diff --git a/tests/nop_property.c b/tests/nop_property.c
index e6ef4d9..644b0a6 100644
--- a/tests/nop_property.c
+++ b/tests/nop_property.c
@@ -24,7 +24,6 @@
 #include <ctype.h>
 #include <stdint.h>
 
-#include <fdt.h>
 #include <libfdt.h>
 
 #include "tests.h"
diff --git a/tests/nopulate.c b/tests/nopulate.c
index 3cbbe21..cd79872 100644
--- a/tests/nopulate.c
+++ b/tests/nopulate.c
@@ -24,7 +24,6 @@
 #include <limits.h>
 #include <stdint.h>
 
-#include <fdt.h>
 #include <libfdt.h>
 
 #include "tests.h"
diff --git a/tests/notfound.c b/tests/notfound.c
index 4d55b88..dc623d6 100644
--- a/tests/notfound.c
+++ b/tests/notfound.c
@@ -22,7 +22,6 @@
 #include <string.h>
 #include <stdint.h>
 
-#include <fdt.h>
 #include <libfdt.h>
 
 #include "tests.h"
diff --git a/tests/open_pack.c b/tests/open_pack.c
index 0a5a3fc..407ef6c 100644
--- a/tests/open_pack.c
+++ b/tests/open_pack.c
@@ -24,7 +24,6 @@
 #include <limits.h>
 #include <stdint.h>
 
-#include <fdt.h>
 #include <libfdt.h>
 
 #include "tests.h"
diff --git a/tests/parent_offset.c b/tests/parent_offset.c
index e7affcc..d4ab3cf 100644
--- a/tests/parent_offset.c
+++ b/tests/parent_offset.c
@@ -22,7 +22,6 @@
 #include <string.h>
 #include <stdint.h>
 
-#include <fdt.h>
 #include <libfdt.h>
 
 #include "tests.h"
diff --git a/tests/path-references.c b/tests/path-references.c
index 9f363b3..0746b3f 100644
--- a/tests/path-references.c
+++ b/tests/path-references.c
@@ -22,7 +22,6 @@
 #include <string.h>
 #include <stdint.h>
 
-#include <fdt.h>
 #include <libfdt.h>
 
 #include "tests.h"
diff --git a/tests/path_offset.c b/tests/path_offset.c
index d3e1f8e..4e5b7a1 100644
--- a/tests/path_offset.c
+++ b/tests/path_offset.c
@@ -22,7 +22,6 @@
 #include <string.h>
 #include <stdint.h>
 
-#include <fdt.h>
 #include <libfdt.h>
 
 #include "tests.h"
diff --git a/tests/path_offset_aliases.c b/tests/path_offset_aliases.c
index 3682da4..78d5a46 100644
--- a/tests/path_offset_aliases.c
+++ b/tests/path_offset_aliases.c
@@ -23,7 +23,6 @@
 #include <string.h>
 #include <stdint.h>
 
-#include <fdt.h>
 #include <libfdt.h>
 
 #include "tests.h"
diff --git a/tests/phandle_format.c b/tests/phandle_format.c
index 7e4d816..5874ae7 100644
--- a/tests/phandle_format.c
+++ b/tests/phandle_format.c
@@ -22,7 +22,6 @@
 #include <string.h>
 #include <stdint.h>
 
-#include <fdt.h>
 #include <libfdt.h>
 
 #include "tests.h"
diff --git a/tests/propname_escapes.c b/tests/propname_escapes.c
index 3aec28f..e91bd99 100644
--- a/tests/propname_escapes.c
+++ b/tests/propname_escapes.c
@@ -24,7 +24,6 @@
 #include <string.h>
 #include <stdint.h>
 
-#include <fdt.h>
 #include <libfdt.h>
 
 #include "tests.h"
diff --git a/tests/references.c b/tests/references.c
index b20f21f..c9d05a2 100644
--- a/tests/references.c
+++ b/tests/references.c
@@ -22,7 +22,6 @@
 #include <string.h>
 #include <stdint.h>
 
-#include <fdt.h>
 #include <libfdt.h>
 
 #include "tests.h"
diff --git a/tests/root_node.c b/tests/root_node.c
index 3f47829..58aebf6 100644
--- a/tests/root_node.c
+++ b/tests/root_node.c
@@ -23,7 +23,6 @@
 #include <string.h>
 #include <stdint.h>
 
-#include <fdt.h>
 #include <libfdt.h>
 
 #include "tests.h"
diff --git a/tests/rw_tree1.c b/tests/rw_tree1.c
index 103a24d..efd4718 100644
--- a/tests/rw_tree1.c
+++ b/tests/rw_tree1.c
@@ -24,7 +24,6 @@
 #include <ctype.h>
 #include <stdint.h>
 
-#include <fdt.h>
 #include <libfdt.h>
 
 #include "tests.h"
diff --git a/tests/set_name.c b/tests/set_name.c
index 5d1149e..9861587 100644
--- a/tests/set_name.c
+++ b/tests/set_name.c
@@ -22,7 +22,6 @@
 #include <string.h>
 #include <stdint.h>
 
-#include <fdt.h>
 #include <libfdt.h>
 
 #include "tests.h"
diff --git a/tests/setprop.c b/tests/setprop.c
index 9f2bc88..d089f8d 100644
--- a/tests/setprop.c
+++ b/tests/setprop.c
@@ -24,7 +24,6 @@
 #include <ctype.h>
 #include <stdint.h>
 
-#include <fdt.h>
 #include <libfdt.h>
 
 #include "tests.h"
diff --git a/tests/setprop_inplace.c b/tests/setprop_inplace.c
index 82d8951..daef182 100644
--- a/tests/setprop_inplace.c
+++ b/tests/setprop_inplace.c
@@ -25,7 +25,6 @@
 #include <ctype.h>
 #include <stdint.h>
 
-#include <fdt.h>
 #include <libfdt.h>
 
 #include "tests.h"
diff --git a/tests/sized_cells.c b/tests/sized_cells.c
index 847ec96..94da03b 100644
--- a/tests/sized_cells.c
+++ b/tests/sized_cells.c
@@ -23,7 +23,6 @@
 #include <string.h>
 #include <stdint.h>
 
-#include <fdt.h>
 #include <libfdt.h>
 
 #include "tests.h"
diff --git a/tests/string_escapes.c b/tests/string_escapes.c
index 30eb6a8..8cdee4b 100644
--- a/tests/string_escapes.c
+++ b/tests/string_escapes.c
@@ -22,7 +22,6 @@
 #include <string.h>
 #include <stdint.h>
 
-#include <fdt.h>
 #include <libfdt.h>
 
 #include "tests.h"
diff --git a/tests/subnode_offset.c b/tests/subnode_offset.c
index e58c192..231fcb5 100644
--- a/tests/subnode_offset.c
+++ b/tests/subnode_offset.c
@@ -22,7 +22,6 @@
 #include <string.h>
 #include <stdint.h>
 
-#include <fdt.h>
 #include <libfdt.h>
 
 #include "tests.h"
diff --git a/tests/supernode_atdepth_offset.c b/tests/supernode_atdepth_offset.c
index 73f41ae..43e120d 100644
--- a/tests/supernode_atdepth_offset.c
+++ b/tests/supernode_atdepth_offset.c
@@ -22,7 +22,6 @@
 #include <string.h>
 #include <stdint.h>
 
-#include <fdt.h>
 #include <libfdt.h>
 
 #include "tests.h"
diff --git a/tests/sw_tree1.c b/tests/sw_tree1.c
index 5c71414..8eb6e5f 100644
--- a/tests/sw_tree1.c
+++ b/tests/sw_tree1.c
@@ -24,7 +24,6 @@
 #include <ctype.h>
 #include <stdint.h>
 
-#include <fdt.h>
 #include <libfdt.h>
 
 #include "tests.h"
diff --git a/tests/truncated_property.c b/tests/truncated_property.c
index 56daa22..f820d99 100644
--- a/tests/truncated_property.c
+++ b/tests/truncated_property.c
@@ -23,7 +23,6 @@
 #include <string.h>
 #include <stdint.h>
 
-#include <fdt.h>
 #include <libfdt.h>
 
 #include "tests.h"
diff --git a/tests/utilfdt_test.c b/tests/utilfdt_test.c
index 36b4aa5..274c3d6 100644
--- a/tests/utilfdt_test.c
+++ b/tests/utilfdt_test.c
@@ -24,7 +24,6 @@
 #include <stdint.h>
 #include <stdarg.h>
 
-#include <fdt.h>
 #include <libfdt.h>
 #include <util.h>
 
diff --git a/tests/value-labels.c b/tests/value-labels.c
index abe2721..dcf2059 100644
--- a/tests/value-labels.c
+++ b/tests/value-labels.c
@@ -26,7 +26,6 @@
 
 #include <dlfcn.h>
 
-#include <fdt.h>
 #include <libfdt.h>
 
 #include "tests.h"

commit 20b866a7ce1651c4ca3f28cf380df66d9ed35719
Author: Kim Phillips <kim.phillips@freescale.com>
Date:   Tue Nov 13 18:34:09 2012 -0600

    dtc/fdtdump: include libfdt_env.h prior to fdt.h
    
    in order to get the upcoming fdt type definitions.
    
    Signed-off-by: Kim Phillips <kim.phillips@freescale.com>
    Acked-by: David Gibson <david@gibson.dropbear.id.au>

diff --git a/fdtdump.c b/fdtdump.c
index d4fa6d7..b2c5b37 100644
--- a/fdtdump.c
+++ b/fdtdump.c
@@ -8,8 +8,8 @@
 #include <string.h>
 #include <ctype.h>
 
-#include <fdt.h>
 #include <libfdt_env.h>
+#include <fdt.h>
 
 #include "util.h"
 

commit feafcd972cb744750a65728440c99526e6199a6d
Author: Kim Phillips <kim.phillips@freescale.com>
Date:   Wed Nov 28 17:33:01 2012 -0600

    dtc/libfdt: introduce fdt types for annotation by endian checkers
    
    Projects such as linux and u-boot run sparse on libfdt.  libfdt
    contains the notion of endianness via usage of endian conversion
    functions such as fdt32_to_cpu.  As such, in order to pass endian
    checks, libfdt has to annotate its fdt variables such that sparse
    can warn when mixing bitwise and regular integers.  This patch adds
    these new fdtXX_t types and, ifdef __CHECKER__ (a symbol sparse
    defines), includes the bitwise annotation.
    
    Signed-off-by: Kim Phillips <kim.phillips@freescale.com>
    Acked-by: David Gibson <david@gibson.dropbear.id.au>

diff --git a/libfdt/fdt.h b/libfdt/fdt.h
index 48ccfd9..45dd134 100644
--- a/libfdt/fdt.h
+++ b/libfdt/fdt.h
@@ -4,45 +4,45 @@
 #ifndef __ASSEMBLY__
 
 struct fdt_header {
-	uint32_t magic;			 /* magic word FDT_MAGIC */
-	uint32_t totalsize;		 /* total size of DT block */
-	uint32_t off_dt_struct;		 /* offset to structure */
-	uint32_t off_dt_strings;	 /* offset to strings */
-	uint32_t off_mem_rsvmap;	 /* offset to memory reserve map */
-	uint32_t version;		 /* format version */
-	uint32_t last_comp_version;	 /* last compatible version */
+	fdt32_t magic;			 /* magic word FDT_MAGIC */
+	fdt32_t totalsize;		 /* total size of DT block */
+	fdt32_t off_dt_struct;		 /* offset to structure */
+	fdt32_t off_dt_strings;		 /* offset to strings */
+	fdt32_t off_mem_rsvmap;		 /* offset to memory reserve map */
+	fdt32_t version;		 /* format version */
+	fdt32_t last_comp_version;	 /* last compatible version */
 
 	/* version 2 fields below */
-	uint32_t boot_cpuid_phys;	 /* Which physical CPU id we're
+	fdt32_t boot_cpuid_phys;	 /* Which physical CPU id we're
 					    booting on */
 	/* version 3 fields below */
-	uint32_t size_dt_strings;	 /* size of the strings block */
+	fdt32_t size_dt_strings;	 /* size of the strings block */
 
 	/* version 17 fields below */
-	uint32_t size_dt_struct;	 /* size of the structure block */
+	fdt32_t size_dt_struct;		 /* size of the structure block */
 };
 
 struct fdt_reserve_entry {
-	uint64_t address;
-	uint64_t size;
+	fdt64_t address;
+	fdt64_t size;
 };
 
 struct fdt_node_header {
-	uint32_t tag;
+	fdt32_t tag;
 	char name[0];
 };
 
 struct fdt_property {
-	uint32_t tag;
-	uint32_t len;
-	uint32_t nameoff;
+	fdt32_t tag;
+	fdt32_t len;
+	fdt32_t nameoff;
 	char data[0];
 };
 
 #endif /* !__ASSEMBLY */
 
 #define FDT_MAGIC	0xd00dfeed	/* 4: version, 4: total size */
-#define FDT_TAGSIZE	sizeof(uint32_t)
+#define FDT_TAGSIZE	sizeof(fdt32_t)
 
 #define FDT_BEGIN_NODE	0x1		/* Start node: full name */
 #define FDT_END_NODE	0x2		/* End node */
@@ -51,10 +51,10 @@ struct fdt_property {
 #define FDT_NOP		0x4		/* nop */
 #define FDT_END		0x9
 
-#define FDT_V1_SIZE	(7*sizeof(uint32_t))
-#define FDT_V2_SIZE	(FDT_V1_SIZE + sizeof(uint32_t))
-#define FDT_V3_SIZE	(FDT_V2_SIZE + sizeof(uint32_t))
+#define FDT_V1_SIZE	(7*sizeof(fdt32_t))
+#define FDT_V2_SIZE	(FDT_V1_SIZE + sizeof(fdt32_t))
+#define FDT_V3_SIZE	(FDT_V2_SIZE + sizeof(fdt32_t))
 #define FDT_V16_SIZE	FDT_V3_SIZE
-#define FDT_V17_SIZE	(FDT_V16_SIZE + sizeof(uint32_t))
+#define FDT_V17_SIZE	(FDT_V16_SIZE + sizeof(fdt32_t))
 
 #endif /* _FDT_H */
diff --git a/libfdt/libfdt_env.h b/libfdt/libfdt_env.h
index 213d7fb..956b4ae 100644
--- a/libfdt/libfdt_env.h
+++ b/libfdt/libfdt_env.h
@@ -5,25 +5,56 @@
 #include <stdint.h>
 #include <string.h>
 
-#define EXTRACT_BYTE(n)	((unsigned long long)((uint8_t *)&x)[n])
-static inline uint16_t fdt16_to_cpu(uint16_t x)
+#ifdef __CHECKER__
+#define __force __attribute__((force))
+#define __bitwise __attribute__((bitwise))
+#else
+#define __force
+#define __bitwise
+#endif
+
+typedef uint16_t __bitwise fdt16_t;
+typedef uint32_t __bitwise fdt32_t;
+typedef uint64_t __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))
+#define CPU_TO_FDT32(x) ((EXTRACT_BYTE(x, 0) << 24) | (EXTRACT_BYTE(x, 1) << 16) | \
+			 (EXTRACT_BYTE(x, 2) << 8) | EXTRACT_BYTE(x, 3))
+#define CPU_TO_FDT64(x) ((EXTRACT_BYTE(x, 0) << 56) | (EXTRACT_BYTE(x, 1) << 48) | \
+			 (EXTRACT_BYTE(x, 2) << 40) | (EXTRACT_BYTE(x, 3) << 32) | \
+			 (EXTRACT_BYTE(x, 4) << 24) | (EXTRACT_BYTE(x, 5) << 16) | \
+			 (EXTRACT_BYTE(x, 6) << 8) | EXTRACT_BYTE(x, 7))
+
+static inline uint16_t fdt16_to_cpu(fdt16_t x)
+{
+	return (__force uint16_t)CPU_TO_FDT16(x);
+}
+static inline fdt16_t cpu_to_fdt16(uint16_t x)
 {
-	return (EXTRACT_BYTE(0) << 8) | EXTRACT_BYTE(1);
+	return (__force fdt16_t)CPU_TO_FDT16(x);
 }
-#define cpu_to_fdt16(x) fdt16_to_cpu(x)
 
-static inline uint32_t fdt32_to_cpu(uint32_t x)
+static inline uint32_t fdt32_to_cpu(fdt32_t x)
 {
-	return (EXTRACT_BYTE(0) << 24) | (EXTRACT_BYTE(1) << 16) | (EXTRACT_BYTE(2) << 8) | EXTRACT_BYTE(3);
+	return (__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);
 }
-#define cpu_to_fdt32(x) fdt32_to_cpu(x)
 
-static inline uint64_t fdt64_to_cpu(uint64_t x)
+static inline uint64_t fdt64_to_cpu(fdt64_t x)
+{
+	return (__force uint64_t)CPU_TO_FDT64(x);
+}
+static inline fdt64_t cpu_to_fdt64(uint64_t x)
 {
-	return (EXTRACT_BYTE(0) << 56) | (EXTRACT_BYTE(1) << 48) | (EXTRACT_BYTE(2) << 40) | (EXTRACT_BYTE(3) << 32)
-		| (EXTRACT_BYTE(4) << 24) | (EXTRACT_BYTE(5) << 16) | (EXTRACT_BYTE(6) << 8) | EXTRACT_BYTE(7);
+	return (__force fdt64_t)CPU_TO_FDT64(x);
 }
-#define cpu_to_fdt64(x) fdt64_to_cpu(x)
+#undef CPU_TO_FDT64
+#undef CPU_TO_FDT32
+#undef CPU_TO_FDT16
 #undef EXTRACT_BYTE
 
 #endif /* _LIBFDT_ENV_H */

commit 142419e43c99e88cbe72a760a72cdbf520690eb6
Author: Kim Phillips <kim.phillips@freescale.com>
Date:   Tue Nov 13 18:34:30 2012 -0600

    dtc/libfdt: sparse fixes
    
    libfdt/fdt.c:104:28: warning: incorrect type in argument 1 (different base types)
    libfdt/fdt.c:104:28:    expected restricted fdt32_t [usertype] x
    libfdt/fdt.c:104:28:    got unsigned int const [unsigned] [usertype] <noident>
    libfdt/fdt.c:124:40: warning: incorrect type in argument 1 (different base types)
    libfdt/fdt.c:124:40:    expected restricted fdt32_t [usertype] x
    libfdt/fdt.c:124:40:    got unsigned int const [unsigned] [usertype] <noident>
    libfdt/fdt_ro.c:337:29: warning: incorrect type in argument 1 (different base types)
    libfdt/fdt_ro.c:337:29:    expected restricted fdt32_t [usertype] x
    libfdt/fdt_ro.c:337:29:    got unsigned int const [unsigned] [usertype] <noident>
    libfdt/fdt_rw.c:370:17: warning: incorrect type in assignment (different base types)
    libfdt/fdt_rw.c:370:17:    expected unsigned int [unsigned] [usertype] <noident>
    libfdt/fdt_rw.c:370:17:    got restricted fdt32_t
    libfdt/fdt_sw.c:164:13: warning: incorrect type in assignment (different base types)
    libfdt/fdt_sw.c:164:13:    expected unsigned int [unsigned] [usertype] <noident>
    libfdt/fdt_sw.c:164:13:    got restricted fdt32_t
    libfdt/fdt_sw.c:227:14: warning: incorrect type in assignment (different base types)
    libfdt/fdt_sw.c:227:14:    expected unsigned int [unsigned] [usertype] <noident>
    libfdt/fdt_sw.c:227:14:    got restricted fdt32_t
    libfdt/fdt_wip.c:80:20: warning: incorrect type in assignment (different base types)
    libfdt/fdt_wip.c:80:20:    expected unsigned int [unsigned] [usertype] <noident>
    libfdt/fdt_wip.c:80:20:    got restricted fdt32_t
    libfdt/libfdt.h:1001:13: warning: incorrect type in assignment (different base types)
    libfdt/libfdt.h:1001:13:    expected unsigned long [unsigned] [usertype] val
    libfdt/libfdt.h:1001:13:    got restricted fdt64_t
    libfdt/libfdt.h:1157:13: warning: incorrect type in assignment (different base types)
    libfdt/libfdt.h:1157:13:    expected unsigned int [unsigned] [usertype] val
    libfdt/libfdt.h:1157:13:    got restricted fdt32_t
    libfdt/libfdt.h:1192:13: warning: incorrect type in assignment (different base types)
    libfdt/libfdt.h:1192:13:    expected unsigned long [unsigned] [usertype] val
    libfdt/libfdt.h:1192:13:    got restricted fdt64_t
    libfdt/libfdt.h:1299:13: warning: incorrect type in assignment (different base types)
    libfdt/libfdt.h:1299:13:    expected unsigned int [unsigned] [usertype] val
    libfdt/libfdt.h:1299:13:    got restricted fdt32_t
    libfdt/libfdt.h:1334:13: warning: incorrect type in assignment (different base types)
    libfdt/libfdt.h:1334:13:    expected unsigned long [unsigned] [usertype] val
    libfdt/libfdt.h:1334:13:    got restricted fdt64_t
    libfdt/libfdt.h:885:13: warning: incorrect type in assignment (different base types)
    libfdt/libfdt.h:885:13:    expected unsigned int [unsigned] [usertype] val
    libfdt/libfdt.h:885:13:    got restricted fdt32_t
    libfdt/libfdt.h:920:13: warning: incorrect type in assignment (different base types)
    libfdt/libfdt.h:920:13:    expected unsigned long [unsigned] [usertype] val
    libfdt/libfdt.h:920:13:    got restricted fdt64_t
    libfdt/libfdt.h:996:13: warning: incorrect type in assignment (different base types)
    libfdt/libfdt.h:996:13:    expected unsigned int [unsigned] [usertype] val
    libfdt/libfdt.h:996:13:    got restricted fdt32_t
    
    Signed-off-by: Kim Phillips <kim.phillips@freescale.com>

diff --git a/libfdt/fdt.c b/libfdt/fdt.c
index e56833a..57faba3 100644
--- a/libfdt/fdt.c
+++ b/libfdt/fdt.c
@@ -92,7 +92,7 @@ const void *fdt_offset_ptr(const void *fdt, int offset, unsigned int len)
 
 uint32_t fdt_next_tag(const void *fdt, int startoffset, int *nextoffset)
 {
-	const uint32_t *tagp, *lenp;
+	const fdt32_t *tagp, *lenp;
 	uint32_t tag;
 	int offset = startoffset;
 	const char *p;
diff --git a/libfdt/fdt_ro.c b/libfdt/fdt_ro.c
index 02b6d68..42da2bd 100644
--- a/libfdt/fdt_ro.c
+++ b/libfdt/fdt_ro.c
@@ -322,7 +322,7 @@ const void *fdt_getprop(const void *fdt, int nodeoffset,
 
 uint32_t fdt_get_phandle(const void *fdt, int nodeoffset)
 {
-	const uint32_t *php;
+	const fdt32_t *php;
 	int len;
 
 	/* FIXME: This is a bit sub-optimal, since we potentially scan
diff --git a/libfdt/fdt_rw.c b/libfdt/fdt_rw.c
index 24437df..fdba618 100644
--- a/libfdt/fdt_rw.c
+++ b/libfdt/fdt_rw.c
@@ -339,7 +339,7 @@ int fdt_add_subnode_namelen(void *fdt, int parentoffset,
 	int nodelen;
 	int err;
 	uint32_t tag;
-	uint32_t *endtag;
+	fdt32_t *endtag;
 
 	FDT_RW_CHECK_HEADER(fdt);
 
@@ -366,7 +366,7 @@ int fdt_add_subnode_namelen(void *fdt, int parentoffset,
 	nh->tag = cpu_to_fdt32(FDT_BEGIN_NODE);
 	memset(nh->name, 0, FDT_TAGALIGN(namelen+1));
 	memcpy(nh->name, name, namelen);
-	endtag = (uint32_t *)((char *)nh + nodelen - FDT_TAGSIZE);
+	endtag = (fdt32_t *)((char *)nh + nodelen - FDT_TAGSIZE);
 	*endtag = cpu_to_fdt32(FDT_END_NODE);
 
 	return offset;
diff --git a/libfdt/fdt_sw.c b/libfdt/fdt_sw.c
index 55ebebf..f422754 100644
--- a/libfdt/fdt_sw.c
+++ b/libfdt/fdt_sw.c
@@ -153,7 +153,7 @@ int fdt_begin_node(void *fdt, const char *name)
 
 int fdt_end_node(void *fdt)
 {
-	uint32_t *en;
+	fdt32_t *en;
 
 	FDT_SW_CHECK_HEADER(fdt);
 
@@ -213,7 +213,7 @@ int fdt_property(void *fdt, const char *name, const void *val, int len)
 int fdt_finish(void *fdt)
 {
 	char *p = (char *)fdt;
-	uint32_t *end;
+	fdt32_t *end;
 	int oldstroffset, newstroffset;
 	uint32_t tag;
 	int offset, nextoffset;
diff --git a/libfdt/fdt_wip.c b/libfdt/fdt_wip.c
index 6025fa1..c5bbb68 100644
--- a/libfdt/fdt_wip.c
+++ b/libfdt/fdt_wip.c
@@ -74,7 +74,7 @@ int fdt_setprop_inplace(void *fdt, int nodeoffset, const char *name,
 
 static void _fdt_nop_region(void *start, int len)
 {
-	uint32_t *p;
+	fdt32_t *p;
 
 	for (p = start; (char *)p < ((char *)start + len); p++)
 		*p = cpu_to_fdt32(FDT_NOP);
diff --git a/libfdt/libfdt.h b/libfdt/libfdt.h
index 73f4975..8e57a06 100644
--- a/libfdt/libfdt.h
+++ b/libfdt/libfdt.h
@@ -882,8 +882,8 @@ int fdt_setprop_inplace(void *fdt, int nodeoffset, const char *name,
 static inline int fdt_setprop_inplace_u32(void *fdt, int nodeoffset,
 					  const char *name, uint32_t val)
 {
-	val = cpu_to_fdt32(val);
-	return fdt_setprop_inplace(fdt, nodeoffset, name, &val, sizeof(val));
+	fdt32_t tmp = cpu_to_fdt32(val);
+	return fdt_setprop_inplace(fdt, nodeoffset, name, &tmp, sizeof(tmp));
 }
 
 /**
@@ -917,8 +917,8 @@ static inline int fdt_setprop_inplace_u32(void *fdt, int nodeoffset,
 static inline int fdt_setprop_inplace_u64(void *fdt, int nodeoffset,
 					  const char *name, uint64_t val)
 {
-	val = cpu_to_fdt64(val);
-	return fdt_setprop_inplace(fdt, nodeoffset, name, &val, sizeof(val));
+	fdt64_t tmp = cpu_to_fdt64(val);
+	return fdt_setprop_inplace(fdt, nodeoffset, name, &tmp, sizeof(tmp));
 }
 
 /**
@@ -993,13 +993,13 @@ int fdt_begin_node(void *fdt, const char *name);
 int fdt_property(void *fdt, const char *name, const void *val, int len);
 static inline int fdt_property_u32(void *fdt, const char *name, uint32_t val)
 {
-	val = cpu_to_fdt32(val);
-	return fdt_property(fdt, name, &val, sizeof(val));
+	fdt32_t tmp = cpu_to_fdt32(val);
+	return fdt_property(fdt, name, &tmp, sizeof(tmp));
 }
 static inline int fdt_property_u64(void *fdt, const char *name, uint64_t val)
 {
-	val = cpu_to_fdt64(val);
-	return fdt_property(fdt, name, &val, sizeof(val));
+	fdt64_t tmp = cpu_to_fdt64(val);
+	return fdt_property(fdt, name, &tmp, sizeof(tmp));
 }
 static inline int fdt_property_cell(void *fdt, const char *name, uint32_t val)
 {
@@ -1154,8 +1154,8 @@ int fdt_setprop(void *fdt, int nodeoffset, const char *name,
 static inline int fdt_setprop_u32(void *fdt, int nodeoffset, const char *name,
 				  uint32_t val)
 {
-	val = cpu_to_fdt32(val);
-	return fdt_setprop(fdt, nodeoffset, name, &val, sizeof(val));
+	fdt32_t tmp = cpu_to_fdt32(val);
+	return fdt_setprop(fdt, nodeoffset, name, &tmp, sizeof(tmp));
 }
 
 /**
@@ -1189,8 +1189,8 @@ static inline int fdt_setprop_u32(void *fdt, int nodeoffset, const char *name,
 static inline int fdt_setprop_u64(void *fdt, int nodeoffset, const char *name,
 				  uint64_t val)
 {
-	val = cpu_to_fdt64(val);
-	return fdt_setprop(fdt, nodeoffset, name, &val, sizeof(val));
+	fdt64_t tmp = cpu_to_fdt64(val);
+	return fdt_setprop(fdt, nodeoffset, name, &tmp, sizeof(tmp));
 }
 
 /**
@@ -1296,8 +1296,8 @@ int fdt_appendprop(void *fdt, int nodeoffset, const char *name,
 static inline int fdt_appendprop_u32(void *fdt, int nodeoffset,
 				     const char *name, uint32_t val)
 {
-	val = cpu_to_fdt32(val);
-	return fdt_appendprop(fdt, nodeoffset, name, &val, sizeof(val));
+	fdt32_t tmp = cpu_to_fdt32(val);
+	return fdt_appendprop(fdt, nodeoffset, name, &tmp, sizeof(tmp));
 }
 
 /**
@@ -1331,8 +1331,8 @@ static inline int fdt_appendprop_u32(void *fdt, int nodeoffset,
 static inline int fdt_appendprop_u64(void *fdt, int nodeoffset,
 				     const char *name, uint64_t val)
 {
-	val = cpu_to_fdt64(val);
-	return fdt_appendprop(fdt, nodeoffset, name, &val, sizeof(val));
+	fdt64_t tmp = cpu_to_fdt64(val);
+	return fdt_appendprop(fdt, nodeoffset, name, &tmp, sizeof(tmp));
 }
 
 /**

commit 19cd5ead0b692c8c10e286252a7f4a725133d8f4
Author: KRONSTORFER Horst <Horst.KRONSTORFER@frequentis.com>
Date:   Tue Dec 11 21:12:14 2012 +0000

    dtc: Drop the '-S is deprecated' warning
    
    The 'deprecated' warning is in there for more than 4 years now
    and nobody seemed to be confused enough to vote it out.  Let's
    drop the warning then.
    
    This reverts commit 315c5d095ebdf29f1912186e76ab9f95e694b18a.
    
    Signed-off-by: Horst Kronstorfer <hkronsto@frequentis.com>

diff --git a/dtc.c b/dtc.c
index a375683..d40e220 100644
--- a/dtc.c
+++ b/dtc.c
@@ -201,9 +201,6 @@ int main(int argc, char *argv[])
 	if (minsize && padsize)
 		die("Can't set both -p and -S\n");
 
-	if (minsize)
-		fprintf(stderr, "DTC: Use of \"-S\" is deprecated; it will be removed soon, use \"-p\" instead\n");
-
 	if (depname) {
 		depfile = fopen(depname, "w");
 		if (!depfile)

commit 1760e7ca03894689118646e229ca9487158cd0e8
Author: Stephen Warren <swarren@nvidia.com>
Date:   Tue Dec 11 10:05:51 2012 -0700

    fdtget-runtest.sh: use printf instead of /bin/echo -e
    
    Not all /bin/echo implementations support the -e option. Instead, use
    printf, which appears to be more widely available than /bin/echo -e.
    
    See commit eaec1db "fdtget-runtest.sh: Fix failures when /bin/sh isn't
    bash" for history.
    
    I have tested this on Ubuntu 10.04 with /bin/sh pointing to both dash
    and bash.
    
    Reported-by: Mike Frysinger <vapier@gentoo.org> # and implemented-by
    Signed-off-by: Stephen Warren <swarren@nvidia.com>
    Acked-by: David Gibson <david@gibson.dropbear.id.au>

diff --git a/tests/fdtget-runtest.sh b/tests/fdtget-runtest.sh
index c3a3559..8d8b058 100755
--- a/tests/fdtget-runtest.sh
+++ b/tests/fdtget-runtest.sh
@@ -8,7 +8,7 @@ rm -f $LOG $EXPECT
 trap "rm -f $LOG $EXPECT" 0
 
 expect="$1"
-/bin/echo -e $expect >$EXPECT
+printf '%b\n' "$expect" > $EXPECT
 shift
 
 verbose_run_log_check "$LOG" $VALGRIND $DTGET "$@"

commit 8055d77a5be3a4204b3aa5cd73ce5cc03362e193
Author: Simon Glass <sjg@chromium.org>
Date:   Sun Jan 27 11:13:11 2013 -0800

    Adjust util_is_printable_string() comment and fix test
    
    This commit which changed the behaviour of this function broke one
    of the tests. Also the comment should be updated to reflect its new
    behaviour.
    
    Signed-off-by: Simon Glass <sjg@chromium.org>
    Acked-by: David Gibson <david@gibson.dropbear.id.au>

diff --git a/tests/run_tests.sh b/tests/run_tests.sh
index dd7f217..b56b626 100755
--- a/tests/run_tests.sh
+++ b/tests/run_tests.sh
@@ -498,9 +498,10 @@ fdtget_tests () {
 
     # run_fdtget_test <expected-result> [<flags>] <file> <node> <property>
     run_fdtget_test "MyBoardName" $dtb / model
+    run_fdtget_test "MyBoardName MyBoardFamilyName" $dtb / compatible
     run_fdtget_test "77 121 66 111 \
 97 114 100 78 97 109 101 0 77 121 66 111 97 114 100 70 97 109 105 \
-108 121 78 97 109 101 0" $dtb / compatible
+108 121 78 97 109 101 0" -t bu $dtb / compatible
     run_fdtget_test "MyBoardName MyBoardFamilyName" -t s $dtb / compatible
     run_fdtget_test 32768 $dtb /cpus/PowerPC,970@1 d-cache-size
     run_fdtget_test 8000 -tx $dtb /cpus/PowerPC,970@1 d-cache-size
diff --git a/util.h b/util.h
index c8eb45d..e9043be 100644
--- a/util.h
+++ b/util.h
@@ -57,12 +57,14 @@ extern char *xstrdup(const char *s);
 extern char *join_path(const char *path, const char *name);
 
 /**
- * Check a string of a given length to see if it is all printable and
- * has a valid terminator.
+ * Check a property of a given length to see if it is all printable and
+ * has a valid terminator. The property can contain either a single string,
+ * or multiple strings each of non-zero length.
  *
  * @param data	The string to check
  * @param len	The string length including terminator
- * @return 1 if a valid printable string, 0 if not */
+ * @return 1 if a valid printable string, 0 if not
+ */
 int util_is_printable_string(const void *data, int len);
 
 /*

commit d20391d6ff45c8fa7281e945491817c35f42b51b
Author: Simon Glass <sjg@chromium.org>
Date:   Mon Jan 21 12:59:16 2013 -0800

    Move property-printing into util
    
    The function that prints a property can be useful to other programs,
    so move it into util.
    
    Signed-off-by: Simon Glass <sjg@chromium.org>
    Acked-by: David Gibson <david@gibson.dropbear.id.au>

diff --git a/fdtdump.c b/fdtdump.c
index b2c5b37..03ea429 100644
--- a/fdtdump.c
+++ b/fdtdump.c
@@ -17,41 +17,6 @@
 #define PALIGN(p, a)	((void *)(ALIGN((unsigned long)(p), (a))))
 #define GET_CELL(p)	(p += 4, *((const uint32_t *)(p-4)))
 
-static void print_data(const char *data, int len)
-{
-	int i;
-	const char *p = data;
-	const char *s;
-
-	/* no data, don't print */
-	if (len == 0)
-		return;
-
-	if (util_is_printable_string(data, len)) {
-		printf(" = ");
-
-		s = data;
-		do {
-			printf("\"%s\"", s);
-			s += strlen(s) + 1;
-			if (s < data + len)
-				printf(", ");
-		} while (s < data + len);
-
-	} 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("]");
-	}
-}
-
 static void dump_blob(void *blob)
 {
 	struct fdt_header *bph = blob;
@@ -147,7 +112,7 @@ static void dump_blob(void *blob)
 		p = PALIGN(p + sz, 4);
 
 		printf("%*s%s", depth * shift, "", s);
-		print_data(t, sz);
+		utilfdt_print_data(t, sz);
 		printf(";\n");
 	}
 }
diff --git a/util.c b/util.c
index 45f186b..b081fa8 100644
--- a/util.c
+++ b/util.c
@@ -335,3 +335,40 @@ int utilfdt_decode_type(const char *fmt, int *type, int *size)
 		return -1;
 	return 0;
 }
+
+void utilfdt_print_data(const char *data, int len)
+{
+	int i;
+	const char *p = data;
+	const char *s;
+
+	/* no data, don't print */
+	if (len == 0)
+		return;
+
+	if (util_is_printable_string(data, len)) {
+		printf(" = ");
+
+		s = data;
+		do {
+			printf("\"%s\"", s);
+			s += strlen(s) + 1;
+			if (s < data + len)
+				printf(", ");
+		} while (s < data + len);
+
+	} else if ((len % 4) == 0) {
+		const uint32_t *cell = (const uint32_t *)data;
+
+		printf(" = <");
+		for (i = 0; i < len; i += 4)
+			printf("0x%08x%s", fdt32_to_cpu(cell[i]),
+			       i < (len - 4) ? " " : "");
+		printf(">");
+	} else {
+		printf(" = [");
+		for (i = 0; i < len; i++)
+			printf("%02x%s", *p++, i < len - 1 ? " " : "");
+		printf("]");
+	}
+}
diff --git a/util.h b/util.h
index e9043be..543a173 100644
--- a/util.h
+++ b/util.h
@@ -152,4 +152,18 @@ int utilfdt_decode_type(const char *fmt, int *type, int *size);
 	"\tOptional modifier prefix:\n" \
 	"\t\thh or b=byte, h=2 byte, l=4 byte (default)\n";
 
+/**
+ * Print property data in a readable format to stdout
+ *
+ * Properties that look like strings will be printed as strings. Otherwise
+ * the data will be displayed either as cells (if len is a multiple of 4
+ * bytes) or bytes.
+ *
+ * If len is 0 then this function does nothing.
+ *
+ * @param data	Pointers to property data
+ * @param len	Length of property data
+ */
+void utilfdt_print_data(const char *data, int len);
+
 #endif /* _UTIL_H */

commit d59b8078bd79a3ed0cd4bdb9bb92de4475bc1a84
Author: Simon Glass <sjg@chromium.org>
Date:   Mon Jan 21 12:59:17 2013 -0800

    .gitignore: Add rule for *.patch
    
    Ignore any patch files that we find, since these are likely to be
    used when sending patches upstream.
    
    Signed-off-by: Simon Glass <sjg@chromium.org>
    Acked-by: David Gibson <david@gibson.dropbear.id.au>

diff --git a/.gitignore b/.gitignore
index 7cabc49..545b899 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,6 +1,7 @@
 *.o
 *.d
 *.a
+*.patch
 *.so
 *~
 *.tab.[ch]

commit b7aa300eee001872134345416e73e0f81159798f
Author: Simon Glass <sjg@chromium.org>
Date:   Mon Jan 21 12:59:18 2013 -0800

    Export fdt_stringlist_contains()
    
    This function is useful outside libfdt, so export it.
    
    Signed-off-by: Simon Glass <sjg@chromium.org>
    Acked-by: David Gibson <david@gibson.dropbear.id.au>

diff --git a/libfdt/fdt_ro.c b/libfdt/fdt_ro.c
index 42da2bd..50007f6 100644
--- a/libfdt/fdt_ro.c
+++ b/libfdt/fdt_ro.c
@@ -515,8 +515,7 @@ int fdt_node_offset_by_phandle(const void *fdt, uint32_t phandle)
 	return offset; /* error from fdt_next_node() */
 }
 
-static int _fdt_stringlist_contains(const char *strlist, int listlen,
-				    const char *str)
+int fdt_stringlist_contains(const char *strlist, int listlen, const char *str)
 {
 	int len = strlen(str);
 	const char *p;
@@ -542,7 +541,7 @@ 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))
+	if (fdt_stringlist_contains(prop, len, compatible))
 		return 0;
 	else
 		return 1;
diff --git a/libfdt/libfdt.h b/libfdt/libfdt.h
index 8e57a06..c0075e7 100644
--- a/libfdt/libfdt.h
+++ b/libfdt/libfdt.h
@@ -816,6 +816,20 @@ int fdt_node_check_compatible(const void *fdt, int nodeoffset,
 int fdt_node_offset_by_compatible(const void *fdt, int startoffset,
 				  const char *compatible);
 
+/**
+ * fdt_stringlist_contains - check a string list property for a string
+ * @strlist: Property containing a list of strings to check
+ * @listlen: Length of property
+ * @str: String to search for
+ *
+ * This is a utility function provided for convenience. The list contains
+ * one or more strings, each terminated by \0, as is found in a device tree
+ * "compatible" property.
+ *
+ * @return: 1 if the string is found in the list, 0 not found, or invalid list
+ */
+int fdt_stringlist_contains(const char *strlist, int listlen, const char *str);
+
 /**********************************************************************/
 /* Write-in-place functions                                           */
 /**********************************************************************/

commit cc11e522a3f50ad3ad289d1313cd0bf0ba491e24
Author: François Revol <revol@free.fr>
Date:   Sun Feb 3 00:52:21 2013 +0100

    Fix typo
    
    Signed-off-by: François Revol <revol@free.fr>

diff --git a/libfdt/libfdt.h b/libfdt/libfdt.h
index c0075e7..130789a 100644
--- a/libfdt/libfdt.h
+++ b/libfdt/libfdt.h
@@ -582,7 +582,7 @@ const char *fdt_get_alias_namelen(const void *fdt,
  * value of the property named 'name' in the node /aliases.
  *
  * returns:
- *	a pointer to the expansion of the alias named 'name', of it exists
+ *	a pointer to the expansion of the alias named 'name', if it exists
  *	NULL, if the given alias or the /aliases node does not exist
  */
 const char *fdt_get_alias(const void *fdt, const char *name);

commit 27cdc1b16f86f970c3c049795d4e71ad531cca3d
Author: Justin Sobota <jsobota@ti.com>
Date:   Fri Feb 15 11:06:10 2013 -0500

    Added license header to dtc/libfdt/fdt.h and libfdt_env.h
    
    This commit adds a license header to fdt.h and libfdt_env.h
    because the license was omitted.
    
    Signed-off-by: Justin Sobota <jsobota@ti.com>
    Acked-by: David Gibson <david@gibson.dropbear.id.au>

diff --git a/libfdt/fdt.h b/libfdt/fdt.h
index 45dd134..526aedb 100644
--- a/libfdt/fdt.h
+++ b/libfdt/fdt.h
@@ -1,5 +1,56 @@
 #ifndef _FDT_H
 #define _FDT_H
+/*
+ * libfdt - Flat Device Tree manipulation
+ * Copyright (C) 2006 David Gibson, IBM Corporation.
+ * Copyright 2012 Kim Phillips, Freescale Semiconductor.
+ *
+ * libfdt is dual licensed: you can use it either under the terms of
+ * the GPL, or the BSD license, at your option.
+ *
+ *  a) This library is free software; you can redistribute it and/or
+ *     modify it under the terms of the GNU General Public License as
+ *     published by the Free Software Foundation; either version 2 of the
+ *     License, or (at your option) any later version.
+ *
+ *     This library is distributed in the hope that it will be useful,
+ *     but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *     GNU General Public License for more details.
+ *
+ *     You should have received a copy of the GNU General Public
+ *     License along with this library; if not, write to the Free
+ *     Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
+ *     MA 02110-1301 USA
+ *
+ * Alternatively,
+ *
+ *  b) Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *     1. Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *     2. Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ *     THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+ *     CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ *     INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ *     MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ *     DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ *     CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *     SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ *     NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ *     LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ *     HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ *     CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ *     OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+ *     EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
 
 #ifndef __ASSEMBLY__
 
diff --git a/libfdt/libfdt_env.h b/libfdt/libfdt_env.h
index 956b4ae..9dea97d 100644
--- a/libfdt/libfdt_env.h
+++ b/libfdt/libfdt_env.h
@@ -1,5 +1,56 @@
 #ifndef _LIBFDT_ENV_H
 #define _LIBFDT_ENV_H
+/*
+ * libfdt - Flat Device Tree manipulation
+ * Copyright (C) 2006 David Gibson, IBM Corporation.
+ * Copyright 2012 Kim Phillips, Freescale Semiconductor.
+ *
+ * libfdt is dual licensed: you can use it either under the terms of
+ * the GPL, or the BSD license, at your option.
+ *
+ *  a) This library is free software; you can redistribute it and/or
+ *     modify it under the terms of the GNU General Public License as
+ *     published by the Free Software Foundation; either version 2 of the
+ *     License, or (at your option) any later version.
+ *
+ *     This library is distributed in the hope that it will be useful,
+ *     but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *     GNU General Public License for more details.
+ *
+ *     You should have received a copy of the GNU General Public
+ *     License along with this library; if not, write to the Free
+ *     Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
+ *     MA 02110-1301 USA
+ *
+ * Alternatively,
+ *
+ *  b) Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *     1. Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *     2. Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ *     THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+ *     CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ *     INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ *     MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ *     DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ *     CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *     SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ *     NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ *     LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ *     HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ *     CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ *     OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+ *     EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
 
 #include <stddef.h>
 #include <stdint.h>

commit f8cb5dd94903a5cfa1609695328b8f1d5557367f
Author: Mike Frysinger <vapier@gentoo.org>
Date:   Wed Apr 10 14:29:06 2013 -0400

    utilfdt_read_err: use xmalloc funcs
    
    We've got these handy helpers, so let's use them.
    
    Acked-by: David Gibson <David@gibson.dropbear.id.au>
    Signed-off-by: Mike Frysinger <vapier@gentoo.org>

diff --git a/util.c b/util.c
index b081fa8..12f0614 100644
--- a/util.c
+++ b/util.c
@@ -212,12 +212,12 @@ int utilfdt_read_err(const char *filename, char **buffp)
 	}
 
 	/* Loop until we have read everything */
-	buf = malloc(bufsize);
+	buf = xmalloc(bufsize);
 	do {
 		/* Expand the buffer to hold the next chunk */
 		if (offset == bufsize) {
 			bufsize *= 2;
-			buf = realloc(buf, bufsize);
+			buf = xrealloc(buf, bufsize);
 			if (!buf) {
 				ret = ENOMEM;
 				break;

commit cc2c178727cdeca4eb9756637c2e09e50e0856e7
Author: Mike Frysinger <vapier@gentoo.org>
Date:   Wed Apr 10 14:29:07 2013 -0400

    utilfdt_read: pass back up the length of data read
    
    For a follow up commit, we want to be able to scan the buffer that was
    returned to us.  In order to do that safely, we need to know how big
    the buffer actually is, so pass that back if requested.
    
    Signed-off-by: Mike Frysinger <vapier@gentoo.org>

diff --git a/fdtget.c b/fdtget.c
index c2fbab2..374bee2 100644
--- a/fdtget.c
+++ b/fdtget.c
@@ -254,7 +254,7 @@ static int do_fdtget(struct display_info *disp, const char *filename,
 	const char *prop;
 	int i, node;
 
-	blob = utilfdt_read(filename);
+	blob = utilfdt_read(filename, NULL);
 	if (!blob)
 		return -1;
 
diff --git a/fdtput.c b/fdtput.c
index f2197f5..572d6da 100644
--- a/fdtput.c
+++ b/fdtput.c
@@ -239,7 +239,7 @@ static int do_fdtput(struct display_info *disp, const char *filename,
 	char *blob;
 	int len, ret = 0;
 
-	blob = utilfdt_read(filename);
+	blob = utilfdt_read(filename, NULL);
 	if (!blob)
 		return -1;
 
diff --git a/tests/testutils.c b/tests/testutils.c
index f185133..67b39b0 100644
--- a/tests/testutils.c
+++ b/tests/testutils.c
@@ -160,7 +160,7 @@ int nodename_eq(const char *s1, const char *s2)
 void *load_blob(const char *filename)
 {
 	char *blob;
-	int ret = utilfdt_read_err(filename, &blob);
+	int ret = utilfdt_read_err(filename, &blob, NULL);
 
 	if (ret)
 		CONFIG("Couldn't open blob from \"%s\": %s", filename,
diff --git a/util.c b/util.c
index 12f0614..c689ea7 100644
--- a/util.c
+++ b/util.c
@@ -197,7 +197,7 @@ char get_escape_char(const char *s, int *i)
 	return val;
 }
 
-int utilfdt_read_err(const char *filename, char **buffp)
+int utilfdt_read_err(const char *filename, char **buffp, off_t *len)
 {
 	int fd = 0;	/* assume stdin */
 	char *buf = NULL;
@@ -238,13 +238,15 @@ int utilfdt_read_err(const char *filename, char **buffp)
 		free(buf);
 	else
 		*buffp = buf;
+	if (len)
+		*len = bufsize;
 	return ret;
 }
 
-char *utilfdt_read(const char *filename)
+char *utilfdt_read(const char *filename, off_t *len)
 {
 	char *buff;
-	int ret = utilfdt_read_err(filename, &buff);
+	int ret = utilfdt_read_err(filename, &buff, len);
 
 	if (ret) {
 		fprintf(stderr, "Couldn't open blob from '%s': %s\n", filename,
diff --git a/util.h b/util.h
index 543a173..3c20b15 100644
--- a/util.h
+++ b/util.h
@@ -80,9 +80,10 @@ char get_escape_char(const char *s, int *i);
  * stderr.
  *
  * @param filename	The filename to read, or - for stdin
+ * @param len		If non-NULL, the amount of data we managed to read
  * @return Pointer to allocated buffer containing fdt, or NULL on error
  */
-char *utilfdt_read(const char *filename);
+char *utilfdt_read(const char *filename, off_t *len);
 
 /**
  * Read a device tree file into a buffer. Does not report errors, but only
@@ -91,9 +92,10 @@ char *utilfdt_read(const char *filename);
  *
  * @param filename	The filename to read, or - for stdin
  * @param buffp		Returns pointer to buffer containing fdt
+ * @param len		If non-NULL, the amount of data we managed to read
  * @return 0 if ok, else an errno value representing the error
  */
-int utilfdt_read_err(const char *filename, char **buffp);
+int utilfdt_read_err(const char *filename, char **buffp, off_t *len);
 
 
 /**

commit 97c122eacc8636b26992cf6e080775f7c28660f9
Author: Mike Frysinger <vapier@gentoo.org>
Date:   Wed Apr 10 14:29:08 2013 -0400

    die: constify format string arg
    
    We only display this string, so there's no need for it to be writable.
    Constify away!
    
    Acked-by: David Gibson <David@gibson.dropbear.id.au>
    Signed-off-by: Mike Frysinger <vapier@gentoo.org>

diff --git a/util.h b/util.h
index 3c20b15..d856eb9 100644
--- a/util.h
+++ b/util.h
@@ -23,7 +23,7 @@
  *                                                                   USA
  */
 
-static inline void __attribute__((noreturn)) die(char * str, ...)
+static inline void __attribute__((noreturn)) die(const char *str, ...)
 {
 	va_list ap;
 

commit 31be4ce7ca550a6fd9c4eb39abdd2f9f5ac8db44
Author: Mike Frysinger <vapier@gentoo.org>
Date:   Wed Apr 10 14:29:09 2013 -0400

    util_version: new helper for displaying version info
    
    This is so all utilities can have this flag and not just dtc.
    
    Acked-by: David Gibson <david@gibson.dropbear.id.au>
    Signed-off-by: Mike Frysinger <vapier@gentoo.org>

diff --git a/dtc.c b/dtc.c
index d40e220..e4e1b84 100644
--- a/dtc.c
+++ b/dtc.c
@@ -21,8 +21,6 @@
 #include "dtc.h"
 #include "srcpos.h"
 
-#include "version_gen.h"
-
 /*
  * Command line options
  */
@@ -158,8 +156,7 @@ int main(int argc, char *argv[])
 			srcfile_add_search_path(optarg);
 			break;
 		case 'v':
-			printf("Version: %s\n", DTC_VERSION);
-			exit(0);
+			util_version();
 		case 'H':
 			if (streq(optarg, "legacy"))
 				phandle_format = PHANDLE_LEGACY;
diff --git a/util.c b/util.c
index c689ea7..a9b118c 100644
--- a/util.c
+++ b/util.c
@@ -34,6 +34,7 @@
 
 #include "libfdt.h"
 #include "util.h"
+#include "version_gen.h"
 
 char *xstrdup(const char *s)
 {
@@ -374,3 +375,9 @@ void utilfdt_print_data(const char *data, int len)
 		printf("]");
 	}
 }
+
+void util_version(void)
+{
+	printf("Version: %s\n", DTC_VERSION);
+	exit(0);
+}
diff --git a/util.h b/util.h
index d856eb9..e09cc25 100644
--- a/util.h
+++ b/util.h
@@ -168,4 +168,9 @@ int utilfdt_decode_type(const char *fmt, int *type, int *size);
  */
 void utilfdt_print_data(const char *data, int len);
 
+/**
+ * Show source version and exit
+ */
+void util_version(void) __attribute__((noreturn));
+
 #endif /* _UTIL_H */

commit 5543b88d5e3047b781552eb431bc2e3bdd9ade06
Author: Jon Loeliger <jdl@jdl.com>
Date:   Mon Apr 22 15:41:41 2013 -0500

    Revert "utilfdt_read: pass back up the length of data read"
    
    This reverts commit cc2c178727cdeca4eb9756637c2e09e50e0856e7.
    It was the wrong version of the patch.

diff --git a/fdtget.c b/fdtget.c
index 374bee2..c2fbab2 100644
--- a/fdtget.c
+++ b/fdtget.c
@@ -254,7 +254,7 @@ static int do_fdtget(struct display_info *disp, const char *filename,
 	const char *prop;
 	int i, node;
 
-	blob = utilfdt_read(filename, NULL);
+	blob = utilfdt_read(filename);
 	if (!blob)
 		return -1;
 
diff --git a/fdtput.c b/fdtput.c
index 572d6da..f2197f5 100644
--- a/fdtput.c
+++ b/fdtput.c
@@ -239,7 +239,7 @@ static int do_fdtput(struct display_info *disp, const char *filename,
 	char *blob;
 	int len, ret = 0;
 
-	blob = utilfdt_read(filename, NULL);
+	blob = utilfdt_read(filename);
 	if (!blob)
 		return -1;
 
diff --git a/tests/testutils.c b/tests/testutils.c
index 67b39b0..f185133 100644
--- a/tests/testutils.c
+++ b/tests/testutils.c
@@ -160,7 +160,7 @@ int nodename_eq(const char *s1, const char *s2)
 void *load_blob(const char *filename)
 {
 	char *blob;
-	int ret = utilfdt_read_err(filename, &blob, NULL);
+	int ret = utilfdt_read_err(filename, &blob);
 
 	if (ret)
 		CONFIG("Couldn't open blob from \"%s\": %s", filename,
diff --git a/util.c b/util.c
index a9b118c..4cdad10 100644
--- a/util.c
+++ b/util.c
@@ -198,7 +198,7 @@ char get_escape_char(const char *s, int *i)
 	return val;
 }
 
-int utilfdt_read_err(const char *filename, char **buffp, off_t *len)
+int utilfdt_read_err(const char *filename, char **buffp)
 {
 	int fd = 0;	/* assume stdin */
 	char *buf = NULL;
@@ -239,15 +239,13 @@ int utilfdt_read_err(const char *filename, char **buffp, off_t *len)
 		free(buf);
 	else
 		*buffp = buf;
-	if (len)
-		*len = bufsize;
 	return ret;
 }
 
-char *utilfdt_read(const char *filename, off_t *len)
+char *utilfdt_read(const char *filename)
 {
 	char *buff;
-	int ret = utilfdt_read_err(filename, &buff, len);
+	int ret = utilfdt_read_err(filename, &buff);
 
 	if (ret) {
 		fprintf(stderr, "Couldn't open blob from '%s': %s\n", filename,
diff --git a/util.h b/util.h
index e09cc25..3f02cd8 100644
--- a/util.h
+++ b/util.h
@@ -80,10 +80,9 @@ char get_escape_char(const char *s, int *i);
  * stderr.
  *
  * @param filename	The filename to read, or - for stdin
- * @param len		If non-NULL, the amount of data we managed to read
  * @return Pointer to allocated buffer containing fdt, or NULL on error
  */
-char *utilfdt_read(const char *filename, off_t *len);
+char *utilfdt_read(const char *filename);
 
 /**
  * Read a device tree file into a buffer. Does not report errors, but only
@@ -92,10 +91,9 @@ char *utilfdt_read(const char *filename, off_t *len);
  *
  * @param filename	The filename to read, or - for stdin
  * @param buffp		Returns pointer to buffer containing fdt
- * @param len		If non-NULL, the amount of data we managed to read
  * @return 0 if ok, else an errno value representing the error
  */
-int utilfdt_read_err(const char *filename, char **buffp, off_t *len);
+int utilfdt_read_err(const char *filename, char **buffp);
 
 
 /**

commit a6d55e039fd22048687fe061b4609e2807efe764
Author: Mike Frysinger <vapier@gentoo.org>
Date:   Mon Apr 8 00:56:54 2013 -0400

    utilfdt_read: pass back up the length of data read
    
    For a follow up commit, we want to be able to scan the buffer that was
    returned to us.  In order to do that safely, we need to know how big
    the buffer actually is, so create a new set of funcs to pass that back.
    
    Acked-by: David Gibson <david@gibson.dropbear.id.au>
    Signed-off-by: Mike Frysinger <vapier@gentoo.org>

diff --git a/util.c b/util.c
index 4cdad10..350cf8b 100644
--- a/util.c
+++ b/util.c
@@ -198,7 +198,7 @@ char get_escape_char(const char *s, int *i)
 	return val;
 }
 
-int utilfdt_read_err(const char *filename, char **buffp)
+int utilfdt_read_err_len(const char *filename, char **buffp, off_t *len)
 {
 	int fd = 0;	/* assume stdin */
 	char *buf = NULL;
@@ -239,13 +239,20 @@ int utilfdt_read_err(const char *filename, char **buffp)
 		free(buf);
 	else
 		*buffp = buf;
+	*len = bufsize;
 	return ret;
 }
 
-char *utilfdt_read(const char *filename)
+int utilfdt_read_err(const char *filename, char **buffp)
+{
+	off_t len;
+	return utilfdt_read_err_len(filename, buffp, &len);
+}
+
+char *utilfdt_read_len(const char *filename, off_t *len)
 {
 	char *buff;
-	int ret = utilfdt_read_err(filename, &buff);
+	int ret = utilfdt_read_err_len(filename, &buff, len);
 
 	if (ret) {
 		fprintf(stderr, "Couldn't open blob from '%s': %s\n", filename,
@@ -256,6 +263,12 @@ char *utilfdt_read(const char *filename)
 	return buff;
 }
 
+char *utilfdt_read(const char *filename)
+{
+	off_t len;
+	return utilfdt_read_len(filename, &len);
+}
+
 int utilfdt_write_err(const char *filename, const void *blob)
 {
 	int fd = 1;	/* assume stdout */
diff --git a/util.h b/util.h
index 3f02cd8..95ae531 100644
--- a/util.h
+++ b/util.h
@@ -85,6 +85,13 @@ char get_escape_char(const char *s, int *i);
 char *utilfdt_read(const char *filename);
 
 /**
+ * Like utilfdt_read(), but also passes back the size of the file read.
+ *
+ * @param len		If non-NULL, the amount of data we managed to read
+ */
+char *utilfdt_read_len(const char *filename, off_t *len);
+
+/**
  * Read a device tree file into a buffer. Does not report errors, but only
  * returns them. The value returned can be passed to strerror() to obtain
  * an error message for the user.
@@ -95,6 +102,12 @@ char *utilfdt_read(const char *filename);
  */
 int utilfdt_read_err(const char *filename, char **buffp);
 
+/**
+ * Like utilfdt_read_err(), but also passes back the size of the file read.
+ *
+ * @param len		If non-NULL, the amount of data we managed to read
+ */
+int utilfdt_read_err_len(const char *filename, char **buffp, off_t *len);
 
 /**
  * Write a device tree buffer to a file. This will report any errors on

commit 4e76ec796c90d44d417f82d9db2d67cfe575f8ed
Author: Simon Glass <sjg@chromium.org>
Date:   Fri Apr 26 05:43:31 2013 -0700

    libfdt: Add fdt_next_subnode() to permit easy subnode iteration
    
    Iterating through subnodes with libfdt is a little painful to write as we
    need something like this:
    
    for (depth = 0, count = 0,
    	offset = fdt_next_node(fdt, parent_offset, &depth);
         (offset >= 0) && (depth > 0);
         offset = fdt_next_node(fdt, offset, &depth)) {
    	if (depth == 1) {
    		/* code body */
    	}
    }
    
    Using fdt_next_subnode() we can instead write this, which is shorter and
    easier to get right:
    
    for (offset = fdt_first_subnode(fdt, parent_offset);
         offset >= 0;
         offset = fdt_next_subnode(fdt, offset)) {
    	/* code body */
    }
    
    Also, it doesn't require two levels of indentation for the loop body.
    
    Signed-off-by: Simon Glass <sjg@chromium.org>
    Acked-by: David Gibson <david@gibson.dropbear.id.au>

diff --git a/libfdt/fdt.c b/libfdt/fdt.c
index 57faba3..2ce6a44 100644
--- a/libfdt/fdt.c
+++ b/libfdt/fdt.c
@@ -198,6 +198,34 @@ int fdt_next_node(const void *fdt, int offset, int *depth)
 	return offset;
 }
 
+int fdt_first_subnode(const void *fdt, int offset)
+{
+	int depth = 0;
+
+	offset = fdt_next_node(fdt, offset, &depth);
+	if (offset < 0 || depth != 1)
+		return -FDT_ERR_NOTFOUND;
+
+	return offset;
+}
+
+int fdt_next_subnode(const void *fdt, int offset)
+{
+	int depth = 1;
+
+	/*
+	 * With respect to the parent, the depth of the next subnode will be
+	 * the same as the last.
+	 */
+	do {
+		offset = fdt_next_node(fdt, offset, &depth);
+		if (offset < 0 || depth < 1)
+			return -FDT_ERR_NOTFOUND;
+	} while (depth > 1);
+
+	return offset;
+}
+
 const char *_fdt_find_string(const char *strtab, int tabsize, const char *s)
 {
 	int len = strlen(s) + 1;
diff --git a/libfdt/libfdt.h b/libfdt/libfdt.h
index 130789a..02baa84 100644
--- a/libfdt/libfdt.h
+++ b/libfdt/libfdt.h
@@ -136,6 +136,28 @@ uint32_t fdt_next_tag(const void *fdt, int offset, int *nextoffset);
 
 int fdt_next_node(const void *fdt, int offset, int *depth);
 
+/**
+ * fdt_first_subnode() - get offset of first direct subnode
+ *
+ * @fdt:	FDT blob
+ * @offset:	Offset of node to check
+ * @return offset of first subnode, or -FDT_ERR_NOTFOUND if there is none
+ */
+int fdt_first_subnode(const void *fdt, int offset);
+
+/**
+ * fdt_next_subnode() - get offset of next direct subnode
+ *
+ * After first calling fdt_first_subnode(), call this function repeatedly to
+ * get direct subnodes of a parent node.
+ *
+ * @fdt:	FDT blob
+ * @offset:	Offset of previous subnode
+ * @return offset of next subnode, or -FDT_ERR_NOTFOUND if there are no more
+ * subnodes
+ */
+int fdt_next_subnode(const void *fdt, int offset);
+
 /**********************************************************************/
 /* General functions                                                  */
 /**********************************************************************/
diff --git a/tests/Makefile.tests b/tests/Makefile.tests
index d59bff8..dafb618 100644
--- a/tests/Makefile.tests
+++ b/tests/Makefile.tests
@@ -20,7 +20,8 @@ LIB_TESTS_L = get_mem_rsv \
 	dtb_reverse dtbs_equal_unordered \
 	add_subnode_with_nops path_offset_aliases \
 	utilfdt_test \
-	integer-expressions
+	integer-expressions \
+	subnode_iterate
 LIB_TESTS = $(LIB_TESTS_L:%=$(TESTS_PREFIX)%)
 
 LIBTREE_TESTS_L = truncated_property
diff --git a/tests/run_tests.sh b/tests/run_tests.sh
index b56b626..b013761 100755
--- a/tests/run_tests.sh
+++ b/tests/run_tests.sh
@@ -241,6 +241,9 @@ libfdt_tests () {
 	tree1_tests_rw noppy.$basetree
     done
 
+    run_dtc_test -I dts -O dtb -o subnode_iterate.dtb subnode_iterate.dts
+    run_test subnode_iterate subnode_iterate.dtb
+
     # Tests for behaviour on various sorts of corrupted trees
     run_test truncated_property
 
diff --git a/tests/subnode_iterate.c b/tests/subnode_iterate.c
new file mode 100644
index 0000000..b9f379d
--- /dev/null
+++ b/tests/subnode_iterate.c
@@ -0,0 +1,94 @@
+/*
+ * libfdt - Flat Device Tree manipulation
+ *	Tests that fdt_next_subnode() works as expected
+ *
+ * Copyright (C) 2013 Google, Inc
+ *
+ * Copyright (C) 2007 David Gibson, IBM Corporation.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser 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
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdint.h>
+
+#include <libfdt.h>
+
+#include "tests.h"
+#include "testdata.h"
+
+static void test_node(void *fdt, int parent_offset)
+{
+	fdt32_t subnodes;
+	const fdt32_t *prop;
+	int offset;
+	int count;
+	int len;
+
+	/* This property indicates the number of subnodes to expect */
+	prop = fdt_getprop(fdt, parent_offset, "subnodes", &len);
+	if (!prop || len != sizeof(fdt32_t)) {
+		FAIL("Missing/invalid subnodes property at '%s'",
+		     fdt_get_name(fdt, parent_offset, NULL));
+	}
+	subnodes = cpu_to_fdt32(*prop);
+
+	count = 0;
+	for (offset = fdt_first_subnode(fdt, parent_offset);
+	     offset >= 0;
+	     offset = fdt_next_subnode(fdt, offset))
+		count++;
+
+	if (count != subnodes) {
+		FAIL("Node '%s': Expected %d subnodes, got %d\n",
+		     fdt_get_name(fdt, parent_offset, NULL), subnodes,
+		     count);
+	}
+}
+
+static void check_fdt_next_subnode(void *fdt)
+{
+	int offset;
+	int count = 0;
+
+	for (offset = fdt_first_subnode(fdt, 0);
+	     offset >= 0;
+	     offset = fdt_next_subnode(fdt, offset)) {
+		test_node(fdt, offset);
+		count++;
+	}
+
+	if (count != 2)
+		FAIL("Expected %d tests, got %d\n", 2, count);
+}
+
+int main(int argc, char *argv[])
+{
+	void *fdt;
+
+	test_init(argc, argv);
+	if (argc != 2)
+		CONFIG("Usage: %s <dtb file>", argv[0]);
+
+	fdt = load_blob(argv[1]);
+	if (!fdt)
+		FAIL("No device tree available");
+
+	check_fdt_next_subnode(fdt);
+
+	PASS();
+}
diff --git a/tests/subnode_iterate.dts b/tests/subnode_iterate.dts
new file mode 100644
index 0000000..14a0d3a
--- /dev/null
+++ b/tests/subnode_iterate.dts
@@ -0,0 +1,44 @@
+/dts-v1/;
+
+/ {
+	#address-cells = <1>;
+	#size-cells = <0>;
+
+	test1 {
+		subnodes = <2>;
+		linux,phandle = <0x1>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+		PowerPC,970@0 {
+			name = "PowerPC,970";
+			device_type = "cpu";
+			reg = <0x00000000>;
+			clock-frequency = <1600000000>;
+			timebase-frequency = <33333333>;
+			linux,boot-cpu;
+			i-cache-size = <65536>;
+			d-cache-size = <32768>;
+			another-sub-node {
+				should-be-ignored;
+				yet-another {
+					should-also-be-ignored;
+				};
+			};
+		};
+
+		PowerPC,970@1 {
+			name = "PowerPC,970";
+			device_type = "cpu";
+			reg = <0x00000001>;
+			clock-frequency = <1600000000>;
+			timebase-frequency = <33333333>;
+			i-cache-size = <65536>;
+			d-cache-size = <32768>;
+		};
+	};
+
+	test2 {
+		subnodes = <0>;
+	};
+};
+
