diff --git a/dtc-check.patch b/dtc-check.patch deleted file mode 100644 index f3560fd..0000000 --- a/dtc-check.patch +++ /dev/null @@ -1,65 +0,0 @@ -From jwboyer@linux.vnet.ibm.com Tue Jun 28 08:47:09 2011 -Date: Tue, 28 Jun 2011 08:47:09 -0400 -From: Josh Boyer -To: Jon Loeliger -Cc: linuxppc-dev@lists.ozlabs.org -Subject: [PATCH] dtc: Remove unused check variable -Message-ID: <20110628124709.GC10237@zod.rchland.ibm.com> -MIME-Version: 1.0 -Content-Type: text/plain; charset=us-ascii -Content-Disposition: inline -User-Agent: Mutt/1.5.21 (2010-09-15) -Status: RO -Content-Length: 1315 -Lines: 49 - -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 - ---- - -t 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; - - diff --git a/dtc-flattree.patch b/dtc-flattree.patch deleted file mode 100644 index c8ba010..0000000 --- a/dtc-flattree.patch +++ /dev/null @@ -1,52 +0,0 @@ -From jwboyer@linux.vnet.ibm.com Tue Jun 28 09:42:53 2011 -Date: Tue, 28 Jun 2011 09:42:53 -0400 -From: Josh Boyer -To: jdl@jdl.com, david@gibson.dropbear.id.au -Cc: linuxppc-dev@lists.ozlabs.org -Subject: [PATCH] dtc: Remove unused variable in flat_read_mem_reserve -Message-ID: <20110628134253.GD10237@zod.rchland.ibm.com> -MIME-Version: 1.0 -Content-Type: text/plain; charset=us-ascii -Content-Disposition: inline -User-Agent: Mutt/1.5.21 (2010-09-15) -Status: RO -Content-Length: 1865 -Lines: 68 - -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 - ---- - -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); - - diff --git a/dtc-update.patch b/dtc-update.patch new file mode 100644 index 0000000..761daf3 --- /dev/null +++ b/dtc-update.patch @@ -0,0 +1,14335 @@ +From 0a5aca98ba104ec4101322ccaf36da45064ad3ce Mon Sep 17 00:00:00 2001 +From: Josh Boyer +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 +Acked-by: David Gibson +--- + 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 +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 +Acked-by: David Gibson +--- + 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 +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 +Acked-by: David Gibson +--- + 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 + #include + ++#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 ++ * + * 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 + #include + #include + #include +@@ -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 ++ + /* + * 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 +Date: Tue, 5 Jul 2011 12:02:52 -0700 +Subject: [PATCH 04/96] Add missing tests to .gitignore + +Signed-off-by: Simon Glass +Acked-by: David Gibson +--- + 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 +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 +Acked-by: David Gibson +--- + 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 + #include + #include ++#include + + #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 +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 +--- + 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 +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 +Acked-by: David Gibson +--- + 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 DT_PROPNODENAME + %token DT_LITERAL ++%token DT_CHAR_LITERAL + %token DT_BASE + %token DT_BYTE + %token 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 ++#include ++#include ++#include ++ ++#include ++#include ++ ++#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 +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 +Signed-off-by: Simon Glass +--- + 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 +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 +Acked-by: David Gibson +--- + 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 ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++ ++#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 + #include + ++#include ++#include ++#include ++ ++#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 + + /* ++ * 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 +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 +Acked-by: David Gibson +--- + 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 +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 +Acked-by: David Gibson +--- + 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 +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 +Acked-by: David Gibson +--- + 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 + + #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 +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 +Acked-by: David Gibson +--- + 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 +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 +Acked-by: David Gibson +--- + 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 + -- Yoder Stuart ++ -- Anton Staaf +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 DT_PROPNODENAME + %token DT_LITERAL + %token DT_CHAR_LITERAL +@@ -71,8 +76,7 @@ static unsigned char eval_char_literal(const char *s); + %type memreserve + %type memreserves + %type addr +-%type celllist +-%type cellval ++%type arrayprefix + %type bytestring + %type propdef + %type 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 ++#include ++#include ++#include ++ ++#include ++#include ++ ++#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 +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 +Acked-by: David Gibson +--- + .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 ++ fdtdump +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 ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++ ++#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 +- */ +- +-#include +-#include +-#include +-#include +-#include +- +-#include +-#include +- +-#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 +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 +Signed-off-by: David Gibson +--- + 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 ++#include ++#include ++#include ++#include ++ ++#include ++#include ++ ++#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 ++#include ++#include ++#include ++#include ++ ++#include ++#include ++ ++#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 +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 +--- + 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 +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 +Acked-by: David Gibson +--- + 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 + The generated output format, as listed above. + ++ -d ++ 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 \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 \n"); + fprintf(stderr, "\t-R \n"); + fprintf(stderr, "\t\tMake space for reserve map entries (relevant for \n\t\tdtb and asm output only)\n"); + fprintf(stderr, "\t-S \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 +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: + -t Type of data + -h Print this help + + 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 +--- + .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 ++#include ++#include ++#include ++#include ++ ++#include ++ ++#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
[ ]...\n" ++ "Options:\n" ++ "\t-t \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 ... ++ 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 \ ++ "\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 +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: + -t Type of data + -v Verbose: display each value decoded from command line + -h Print this help + + 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 +--- + .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 ++#include ++#include ++#include ++#include ++#include ++ ++#include ++ ++#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
< [...]\n" ++ "Options:\n" ++ "\t-t \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 ++ # ... ++ 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 +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 +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 +--- + 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 +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 +--- + .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 +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 +--- + 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 +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 +--- + 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 +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 +--- + 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 +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 +--- + 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 +-- +1.8.1.4 + + +From c879a8a28b168b3b448ca8a107e3386eda6829c7 Mon Sep 17 00:00:00 2001 +From: David Gibson +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 +--- + 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 +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 +--- + 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 ... +- run_fdtget_test "Simple string" "MyBoardName" $file / model +- run_fdtget_test "Multiple string i" "77 121 66 111 \ ++ # run_fdtget_test [] ++ 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 +- # ... +- 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 ++ 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 +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 +--- + 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 +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 +--- + 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 + 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 +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 +--- + 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 +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 +--- + 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 +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 +Acked-by: David Gibson +--- + 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 +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 +Acked-by: David Gibson +--- + 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 and ++ * Matthew McClintock ++ * + * 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 + #include + #include + #include +@@ -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
[ ]...\n" ++ " fdtget -p
[ ]...\n" + "Options:\n" + "\t-t \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 +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 +Acked-by: David Gibson +--- + 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 \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 +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 +Acked-by: David Gibson +--- + 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 \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 "" -tx \ ++ -d "" $dtb /randomnode doctor-who ++ run_fdtget_test "" -tx -d "" $dtb /memory doctor-who + } + + fdtput_tests () { +-- +1.8.1.4 + + +From de6b76240e91b9288cdce63ab81e51a7232d0927 Mon Sep 17 00:00:00 2001 +From: Simon Glass +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 +--- + 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(""); + } 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 +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 +Acked-by: David Gibson +--- + 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 +Date: Tue, 3 Apr 2012 20:56:00 -0600 +Subject: [PATCH 40/96] dtc: Basic integer expressions + +Written by David Gibson . 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 +--- + 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; + } + +-[0-9]+|0[xX][0-9a-fA-F]+ { ++([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 DT_PROPNODENAME + %token DT_LITERAL +@@ -75,7 +76,6 @@ static unsigned char eval_char_literal(const char *s); + %type propdataprefix + %type memreserve + %type memreserves +-%type addr + %type arrayprefix + %type bytestring + %type propdef +@@ -86,6 +86,21 @@ static unsigned char eval_char_literal(const char *s); + %type subnode + %type subnodes + ++%type integer_prim ++%type integer_unary ++%type integer_mul ++%type integer_add ++%type integer_shift ++%type integer_rela ++%type integer_eq ++%type integer_bitand ++%type integer_bitxor ++%type integer_bitor ++%type integer_and ++%type integer_or ++%type integer_trinary ++%type 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 ++#include ++#include ++#include ++#include ++ ++ ++#include ++#include ++ ++#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 +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 +--- + 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 + #include + +-#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 +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 +Acked-by: David Gibson +--- + 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 +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 +--- + 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 +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 +--- + 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 +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 +--- + 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 +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 +--- + 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 +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 +--- + 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 ++#include ++ ++#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 +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 to solve this. + +Signed-off-by: Stephen Warren +Acked-by: David Gibson +--- + 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 + #include + #include + #include +@@ -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 +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 +Acked-by: David Gibson +--- + 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 +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 +--- + 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 + #include + #include ++#include + #include + #include + #include +-- +1.8.1.4 + + +From d5399197e9e0d8bad13de5c41df3b93804c0558a Mon Sep 17 00:00:00 2001 +From: David Gibson +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 +--- + 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-]\n"); ++ fprintf(stderr, "\t-E [no-]\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 +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 +Acked-by: David Gibson +--- + 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
< [...]\n" ++ " fdtput
[...]\n" + "Options:\n" + "\t-t \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 +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 +--- + 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 +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 + +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 +Acked-by: David Gibson +--- + 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
[...]\n" ++ " fdtput -c
[...]\n" + "Options:\n" ++ "\t-c\t\tCreate nodes if they don't already exist\n" + "\t-t \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 +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 +Acked-by: David Gibson +--- + 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 +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 +--- + 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
[...]\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 \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" +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" +Acked-by: David Gibson +--- + 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 +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 +Acked-by: David Gibson +--- + 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("\n"); ++ BEGIN(PROPNODENAME); ++ return DT_DEL_PROP; ++ } ++ ++<*>"/delete-node/" { ++ DPRINT("Keyword: /delete-node/\n"); ++ DPRINT("\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 DT_PROPNODENAME + %token DT_LITERAL + %token 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 +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 +Acked-by: David Gibson +--- + 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 ']'; + } + +-{PROPNODECHAR}+ { ++\\?{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 ++#include ++#include ++#include ++ ++#include ++#include ++ ++#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 +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 +Acked-by: David Gibson +--- + 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); ++ } ++ + <*><> { + 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 +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 +--- + 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 +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 +Acked-by: David Gibson +--- + 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 +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 +Acked-by: David Gibson +--- + 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 +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 +Acked-by: David Gibson +--- + 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 +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 +Acked-by: David Gibson +--- + 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 +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 +Acked-by: David Gibson +--- + 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 +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 +Acked-by: David Gibson +--- + 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 +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 +Acked-by: David Gibson +--- + 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 + #include + +-#include + #include + + #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 + #include + +-#include + #include + + #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 + #include + +-#include + #include + + #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 + +-#include + #include + + #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 + #include + +-#include + #include + + #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 + #include + +-#include + #include + + #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 + #include + +-#include + #include + + #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 + #include + +-#include + #include + + #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 + #include + +-#include + #include + + #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 + #include + +-#include + #include + + #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 + #include + +-#include + #include + + #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 + #include + +-#include + #include +-#include + + #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 + #include + +-#include + #include + + #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 + #include + +-#include + #include + + #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 + #include + +-#include + #include + + #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 + #include + +-#include + #include + + #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 + #include + +-#include + #include + + #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 + #include + +-#include + #include + + #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 + #include + +-#include + #include + + #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 + #include + +-#include + #include + + #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 + #include + +-#include + #include + + #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 + + +-#include + #include + + #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 + #include + +-#include + #include + + #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 + #include + +-#include + #include + + #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 + #include + +-#include + #include + + #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 + #include + +-#include + #include + + #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 + #include + +-#include + #include + + #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 + #include + +-#include + #include + + #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 + #include + +-#include + #include + + #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 + #include + +-#include + #include + + #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 + #include + +-#include + #include + + #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 + #include + +-#include + #include + + #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 + #include + +-#include + #include + + #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 + #include + +-#include + #include + + #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 + #include + +-#include + #include + + #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 + #include + +-#include + #include + + #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 + #include + +-#include + #include + + #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 + #include + +-#include + #include + + #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 + #include + +-#include + #include + + #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 + #include + +-#include + #include + + #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 + #include + +-#include + #include + + #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 + #include + +-#include + #include + + #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 + #include + +-#include + #include + + #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 + #include + +-#include + #include + + #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 + #include + +-#include + #include + + #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 + #include + +-#include + #include + + #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 + #include + +-#include + #include + + #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 + #include + +-#include + #include + + #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 + #include + +-#include + #include + + #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 + #include + +-#include + #include + + #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 + #include + +-#include + #include + + #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 + #include + +-#include + #include + #include + +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 + +-#include + #include + + #include "tests.h" +-- +1.8.1.4 + + +From 20b866a7ce1651c4ca3f28cf380df66d9ed35719 Mon Sep 17 00:00:00 2001 +From: Kim Phillips +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 +Acked-by: David Gibson +--- + 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 + #include + +-#include + #include ++#include + + #include "util.h" + +-- +1.8.1.4 + + +From feafcd972cb744750a65728440c99526e6199a6d Mon Sep 17 00:00:00 2001 +From: Kim Phillips +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 +Acked-by: David Gibson +--- + 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 + #include + +-#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 +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] +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] +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] +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] +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] +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] +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] +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 +--- + 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 +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 +--- + 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 +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 # and implemented-by +Signed-off-by: Stephen Warren +Acked-by: David Gibson +--- + 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 +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 +Acked-by: David Gibson +--- + 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 [] + 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 +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 +Acked-by: David Gibson +--- + 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 +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 +Acked-by: David Gibson +--- + .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 +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 +Acked-by: David Gibson +--- + 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?= +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 +--- + 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 +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 +Acked-by: David Gibson +--- + 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 + #include +-- +1.8.1.4 + + +From f8cb5dd94903a5cfa1609695328b8f1d5557367f Mon Sep 17 00:00:00 2001 +From: Mike Frysinger +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 +Signed-off-by: Mike Frysinger +--- + 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 +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 +--- + 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 +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 +Signed-off-by: Mike Frysinger +--- + 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 +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 +Signed-off-by: Mike Frysinger +--- + 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 +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 +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 +Signed-off-by: Mike Frysinger +--- + 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 +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 +Acked-by: David Gibson +--- + 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 ++#include ++#include ++#include ++ ++#include ++ ++#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 ", 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 +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 +Signed-off-by: David Gibson +--- + 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] "; ++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[] = ""; ++ 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 ++#include + + /* + * 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 +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 +Signed-off-by: David Gibson +--- + 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 + */ + ++#include + #include + #include + #include + #include + #include + ++#include + #include + #include + +@@ -119,11 +121,13 @@ static void dump_blob(void *blob) + + /* Usage related data. */ + static const char usage_synopsis[] = "fdtdump [options] "; +-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 +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 +Signed-off-by: David Gibson +--- + 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 ...\n"); +- exit(3); +-} ++/* Usage related data. */ ++static const char usage_synopsis[] = "convert-dtsv0 [options] ..."; ++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] \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 \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 \n"); +- fprintf(stderr, "\t-O \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 \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 \n"); +- fprintf(stderr, "\t-R \n"); +- fprintf(stderr, "\t\tMake space for reserve map entries (relevant for \n\t\tdtb and asm output only)\n"); +- fprintf(stderr, "\t-S \n"); +- fprintf(stderr, "\t\tMake the blob at least long (extra space)\n"); +- fprintf(stderr, "\t-p \n"); +- fprintf(stderr, "\t\tAdd padding to the blob of long (extra space)\n"); +- fprintf(stderr, "\t-b \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 \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-]\n"); +- fprintf(stderr, "\t-E [no-]\n"); +- fprintf(stderr, "\t\t\tenable or disable warnings and errors\n"); +- exit(3); +-} ++/* Usage related data. */ ++static const char usage_synopsis[] = "dtc [options] "; ++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 reserve map entries (for dtb and asm output)", ++ "\n\tMake the blob at least long (extra space)", ++ "\n\tAdd padding to the blob of 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
[ ]...\n" + " fdtget -p
[ ]...\n" +- "Options:\n" +- "\t-t \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
[...]\n" + " fdtput -c
[...]\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 \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 \ + "\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 +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 +Signed-off-by: David Gibson +--- + 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[] = ""; +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 +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 +Signed-off-by: David Gibson +--- + 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 +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 +Signed-off-by: David Gibson +--- + 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] "; +-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 +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 +--- + 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 +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 +--- + 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 +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 +Signed-off-by: David Gibson +--- + 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 +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 +--- + 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 + diff --git a/dtc.spec b/dtc.spec index 6a20a74..d3c628e 100644 --- a/dtc.spec +++ b/dtc.spec @@ -1,13 +1,12 @@ Name: dtc Version: 1.3.0 -Release: 6%{?dist} +Release: 7%{?dist} Summary: Device Tree Compiler Group: Development/Tools License: GPLv2+ URL: http://git.jdl.com/gitweb/?p=dtc.git;a=summary Source: http://www.jdl.com/software/dtc-v%{version}.tgz -Patch0: dtc-check.patch -Patch1: dtc-flattree.patch +Patch0: dtc-update.patch BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n) BuildRequires: flex, bison @@ -35,7 +34,6 @@ This package provides development files for libfdt %prep %setup -q -n dtc-v%{version} %patch0 -p1 -%patch1 -p1 %build make %{?_smp_mflags} @@ -75,6 +73,9 @@ rm -rf $RPM_BUILD_ROOT /sbin/ldconfig %changelog +* Mon Jun 03 2013 Josh Boyer - 1.3.0-7 +- Update dtc to include libfdt_env.h (rhbz 969955) + * Wed Feb 13 2013 Fedora Release Engineering - 1.3.0-6 - Rebuilt for https://fedoraproject.org/wiki/Fedora_19_Mass_Rebuild