Blob Blame History Raw
From 0a5aca98ba104ec4101322ccaf36da45064ad3ce Mon Sep 17 00:00:00 2001
From: Josh Boyer <jwboyer@linux.vnet.ibm.com>
Date: Tue, 28 Jun 2011 08:47:09 -0400
Subject: [PATCH 01/96] 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>
---
 dtc.c | 7 ++-----
 1 file changed, 2 insertions(+), 5 deletions(-)

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;
-- 
1.8.1.4


From d5b3165023b1cc3914e9943b91964ec9ad4be8b2 Mon Sep 17 00:00:00 2001
From: Josh Boyer <jwboyer@linux.vnet.ibm.com>
Date: Tue, 28 Jun 2011 09:47:11 -0400
Subject: [PATCH 02/96] 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>
---
 flattree.c | 2 --
 1 file changed, 2 deletions(-)

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);
-- 
1.8.1.4


From 492f9d5de7db74aeb3a905246c4efd7cb29227a8 Mon Sep 17 00:00:00 2001
From: Simon Glass <sjg@chromium.org>
Date: Tue, 5 Jul 2011 12:02:49 -0700
Subject: [PATCH 03/96] 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>
---
 Makefile.ftdump |  3 ++-
 ftdump.c        | 28 +++-------------------------
 util.c          | 28 ++++++++++++++++++++++++++++
 util.h          | 11 +++++++++++
 4 files changed, 44 insertions(+), 26 deletions(-)

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 */
-- 
1.8.1.4


From ed8fee1a649b5430afc9b551e3bb6746ebe32449 Mon Sep 17 00:00:00 2001
From: Simon Glass <sjg@chromium.org>
Date: Tue, 5 Jul 2011 12:02:52 -0700
Subject: [PATCH 04/96] Add missing tests to .gitignore

Signed-off-by: Simon Glass <sjg@chromium.org>
Acked-by: David Gibson <david@gibson.dropbear.id.au>
---
 tests/.gitignore | 2 ++
 1 file changed, 2 insertions(+)

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
-- 
1.8.1.4


From b43335a23854b2620140eda6cca2ffae59e8de23 Mon Sep 17 00:00:00 2001
From: Anton Staaf <robotboy@chromium.org>
Date: Fri, 9 Sep 2011 12:16:29 -0700
Subject: [PATCH 05/96] 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>
---
 data.c | 85 +++-----------------------------------------------------
 util.c | 99 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 util.h |  8 ++++++
 3 files changed, 111 insertions(+), 81 deletions(-)

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 */
-- 
1.8.1.4


From 83df28bd39979b32a75656cac291c36dbd4e5497 Mon Sep 17 00:00:00 2001
From: David Gibson <david@gibson.dropbear.id.au>
Date: Mon, 12 Sep 2011 11:18:43 +1000
Subject: [PATCH 06/96] 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>
---
 tests/notfound.c       | 8 +++-----
 tests/path_offset.c    | 4 ++++
 tests/subnode_offset.c | 6 +++---
 3 files changed, 10 insertions(+), 8 deletions(-)

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();
 }
-- 
1.8.1.4


From a4ea2fa9518ff0f4d7f4a08647599a727faac2e0 Mon Sep 17 00:00:00 2001
From: Anton Staaf <robotboy@chromium.org>
Date: Fri, 9 Sep 2011 12:16:30 -0700
Subject: [PATCH 07/96] 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>
---
 Documentation/dts-format.txt |  2 +-
 dtc-lexer.l                  |  8 +++++++
 dtc-parser.y                 | 32 ++++++++++++++++++++++++++++
 tests/.gitignore             |  1 +
 tests/Makefile.tests         |  1 +
 tests/char_literal.c         | 50 ++++++++++++++++++++++++++++++++++++++++++++
 tests/char_literal.dts       |  5 +++++
 tests/run_tests.sh           |  3 +++
 tests/testdata.h             |  6 ++++++
 9 files changed, 107 insertions(+), 1 deletion(-)
 create mode 100644 tests/char_literal.c
 create mode 100644 tests/char_literal.dts

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;
-- 
1.8.1.4


From 9ebd9b4a56e54656431111e5ea7cd74e651910bf Mon Sep 17 00:00:00 2001
From: Simon Glass <sjg@chromium.org>
Date: Wed, 21 Sep 2011 13:32:44 -0700
Subject: [PATCH 08/96] 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>
---
 Makefile        |  2 +-
 Makefile.ftdump | 13 -------------
 Makefile.utils  | 10 ++++++++++
 3 files changed, 11 insertions(+), 14 deletions(-)
 delete mode 100644 Makefile.ftdump
 create mode 100644 Makefile.utils

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


From 36204fdf742cabc074617648a5b2cf62409dc40b Mon Sep 17 00:00:00 2001
From: Simon Glass <sjg@chromium.org>
Date: Thu, 22 Sep 2011 10:11:02 -0700
Subject: [PATCH 09/96] 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>
---
 Makefile             |   2 +-
 tests/Makefile.tests |   5 +-
 tests/run_tests.sh   |   9 +++-
 tests/tests.h        |  18 +------
 tests/utilfdt_test.c | 128 ++++++++++++++++++++++++++++++++++++++++++++++
 util.c               | 142 +++++++++++++++++++++++++++++++++++++++++++++++++++
 util.h               |  68 ++++++++++++++++++++++++
 7 files changed, 352 insertions(+), 20 deletions(-)
 create mode 100644 tests/utilfdt_test.c

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 */
-- 
1.8.1.4


From 1c25c0d520dee58bfd86626a07036fe9febfebe6 Mon Sep 17 00:00:00 2001
From: Simon Glass <sjg@chromium.org>
Date: Thu, 22 Sep 2011 10:11:03 -0700
Subject: [PATCH 10/96] 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>
---
 tests/Makefile.tests |  5 +++--
 tests/testutils.c    | 59 ++++++++++------------------------------------------
 2 files changed, 14 insertions(+), 50 deletions(-)

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


From 07a8691fbbeb2a7e0cff85fb24435e2dc71facaf Mon Sep 17 00:00:00 2001
From: Simon Glass <sjg@chromium.org>
Date: Thu, 22 Sep 2011 10:11:04 -0700
Subject: [PATCH 11/96] 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>
---
 ftdump.c | 32 ++++----------------------------
 1 file changed, 4 insertions(+), 28 deletions(-)

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;
 }
-- 
1.8.1.4


From 2cd4c8d27d6b5ea83723754da4eba5d51aa71b95 Mon Sep 17 00:00:00 2001
From: Anton Staaf <robotboy@chromium.org>
Date: Tue, 11 Oct 2011 10:22:27 -0700
Subject: [PATCH 12/96] 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>
---
 libfdt/libfdt_env.h | 6 ++++++
 1 file changed, 6 insertions(+)

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);
-- 
1.8.1.4


From a4b515c03804dbc0eff5bbf281bd22438717e773 Mon Sep 17 00:00:00 2001
From: Anton Staaf <robotboy@chromium.org>
Date: Tue, 11 Oct 2011 10:22:28 -0700
Subject: [PATCH 13/96] 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>
---
 data.c | 39 ++++++++++++++++++++++++++++++++-------
 dtc.h  |  1 +
 2 files changed, 33 insertions(+), 7 deletions(-)

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);
-- 
1.8.1.4


From 033089f29099bdfd5c2d6986cdb9fd07b16cfde0 Mon Sep 17 00:00:00 2001
From: Anton Staaf <robotboy@chromium.org>
Date: Tue, 11 Oct 2011 10:22:29 -0700
Subject: [PATCH 14/96] 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>
---
 Documentation/dts-format.txt | 34 ++++++++++++------
 dtc-lexer.l                  |  6 ++++
 dtc-parser.y                 | 70 ++++++++++++++++++++++++------------
 tests/.gitignore             |  1 +
 tests/Makefile.tests         |  1 +
 tests/run_tests.sh           |  3 ++
 tests/sized_cells.c          | 84 ++++++++++++++++++++++++++++++++++++++++++++
 tests/sized_cells.dts        | 11 ++++++
 8 files changed, 177 insertions(+), 33 deletions(-)
 create mode 100644 tests/sized_cells.c
 create mode 100644 tests/sized_cells.dts

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>;
+};
-- 
1.8.1.4


From 8f459c5d72673e1a3a119ac58a7eee56236fca73 Mon Sep 17 00:00:00 2001
From: Mike Frysinger <vapier@gentoo.org>
Date: Tue, 25 Oct 2011 17:29:24 -0400
Subject: [PATCH 15/96] 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>
---
 .gitignore               |   2 +-
 Documentation/manual.txt |  10 +--
 Makefile                 |   6 +-
 Makefile.utils           |   6 +-
 fdtdump.c                | 162 +++++++++++++++++++++++++++++++++++++++++++++++
 ftdump.c                 | 162 -----------------------------------------------
 6 files changed, 174 insertions(+), 174 deletions(-)
 create mode 100644 fdtdump.c
 delete mode 100644 ftdump.c

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;
-}
-- 
1.8.1.4


From a31e3ef83bfce62d07695355e5f06cd4d0e44b86 Mon Sep 17 00:00:00 2001
From: Minghuan Lian <Minghuan.Lian@freescale.com>
Date: Mon, 5 Dec 2011 12:22:07 +1100
Subject: [PATCH 16/96] 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>
---
 libfdt/fdt_rw.c      | 27 +++++++++++++++
 libfdt/libfdt.h      | 95 ++++++++++++++++++++++++++++++++++++++++++++++++++++
 tests/appendprop.dts |  7 ++++
 tests/appendprop1.c  | 70 ++++++++++++++++++++++++++++++++++++++
 tests/appendprop2.c  | 64 +++++++++++++++++++++++++++++++++++
 5 files changed, 263 insertions(+)
 create mode 100644 tests/appendprop.dts
 create mode 100644 tests/appendprop1.c
 create mode 100644 tests/appendprop2.c

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();
+}
-- 
1.8.1.4


From 97b909f852039daaae267a66f5df2c90ed05b586 Mon Sep 17 00:00:00 2001
From: David Gibson <david@gibson.dropbear.id.au>
Date: Wed, 11 Jan 2012 23:41:32 +1100
Subject: [PATCH 17/96] 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>
---
 tests/Makefile.tests | 1 +
 tests/run_tests.sh   | 4 ++++
 2 files changed, 5 insertions(+)

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
-- 
1.8.1.4


From 69df9f0de25db1c37970850115cdf48335d41802 Mon Sep 17 00:00:00 2001
From: Stephen Warren <swarren@nvidia.com>
Date: Thu, 12 Jan 2012 11:31:00 -0700
Subject: [PATCH 18/96] 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>
---
 Documentation/manual.txt |  3 +++
 dtc.c                    | 20 +++++++++++++++++++-
 srcpos.c                 |  4 ++++
 srcpos.h                 |  1 +
 tests/dependencies.cmp   |  1 +
 tests/dependencies.dts   |  6 ++++++
 tests/deps_inc1.dtsi     |  1 +
 tests/deps_inc2.dtsi     |  1 +
 tests/run_tests.sh       |  4 ++++
 9 files changed, 40 insertions(+), 1 deletion(-)
 create mode 100644 tests/dependencies.cmp
 create mode 100644 tests/dependencies.dts
 create mode 100644 tests/deps_inc1.dtsi
 create mode 100644 tests/deps_inc2.dtsi

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


From 68d057f20d7c3a93b441d2892c4749392bc83b45 Mon Sep 17 00:00:00 2001
From: Simon Glass <sjg@chromium.org>
Date: Sat, 21 Jan 2012 10:14:47 -0800
Subject: [PATCH 19/96] 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>
---
 .gitignore              |   1 +
 Makefile                |   4 +
 Makefile.utils          |   7 ++
 fdtget.c                | 226 ++++++++++++++++++++++++++++++++++++++++++++++++
 tests/fdtget-runtest.sh |  35 ++++++++
 tests/run_tests.sh      |  43 ++++++++-
 tests/tests.sh          |   1 +
 util.h                  |  10 +++
 8 files changed, 326 insertions(+), 1 deletion(-)
 create mode 100644 fdtget.c
 create mode 100755 tests/fdtget-runtest.sh

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 */
-- 
1.8.1.4


From 1ede50c3559bbfca79fadcbfd8acb9388f4aac87 Mon Sep 17 00:00:00 2001
From: Simon Glass <sjg@chromium.org>
Date: Sat, 21 Jan 2012 10:14:48 -0800
Subject: [PATCH 20/96] 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>
---
 .gitignore              |   1 +
 Makefile                |   4 +
 Makefile.utils          |   7 ++
 fdtput.c                | 235 ++++++++++++++++++++++++++++++++++++++++++++++++
 tests/fdtput-runtest.sh |  55 ++++++++++++
 tests/run_tests.sh      |  73 ++++++++++++++-
 tests/tests.sh          |   1 +
 7 files changed, 375 insertions(+), 1 deletion(-)
 create mode 100644 fdtput.c
 create mode 100644 tests/fdtput-runtest.sh

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
-- 
1.8.1.4


From 1456da7e2d3054882b20c120d817096bea21571e Mon Sep 17 00:00:00 2001
From: Jon Loeliger <jdl@jdl.com>
Date: Sat, 21 Jan 2012 15:24:51 -0600
Subject: [PATCH 21/96] Introduce ${TESTS_BIN} in Makefiles to identify tested
 executables.

---
 Makefile             | 6 ++++++
 tests/Makefile.tests | 6 +++---
 2 files changed, 9 insertions(+), 3 deletions(-)

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),)
-- 
1.8.1.4


From 81f11f4f109cc16e1ec31a85c222a1caabea5654 Mon Sep 17 00:00:00 2001
From: David Gibson <david@gibson.dropbear.id.au>
Date: Fri, 3 Feb 2012 16:12:00 +1100
Subject: [PATCH 22/96] 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>
---
 tests/.gitignore | 3 +++
 1 file changed, 3 insertions(+)

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
-- 
1.8.1.4


From 9cf26ffa4a9dfa477971f989dcd7392bedbaaaed Mon Sep 17 00:00:00 2001
From: David Gibson <david@gibson.dropbear.id.au>
Date: Fri, 3 Feb 2012 16:12:01 +1100
Subject: [PATCH 23/96] 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>
---
 .gitignore | 2 ++
 1 file changed, 2 insertions(+)

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
-- 
1.8.1.4


From 53d6ca639d1e95d0d62e84b25f3d22d721d1f4a3 Mon Sep 17 00:00:00 2001
From: David Gibson <david@gibson.dropbear.id.au>
Date: Fri, 3 Feb 2012 16:12:02 +1100
Subject: [PATCH 24/96] 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>
---
 fdtget.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

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;
-- 
1.8.1.4


From 9a50d82c4e3a44ca004ada288f7c37004da0b0cc Mon Sep 17 00:00:00 2001
From: David Gibson <david@gibson.dropbear.id.au>
Date: Fri, 3 Feb 2012 16:12:03 +1100
Subject: [PATCH 25/96] 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>
---
 tests/dtc-checkfails.sh | 2 +-
 tests/fdtget-runtest.sh | 2 +-
 tests/fdtput-runtest.sh | 2 +-
 3 files changed, 3 insertions(+), 3 deletions(-)

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
-- 
1.8.1.4


From 2ca83614e78f32e68202100e94668b0bb62f1ba6 Mon Sep 17 00:00:00 2001
From: David Gibson <david@gibson.dropbear.id.au>
Date: Fri, 3 Feb 2012 16:12:04 +1100
Subject: [PATCH 26/96] 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>
---
 tests/dtc-checkfails.sh |  6 ++----
 tests/fdtget-runtest.sh | 10 ++++------
 tests/fdtput-runtest.sh | 10 ++++------
 3 files changed, 10 insertions(+), 16 deletions(-)

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
-- 
1.8.1.4


From a90b5b149197a8b38bd569c6a8abc9fc0363fa4b Mon Sep 17 00:00:00 2001
From: David Gibson <david@gibson.dropbear.id.au>
Date: Fri, 3 Feb 2012 16:12:05 +1100
Subject: [PATCH 27/96] 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>
---
 tests/run_tests.sh | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

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>
-- 
1.8.1.4


From c879a8a28b168b3b448ca8a107e3386eda6829c7 Mon Sep 17 00:00:00 2001
From: David Gibson <david@gibson.dropbear.id.au>
Date: Fri, 3 Feb 2012 16:12:06 +1100
Subject: [PATCH 28/96] 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>
---
 tests/dtc-checkfails.sh |  5 +----
 tests/fdtget-runtest.sh |  5 +----
 tests/fdtput-runtest.sh | 11 +++--------
 tests/tests.sh          |  8 ++++++++
 4 files changed, 13 insertions(+), 16 deletions(-)

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
-- 
1.8.1.4


From 15b23d21a62b5a0295ee08b54d0842889ce94c92 Mon Sep 17 00:00:00 2001
From: David Gibson <david@gibson.dropbear.id.au>
Date: Fri, 3 Feb 2012 16:12:07 +1100
Subject: [PATCH 29/96] 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>
---
 tests/fdtget-runtest.sh |  11 +---
 tests/fdtput-runtest.sh |  16 +-----
 tests/run_tests.sh      | 144 +++++++++++++++++++++++++++---------------------
 tests/tests.sh          |  19 +++++++
 4 files changed, 104 insertions(+), 86 deletions(-)

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
+}
+
-- 
1.8.1.4


From c34e88354a07099dbc15a41621c81f71325d25fd Mon Sep 17 00:00:00 2001
From: David Gibson <david@gibson.dropbear.id.au>
Date: Fri, 3 Feb 2012 16:12:08 +1100
Subject: [PATCH 30/96] 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>
---
 tests/fdtget-runtest.sh | 13 +++++++------
 tests/fdtput-runtest.sh | 13 +++++++------
 2 files changed, 14 insertions(+), 12 deletions(-)

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
-- 
1.8.1.4


From 0b3b46e019f546a24927bb7ca009670762c00107 Mon Sep 17 00:00:00 2001
From: David Gibson <david@gibson.dropbear.id.au>
Date: Fri, 3 Feb 2012 16:12:09 +1100
Subject: [PATCH 31/96] 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>
---
 tests/lorem.txt    | 35 +++++++++++++++++++++++++++++++++++
 tests/run_tests.sh | 32 ++++++--------------------------
 2 files changed, 41 insertions(+), 26 deletions(-)
 create mode 100644 tests/lorem.txt

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?
 }
-- 
1.8.1.4


From e280442e08fcbe8431dc85d836ff3ecc489932fb Mon Sep 17 00:00:00 2001
From: David Gibson <david@gibson.dropbear.id.au>
Date: Fri, 3 Feb 2012 17:06:12 +1100
Subject: [PATCH 32/96] 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>
---
 util.c | 5 ++++-
 1 file changed, 4 insertions(+), 1 deletion(-)

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 */
-- 
1.8.1.4


From a6e6c60e3a97a6b3a033cd052bb3740fd53cbf4c Mon Sep 17 00:00:00 2001
From: Horst Kronstorfer <hkronsto@frequentis.com>
Date: Tue, 7 Feb 2012 10:02:53 +0100
Subject: [PATCH 33/96] 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>
---
 treesource.c | 2 ++
 1 file changed, 2 insertions(+)

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");
-- 
1.8.1.4


From 097ec97c1a35685957210adb93692c3e210bc82c Mon Sep 17 00:00:00 2001
From: Simon Glass <sjg@chromium.org>
Date: Fri, 2 Mar 2012 17:12:07 -0800
Subject: [PATCH 34/96] 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>
---
 fdtget.c                | 6 +++---
 tests/fdtget-runtest.sh | 2 +-
 tests/run_tests.sh      | 3 +++
 3 files changed, 7 insertions(+), 4 deletions(-)

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


From 30eb201adae2132c36874c89d4c6cf3195659d71 Mon Sep 17 00:00:00 2001
From: Simon Glass <sjg@chromium.org>
Date: Fri, 2 Mar 2012 17:12:08 -0800
Subject: [PATCH 35/96] 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>
---
 fdtget.c | 66 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++------
 1 file changed, 60 insertions(+), 6 deletions(-)

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;
 }
-- 
1.8.1.4


From 16c99ee8e3e60fb47b5eaa1778996fe6ef11c611 Mon Sep 17 00:00:00 2001
From: Simon Glass <sjg@chromium.org>
Date: Tue, 6 Mar 2012 16:41:46 -0800
Subject: [PATCH 36/96] 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>
---
 fdtget.c | 96 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++--------
 1 file changed, 84 insertions(+), 12 deletions(-)

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;
 		}
 	}
 
-- 
1.8.1.4


From 7fcbef275741793064268cf0a1bdcd59144a9a10 Mon Sep 17 00:00:00 2001
From: Simon Glass <sjg@chromium.org>
Date: Tue, 6 Mar 2012 16:41:47 -0800
Subject: [PATCH 37/96] 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>
---
 fdtget.c           | 20 +++++++++++++++++---
 tests/run_tests.sh |  6 ++++++
 2 files changed, 23 insertions(+), 3 deletions(-)

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


From de6b76240e91b9288cdce63ab81e51a7232d0927 Mon Sep 17 00:00:00 2001
From: Simon Glass <sjg@chromium.org>
Date: Wed, 14 Mar 2012 20:04:13 -0700
Subject: [PATCH 38/96] 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>
---
 dtc.c                                      |  8 ++-
 srcpos.c                                   | 92 +++++++++++++++++++++++++++---
 srcpos.h                                   | 29 ++++++++++
 tests/run_tests.sh                         | 11 ++++
 tests/search_dir/search_test.dtsi          |  4 ++
 tests/search_dir/search_test2.dtsi         |  3 +
 tests/search_dir_b/search_paths_subdir.dts |  6 ++
 tests/search_dir_b/search_test_b.dtsi      |  4 ++
 tests/search_dir_b/search_test_b2.dtsi     |  5 ++
 tests/search_dir_b/search_test_c.dtsi      |  2 +
 tests/search_paths.dts                     |  6 ++
 tests/search_paths_b.dts                   |  6 ++
 12 files changed, 168 insertions(+), 8 deletions(-)
 create mode 100644 tests/search_dir/search_test.dtsi
 create mode 100644 tests/search_dir/search_test2.dtsi
 create mode 100644 tests/search_dir_b/search_paths_subdir.dts
 create mode 100644 tests/search_dir_b/search_test_b.dtsi
 create mode 100644 tests/search_dir_b/search_test_b2.dtsi
 create mode 100644 tests/search_dir_b/search_test_c.dtsi
 create mode 100644 tests/search_paths.dts
 create mode 100644 tests/search_paths_b.dts

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"
+
+/ {
+};
-- 
1.8.1.4


From eaec1dbc5946d5fd01a9ef7120f8461c74d759a0 Mon Sep 17 00:00:00 2001
From: Stephen Warren <swarren@wwwdotorg.org>
Date: Tue, 20 Mar 2012 20:23:46 -0600
Subject: [PATCH 39/96] 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>
---
 tests/fdtget-runtest.sh | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

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 "$@"
-- 
1.8.1.4


From 5f0c3b2d6235dec65fff1628a97f45e21680b36d Mon Sep 17 00:00:00 2001
From: Stephen Warren <swarren@wwwdotorg.org>
Date: Tue, 3 Apr 2012 20:56:00 -0600
Subject: [PATCH 40/96] 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>
---
 dtc-lexer.l                 |  11 +++-
 dtc-parser.y                | 156 +++++++++++++++++++++++++++++++++++++-------
 tests/Makefile.tests        |   3 +-
 tests/integer-expressions.c | 117 +++++++++++++++++++++++++++++++++
 tests/run_tests.sh          |   5 ++
 5 files changed, 266 insertions(+), 26 deletions(-)
 create mode 100644 tests/integer-expressions.c

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
-- 
1.8.1.4


From 37b167f68afa21fbecb3077839f9c037a1459701 Mon Sep 17 00:00:00 2001
From: Bert Kenward <bert.kenward@broadcom.com>
Date: Tue, 10 Apr 2012 08:00:15 -0700
Subject: [PATCH 41/96] 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>
---
 libfdt/libfdt_env.h | 12 ++++++------
 1 file changed, 6 insertions(+), 6 deletions(-)

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 */
-- 
1.8.1.4


From 3cbf82987425f0bfcdd898a24db9647b35ee7351 Mon Sep 17 00:00:00 2001
From: Simon Glass <sjg@chromium.org>
Date: Wed, 11 Apr 2012 16:32:26 -0700
Subject: [PATCH 42/96] 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>
---
 dtc.c | 3 ---
 1 file changed, 3 deletions(-)

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


From 84a94f6ffcab762f44e44cba3409b7bc5fa46a89 Mon Sep 17 00:00:00 2001
From: Simon Glass <sjg@chromium.org>
Date: Thu, 19 Apr 2012 09:33:35 -0700
Subject: [PATCH 43/96] dtc: Adjust .gitignore to be in alphabetical order

This is the intent, so correct it.

Signed-off-by: Simon Glass <sjg@chromium.org>
---
 tests/.gitignore | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

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
-- 
1.8.1.4


From 3ec9cb570333769295774e4fd0e2000d35cf6eda Mon Sep 17 00:00:00 2001
From: Simon Glass <sjg@chromium.org>
Date: Thu, 19 Apr 2012 09:33:36 -0700
Subject: [PATCH 44/96] 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>
---
 tests/.gitignore | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

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
-- 
1.8.1.4


From 4adbb5336b0eed99f30c852d9dcf3cd125cae921 Mon Sep 17 00:00:00 2001
From: David Gibson <david@gibson.dropbear.id.au>
Date: Fri, 1 Jun 2012 14:12:36 +1000
Subject: [PATCH 45/96] 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>
---
 tests/run_tests.sh        |  4 ----
 tests/test_tree1_dts0.dts | 37 -------------------------------------
 2 files changed, 41 deletions(-)
 delete mode 100644 tests/test_tree1_dts0.dts

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 {
-		};
-	};
-};
-- 
1.8.1.4


From cbf1410eab4b7ce7be1b15f985ef71bfc1f5886d Mon Sep 17 00:00:00 2001
From: David Gibson <david@gibson.dropbear.id.au>
Date: Fri, 1 Jun 2012 14:12:37 +1000
Subject: [PATCH 46/96] 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>
---
 libfdt/libfdt.h                     | 193 +++++++++++++++++++++++++++++++-----
 tests/appendprop.dts                |   1 +
 tests/appendprop1.c                 |   1 +
 tests/appendprop2.c                 |   1 +
 tests/include1.dts                  |   1 +
 tests/include5a.dts                 |   1 +
 tests/rw_tree1.c                    |   3 +-
 tests/setprop.c                     |  18 ++++
 tests/setprop_inplace.c             |  15 +++
 tests/sw_tree1.c                    |   3 +-
 tests/test_tree1.dts                |   1 +
 tests/test_tree1_merge.dts          |   1 +
 tests/test_tree1_merge_labelled.dts |   1 +
 tests/test_tree1_merge_path.dts     |   1 +
 tests/testdata.h                    |   2 +
 tests/tests.h                       |   5 +
 tests/trees.S                       |   6 ++
 17 files changed, 229 insertions(+), 25 deletions(-)
 create mode 100644 tests/include5a.dts

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")
-- 
1.8.1.4


From be6026838e45b67800ac803f4ad8cca3cde57d6d Mon Sep 17 00:00:00 2001
From: David Gibson <david@gibson.dropbear.id.au>
Date: Fri, 1 Jun 2012 14:12:38 +1000
Subject: [PATCH 47/96] 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>
---
 libfdt/Makefile.libfdt  |  2 +-
 libfdt/fdt_empty_tree.c | 84 +++++++++++++++++++++++++++++++++++++++++++++++++
 libfdt/libfdt.h         |  1 +
 tests/rw_tree1.c        | 12 +------
 4 files changed, 87 insertions(+), 12 deletions(-)
 create mode 100644 libfdt/fdt_empty_tree.c

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));
-- 
1.8.1.4


From 942b3c065fb1c8788d2317977945c7283f1db7e2 Mon Sep 17 00:00:00 2001
From: Stephen Warren <swarren@nvidia.com>
Date: Tue, 12 Jun 2012 14:48:12 -0600
Subject: [PATCH 48/96] Fix compilation warning/error in setprop_inplace.c
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

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>
---
 tests/setprop_inplace.c | 9 +++++----
 1 file changed, 5 insertions(+), 4 deletions(-)

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);
-- 
1.8.1.4


From f67dfe845930b32ea14df6ff18d69799828a5909 Mon Sep 17 00:00:00 2001
From: Stephen Warren <swarren@nvidia.com>
Date: Tue, 3 Jul 2012 14:09:30 -0600
Subject: [PATCH 49/96] 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>
---
 tests/label_repeated.dts | 15 +++++++++++++++
 tests/run_tests.sh       |  2 ++
 2 files changed, 17 insertions(+)
 create mode 100644 tests/label_repeated.dts

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
-- 
1.8.1.4


From 511dedd40f0372cd7c85e3d4c66553f5829142b7 Mon Sep 17 00:00:00 2001
From: David Gibson <david@gibson.dropbear.id.au>
Date: Sun, 8 Jul 2012 23:25:21 +1000
Subject: [PATCH 50/96] 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>
---
 checks.c | 117 +++++++++++++++++++++++++++++++++------------------------------
 dtc.h    |   1 +
 2 files changed, 63 insertions(+), 55 deletions(-)

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>
-- 
1.8.1.4


From d5399197e9e0d8bad13de5c41df3b93804c0558a Mon Sep 17 00:00:00 2001
From: David Gibson <david@gibson.dropbear.id.au>
Date: Sun, 8 Jul 2012 23:25:22 +1000
Subject: [PATCH 51/96] 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>
---
 checks.c                | 84 +++++++++++++++++++++++++++++++++++++++++++++++--
 dtc.c                   | 13 +++++++-
 dtc.h                   |  1 +
 tests/dtc-checkfails.sh | 20 ++++++++++--
 tests/dtc-fails.sh      | 30 ++++++++++++++++++
 tests/run_tests.sh      | 12 +++++++
 6 files changed, 154 insertions(+), 6 deletions(-)
 create mode 100755 tests/dtc-fails.sh

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
-- 
1.8.1.4


From bb21f0a766056114e4d9336324b4c294f640d9d1 Mon Sep 17 00:00:00 2001
From: Simon Glass <sjg@chromium.org>
Date: Tue, 10 Jul 2012 05:56:44 -0700
Subject: [PATCH 52/96] 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>
---
 fdtput.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

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"
-- 
1.8.1.4


From f58dff50407c0ee56b372ab201469c18dc042f56 Mon Sep 17 00:00:00 2001
From: Simon Glass <sjg@chromium.org>
Date: Thu, 12 Jul 2012 08:52:48 -0700
Subject: [PATCH 53/96] 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>
---
 fdtput.c | 37 ++++++++++++++++++++++++++-----------
 1 file changed, 26 insertions(+), 11 deletions(-)

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;
-- 
1.8.1.4


From d46c2de5700fd8d43de67ca3709c276beba39b39 Mon Sep 17 00:00:00 2001
From: Simon Glass <sjg@chromium.org>
Date: Thu, 12 Jul 2012 08:52:49 -0700
Subject: [PATCH 54/96] 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>
---
 fdtput.c           | 52 +++++++++++++++++++++++++++++++++++++++++++++++++++-
 tests/run_tests.sh | 13 +++++++++++++
 2 files changed, 64 insertions(+), 1 deletion(-)

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?
 }
 
-- 
1.8.1.4


From 3553dfac224435233f2c0d33169194098e979c88 Mon Sep 17 00:00:00 2001
From: Simon Glass <sjg@chromium.org>
Date: Tue, 10 Jul 2012 05:56:47 -0700
Subject: [PATCH 55/96] 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>
---
 fdtput.c | 25 ++++++++++++++++++-------
 1 file changed, 18 insertions(+), 7 deletions(-)

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;
 	}
 
-- 
1.8.1.4


From f807af192828222dee7a5c9f94d999673bb4d8a1 Mon Sep 17 00:00:00 2001
From: Simon Glass <sjg@chromium.org>
Date: Thu, 12 Jul 2012 08:52:51 -0700
Subject: [PATCH 56/96] 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>
---
 fdtput.c           | 59 ++++++++++++++++++++++++++++++++++++++++++++++++++----
 tests/run_tests.sh | 13 ++++++++++++
 2 files changed, 68 insertions(+), 4 deletions(-)

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?
 }
 
-- 
1.8.1.4


From 8716901d2215a314504b7df6282aedfcf89da1ea Mon Sep 17 00:00:00 2001
From: "Yann E. MORIN" <yann.morin.1998@anciens.enib.fr>
Date: Wed, 22 Aug 2012 01:48:17 +0200
Subject: [PATCH 57/96] 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>
---
 libfdt/Makefile.libfdt | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

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


From 45013d86197fea96810a7ae1b920d22b4c887688 Mon Sep 17 00:00:00 2001
From: Stephen Warren <swarren@nvidia.com>
Date: Tue, 7 Aug 2012 22:50:15 -0600
Subject: [PATCH 58/96] 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>
---
 checks.c                    |   8 ++-
 dtc-lexer.l                 |  14 +++++
 dtc-parser.y                |  21 ++++++++
 dtc.h                       |  48 ++++++++++++++++-
 flattree.c                  |   3 ++
 livetree.c                  | 125 +++++++++++++++++++++++++++++++++++++++-----
 tests/run_tests.sh          |   4 ++
 tests/test_tree1.dts        |  37 +------------
 tests/test_tree1_body.dtsi  |  36 +++++++++++++
 tests/test_tree1_delete.dts |  68 ++++++++++++++++++++++++
 10 files changed, 312 insertions(+), 52 deletions(-)
 create mode 100644 tests/test_tree1_body.dtsi
 create mode 100644 tests/test_tree1_delete.dts

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;
+};
-- 
1.8.1.4


From 1ff3d3f8de701ed107e908030b5c1fed9d17125a Mon Sep 17 00:00:00 2001
From: Stephen Warren <swarren@nvidia.com>
Date: Thu, 27 Sep 2012 17:11:04 -0600
Subject: [PATCH 59/96] 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>
---
 dtc-lexer.l                |  5 +++--
 tests/.gitignore           |  1 +
 tests/Makefile.tests       |  2 +-
 tests/propname_escapes.c   | 43 +++++++++++++++++++++++++++++++++++++++++++
 tests/propname_escapes.dts |  6 ++++++
 tests/run_tests.sh         |  3 +++
 6 files changed, 57 insertions(+), 3 deletions(-)
 create mode 100644 tests/propname_escapes.c
 create mode 100644 tests/propname_escapes.dts

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
 
-- 
1.8.1.4


From 1b6d1941dc5b589632c254ee6e960404d7cef5f2 Mon Sep 17 00:00:00 2001
From: Stephen Warren <swarren@nvidia.com>
Date: Thu, 27 Sep 2012 17:11:05 -0600
Subject: [PATCH 60/96] 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>
---
 dtc-lexer.l               | 21 +++++++++++++++++++++
 srcpos.c                  |  6 ++++++
 srcpos.h                  |  2 ++
 tests/line_directives.dts | 11 +++++++++++
 tests/run_tests.sh        |  2 ++
 5 files changed, 42 insertions(+)
 create mode 100644 tests/line_directives.dts

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
 
-- 
1.8.1.4


From 317a5d92bc357aba2c993ee78b4c089b7539fcc6 Mon Sep 17 00:00:00 2001
From: Stephen Warren <swarren@nvidia.com>
Date: Fri, 28 Sep 2012 12:39:22 -0600
Subject: [PATCH 61/96] 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>
---
 livetree.c | 1 +
 1 file changed, 1 insertion(+)

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;
-- 
1.8.1.4


From c6fb1d239191daa3323fb6caeff56d48c4777793 Mon Sep 17 00:00:00 2001
From: Anders Hedlund <anders.hedlund@windriver.com>
Date: Mon, 10 Sep 2012 13:50:56 +0200
Subject: [PATCH 62/96] 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>
---
 libfdt/version.lds | 6 ++++++
 1 file changed, 6 insertions(+)

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:
 		*;
-- 
1.8.1.4


From 1762ab42ef77db7ab2776d0d6cba3515150f518a Mon Sep 17 00:00:00 2001
From: Stephen Warren <swarren@nvidia.com>
Date: Fri, 5 Oct 2012 09:57:41 -0600
Subject: [PATCH 63/96] 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>
---
 dtc.h                                     | 44 +++++++------------------------
 tests/delete_reinstate_multilabel.dts     | 37 ++++++++++++++++++++++++++
 tests/delete_reinstate_multilabel_ref.dts |  9 +++++++
 tests/run_tests.sh                        |  3 +++
 4 files changed, 59 insertions(+), 34 deletions(-)
 create mode 100644 tests/delete_reinstate_multilabel.dts
 create mode 100644 tests/delete_reinstate_multilabel_ref.dts

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
-- 
1.8.1.4


From 8dec4d86ad3f44ef5011f86394d8f3061a09237a Mon Sep 17 00:00:00 2001
From: Michael Ellerman <michael@ellerman.id.au>
Date: Tue, 16 Oct 2012 17:58:56 +1100
Subject: [PATCH 64/96] 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>
---
 srcpos.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

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
-- 
1.8.1.4


From e4b497f367a3b2ae99cc52089a14a221b13a76ef Mon Sep 17 00:00:00 2001
From: Michael Ellerman <michael@ellerman.id.au>
Date: Tue, 16 Oct 2012 18:04:20 +1100
Subject: [PATCH 65/96] 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>
---
 Documentation/manual.txt | 5 +++++
 1 file changed, 5 insertions(+)

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
 
-- 
1.8.1.4


From 94a4799b200451d4037ec9219023becfe8c45ef1 Mon Sep 17 00:00:00 2001
From: Pantelis Antoniou <panto@antoniou-consulting.com>
Date: Fri, 4 Jan 2013 21:12:46 +0200
Subject: [PATCH 66/96] 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>
---
 fdtdump.c | 12 +++++++++++-
 1 file changed, 11 insertions(+), 1 deletion(-)

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


From 1c1efd69545a101d7181fc8e5df2b9a3545a58e8 Mon Sep 17 00:00:00 2001
From: Pantelis Antoniou <panto@antoniou-consulting.com>
Date: Fri, 4 Jan 2013 21:12:58 +0200
Subject: [PATCH 67/96] 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>
---
 util.c | 20 +++++++++++++-------
 1 file changed, 13 insertions(+), 7 deletions(-)

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;
 }
-- 
1.8.1.4


From 38ad79d33946590c862567c7cbdf25b5a46d8149 Mon Sep 17 00:00:00 2001
From: Kim Phillips <kim.phillips@freescale.com>
Date: Tue, 13 Nov 2012 18:34:01 -0600
Subject: [PATCH 68/96] 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>
---
 tests/add_subnode_with_nops.c     | 1 -
 tests/appendprop1.c               | 1 -
 tests/appendprop2.c               | 1 -
 tests/asm_tree_dump.c             | 1 -
 tests/boot-cpuid.c                | 1 -
 tests/char_literal.c              | 1 -
 tests/del_node.c                  | 1 -
 tests/del_property.c              | 1 -
 tests/dtb_reverse.c               | 1 -
 tests/dtbs_equal_ordered.c        | 1 -
 tests/dtbs_equal_unordered.c      | 1 -
 tests/dumptrees.c                 | 2 --
 tests/extra-terminating-null.c    | 1 -
 tests/find_property.c             | 1 -
 tests/get_alias.c                 | 1 -
 tests/get_mem_rsv.c               | 1 -
 tests/get_name.c                  | 1 -
 tests/get_path.c                  | 1 -
 tests/get_phandle.c               | 1 -
 tests/getprop.c                   | 1 -
 tests/incbin.c                    | 1 -
 tests/integer-expressions.c       | 1 -
 tests/mangle-layout.c             | 1 -
 tests/move_and_save.c             | 1 -
 tests/node_check_compatible.c     | 1 -
 tests/node_offset_by_compatible.c | 1 -
 tests/node_offset_by_phandle.c    | 1 -
 tests/node_offset_by_prop_value.c | 1 -
 tests/nop_node.c                  | 1 -
 tests/nop_property.c              | 1 -
 tests/nopulate.c                  | 1 -
 tests/notfound.c                  | 1 -
 tests/open_pack.c                 | 1 -
 tests/parent_offset.c             | 1 -
 tests/path-references.c           | 1 -
 tests/path_offset.c               | 1 -
 tests/path_offset_aliases.c       | 1 -
 tests/phandle_format.c            | 1 -
 tests/propname_escapes.c          | 1 -
 tests/references.c                | 1 -
 tests/root_node.c                 | 1 -
 tests/rw_tree1.c                  | 1 -
 tests/set_name.c                  | 1 -
 tests/setprop.c                   | 1 -
 tests/setprop_inplace.c           | 1 -
 tests/sized_cells.c               | 1 -
 tests/string_escapes.c            | 1 -
 tests/subnode_offset.c            | 1 -
 tests/supernode_atdepth_offset.c  | 1 -
 tests/sw_tree1.c                  | 1 -
 tests/truncated_property.c        | 1 -
 tests/utilfdt_test.c              | 1 -
 tests/value-labels.c              | 1 -
 53 files changed, 54 deletions(-)

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"
-- 
1.8.1.4


From 20b866a7ce1651c4ca3f28cf380df66d9ed35719 Mon Sep 17 00:00:00 2001
From: Kim Phillips <kim.phillips@freescale.com>
Date: Tue, 13 Nov 2012 18:34:09 -0600
Subject: [PATCH 69/96] 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>
---
 fdtdump.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

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"
 
-- 
1.8.1.4


From feafcd972cb744750a65728440c99526e6199a6d Mon Sep 17 00:00:00 2001
From: Kim Phillips <kim.phillips@freescale.com>
Date: Wed, 28 Nov 2012 17:33:01 -0600
Subject: [PATCH 70/96] 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>
---
 libfdt/fdt.h        | 42 +++++++++++++++++++++---------------------
 libfdt/libfdt_env.h | 53 ++++++++++++++++++++++++++++++++++++++++++-----------
 2 files changed, 63 insertions(+), 32 deletions(-)

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 */
-- 
1.8.1.4


From 142419e43c99e88cbe72a760a72cdbf520690eb6 Mon Sep 17 00:00:00 2001
From: Kim Phillips <kim.phillips@freescale.com>
Date: Tue, 13 Nov 2012 18:34:30 -0600
Subject: [PATCH 71/96] 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>
---
 libfdt/fdt.c     |  2 +-
 libfdt/fdt_ro.c  |  2 +-
 libfdt/fdt_rw.c  |  4 ++--
 libfdt/fdt_sw.c  |  4 ++--
 libfdt/fdt_wip.c |  2 +-
 libfdt/libfdt.h  | 32 ++++++++++++++++----------------
 6 files changed, 23 insertions(+), 23 deletions(-)

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));
 }
 
 /**
-- 
1.8.1.4


From 19cd5ead0b692c8c10e286252a7f4a725133d8f4 Mon Sep 17 00:00:00 2001
From: KRONSTORFER Horst <Horst.KRONSTORFER@frequentis.com>
Date: Tue, 11 Dec 2012 21:12:14 +0000
Subject: [PATCH 72/96] 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>
---
 dtc.c | 3 ---
 1 file changed, 3 deletions(-)

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


From 1760e7ca03894689118646e229ca9487158cd0e8 Mon Sep 17 00:00:00 2001
From: Stephen Warren <swarren@nvidia.com>
Date: Tue, 11 Dec 2012 10:05:51 -0700
Subject: [PATCH 73/96] 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>
---
 tests/fdtget-runtest.sh | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

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 "$@"
-- 
1.8.1.4


From 8055d77a5be3a4204b3aa5cd73ce5cc03362e193 Mon Sep 17 00:00:00 2001
From: Simon Glass <sjg@chromium.org>
Date: Sun, 27 Jan 2013 11:13:11 -0800
Subject: [PATCH 74/96] 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>
---
 tests/run_tests.sh | 3 ++-
 util.h             | 8 +++++---
 2 files changed, 7 insertions(+), 4 deletions(-)

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);
 
 /*
-- 
1.8.1.4


From d20391d6ff45c8fa7281e945491817c35f42b51b Mon Sep 17 00:00:00 2001
From: Simon Glass <sjg@chromium.org>
Date: Mon, 21 Jan 2013 12:59:16 -0800
Subject: [PATCH 75/96] 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>
---
 fdtdump.c | 37 +------------------------------------
 util.c    | 37 +++++++++++++++++++++++++++++++++++++
 util.h    | 14 ++++++++++++++
 3 files changed, 52 insertions(+), 36 deletions(-)

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 */
-- 
1.8.1.4


From d59b8078bd79a3ed0cd4bdb9bb92de4475bc1a84 Mon Sep 17 00:00:00 2001
From: Simon Glass <sjg@chromium.org>
Date: Mon, 21 Jan 2013 12:59:17 -0800
Subject: [PATCH 76/96] .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>
---
 .gitignore | 1 +
 1 file changed, 1 insertion(+)

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]
-- 
1.8.1.4


From b7aa300eee001872134345416e73e0f81159798f Mon Sep 17 00:00:00 2001
From: Simon Glass <sjg@chromium.org>
Date: Mon, 21 Jan 2013 12:59:18 -0800
Subject: [PATCH 77/96] 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>
---
 libfdt/fdt_ro.c |  5 ++---
 libfdt/libfdt.h | 14 ++++++++++++++
 2 files changed, 16 insertions(+), 3 deletions(-)

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                                           */
 /**********************************************************************/
-- 
1.8.1.4


From cc11e522a3f50ad3ad289d1313cd0bf0ba491e24 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Fran=C3=A7ois=20Revol?= <revol@free.fr>
Date: Sun, 3 Feb 2013 00:52:21 +0100
Subject: [PATCH 78/96] Fix typo
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Signed-off-by: François Revol <revol@free.fr>
---
 libfdt/libfdt.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

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);
-- 
1.8.1.4


From 27cdc1b16f86f970c3c049795d4e71ad531cca3d Mon Sep 17 00:00:00 2001
From: Justin Sobota <jsobota@ti.com>
Date: Fri, 15 Feb 2013 11:06:10 -0500
Subject: [PATCH 79/96] 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>
---
 libfdt/fdt.h        | 51 +++++++++++++++++++++++++++++++++++++++++++++++++++
 libfdt/libfdt_env.h | 51 +++++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 102 insertions(+)

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>
-- 
1.8.1.4


From f8cb5dd94903a5cfa1609695328b8f1d5557367f Mon Sep 17 00:00:00 2001
From: Mike Frysinger <vapier@gentoo.org>
Date: Wed, 10 Apr 2013 14:29:06 -0400
Subject: [PATCH 80/96] 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>
---
 util.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

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;
-- 
1.8.1.4


From cc2c178727cdeca4eb9756637c2e09e50e0856e7 Mon Sep 17 00:00:00 2001
From: Mike Frysinger <vapier@gentoo.org>
Date: Wed, 10 Apr 2013 14:29:07 -0400
Subject: [PATCH 81/96] 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>
---
 fdtget.c          | 2 +-
 fdtput.c          | 2 +-
 tests/testutils.c | 2 +-
 util.c            | 8 +++++---
 util.h            | 6 ++++--
 5 files changed, 12 insertions(+), 8 deletions(-)

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);
 
 
 /**
-- 
1.8.1.4


From 97c122eacc8636b26992cf6e080775f7c28660f9 Mon Sep 17 00:00:00 2001
From: Mike Frysinger <vapier@gentoo.org>
Date: Wed, 10 Apr 2013 14:29:08 -0400
Subject: [PATCH 82/96] 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>
---
 util.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

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;
 
-- 
1.8.1.4


From 31be4ce7ca550a6fd9c4eb39abdd2f9f5ac8db44 Mon Sep 17 00:00:00 2001
From: Mike Frysinger <vapier@gentoo.org>
Date: Wed, 10 Apr 2013 14:29:09 -0400
Subject: [PATCH 83/96] 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>
---
 dtc.c  | 5 +----
 util.c | 7 +++++++
 util.h | 5 +++++
 3 files changed, 13 insertions(+), 4 deletions(-)

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 */
-- 
1.8.1.4


From 5543b88d5e3047b781552eb431bc2e3bdd9ade06 Mon Sep 17 00:00:00 2001
From: Jon Loeliger <jdl@jdl.com>
Date: Mon, 22 Apr 2013 15:41:41 -0500
Subject: [PATCH 84/96] Revert "utilfdt_read: pass back up the length of data
 read"

This reverts commit cc2c178727cdeca4eb9756637c2e09e50e0856e7.
It was the wrong version of the patch.
---
 fdtget.c          | 2 +-
 fdtput.c          | 2 +-
 tests/testutils.c | 2 +-
 util.c            | 8 +++-----
 util.h            | 6 ++----
 5 files changed, 8 insertions(+), 12 deletions(-)

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);
 
 
 /**
-- 
1.8.1.4


From a6d55e039fd22048687fe061b4609e2807efe764 Mon Sep 17 00:00:00 2001
From: Mike Frysinger <vapier@gentoo.org>
Date: Mon, 8 Apr 2013 00:56:54 -0400
Subject: [PATCH 85/96] 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>
---
 util.c | 19 ++++++++++++++++---
 util.h | 13 +++++++++++++
 2 files changed, 29 insertions(+), 3 deletions(-)

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
-- 
1.8.1.4


From 4e76ec796c90d44d417f82d9db2d67cfe575f8ed Mon Sep 17 00:00:00 2001
From: Simon Glass <sjg@chromium.org>
Date: Fri, 26 Apr 2013 05:43:31 -0700
Subject: [PATCH 86/96] 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>
---
 libfdt/fdt.c              | 28 ++++++++++++++
 libfdt/libfdt.h           | 22 +++++++++++
 tests/Makefile.tests      |  3 +-
 tests/run_tests.sh        |  3 ++
 tests/subnode_iterate.c   | 94 +++++++++++++++++++++++++++++++++++++++++++++++
 tests/subnode_iterate.dts | 44 ++++++++++++++++++++++
 6 files changed, 193 insertions(+), 1 deletion(-)
 create mode 100644 tests/subnode_iterate.c
 create mode 100644 tests/subnode_iterate.dts

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>;
+	};
+};
+
-- 
1.8.1.4


From be8d1c82cb0a9caeb7e2f804f9a9f845063d7d53 Mon Sep 17 00:00:00 2001
From: Mike Frysinger <vapier@gentoo.org>
Date: Mon, 15 Apr 2013 22:13:12 -0400
Subject: [PATCH 87/96] fdtdump: make usage a bit more friendly

This starts a new usage framework and then cuts fdtdump over to it.
Now we can do `fdtdump -h` and get something useful back.

Signed-off-by: Mike Frysinger <vapier@gentoo.org>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
---
 fdtdump.c | 31 +++++++++++++++++++++++--------
 util.c    | 54 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
 util.h    | 61 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 138 insertions(+), 8 deletions(-)

diff --git a/fdtdump.c b/fdtdump.c
index 03ea429..a6e522c 100644
--- a/fdtdump.c
+++ b/fdtdump.c
@@ -117,21 +117,36 @@ static void dump_blob(void *blob)
 	}
 }
 
+/* Usage related data. */
+static const char usage_synopsis[] = "fdtdump [options] <file>";
+static const char usage_short_opts[] = USAGE_COMMON_SHORT_OPTS;
+static struct option const usage_long_opts[] = {
+	USAGE_COMMON_LONG_OPTS
+};
+static const char * const usage_opts_help[] = {
+	USAGE_COMMON_OPTS_HELP
+};
 
 int main(int argc, char *argv[])
 {
+	int opt;
+	const char *file;
 	char *buf;
 
-	if (argc < 2) {
-		fprintf(stderr, "supply input filename\n");
-		return 5;
+	while ((opt = util_getopt_long()) != EOF) {
+		switch (opt) {
+		case_USAGE_COMMON_FLAGS
+		}
 	}
+	if (optind != argc - 1)
+		long_usage("missing input filename");
+	file = argv[optind];
+
+	buf = utilfdt_read(file);
+	if (!buf)
+		die("could not read: %s\n", file);
 
-	buf = utilfdt_read(argv[1]);
-	if (buf)
-		dump_blob(buf);
-	else
-		return 10;
+	dump_blob(buf);
 
 	return 0;
 }
diff --git a/util.c b/util.c
index 350cf8b..d9a823a 100644
--- a/util.c
+++ b/util.c
@@ -392,3 +392,57 @@ void util_version(void)
 	printf("Version: %s\n", DTC_VERSION);
 	exit(0);
 }
+
+void util_long_usage(const char *errmsg, const char *synopsis,
+		     const char *short_opts, struct option const long_opts[],
+		     const char * const opts_help[])
+{
+	FILE *fp = errmsg ? stderr : stdout;
+	const char a_arg[] = "<arg>";
+	size_t a_arg_len = strlen(a_arg) + 1;
+	size_t i;
+	int optlen;
+
+	fprintf(fp,
+		"Usage: %s\n"
+		"\n"
+		"Options: -[%s]\n", synopsis, short_opts);
+
+	/* prescan the --long opt length to auto-align */
+	optlen = 0;
+	for (i = 0; long_opts[i].name; ++i) {
+		/* +1 is for space between --opt and help text */
+		int l = strlen(long_opts[i].name) + 1;
+		if (long_opts[i].has_arg == a_argument)
+			l += a_arg_len;
+		if (optlen < l)
+			optlen = l;
+	}
+
+	for (i = 0; long_opts[i].name; ++i) {
+		/* helps when adding new applets or options */
+		assert(opts_help[i] != NULL);
+
+		/* first output the short flag if it has one */
+		if (long_opts[i].val > '~')
+			fprintf(fp, "      ");
+		else
+			fprintf(fp, "  -%c, ", long_opts[i].val);
+
+		/* then the long flag */
+		if (long_opts[i].has_arg == no_argument)
+			fprintf(fp, "--%-*s", optlen, long_opts[i].name);
+		else
+			fprintf(fp, "--%s %s%*s", long_opts[i].name, a_arg,
+				(int)(optlen - strlen(long_opts[i].name) - a_arg_len), "");
+
+		/* finally the help text */
+		fprintf(fp, "%s\n", opts_help[i]);
+	}
+
+	if (errmsg) {
+		fprintf(fp, "\nError: %s\n", errmsg);
+		exit(EXIT_FAILURE);
+	} else
+		exit(EXIT_SUCCESS);
+}
diff --git a/util.h b/util.h
index 95ae531..1da3bd3 100644
--- a/util.h
+++ b/util.h
@@ -2,6 +2,7 @@
 #define _UTIL_H
 
 #include <stdarg.h>
+#include <getopt.h>
 
 /*
  * Copyright 2011 The Chromium Authors, All Rights Reserved.
@@ -184,4 +185,64 @@ void utilfdt_print_data(const char *data, int len);
  */
 void util_version(void) __attribute__((noreturn));
 
+/**
+ * Show usage and exit
+ *
+ * This helps standardize the output of various utils.  You most likely want
+ * to use the long_usage() helper below rather than call this.
+ *
+ * @param errmsg	If non-NULL, an error message to display
+ * @param synopsis	The initial example usage text (and possible examples)
+ * @param short_opts	The string of short options
+ * @param long_opts	The structure of long options
+ * @param opts_help	An array of help strings (should align with long_opts)
+ */
+void util_long_usage(const char *errmsg, const char *synopsis,
+		     const char *short_opts, struct option const long_opts[],
+		     const char * const opts_help[]) __attribute__((noreturn));
+
+/**
+ * Show usage and exit
+ *
+ * If you name all your usage variables with usage_xxx, then you can call this
+ * help macro rather than expanding all arguments yourself.
+ *
+ * @param errmsg	If non-NULL, an error message to display
+ */
+#define long_usage(errmsg) \
+	util_long_usage(errmsg, usage_synopsis, usage_short_opts, \
+			usage_long_opts, usage_opts_help)
+
+/**
+ * Call getopt_long() with standard options
+ *
+ * Since all util code runs getopt in the same way, provide a helper.
+ */
+#define util_getopt_long() getopt_long(argc, argv, usage_short_opts, \
+				       usage_long_opts, NULL)
+
+/* Helper for aligning long_opts array */
+#define a_argument required_argument
+
+/* Helper for usage_short_opts string constant */
+#define USAGE_COMMON_SHORT_OPTS "hV"
+
+/* Helper for usage_long_opts option array */
+#define USAGE_COMMON_LONG_OPTS \
+	{"help",      no_argument, NULL, 'h'}, \
+	{"version",   no_argument, NULL, 'V'}, \
+	{NULL,        no_argument, NULL, 0x0}
+
+/* Helper for usage_opts_help array */
+#define USAGE_COMMON_OPTS_HELP \
+	"Print this help and exit", \
+	"Print version and exit", \
+	NULL
+
+/* Helper for getopt case statements */
+#define case_USAGE_COMMON_FLAGS \
+	case 'h': long_usage(NULL); \
+	case 'V': util_version(); \
+	case '?': long_usage("unknown option");
+
 #endif /* _UTIL_H */
-- 
1.8.1.4


From fdc7387845420168ee5dd479fbe4391ff93bddab Mon Sep 17 00:00:00 2001
From: Mike Frysinger <vapier@gentoo.org>
Date: Mon, 15 Apr 2013 22:13:13 -0400
Subject: [PATCH 88/96] fdtdump: add a --scan option

Often times, fdts get embedded in other larger files.  Rather than force
people to `dd` the blob out themselves, make the fdtdump file smarter.

It can now scan the blob looking for the fdt magic.  Once locate, it does
a little validation on the main struct to make sure we didn't hit random
binary data.

Signed-off-by: Mike Frysinger <vapier@gentoo.org>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
---
 fdtdump.c | 46 ++++++++++++++++++++++++++++++++++++++++++++--
 1 file changed, 44 insertions(+), 2 deletions(-)

diff --git a/fdtdump.c b/fdtdump.c
index a6e522c..c8a3ee7 100644
--- a/fdtdump.c
+++ b/fdtdump.c
@@ -2,12 +2,14 @@
  * fdtdump.c - Contributed by Pantelis Antoniou <pantelis.antoniou AT gmail.com>
  */
 
+#include <stdbool.h>
 #include <stdint.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 #include <ctype.h>
 
+#include <libfdt.h>
 #include <libfdt_env.h>
 #include <fdt.h>
 
@@ -119,11 +121,13 @@ static void dump_blob(void *blob)
 
 /* Usage related data. */
 static const char usage_synopsis[] = "fdtdump [options] <file>";
-static const char usage_short_opts[] = USAGE_COMMON_SHORT_OPTS;
+static const char usage_short_opts[] = "s" USAGE_COMMON_SHORT_OPTS;
 static struct option const usage_long_opts[] = {
+	{"scan",             no_argument, NULL, 's'},
 	USAGE_COMMON_LONG_OPTS
 };
 static const char * const usage_opts_help[] = {
+	"Scan for an embedded fdt in file",
 	USAGE_COMMON_OPTS_HELP
 };
 
@@ -132,20 +136,58 @@ int main(int argc, char *argv[])
 	int opt;
 	const char *file;
 	char *buf;
+	bool scan = false;
+	off_t len;
 
 	while ((opt = util_getopt_long()) != EOF) {
 		switch (opt) {
 		case_USAGE_COMMON_FLAGS
+
+		case 's':
+			scan = true;
+			break;
 		}
 	}
 	if (optind != argc - 1)
 		long_usage("missing input filename");
 	file = argv[optind];
 
-	buf = utilfdt_read(file);
+	buf = utilfdt_read_len(file, &len);
 	if (!buf)
 		die("could not read: %s\n", file);
 
+	/* try and locate an embedded fdt in a bigger blob */
+	if (scan) {
+		unsigned char smagic[4];
+		char *p = buf;
+		char *endp = buf + len;
+
+		fdt_set_magic(smagic, FDT_MAGIC);
+
+		/* poor man's memmem */
+		while (true) {
+			p = memchr(p, smagic[0], endp - p - 4);
+			if (!p)
+				break;
+			if (fdt_magic(p) == FDT_MAGIC) {
+				/* try and validate the main struct */
+				off_t this_len = endp - p;
+				fdt32_t max_version = 17;
+				if (fdt_version(p) <= max_version &&
+				    fdt_last_comp_version(p) < max_version &&
+				    fdt_totalsize(p) < this_len &&
+				    fdt_off_dt_struct(p) < this_len &&
+					fdt_off_dt_strings(p) < this_len)
+					break;
+			}
+			++p;
+		}
+		if (!p)
+			die("%s: could not locate fdt magic\n", file);
+		printf("%s: found fdt at offset %#zx\n", file, p - buf);
+		buf = p;
+	}
+
 	dump_blob(buf);
 
 	return 0;
-- 
1.8.1.4


From 03449b84c8f9aee2bf2f438bec2c2ec4606bea48 Mon Sep 17 00:00:00 2001
From: Mike Frysinger <vapier@gentoo.org>
Date: Fri, 24 May 2013 18:02:35 +1000
Subject: [PATCH 89/96] dtc/fdt{get, put}/convert-dtsv0-lexer: convert to new
 usage helpers

This helps standardize the flag processing and the usage screens.

Only lightly tested; would be great if someone who uses these utils
could double check.

Signed-off-by: Mike Frysinger <vapier@gentoo.org>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
---
 convert-dtsv0-lexer.l |  22 +++++++---
 dtc.c                 | 111 ++++++++++++++++++++++++++------------------------
 fdtget.c              |  60 ++++++++++++---------------
 fdtput.c              |  63 +++++++++++++---------------
 util.h                |   2 +-
 5 files changed, 131 insertions(+), 127 deletions(-)

diff --git a/convert-dtsv0-lexer.l b/convert-dtsv0-lexer.l
index 89d540a..e62d27a 100644
--- a/convert-dtsv0-lexer.l
+++ b/convert-dtsv0-lexer.l
@@ -194,11 +194,15 @@ const struct {
 		}
 
 %%
-static void usage(void)
-{
-	fprintf(stderr, "convert-dtsv0 <v0 dts file>...\n");
-	exit(3);
-}
+/* Usage related data. */
+static const char usage_synopsis[] = "convert-dtsv0 [options] <v0 dts file>...";
+static const char usage_short_opts[] = "" USAGE_COMMON_SHORT_OPTS;
+static struct option const usage_long_opts[] = {
+	USAGE_COMMON_LONG_OPTS
+};
+static const char * const usage_opts_help[] = {
+	USAGE_COMMON_OPTS_HELP
+};
 
 static void convert_file(const char *fname)
 {
@@ -226,10 +230,16 @@ static void convert_file(const char *fname)
 
 int main(int argc, char *argv[])
 {
+	int opt;
 	int i;
 
+	while ((opt = util_getopt_long()) != EOF) {
+		switch (opt) {
+		case_USAGE_COMMON_FLAGS
+		}
+	}
 	if (argc < 2)
-		usage();
+		long_usage("missing filename");
 
 	for (i = 1; i < argc; i++) {
 		fprintf(stderr, "Converting %s from dts v0 to dts v1\n", argv[i]);
diff --git a/dtc.c b/dtc.c
index e4e1b84..d0a1f2d 100644
--- a/dtc.c
+++ b/dtc.c
@@ -47,55 +47,60 @@ static void fill_fullpaths(struct node *tree, const char *prefix)
 		fill_fullpaths(child, tree->fullpath);
 }
 
-static void  __attribute__ ((noreturn)) usage(void)
-{
-	fprintf(stderr, "Usage:\n");
-	fprintf(stderr, "\tdtc [options] <input file>\n");
-	fprintf(stderr, "\nOptions:\n");
-	fprintf(stderr, "\t-h\n");
-	fprintf(stderr, "\t\tThis help text\n");
-	fprintf(stderr, "\t-q\n");
-	fprintf(stderr, "\t\tQuiet: -q suppress warnings, -qq errors, -qqq all\n");
-	fprintf(stderr, "\t-I <input format>\n");
-	fprintf(stderr, "\t\tInput formats are:\n");
-	fprintf(stderr, "\t\t\tdts - device tree source text\n");
-	fprintf(stderr, "\t\t\tdtb - device tree blob\n");
-	fprintf(stderr, "\t\t\tfs - /proc/device-tree style directory\n");
-	fprintf(stderr, "\t-o <output file>\n");
-	fprintf(stderr, "\t-O <output format>\n");
-	fprintf(stderr, "\t\tOutput formats are:\n");
-	fprintf(stderr, "\t\t\tdts - device tree source text\n");
-	fprintf(stderr, "\t\t\tdtb - device tree blob\n");
-	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");
-	fprintf(stderr, "\t\tMake the blob at least <bytes> long (extra space)\n");
-	fprintf(stderr, "\t-p <bytes>\n");
-	fprintf(stderr, "\t\tAdd padding to the blob of <bytes> long (extra space)\n");
-	fprintf(stderr, "\t-b <number>\n");
-	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");
-	fprintf(stderr, "\t\tPrint DTC version and exit\n");
-	fprintf(stderr, "\t-H <phandle format>\n");
-	fprintf(stderr, "\t\tphandle formats are:\n");
-	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);
-}
+/* Usage related data. */
+static const char usage_synopsis[] = "dtc [options] <input file>";
+static const char usage_short_opts[] = "qI:O:o:V:d:R:S:p:fb:i:H:sW:E:hv";
+static struct option const usage_long_opts[] = {
+	{"quiet",            no_argument, NULL, 'q'},
+	{"in-format",         a_argument, NULL, 'I'},
+	{"out",               a_argument, NULL, 'o'},
+	{"out-format",        a_argument, NULL, 'O'},
+	{"out-version",       a_argument, NULL, 'V'},
+	{"out-dependency",    a_argument, NULL, 'd'},
+	{"reserve",           a_argument, NULL, 'R'},
+	{"space",             a_argument, NULL, 'S'},
+	{"pad",               a_argument, NULL, 'p'},
+	{"boot-cpu",          a_argument, NULL, 'b'},
+	{"force",            no_argument, NULL, 'f'},
+	{"include",           a_argument, NULL, 'i'},
+	{"sort",             no_argument, NULL, 's'},
+	{"phandle",           a_argument, NULL, 'H'},
+	{"warning",           a_argument, NULL, 'W'},
+	{"error",             a_argument, NULL, 'E'},
+	{"help",             no_argument, NULL, 'h'},
+	{"version",          no_argument, NULL, 'v'},
+	{NULL,               no_argument, NULL, 0x0},
+};
+static const char * const usage_opts_help[] = {
+	"\n\tQuiet: -q suppress warnings, -qq errors, -qqq all",
+	"\n\tInput formats are:\n"
+	 "\t\tdts - device tree source text\n"
+	 "\t\tdtb - device tree blob\n"
+	 "\t\tfs  - /proc/device-tree style directory",
+	"\n\tOutput file",
+	"\n\tOutput formats are:\n"
+	 "\t\tdts - device tree source text\n"
+	 "\t\tdtb - device tree blob\n"
+	 "\t\tasm - assembler source",
+	"\n\tBlob version to produce, defaults to %d (for dtb and asm output)", //, DEFAULT_FDT_VERSION);
+	"\n\tOutput dependency file",
+	"\n\ttMake space for <number> reserve map entries (for dtb and asm output)",
+	"\n\tMake the blob at least <bytes> long (extra space)",
+	"\n\tAdd padding to the blob of <bytes> long (extra space)",
+	"\n\tSet the physical boot cpu",
+	"\n\tTry to produce output even if the input tree has errors",
+	"\n\tAdd a path to search for include files",
+	"\n\tSort nodes and properties before outputting (useful for comparing trees)",
+	"\n\tValid phandle formats are:\n"
+	 "\t\tlegacy - \"linux,phandle\" properties only\n"
+	 "\t\tepapr  - \"phandle\" properties only\n"
+	 "\t\tboth   - Both \"linux,phandle\" and \"phandle\" properties",
+	"\n\tEnable/disable warnings (prefix with \"no-\")",
+	"\n\tEnable/disable errors (prefix with \"no-\")",
+	"\n\tPrint this help and exit",
+	"\n\tPrint version and exit",
+	NULL,
+};
 
 int main(int argc, char *argv[])
 {
@@ -116,8 +121,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:sW:E:"))
-			!= EOF) {
+	while ((opt = util_getopt_long()) != EOF) {
 		switch (opt) {
 		case 'I':
 			inform = optarg;
@@ -182,13 +186,14 @@ int main(int argc, char *argv[])
 			break;
 
 		case 'h':
+			long_usage(NULL);
 		default:
-			usage();
+			long_usage("unknown option");
 		}
 	}
 
 	if (argc > (optind+1))
-		usage();
+		long_usage("missing files");
 	else if (argc < (optind+1))
 		arg = "-";
 	else
diff --git a/fdtget.c b/fdtget.c
index c2fbab2..5008cc1 100644
--- a/fdtget.c
+++ b/fdtget.c
@@ -277,33 +277,33 @@ static int do_fdtget(struct display_info *disp, const char *filename,
 	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"
+/* Usage related data. */
+static const char usage_synopsis[] =
+	"read values from device tree\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-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"
+	"\n"
+	"Each value is printed on a new line.\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);
-}
+static const char usage_short_opts[] = "t:pld:" USAGE_COMMON_SHORT_OPTS;
+static struct option const usage_long_opts[] = {
+	{"type",              a_argument, NULL, 't'},
+	{"properties",       no_argument, NULL, 'p'},
+	{"list",             no_argument, NULL, 'l'},
+	{"default",           a_argument, NULL, 'd'},
+	USAGE_COMMON_LONG_OPTS,
+};
+static const char * const usage_opts_help[] = {
+	"Type of data",
+	"List properties for each node",
+	"List subnodes for each node",
+	"Default value to display when the property is missing",
+	USAGE_COMMON_OPTS_HELP
+};
 
 int main(int argc, char *argv[])
 {
+	int opt;
 	char *filename = NULL;
 	struct display_info disp;
 	int args_per_step = 2;
@@ -312,20 +312,14 @@ int main(int argc, char *argv[])
 	memset(&disp, '\0', sizeof(disp));
 	disp.size = -1;
 	disp.mode = MODE_SHOW_VALUE;
-	for (;;) {
-		int c = getopt(argc, argv, "d:hlpt:");
-		if (c == -1)
-			break;
-
-		switch (c) {
-		case 'h':
-		case '?':
-			usage(NULL);
+	while ((opt = util_getopt_long()) != EOF) {
+		switch (opt) {
+		case_USAGE_COMMON_FLAGS
 
 		case 't':
 			if (utilfdt_decode_type(optarg, &disp.type,
 					&disp.size))
-				usage("Invalid type string");
+				long_usage("invalid type string");
 			break;
 
 		case 'p':
@@ -347,7 +341,7 @@ int main(int argc, char *argv[])
 	if (optind < argc)
 		filename = argv[optind++];
 	if (!filename)
-		usage("Missing filename");
+		long_usage("missing filename");
 
 	argv += optind;
 	argc -= optind;
@@ -358,7 +352,7 @@ int main(int argc, char *argv[])
 
 	/* Check for node, property arguments */
 	if (args_per_step == 2 && (argc % 2))
-		usage("Must have an even number of arguments");
+		long_usage("must have an even number of arguments");
 
 	if (do_fdtget(&disp, filename, argv, argc, args_per_step))
 		return 1;
diff --git a/fdtput.c b/fdtput.c
index f2197f5..99eb05c 100644
--- a/fdtput.c
+++ b/fdtput.c
@@ -272,44 +272,40 @@ static int do_fdtput(struct display_info *disp, const char *filename,
 	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"
+/* Usage related data. */
+static const char usage_synopsis[] =
+	"write a property value to a device tree\n"
 	"	fdtput <options> <dt file> <node> <property> [<value>...]\n"
 	"	fdtput -c <options> <dt file> [<node>...]\n"
-	"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"
+	"\n"
+	"The command line arguments are joined together into a single value.\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);
-}
+static const char usage_short_opts[] = "cpt:v" USAGE_COMMON_SHORT_OPTS;
+static struct option const usage_long_opts[] = {
+	{"create",           no_argument, NULL, 'c'},
+	{"auto-path",        no_argument, NULL, 'p'},
+	{"type",              a_argument, NULL, 't'},
+	{"verbose",          no_argument, NULL, 'v'},
+	USAGE_COMMON_LONG_OPTS,
+};
+static const char * const usage_opts_help[] = {
+	"Create nodes if they don't already exist",
+	"Automatically create nodes as needed for the node path",
+	"Type of data",
+	"Display each value decoded from command line",
+	USAGE_COMMON_OPTS_HELP
+};
 
 int main(int argc, char *argv[])
 {
+	int opt;
 	struct display_info disp;
 	char *filename = NULL;
 
 	memset(&disp, '\0', sizeof(disp));
 	disp.size = -1;
 	disp.oper = OPER_WRITE_PROP;
-	for (;;) {
-		int c = getopt(argc, argv, "chpt:v");
-		if (c == -1)
-			break;
-
+	while ((opt = util_getopt_long()) != EOF) {
 		/*
 		 * TODO: add options to:
 		 * - delete property
@@ -319,20 +315,19 @@ int main(int argc, char *argv[])
 		 * - set amount of free space when writing
 		 * - expand fdt if value doesn't fit
 		 */
-		switch (c) {
+		switch (opt) {
+		case_USAGE_COMMON_FLAGS
+
 		case 'c':
 			disp.oper = OPER_CREATE_NODE;
 			break;
-		case 'h':
-		case '?':
-			usage(NULL);
 		case 'p':
 			disp.auto_path = 1;
 			break;
 		case 't':
 			if (utilfdt_decode_type(optarg, &disp.type,
 					&disp.size))
-				usage("Invalid type string");
+				long_usage("Invalid type string");
 			break;
 
 		case 'v':
@@ -344,16 +339,16 @@ int main(int argc, char *argv[])
 	if (optind < argc)
 		filename = argv[optind++];
 	if (!filename)
-		usage("Missing filename");
+		long_usage("missing filename");
 
 	argv += optind;
 	argc -= optind;
 
 	if (disp.oper == OPER_WRITE_PROP) {
 		if (argc < 1)
-			usage("Missing node");
+			long_usage("missing node");
 		if (argc < 2)
-			usage("Missing property");
+			long_usage("missing property");
 	}
 
 	if (do_fdtput(&disp, filename, argv, argc))
diff --git a/util.h b/util.h
index 1da3bd3..439b2b3 100644
--- a/util.h
+++ b/util.h
@@ -164,7 +164,7 @@ int utilfdt_decode_type(const char *fmt, int *type, int *size);
 #define USAGE_TYPE_MSG \
 	"<type>\ts=string, i=int, u=unsigned, x=hex\n" \
 	"\tOptional modifier prefix:\n" \
-	"\t\thh or b=byte, h=2 byte, l=4 byte (default)\n";
+	"\t\thh or b=byte, h=2 byte, l=4 byte (default)";
 
 /**
  * Print property data in a readable format to stdout
-- 
1.8.1.4


From b9e80656f2de441826ed2ff1cd9c5d43b3ae43d3 Mon Sep 17 00:00:00 2001
From: Mike Frysinger <vapier@gentoo.org>
Date: Fri, 24 May 2013 18:04:43 +1000
Subject: [PATCH 90/96] util: drop "long" from usage helpers

Now that all utils have converted to the new usage framework, we can
rename to just plain "usage()" and avoid naming conflicts.

Signed-off-by: Mike Frysinger <vapier@gentoo.org>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
---
 convert-dtsv0-lexer.l |  2 +-
 dtc.c                 |  6 +++---
 fdtdump.c             |  2 +-
 fdtget.c              |  6 +++---
 fdtput.c              |  8 ++++----
 util.c                |  6 +++---
 util.h                | 18 +++++++++---------
 7 files changed, 24 insertions(+), 24 deletions(-)

diff --git a/convert-dtsv0-lexer.l b/convert-dtsv0-lexer.l
index e62d27a..8902648 100644
--- a/convert-dtsv0-lexer.l
+++ b/convert-dtsv0-lexer.l
@@ -239,7 +239,7 @@ int main(int argc, char *argv[])
 		}
 	}
 	if (argc < 2)
-		long_usage("missing filename");
+		usage("missing filename");
 
 	for (i = 1; i < argc; i++) {
 		fprintf(stderr, "Converting %s from dts v0 to dts v1\n", argv[i]);
diff --git a/dtc.c b/dtc.c
index d0a1f2d..e3c9653 100644
--- a/dtc.c
+++ b/dtc.c
@@ -186,14 +186,14 @@ int main(int argc, char *argv[])
 			break;
 
 		case 'h':
-			long_usage(NULL);
+			usage(NULL);
 		default:
-			long_usage("unknown option");
+			usage("unknown option");
 		}
 	}
 
 	if (argc > (optind+1))
-		long_usage("missing files");
+		usage("missing files");
 	else if (argc < (optind+1))
 		arg = "-";
 	else
diff --git a/fdtdump.c b/fdtdump.c
index c8a3ee7..c2f16ea 100644
--- a/fdtdump.c
+++ b/fdtdump.c
@@ -149,7 +149,7 @@ int main(int argc, char *argv[])
 		}
 	}
 	if (optind != argc - 1)
-		long_usage("missing input filename");
+		usage("missing input filename");
 	file = argv[optind];
 
 	buf = utilfdt_read_len(file, &len);
diff --git a/fdtget.c b/fdtget.c
index 5008cc1..4377419 100644
--- a/fdtget.c
+++ b/fdtget.c
@@ -319,7 +319,7 @@ int main(int argc, char *argv[])
 		case 't':
 			if (utilfdt_decode_type(optarg, &disp.type,
 					&disp.size))
-				long_usage("invalid type string");
+				usage("invalid type string");
 			break;
 
 		case 'p':
@@ -341,7 +341,7 @@ int main(int argc, char *argv[])
 	if (optind < argc)
 		filename = argv[optind++];
 	if (!filename)
-		long_usage("missing filename");
+		usage("missing filename");
 
 	argv += optind;
 	argc -= optind;
@@ -352,7 +352,7 @@ int main(int argc, char *argv[])
 
 	/* Check for node, property arguments */
 	if (args_per_step == 2 && (argc % 2))
-		long_usage("must have an even number of arguments");
+		usage("must have an even number of arguments");
 
 	if (do_fdtget(&disp, filename, argv, argc, args_per_step))
 		return 1;
diff --git a/fdtput.c b/fdtput.c
index 99eb05c..fbb283a 100644
--- a/fdtput.c
+++ b/fdtput.c
@@ -327,7 +327,7 @@ int main(int argc, char *argv[])
 		case 't':
 			if (utilfdt_decode_type(optarg, &disp.type,
 					&disp.size))
-				long_usage("Invalid type string");
+				usage("Invalid type string");
 			break;
 
 		case 'v':
@@ -339,16 +339,16 @@ int main(int argc, char *argv[])
 	if (optind < argc)
 		filename = argv[optind++];
 	if (!filename)
-		long_usage("missing filename");
+		usage("missing filename");
 
 	argv += optind;
 	argc -= optind;
 
 	if (disp.oper == OPER_WRITE_PROP) {
 		if (argc < 1)
-			long_usage("missing node");
+			usage("missing node");
 		if (argc < 2)
-			long_usage("missing property");
+			usage("missing property");
 	}
 
 	if (do_fdtput(&disp, filename, argv, argc))
diff --git a/util.c b/util.c
index d9a823a..3055c16 100644
--- a/util.c
+++ b/util.c
@@ -393,9 +393,9 @@ void util_version(void)
 	exit(0);
 }
 
-void util_long_usage(const char *errmsg, const char *synopsis,
-		     const char *short_opts, struct option const long_opts[],
-		     const char * const opts_help[])
+void util_usage(const char *errmsg, const char *synopsis,
+		const char *short_opts, struct option const long_opts[],
+		const char * const opts_help[])
 {
 	FILE *fp = errmsg ? stderr : stdout;
 	const char a_arg[] = "<arg>";
diff --git a/util.h b/util.h
index 439b2b3..7b9a840 100644
--- a/util.h
+++ b/util.h
@@ -189,7 +189,7 @@ void util_version(void) __attribute__((noreturn));
  * Show usage and exit
  *
  * This helps standardize the output of various utils.  You most likely want
- * to use the long_usage() helper below rather than call this.
+ * to use the usage() helper below rather than call this.
  *
  * @param errmsg	If non-NULL, an error message to display
  * @param synopsis	The initial example usage text (and possible examples)
@@ -197,9 +197,9 @@ void util_version(void) __attribute__((noreturn));
  * @param long_opts	The structure of long options
  * @param opts_help	An array of help strings (should align with long_opts)
  */
-void util_long_usage(const char *errmsg, const char *synopsis,
-		     const char *short_opts, struct option const long_opts[],
-		     const char * const opts_help[]) __attribute__((noreturn));
+void util_usage(const char *errmsg, const char *synopsis,
+		const char *short_opts, struct option const long_opts[],
+		const char * const opts_help[]) __attribute__((noreturn));
 
 /**
  * Show usage and exit
@@ -209,9 +209,9 @@ void util_long_usage(const char *errmsg, const char *synopsis,
  *
  * @param errmsg	If non-NULL, an error message to display
  */
-#define long_usage(errmsg) \
-	util_long_usage(errmsg, usage_synopsis, usage_short_opts, \
-			usage_long_opts, usage_opts_help)
+#define usage(errmsg) \
+	util_usage(errmsg, usage_synopsis, usage_short_opts, \
+		   usage_long_opts, usage_opts_help)
 
 /**
  * Call getopt_long() with standard options
@@ -241,8 +241,8 @@ void util_long_usage(const char *errmsg, const char *synopsis,
 
 /* Helper for getopt case statements */
 #define case_USAGE_COMMON_FLAGS \
-	case 'h': long_usage(NULL); \
+	case 'h': usage(NULL); \
 	case 'V': util_version(); \
-	case '?': long_usage("unknown option");
+	case '?': usage("unknown option");
 
 #endif /* _UTIL_H */
-- 
1.8.1.4


From 4ad49c3a9cdaccac02cd448c2704ea52ad85d1dc Mon Sep 17 00:00:00 2001
From: Mike Frysinger <vapier@gentoo.org>
Date: Mon, 15 Apr 2013 22:13:16 -0400
Subject: [PATCH 91/96] util: add common ARRAY_SIZE define

I want to use this in more places, so put it in util.h rather than
copying & pasting it into another file.

Signed-off-by: Mike Frysinger <vapier@gentoo.org>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
---
 convert-dtsv0-lexer.l | 2 --
 dtc.h                 | 1 -
 util.h                | 2 ++
 3 files changed, 2 insertions(+), 3 deletions(-)

diff --git a/convert-dtsv0-lexer.l b/convert-dtsv0-lexer.l
index 8902648..548e719 100644
--- a/convert-dtsv0-lexer.l
+++ b/convert-dtsv0-lexer.l
@@ -50,8 +50,6 @@ static int saw_hyphen; /* = 0 */
 static unsigned long long last_val;
 static char *last_name; /* = NULL */
 
-#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
-
 const struct {
 	const char *pattern;
 	int obase, width;
diff --git a/dtc.h b/dtc.h
index 3e42a07..264a20c 100644
--- a/dtc.h
+++ b/dtc.h
@@ -66,7 +66,6 @@ typedef uint32_t cell_t;
 #define strneq(a, b, n)	(strncmp((a), (b), (n)) == 0)
 
 #define ALIGN(x, a)	(((x) + (a) - 1) & ~((a) - 1))
-#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
 
 /* Data blobs */
 enum markertype {
diff --git a/util.h b/util.h
index 7b9a840..8f40b44 100644
--- a/util.h
+++ b/util.h
@@ -24,6 +24,8 @@
  *                                                                   USA
  */
 
+#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
+
 static inline void __attribute__((noreturn)) die(const char *str, ...)
 {
 	va_list ap;
-- 
1.8.1.4


From 8ec013ae635f36f0a51a21f8b38e3a2669e3b74e Mon Sep 17 00:00:00 2001
From: Mike Frysinger <vapier@gentoo.org>
Date: Mon, 15 Apr 2013 22:13:17 -0400
Subject: [PATCH 92/96] fdtdump: add a debug mode

When hacking raw fdt files, it's useful to know the actual offsets into
the file each node appears.  Add a --debug mode that includes this.

Signed-off-by: Mike Frysinger <vapier@gentoo.org>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
---
 fdtdump.c | 41 +++++++++++++++++++++++++++++++++++++----
 1 file changed, 37 insertions(+), 4 deletions(-)

diff --git a/fdtdump.c b/fdtdump.c
index c2f16ea..723770d 100644
--- a/fdtdump.c
+++ b/fdtdump.c
@@ -19,8 +19,29 @@
 #define PALIGN(p, a)	((void *)(ALIGN((unsigned long)(p), (a))))
 #define GET_CELL(p)	(p += 4, *((const uint32_t *)(p-4)))
 
-static void dump_blob(void *blob)
+static const char *tagname(uint32_t tag)
 {
+	static const char * const names[] = {
+#define TN(t) [t] #t
+		TN(FDT_BEGIN_NODE),
+		TN(FDT_END_NODE),
+		TN(FDT_PROP),
+		TN(FDT_NOP),
+		TN(FDT_END),
+#undef TN
+	};
+	if (tag < ARRAY_SIZE(names))
+		if (names[tag])
+			return names[tag];
+	return "FDT_???";
+}
+
+#define dumpf(fmt, args...) \
+	do { if (debug) printf("// " fmt, ## args); } while (0)
+
+static void dump_blob(void *blob, bool debug)
+{
+	uintptr_t blob_off = (uintptr_t)blob;
 	struct fdt_header *bph = blob;
 	uint32_t off_mem_rsvmap = fdt32_to_cpu(bph->off_mem_rsvmap);
 	uint32_t off_dt = fdt32_to_cpu(bph->off_dt_struct);
@@ -74,7 +95,8 @@ static void dump_blob(void *blob)
 	p = p_struct;
 	while ((tag = fdt32_to_cpu(GET_CELL(p))) != FDT_END) {
 
-		/* printf("tag: 0x%08x (%d)\n", tag, p - p_struct); */
+		dumpf("%04zx: tag: 0x%08x (%s)\n",
+		        (uintptr_t)p - blob_off - 4, tag, tagname(tag));
 
 		if (tag == FDT_BEGIN_NODE) {
 			s = p;
@@ -113,6 +135,8 @@ static void dump_blob(void *blob)
 
 		p = PALIGN(p + sz, 4);
 
+		dumpf("%04zx: string: %s\n", (uintptr_t)s - blob_off, s);
+		dumpf("%04zx: value\n", (uintptr_t)t - blob_off);
 		printf("%*s%s", depth * shift, "", s);
 		utilfdt_print_data(t, sz);
 		printf(";\n");
@@ -121,12 +145,14 @@ static void dump_blob(void *blob)
 
 /* Usage related data. */
 static const char usage_synopsis[] = "fdtdump [options] <file>";
-static const char usage_short_opts[] = "s" USAGE_COMMON_SHORT_OPTS;
+static const char usage_short_opts[] = "ds" USAGE_COMMON_SHORT_OPTS;
 static struct option const usage_long_opts[] = {
+	{"debug",            no_argument, NULL, 'd'},
 	{"scan",             no_argument, NULL, 's'},
 	USAGE_COMMON_LONG_OPTS
 };
 static const char * const usage_opts_help[] = {
+	"Dump debug information while decoding the file",
 	"Scan for an embedded fdt in file",
 	USAGE_COMMON_OPTS_HELP
 };
@@ -136,6 +162,7 @@ int main(int argc, char *argv[])
 	int opt;
 	const char *file;
 	char *buf;
+	bool debug = false;
 	bool scan = false;
 	off_t len;
 
@@ -143,6 +170,9 @@ int main(int argc, char *argv[])
 		switch (opt) {
 		case_USAGE_COMMON_FLAGS
 
+		case 'd':
+			debug = true;
+			break;
 		case 's':
 			scan = true;
 			break;
@@ -179,6 +209,9 @@ int main(int argc, char *argv[])
 				    fdt_off_dt_struct(p) < this_len &&
 					fdt_off_dt_strings(p) < this_len)
 					break;
+				if (debug)
+					printf("%s: skipping fdt magic at offset %#zx\n",
+						file, p - buf);
 			}
 			++p;
 		}
@@ -188,7 +221,7 @@ int main(int argc, char *argv[])
 		buf = p;
 	}
 
-	dump_blob(buf);
+	dump_blob(buf, debug);
 
 	return 0;
 }
-- 
1.8.1.4


From 1c76ec3c090f230fa8a45a5ef84bda600fc4d064 Mon Sep 17 00:00:00 2001
From: David Gibson <david@gibson.dropbear.id.au>
Date: Wed, 29 May 2013 12:39:47 +1000
Subject: [PATCH 93/96] Use shorten_echo for wrap_tests

We have certain tests which generate extremely long command lines, which
are shortened in the testsuite output with the 'shorten_echo' function.
Currently that is used in run_fdtput_test and run_wrap_test, this patch
uses it for run_wrap_test as well, allowing more general tests with long
command lines.

Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
---
 tests/run_tests.sh | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/tests/run_tests.sh b/tests/run_tests.sh
index b013761..9c87369 100755
--- a/tests/run_tests.sh
+++ b/tests/run_tests.sh
@@ -80,7 +80,7 @@ wrap_test () {
 }
 
 run_wrap_test () {
-    echo -n "$@:	"
+    shorten_echo "$@:	"
     base_run_test wrap_test "$@"
 }
 
-- 
1.8.1.4


From a58afe2eb28645641367f4eacdea2c124d291f6e Mon Sep 17 00:00:00 2001
From: David Gibson <david@gibson.dropbear.id.au>
Date: Wed, 29 May 2013 12:44:18 +1000
Subject: [PATCH 94/96] Remove some tests for misfeatures

There are a couple of fdtput related tests which are rather pointless -
they explicitly test for the presence of an undesirable limitation in
fdtput, which will cause test failures when we fix it.  This patch removes
the tests.

Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
---
 tests/run_tests.sh | 4 ----
 1 file changed, 4 deletions(-)

diff --git a/tests/run_tests.sh b/tests/run_tests.sh
index 9c87369..d0a7f02 100755
--- a/tests/run_tests.sh
+++ b/tests/run_tests.sh
@@ -549,9 +549,6 @@ fdtput_tests () {
 	-tx "a0b0c0d deeaae ef000000"
     run_fdtput_test "$(cat $text)" $dtb /randomnode blob -ts "$(cat $text)"
 
-    # 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
 
@@ -572,7 +569,6 @@ fdtput_tests () {
     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
-- 
1.8.1.4


From d214655904b49938dafcb83797de3f6a0dc725c8 Mon Sep 17 00:00:00 2001
From: Srinivas Kandagatla <srinivas.kandagatla@st.com>
Date: Wed, 29 May 2013 12:47:38 +1000
Subject: [PATCH 95/96] fdtput: expand fdt if value does not fit

If you try to insert a new node or extend a property with large value,
using fdtput you will notice that it always fails.

example:
fdtput -v -p -ts ./tst.dtb "/node-1" "property-1" "value-1
Error at 'node-1': FDT_ERR_NOSPACE

or

fdtput -v -c ./tst.dtb "/node-1"
Error at 'node-1': FDT_ERR_NOSPACE

or

fdtput -v  -ts ./tst.dtb "/node" "property" "very big value"
Decoding value:
	string: 'very big value'
Value size 15
Error at 'property': FDT_ERR_NOSPACE

All these error are returned from libfdt, as the size of the fdt passed
has no space to accomdate these new properties.
This patch adds realloc functions in fdtput to allocate new space in fdt
when it detects a shortage in space for new value or node. With this
patch, fdtput can insert a new node or property or extend a property
with new value greater than original size. Also it packs the final blob
to clean up any extra padding.

Without this patch fdtput tool complains with FDT_ERR_NOSPACE when we
try to add a node/property or extend the value of a property.

Testcases for the new behaviour added by David Gibson.

Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@st.com>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
---
 fdtput.c           | 74 +++++++++++++++++++++++++++++++++++++++++++-----------
 tests/run_tests.sh |  6 +++++
 2 files changed, 65 insertions(+), 15 deletions(-)

diff --git a/fdtput.c b/fdtput.c
index fbb283a..5226a4e 100644
--- a/fdtput.c
+++ b/fdtput.c
@@ -131,19 +131,59 @@ static int encode_value(struct display_info *disp, char **arg, int arg_count,
 	return 0;
 }
 
-static int store_key_value(void *blob, const char *node_name,
+#define ALIGN(x)		(((x) + (FDT_TAGSIZE) - 1) & ~((FDT_TAGSIZE) - 1))
+
+static char *_realloc_fdt(char *fdt, int delta)
+{
+	int new_sz = fdt_totalsize(fdt) + delta;
+	fdt = xrealloc(fdt, new_sz);
+	fdt_open_into(fdt, fdt, new_sz);
+	return fdt;
+}
+
+static char *realloc_node(char *fdt, const char *name)
+{
+	int delta;
+	/* FDT_BEGIN_NODE, node name in off_struct and FDT_END_NODE */
+	delta = sizeof(struct fdt_node_header) + ALIGN(strlen(name) + 1)
+			+ FDT_TAGSIZE;
+	return _realloc_fdt(fdt, delta);
+}
+
+static char *realloc_property(char *fdt, int nodeoffset,
+		const char *name, int newlen)
+{
+	int delta = 0;
+	int oldlen = 0;
+
+	if (!fdt_get_property(fdt, nodeoffset, name, &oldlen))
+		/* strings + property header */
+		delta = sizeof(struct fdt_property) + strlen(name) + 1;
+
+	if (newlen > oldlen)
+		/* actual value in off_struct */
+		delta += ALIGN(newlen) - ALIGN(oldlen);
+
+	return _realloc_fdt(fdt, delta);
+}
+
+static int store_key_value(char **blob, const char *node_name,
 		const char *property, const char *buf, int len)
 {
 	int node;
 	int err;
 
-	node = fdt_path_offset(blob, node_name);
+	node = fdt_path_offset(*blob, node_name);
 	if (node < 0) {
 		report_error(node_name, -1, node);
 		return -1;
 	}
 
-	err = fdt_setprop(blob, node, property, buf, len);
+	err = fdt_setprop(*blob, node, property, buf, len);
+	if (err == -FDT_ERR_NOSPACE) {
+		*blob = realloc_property(*blob, node, property, len);
+		err = fdt_setprop(*blob, node, property, buf, len);
+	}
 	if (err) {
 		report_error(property, -1, err);
 		return -1;
@@ -161,7 +201,7 @@ static int store_key_value(void *blob, const char *node_name,
  * @param in_path	Path to process
  * @return 0 if ok, -1 on error
  */
-static int create_paths(void *blob, const char *in_path)
+static int create_paths(char **blob, const char *in_path)
 {
 	const char *path = in_path;
 	const char *sep;
@@ -177,10 +217,11 @@ static int create_paths(void *blob, const char *in_path)
 		if (!sep)
 			sep = path + strlen(path);
 
-		node = fdt_subnode_offset_namelen(blob, offset, path,
+		node = fdt_subnode_offset_namelen(*blob, offset, path,
 				sep - path);
 		if (node == -FDT_ERR_NOTFOUND) {
-			node = fdt_add_subnode_namelen(blob, offset, path,
+			*blob = realloc_node(*blob, path);
+			node = fdt_add_subnode_namelen(*blob, offset, path,
 						       sep - path);
 		}
 		if (node < 0) {
@@ -203,7 +244,7 @@ static int create_paths(void *blob, const char *in_path)
  * @param node_name	Name of node to create
  * @return new node offset if found, or -1 on failure
  */
-static int create_node(void *blob, const char *node_name)
+static int create_node(char **blob, const char *node_name)
 {
 	int node = 0;
 	char *p;
@@ -215,15 +256,17 @@ static int create_node(void *blob, const char *node_name)
 	}
 	*p = '\0';
 
+	*blob = realloc_node(*blob, p + 1);
+
 	if (p > node_name) {
-		node = fdt_path_offset(blob, node_name);
+		node = fdt_path_offset(*blob, node_name);
 		if (node < 0) {
 			report_error(node_name, -1, node);
 			return -1;
 		}
 	}
 
-	node = fdt_add_subnode(blob, node, p + 1);
+	node = fdt_add_subnode(*blob, node, p + 1);
 	if (node < 0) {
 		report_error(p + 1, -1, node);
 		return -1;
@@ -250,23 +293,25 @@ static int do_fdtput(struct display_info *disp, const char *filename,
 		 * store them into the property.
 		 */
 		assert(arg_count >= 2);
-		if (disp->auto_path && create_paths(blob, *arg))
+		if (disp->auto_path && create_paths(&blob, *arg))
 			return -1;
 		if (encode_value(disp, arg + 2, arg_count - 2, &value, &len) ||
-			store_key_value(blob, *arg, arg[1], value, len))
+			store_key_value(&blob, *arg, arg[1], value, len))
 			ret = -1;
 		break;
 	case OPER_CREATE_NODE:
 		for (; ret >= 0 && arg_count--; arg++) {
 			if (disp->auto_path)
-				ret = create_paths(blob, *arg);
+				ret = create_paths(&blob, *arg);
 			else
-				ret = create_node(blob, *arg);
+				ret = create_node(&blob, *arg);
 		}
 		break;
 	}
-	if (ret >= 0)
+	if (ret >= 0) {
+		fdt_pack(blob);
 		ret = utilfdt_write(filename, blob);
+	}
 
 	free(blob);
 	return ret;
@@ -313,7 +358,6 @@ int main(int argc, char *argv[])
 		 * - rename node
 		 * - pack fdt before writing
 		 * - set amount of free space when writing
-		 * - expand fdt if value doesn't fit
 		 */
 		switch (opt) {
 		case_USAGE_COMMON_FLAGS
diff --git a/tests/run_tests.sh b/tests/run_tests.sh
index d0a7f02..c0a136b 100755
--- a/tests/run_tests.sh
+++ b/tests/run_tests.sh
@@ -549,6 +549,9 @@ fdtput_tests () {
 	-tx "a0b0c0d deeaae ef000000"
     run_fdtput_test "$(cat $text)" $dtb /randomnode blob -ts "$(cat $text)"
 
+    # Test expansion of the blob when insufficient room for property
+    run_fdtput_test "$(cat $text $text)" $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
 
@@ -570,6 +573,9 @@ fdtput_tests () {
 	"-ts" "fine wine"
     run_wrap_test $DTPUT $dtb -p /you/are/drunk/sir/winston slurp -ts twice
 
+    # Test expansion of the blob when insufficent room for a new node
+    run_wrap_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
-- 
1.8.1.4


From 2e3fc7e9b3a4722a5500afaa9faf7874c61b2e6a Mon Sep 17 00:00:00 2001
From: David Gibson <david@gibson.dropbear.id.au>
Date: Wed, 29 May 2013 12:46:35 +1000
Subject: [PATCH 96/96] Add missing test binary to .gitignore

The subnode_iterate test binary was missing from .gitignore, this fixes it.

Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
---
 tests/.gitignore | 1 +
 1 file changed, 1 insertion(+)

diff --git a/tests/.gitignore b/tests/.gitignore
index e2aa24a..bb5e33a 100644
--- a/tests/.gitignore
+++ b/tests/.gitignore
@@ -48,6 +48,7 @@ tmp.*
 /setprop_inplace
 /sized_cells
 /string_escapes
+/subnode_iterate
 /subnode_offset
 /supernode_atdepth_offset
 /sw_tree1
-- 
1.8.1.4