[U-Boot] [PATCH 1/6] fdt: Check error codes returned from fdtlib when loading ITB

Before this patch, error codes returned from fdtlib were ignored and continued access would cause a crash. Now just check if the image is truncated and error if so.
Signed-off-by: Joe Hershberger joe.hershberger@ni.com --- common/image.c | 5 +++++ 1 file changed, 5 insertions(+)
diff --git a/common/image.c b/common/image.c index 91954ac..4252e63 100644 --- a/common/image.c +++ b/common/image.c @@ -2818,6 +2818,11 @@ int fit_image_check_hashes(const void *fit, int image_noffset) } }
+ if (noffset == -FDT_ERR_TRUNCATED || noffset == -FDT_ERR_BADSTRUCTURE) { + err_msg = " error!\nCorrupted or truncated tree"; + goto error; + } + return 1;
error:

Prevent printing the entire image in a itb. It is most likely unhelpful to have the hex of the entire image scroll for minutes on your slow serial console.
Signed-off-by: Joe Hershberger joe.hershberger@ni.com --- common/cmd_fdt.c | 36 ++++++++++++++++++++++++------------ 1 file changed, 24 insertions(+), 12 deletions(-)
diff --git a/common/cmd_fdt.c b/common/cmd_fdt.c index 9a5c53e..a008426 100644 --- a/common/cmd_fdt.c +++ b/common/cmd_fdt.c @@ -35,6 +35,9 @@
#define MAX_LEVEL 32 /* how deeply nested we will go */ #define SCRATCHPAD 1024 /* bytes of scratchpad memory */ +#ifndef CONFIG_CMD_FDT_MAX_DUMP +#define CONFIG_CMD_FDT_MAX_DUMP 64 +#endif
/* * Global data (for the gd->bd) @@ -661,19 +664,28 @@ static void print_data(const void *data, int len) }
if ((len %4) == 0) { - const u32 *p; - - printf("<"); - for (j = 0, p = data; j < len/4; j ++) - printf("0x%x%s", fdt32_to_cpu(p[j]), j < (len/4 - 1) ? " " : ""); - printf(">"); + if (len > CONFIG_CMD_FDT_MAX_DUMP) + printf("* 0x%08x [0x%08x]", (unsigned int)data, len); + else { + const u32 *p; + + printf("<"); + for (j = 0, p = data; j < len/4; j++) + printf("0x%08x%s", fdt32_to_cpu(p[j]), + j < (len/4 - 1) ? " " : ""); + printf(">"); + } } else { /* anything else... hexdump */ - const u8 *s; - - printf("["); - for (j = 0, s = data; j < len; j++) - printf("%02x%s", s[j], j < len - 1 ? " " : ""); - printf("]"); + if (len > CONFIG_CMD_FDT_MAX_DUMP) + printf("* 0x%08x [0x%08x]", (unsigned int)data, len); + else { + const u8 *s; + + printf("["); + for (j = 0, s = data; j < len; j++) + printf("%02x%s", s[j], j < len - 1 ? " " : ""); + printf("]"); + } } }

On Fri, Aug 17, 2012 at 10:34:36AM -0000, Joe Hershberger wrote:
Prevent printing the entire image in a itb. It is most likely unhelpful to have the hex of the entire image scroll for minutes on your slow serial console.
Signed-off-by: Joe Hershberger joe.hershberger@ni.com
This causes: $ uboot-build.sh sandboxTesting sandbox on -00004-gf0a29d4 Thu Oct 25 13:59:03 MST 2012 Configuring for sandbox board... text data bss dec hex filename 140245 6332 28472 175049 2abc9 sandbox/u-boot cmd_fdt.c: In function 'print_data': cmd_fdt.c:679:32: warning: cast from pointer to integer of different size [-Wpointer-to-int-cast] cmd_fdt.c:691:32: warning: cast from pointer to integer of different size [-Wpointer-to-int-cast]

-----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1
Hi Tom, Joe,
On 10/25/2012 04:59 PM, Tom Rini wrote:
On Fri, Aug 17, 2012 at 10:34:36AM -0000, Joe Hershberger wrote:
Prevent printing the entire image in a itb. It is most likely unhelpful to have the hex of the entire image scroll for minutes on your slow serial console.
Signed-off-by: Joe Hershberger joe.hershberger@ni.com
This causes: $ uboot-build.sh sandboxTesting sandbox on -00004-gf0a29d4 Thu Oct 25 13:59:03 MST 2012 Configuring for sandbox board... text data bss dec hex filename 140245 6332 28472 175049 2abc9 sandbox/u-boot cmd_fdt.c: In function 'print_data': cmd_fdt.c:679:32: warning: cast from pointer to integer of different size [-Wpointer-to-int-cast] cmd_fdt.c:691:32: warning: cast from pointer to integer of different size [-Wpointer-to-int-cast]
Sorry, I should have caught that and the 3/6 warning. :-(
I'm tied up with a flight test through Friday (Nov 2) which has been consuming all my available time. Joe, can you look at fixing the warnings?
Thanks, gvb

Add commands to access data in the fdt. This allows data from a dtb or itb to be accessed from the shell scripts.
Signed-off-by: Joe Hershberger joe.hershberger@ni.com --- common/cmd_fdt.c | 144 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 144 insertions(+)
diff --git a/common/cmd_fdt.c b/common/cmd_fdt.c index a008426..60983af 100644 --- a/common/cmd_fdt.c +++ b/common/cmd_fdt.c @@ -47,6 +47,7 @@ DECLARE_GLOBAL_DATA_PTR; static int fdt_valid(void); static int fdt_parse_prop(char *const*newval, int count, char *data, int *len); static int fdt_print(const char *pathp, char *prop, int depth); +static int is_printable_string(const void *data, int len);
/* * The working_fdt points to our working flattened device tree. @@ -64,6 +65,34 @@ void set_working_fdt_addr(void *addr) }
/* + * Get a value from the fdt and format it to be set in the environment + */ +static int fdt_value_setenv(const void *nodep, int len, const char *var) +{ + if (is_printable_string(nodep, len)) + setenv(var, (void *)nodep); + else if (len == 4) { + char buf[11]; + + sprintf(buf, "0x%08X", *(uint32_t *)nodep); + setenv(var, buf); + } else if (len%4 == 0 && len <= 20) { + /* Needed to print things like sha1 hashes. */ + char buf[41]; + int i; + + for (i = 0; i < len; i += sizeof(unsigned int)) + sprintf(buf + (i * 2), "%08x", + *(unsigned int *)(nodep + i)); + setenv(var, buf); + } else { + printf("error: unprintable value\n"); + return 1; + } + return 0; +} + +/* * Flattened Device Tree command, see the help for parameter definitions. */ int do_fdt (cmd_tbl_t * cmdtp, int flag, int argc, char * const argv[]) @@ -242,6 +271,117 @@ int do_fdt (cmd_tbl_t * cmdtp, int flag, int argc, char * const argv[]) return 1; }
+ /******************************************************************** + * Get the value of a property in the working_fdt. + ********************************************************************/ + } else if (argv[1][0] == 'g') { + char *subcmd; /* sub-command */ + char *pathp; /* path */ + char *prop; /* property */ + char *var; /* variable to store result */ + int nodeoffset; /* node offset from libfdt */ + const void *nodep; /* property node pointer */ + int len = 0; /* new length of the property */ + + /* + * Parameters: Node path, property, optional value. + */ + if (argc < 5) + return CMD_RET_USAGE; + + subcmd = argv[2]; + + if (argc < 6 && subcmd[0] != 's') + return CMD_RET_USAGE; + + var = argv[3]; + pathp = argv[4]; + prop = argv[5]; + + nodeoffset = fdt_path_offset(working_fdt, pathp); + if (nodeoffset < 0) { + /* + * Not found or something else bad happened. + */ + printf("libfdt fdt_path_offset() returned %s\n", + fdt_strerror(nodeoffset)); + return 1; + } + + if (subcmd[0] == 'n' || (subcmd[0] == 's' && argc == 5)) { + int reqIndex = -1; + int startDepth = fdt_node_depth( + working_fdt, nodeoffset); + int curDepth = startDepth; + int curIndex = -1; + int nextNodeOffset = fdt_next_node( + working_fdt, nodeoffset, &curDepth); + + if (subcmd[0] == 'n') + reqIndex = simple_strtoul(argv[5], NULL, 16); + + while (curDepth > startDepth) { + if (curDepth == startDepth + 1) + curIndex++; + if (subcmd[0] == 'n' && curIndex == reqIndex) { + const char *nodeName = fdt_get_name( + working_fdt, nextNodeOffset, NULL); + + setenv(var, (char *)nodeName); + return 0; + } + nextNodeOffset = fdt_next_node( + working_fdt, nextNodeOffset, &curDepth); + if (nextNodeOffset < 0) + break; + } + if (subcmd[0] == 's') { + /* get the num nodes at this level */ + char buf[11]; + + sprintf(buf, "%d", curIndex + 1); + setenv(var, buf); + } else { + /* node index not found */ + printf("libfdt node not found\n"); + return 1; + } + } else { + nodep = fdt_getprop( + working_fdt, nodeoffset, prop, &len); + if (len == 0) { + /* no property value */ + setenv(var, ""); + return 0; + } else if (len > 0) { + if (subcmd[0] == 'v') { + int ret; + + ret = fdt_value_setenv(nodep, len, var); + if (ret != 0) + return ret; + } else if (subcmd[0] == 'a') { + /* Get address */ + char buf[11]; + + sprintf(buf, "0x%08X", (uint32_t)nodep); + setenv(var, buf); + } else if (subcmd[0] == 's') { + /* Get size */ + char buf[11]; + + sprintf(buf, "0x%08X", len); + setenv(var, buf); + } else + return CMD_RET_USAGE; + return 0; + } else { + printf("libfdt fdt_getprop(): %s\n", + fdt_strerror(len)); + return 1; + } + } + /* * Print (recursive) / List (single level) */ @@ -825,6 +965,10 @@ U_BOOT_CMD( "fdt resize - Resize fdt to size + padding to 4k addr\n" "fdt print <path> [<prop>] - Recursive print starting at <path>\n" "fdt list <path> [<prop>] - Print one level starting at <path>\n" + "fdt get value <var> <path> <prop> - Get <property> and store in <var>\n" + "fdt get name <var> <path> <index> - Get name of node <index> and store in <var>\n" + "fdt get addr <var> <path> <prop> - Get start address of <property> and store in <var>\n" + "fdt get size <var> <path> [<prop>] - Get size of [<property>] or num nodes and store in <var>\n" "fdt set <path> <prop> [<val>] - Set <property> [to <val>]\n" "fdt mknode <path> <node> - Create a new node after <path>\n" "fdt rm <path> [<prop>] - Delete the node or <property>\n"

On Fri, Aug 17, 2012 at 10:34:37AM -0000, Joe Hershberger wrote:
Add commands to access data in the fdt. This allows data from a dtb or itb to be accessed from the shell scripts.
Signed-off-by: Joe Hershberger joe.hershberger@ni.com
This adds: $ uboot-build.sh sandbox Testing sandbox on -00386-g5e8f983 Thu Oct 25 14:07:28 MST 2012 Configuring for sandbox board... text data bss dec hex filename 143101 6424 28488 178013 2b75d sandbox/u-boot cmd_fdt.c: In function 'do_fdt': cmd_fdt.c:378:29: warning: cast from pointer to integer of different size [-Wpointer-to-int-cast]

Scripts in the ITB format will have spaces in them and will end in a newline charachter. Make sure that these are considered printable.
Signed-off-by: Joe Hershberger joe.hershberger@ni.com --- common/cmd_fdt.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/common/cmd_fdt.c b/common/cmd_fdt.c index 60983af..6ba0e86 100644 --- a/common/cmd_fdt.c +++ b/common/cmd_fdt.c @@ -743,12 +743,12 @@ static int is_printable_string(const void *data, int len) if (len == 0) return 0;
- /* must terminate with zero */ - if (s[len - 1] != '\0') + /* must terminate with zero or '\n' */ + if (s[len - 1] != '\0' && s[len - 1] != '\n') return 0;
/* printable or a null byte (concatenated strings) */ - while (((*s == '\0') || isprint(*s)) && (len > 0)) { + while (((*s == '\0') || isprint(*s) || isspace(*s)) && (len > 0)) { /* * If we see a null, there are three possibilities: * 1) If len == 1, it is the end of the string, printable

Allow the itb file to declare to u-boot that its hash should not be checked automatically on bootm or iminfo. This allows an image to either be checked automatically or to include a script which may check it otherwise (such as after part of the itb has been relocated to RAM by the script).
Signed-off-by: Joe Hershberger joe.hershberger@ni.com --- common/image.c | 41 +++++++++++++++++++++++++++++++++++++++++ include/image.h | 4 ++++ 2 files changed, 45 insertions(+)
diff --git a/common/image.c b/common/image.c index 4252e63..948ce0d 100644 --- a/common/image.c +++ b/common/image.c @@ -2494,6 +2494,36 @@ int fit_image_hash_get_value(const void *fit, int noffset, uint8_t **value, return 0; }
+#ifndef USE_HOSTCC +/** + * fit_image_hash_get_ignore - get hash ignore flag + * @fit: pointer to the FIT format image header + * @noffset: hash node offset + * @ignore: pointer to an int, will hold hash ignore flag + * + * fit_image_hash_get_ignore() finds hash ignore property in a given hash node. + * If the property is found and non-zero, the hash algorithm is not verified by + * u-boot automatically. + * + * returns: + * 0, on ignore not found + * value, on ignore found + */ +int fit_image_hash_get_ignore(const void *fit, int noffset, int *ignore) +{ + int len; + int *value; + + value = (int *)fdt_getprop(fit, noffset, FIT_IGNORE_PROP, &len); + if (value == NULL || len != sizeof(int)) + *ignore = 0; + else + *ignore = *value; + + return 0; +} +#endif + /** * fit_set_timestamp - set node timestamp property * @fit: pointer to the FIT format image header @@ -2757,6 +2787,9 @@ int fit_image_check_hashes(const void *fit, int image_noffset) char *algo; uint8_t *fit_value; int fit_value_len; +#ifndef USE_HOSTCC + int ignore; +#endif uint8_t value[FIT_MAX_HASH_LEN]; int value_len; int noffset; @@ -2793,6 +2826,14 @@ int fit_image_check_hashes(const void *fit, int image_noffset) } printf("%s", algo);
+#ifndef USE_HOSTCC + fit_image_hash_get_ignore(fit, noffset, &ignore); + if (ignore) { + printf("-skipped "); + continue; + } +#endif + if (fit_image_hash_get_value(fit, noffset, &fit_value, &fit_value_len)) { err_msg = " error!\nCan't get hash value " diff --git a/include/image.h b/include/image.h index aa9daa2..8e9daf3 100644 --- a/include/image.h +++ b/include/image.h @@ -510,6 +510,7 @@ static inline int image_check_target_arch(const image_header_t *hdr) #define FIT_HASH_NODENAME "hash" #define FIT_ALGO_PROP "algo" #define FIT_VALUE_PROP "value" +#define FIT_IGNORE_PROP "uboot-ignore"
/* image node */ #define FIT_DATA_PROP "data" @@ -594,6 +595,9 @@ int fit_image_get_data(const void *fit, int noffset, int fit_image_hash_get_algo(const void *fit, int noffset, char **algo); int fit_image_hash_get_value(const void *fit, int noffset, uint8_t **value, int *value_len); +#ifndef USE_HOSTCC +int fit_image_hash_get_ignore(const void *fit, int noffset, int *ignore); +#endif
int fit_set_timestamp(void *fit, int noffset, time_t timestamp); int fit_set_hashes(void *fit);

Designed to be able to access itb files on a filesystem or an mtd partition.
Supports print and list (like the fdt command) and also offset for finding the offset and size of a given property in an FDT file.
This is especially helpful when reading properties from an ITB file.
Signed-off-by: Joe Hershberger joe.hershberger@ni.com --- Makefile | 2 +- tools/fdtview/Makefile | 52 ++++++ tools/fdtview/fdtview.c | 483 ++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 536 insertions(+), 1 deletion(-) create mode 100644 tools/fdtview/Makefile create mode 100644 tools/fdtview/fdtview.c
diff --git a/Makefile b/Makefile index 5ce5cc3..163fb4c 100644 --- a/Makefile +++ b/Makefile @@ -659,7 +659,7 @@ $(TIMESTAMP_FILE): @LC_ALL=C date +'#define U_BOOT_TIME "%T"' >> $@.tmp @cmp -s $@ $@.tmp && rm -f $@.tmp || mv -f $@.tmp $@
-easylogo env gdb: +easylogo env fdtview gdb: $(MAKE) -C tools/$@ all MTD_VERSION=${MTD_VERSION} gdbtools: gdb
diff --git a/tools/fdtview/Makefile b/tools/fdtview/Makefile new file mode 100644 index 0000000..5f1488b --- /dev/null +++ b/tools/fdtview/Makefile @@ -0,0 +1,52 @@ + +include $(TOPDIR)/config.mk + +# Source files which exist outside the tools/fdtview directory +EXT_SRC_FILES-y += lib/crc32.c +EXT_SRC_FILES-y += lib/ctype.c +EXT_SRC_FILES-y += lib/md5.c +EXT_SRC_FILES-y += lib/sha1.c +EXT_SRC_FILES-y += common/image.c + +# Source files located in the tools/fdtview directory +SRC_FILES-y += fdtview.c + +# Flattened device tree objects +LIBFDT_SRC_FILES-y += fdt.c +LIBFDT_SRC_FILES-y += fdt_ro.c +LIBFDT_SRC_FILES-y += fdt_rw.c +LIBFDT_SRC_FILES-y += fdt_strerror.c +LIBFDT_SRC_FILES-y += fdt_wip.c + +HOSTSRCS += $(addprefix $(SRCTREE)/,$(EXT_SRC_FILES-y)) +HOSTSRCS += $(addprefix $(SRCTREE)/tools/fdtview/,$(SRC_FILES-y)) +HOSTSRCS += $(addprefix $(SRCTREE)/lib/libfdt/,$(LIBFDT_SRC_FILES-y)) + +$(warning $(HOSTSRCS)) +# +# Use native tools and options +# Define __KERNEL_STRICT_NAMES to prevent typedef overlaps +# +HOSTCPPFLAGS = -idirafter $(SRCTREE)/include \ + -idirafter $(OBJTREE)/include2 \ + -idirafter $(OBJTREE)/include \ + -I $(SRCTREE)/libfdt \ + -I $(SRCTREE)/tools \ + -DUSE_HOSTCC -D__KERNEL_STRICT_NAMES + +all : $(obj)fdtview$(SFX) + +$(obj)fdtview$(SFX) : $(HOSTSRCS) + $(HOSTCC) $(HOSTCFLAGS_NOPED) $(HOSTLDFLAGS) -o $@ $(HOSTSRCS) + $(HOSTSTRIP) $@ + +clean: + rm -rf $(obj)*.o $(obj)fdtview + +######################################################################### + +include $(TOPDIR)/rules.mk + +sinclude $(obj).depend + +######################################################################### diff --git a/tools/fdtview/fdtview.c b/tools/fdtview/fdtview.c new file mode 100644 index 0000000..70b3243 --- /dev/null +++ b/tools/fdtview/fdtview.c @@ -0,0 +1,483 @@ + +#include "os_support.h" +#include <errno.h> +#include <fcntl.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <sys/ioctl.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <time.h> +#include <unistd.h> +#include <sha1.h> +#include "fdt_host.h" +#include <image.h> +#include <linux/ctype.h> +#include <mtd/mtd-user.h> + +#define MAX_LEVEL 32 /* how deeply nested we will go */ + +static void usage(void); + +struct fdtview_params { + char *path; + char *propname; + char *imagefile; + char *cmdname; + int lflag; + int oflag; + int pflag; +} params; + +/* + * Heuristic to guess if this is a string or concatenated strings. + */ +static int is_printable_string(const void *data, int len) +{ + const char *s = data; + + /* zero length is not */ + if (len == 0) + return 0; + + /* must terminate with zero */ + if (s[len - 1] != '\0' && s[len - 1] != '\n') + return 0; + + /* printable or a null byte (concatenated strings) */ + while (((*s == '\0') || isprint(*s) || isspace(*s)) && (len > 0)) { + /* + * If we see a null, there are three possibilities: + * 1) If len == 1, it is the end of the string, printable + * 2) Next character also a null, not printable. + * 3) Next character not a null, continue to check. + */ + if (s[0] == '\0') { + if (len == 1) + return 1; + if (s[1] == '\0') + return 0; + } + s++; + len--; + } + + /* Not the null termination, or not done yet: not printable */ + if (*s != '\0' || len != 0) + return 0; + + return 1; +} + +/* + * Print the property in the best format, a heuristic guess. Print as + * a string, concatenated strings, a byte, word, double word, or (if all + * else fails) it is printed as a stream of bytes. + */ +static void print_data(const void *data, int len) +{ + int j; + + /* no data, don't print */ + if (len == 0) + return; + + /* + * It is a string, but it may have multiple strings (embedded '\0's). + */ + if (is_printable_string(data, len)) { + printf("""); + j = 0; + while (j < len) { + if (j > 0) + printf("", ""); + printf(data); + j += strlen(data) + 1; + data += strlen(data) + 1; + } + printf("""); + return; + } + + if ((len % 4) == 0) { + const unsigned int *p; + + printf("<"); + for (j = 0, p = data; j < len/4; j++) + printf("0x%x%s", + fdt32_to_cpu(p[j]), j < (len/4 - 1) ? " " : ""); + printf(">"); + } else { /* anything else... hexdump */ + const unsigned char *s; + + printf("["); + for (j = 0, s = data; j < len; j++) + printf("%02x%s", s[j], j < len - 1 ? " " : ""); + printf("]"); + } +} + +/* + * Recursively print (a portion of) the working_fdt. The depth parameter + * determines how deeply nested the fdt is printed. + */ +static int fdt_print(unsigned char *working_fdt, const char *pathp, + char *prop, int depth) +{ + static char tabs[MAX_LEVEL+1] = + "\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t" + "\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t"; + const void *nodep; /* property node pointer */ + int nodeoffset; /* node offset from libfdt */ + int nextoffset; /* next node offset from libfdt */ + uint32_t tag; /* tag */ + int len; /* length of the property */ + int level = 0; /* keep track of nesting level */ + const struct fdt_property *fdt_prop; + + nodeoffset = fdt_path_offset(working_fdt, pathp); + if (nodeoffset < 0) { + /* + * Not found or something else bad happened. + */ + printf("libfdt fdt_path_offset() returned %s\n", + fdt_strerror(nodeoffset)); + return 1; + } + /* + * The user passed in a property as well as node path. + * Print only the given property and then return. + */ + if (prop) { + nodep = fdt_getprop(working_fdt, nodeoffset, prop, &len); + if (len == 0) { + /* no property value */ + printf("%s %s\n", pathp, prop); + return 0; + } else if (len > 0) { + printf("%s = ", prop); + print_data(nodep, len); + printf("\n"); + return 0; + } else { + printf("libfdt fdt_getprop(): %s\n", + fdt_strerror(len)); + return 1; + } + } + + /* + * The user passed in a node path and no property, + * print the node and all subnodes. + */ + while (level >= 0) { + tag = fdt_next_tag(working_fdt, nodeoffset, &nextoffset); + switch (tag) { + case FDT_BEGIN_NODE: + pathp = fdt_get_name(working_fdt, nodeoffset, NULL); + if (level <= depth) { + if (pathp == NULL) + pathp = "/* NULL pointer error */"; + if (*pathp == '\0') + pathp = "/"; /* root is nameless */ + printf("%s%s {\n", + &tabs[MAX_LEVEL - level], pathp); + } + level++; + if (level >= MAX_LEVEL) { + printf("Nested too deep, aborting.\n"); + return 1; + } + break; + case FDT_END_NODE: + level--; + if (level <= depth) + printf("%s};\n", &tabs[MAX_LEVEL - level]); + if (level == 0) + level = -1; /* exit the loop */ + break; + case FDT_PROP: + fdt_prop = fdt_offset_ptr(working_fdt, nodeoffset, + sizeof(*fdt_prop)); + pathp = fdt_string(working_fdt, + fdt32_to_cpu(fdt_prop->nameoff)); + len = fdt32_to_cpu(fdt_prop->len); + nodep = fdt_prop->data; + if (len < 0) { + printf("libfdt fdt_getprop(): %s\n", + fdt_strerror(len)); + return 1; + } else if (len == 0) { + /* the property has no value */ + if (level <= depth) + printf("%s%s;\n", + &tabs[MAX_LEVEL - level], + pathp); + } else { + if (level <= depth) { + printf("%s%s = ", + &tabs[MAX_LEVEL - level], + pathp); + print_data(nodep, len); + printf(";\n"); + } + } + break; + case FDT_NOP: + printf("%s/* NOP */\n", &tabs[MAX_LEVEL - level]); + break; + case FDT_END: + return 1; + default: + if (level <= depth) + printf("Unknown tag 0x%08X\n", tag); + return 1; + } + nodeoffset = nextoffset; + } + return 0; +} + +int main(int argc, char **argv) +{ + int ifd = -1; + struct stat sbuf; + unsigned char *working_fdt; + int retval = 0; + struct mtd_info_user mtd; + off_t file_size = 0; + int mmap_failed = 0; + + params.cmdname = *argv; + params.lflag = 0; + params.oflag = 0; + params.pflag = 0; + + while (--argc > 0 && **++argv == '-') { + while (*++*argv) { + switch (**argv) { + case 'l': + if (argc <= 1) + usage(); + if (argc >= 3) { + params.path = *++argv; + --argc; + } else { + params.path = NULL; + } + if (argc == 3) { + params.propname = *++argv; + --argc; + } else { + params.propname = NULL; + } + params.lflag = 1; + goto NXTARG; + case 'o': + --argc; + if (--argc <= 1) + usage(); + params.path = *++argv; + params.propname = *++argv; + params.oflag = 1; + goto NXTARG; + case 'p': + if (argc <= 1) + usage(); + if (argc >= 3) { + params.path = *++argv; + --argc; + } else { + params.path = NULL; + } + if (argc == 3) { + params.propname = *++argv; + --argc; + } else { + params.propname = NULL; + } + params.pflag = 1; + goto NXTARG; + default: + usage(); + } + } +NXTARG:; + } + + if (argc != 1) + usage(); + + if (!params.lflag && !params.oflag && !params.pflag) + usage(); + + params.imagefile = *argv; + + ifd = open(params.imagefile, O_RDONLY|O_BINARY|O_SYNC); + + if (ifd < 0) { + fprintf(stderr, "%s: Can't open %s: %s\n", + params.cmdname, params.imagefile, + strerror(errno)); + exit(EXIT_FAILURE); + } + + if (fstat(ifd, &sbuf) < 0) { + fprintf(stderr, "%s: Can't stat %s: %s\n", + params.cmdname, params.imagefile, + strerror(errno)); + exit(EXIT_FAILURE); + } else { + file_size = sbuf.st_size; + } + + if ((sbuf.st_rdev & 0xFF00) == 0x1F00) { + fprintf(stderr, "%s: Can't access the block interface to %s\n", + params.cmdname, params.imagefile); + exit(EXIT_FAILURE); + } + if ((sbuf.st_rdev & 0xFF00) == 0x5A00) { + if (ioctl(ifd, MEMGETINFO, mtd) < 0) { + fprintf(stderr, "%s: Can't query mem info for %s: %s\n", + params.cmdname, params.imagefile, + strerror(errno)); + exit(EXIT_FAILURE); + } else { + file_size = mtd.size; + } + } + + if ((unsigned)file_size < sizeof(image_header_t)) { + fprintf(stderr, + "%s: Bad size: "%s" is not valid image\n", + params.cmdname, params.imagefile); + exit(EXIT_FAILURE); + } + + working_fdt = mmap(0, file_size, PROT_READ, MAP_SHARED, ifd, 0); + if (working_fdt == MAP_FAILED) { + int readsize; + int totalsize; + mmap_failed = 1; + + printf("mmap() failed. Falling back to read."); + working_fdt = malloc(sizeof(image_header_t)); + if (working_fdt == NULL) { + fprintf(stderr, "%s: malloc of %d" + " bytes (header) failed: %s\n", + params.cmdname, (int) file_size, + strerror(errno)); + retval = 1; + goto error; + } + readsize = read(ifd, working_fdt, sizeof(image_header_t)); + if (readsize < 0) { + fprintf(stderr, "%s: Can't read header from %s: %s\n", + params.cmdname, params.imagefile, + strerror(errno)); + retval = readsize; + goto error; + } + retval = fdt_check_header((void *) working_fdt); + if (retval < 0) { + fprintf(stderr, "%s: Invalid image %s\n", + params.cmdname, params.imagefile); + goto error; + } + totalsize = fdt_totalsize(working_fdt); + if (totalsize < 0) { + fprintf(stderr, "%s: Invalid image size: %d\n", + params.cmdname, totalsize); + retval = totalsize; + goto error; + } + if (file_size > totalsize) + file_size = totalsize; + working_fdt = realloc(working_fdt, file_size); + if (working_fdt == NULL) { + fprintf(stderr, "%s: malloc of %d bytes failed: %s\n", + params.cmdname, (int) file_size, + strerror(errno)); + retval = 1; + goto error; + } + if (read(ifd, working_fdt + readsize, + file_size - readsize) < 0) { + fprintf(stderr, "%s: Can't read %s: %s\n", + params.cmdname, params.imagefile, + strerror(errno)); + retval = readsize; + goto error; + } + } + + retval = fdt_check_header((void *)working_fdt); + if (retval < 0) { + fprintf(stderr, "%s: Invalid image %s\n", + params.cmdname, params.imagefile); + goto error; + } + + if (params.oflag) { + int offset; + offset = fdt_path_offset(working_fdt, params.path); + if (offset > 0) { + int propLength = 0; + const unsigned char *propData = (const uint8_t *) + fdt_getprop(working_fdt, offset, + params.propname, &propLength); + if (propLength >= 0) + printf("%d %d\n", propData - working_fdt, + propLength); + } else { + retval = offset; + goto error; + } + } else if (params.lflag || params.pflag) { + int depth = MAX_LEVEL; /* how deep to print */ + int ret; /* return value */ + static char root[2] = "/"; + + /* + * list is an alias for print, but limited to 1 level + */ + if (params.lflag) + depth = 1; + + /* + * Get the starting path. The root node is an oddball, + * the offset is zero and has no name. + */ + if (params.path == NULL) + params.path = root; + + ret = fdt_print(working_fdt, params.path, params.propname, + depth); + if (ret != 0) + return ret; + } + +error: + if (mmap_failed) + free(working_fdt); + else + munmap((void *)working_fdt, file_size); + + close(ifd); + + exit(retval); +} + + +static void usage() +{ + fprintf(stderr, " %s [-l [path [propname]] | -o path propname |" + " -p [path [propname]]] image\n" + " -l ==> Print one level starting at <path>\n" + " -o ==> print the offset and size of a property\n" + " -p ==> Recursive print starting at <path>\n", + params.cmdname); + + exit(EXIT_FAILURE); +}

On Friday 17 August 2012 16:34:40 Joe Hershberger wrote:
Designed to be able to access itb files on a filesystem or an mtd partition.
Supports print and list (like the fdt command) and also offset for finding the offset and size of a given property in an FDT file.
This is especially helpful when reading properties from an ITB file.
doesn't the ftdump utility from the dtc package cover your needs ? -mike

Hi Mike,
On Fri, Aug 17, 2012 at 6:35 PM, Mike Frysinger vapier@gentoo.org wrote:
On Friday 17 August 2012 16:34:40 Joe Hershberger wrote:
Designed to be able to access itb files on a filesystem or an mtd partition.
Supports print and list (like the fdt command) and also offset for finding the offset and size of a given property in an FDT file.
This is especially helpful when reading properties from an ITB file.
doesn't the ftdump utility from the dtc package cover your needs ?
No. The purpose is to use this utility e.g. in a Linux shell script to retrieve a property from the ITB. The two places I use it are to retrieve a version number from the ITB and to identify the offset and size of a data block (image) in the ITB.
From what I can see the ftdump utility in the dtc component just dumps
the ITB as a single blob with no options. I'm looking at the dtc 1.2.0 source.
-Joe

On Monday 20 August 2012 19:40:45 Joe Hershberger wrote:
On Fri, Aug 17, 2012 at 6:35 PM, Mike Frysinger wrote:
On Friday 17 August 2012 16:34:40 Joe Hershberger wrote:
Designed to be able to access itb files on a filesystem or an mtd partition.
Supports print and list (like the fdt command) and also offset for finding the offset and size of a given property in an FDT file.
This is especially helpful when reading properties from an ITB file.
doesn't the ftdump utility from the dtc package cover your needs ?
No. The purpose is to use this utility e.g. in a Linux shell script to retrieve a property from the ITB. The two places I use it are to retrieve a version number from the ITB and to identify the offset and size of a data block (image) in the ITB.
From what I can see the ftdump utility in the dtc component just dumps the ITB as a single blob with no options. I'm looking at the dtc 1.2.0 source.
... so wouldn't the logical thing be to extend ftdump to support your needs and send a patch to the DTC authors rather than to write an entire tool from scratch and commit it to a tree that is merely a user of device trees ? -mike

Hi Mike,
On Mon, Aug 20, 2012 at 7:24 PM, Mike Frysinger vapier@gentoo.org wrote:
On Monday 20 August 2012 19:40:45 Joe Hershberger wrote:
On Fri, Aug 17, 2012 at 6:35 PM, Mike Frysinger wrote:
On Friday 17 August 2012 16:34:40 Joe Hershberger wrote:
Designed to be able to access itb files on a filesystem or an mtd partition.
Supports print and list (like the fdt command) and also offset for finding the offset and size of a given property in an FDT file.
This is especially helpful when reading properties from an ITB file.
doesn't the ftdump utility from the dtc package cover your needs ?
No. The purpose is to use this utility e.g. in a Linux shell script to retrieve a property from the ITB. The two places I use it are to retrieve a version number from the ITB and to identify the offset and size of a data block (image) in the ITB.
From what I can see the ftdump utility in the dtc component just dumps the ITB as a single blob with no options. I'm looking at the dtc 1.2.0 source.
... so wouldn't the logical thing be to extend ftdump to support your needs and send a patch to the DTC authors rather than to write an entire tool from scratch and commit it to a tree that is merely a user of device trees ?
Yes it probably would have been, if I had noticed that the ftdump utility existed, then that is the approach I would have taken. I think it is of specific use to u-boot users, but if you think it's better to extend ftdump, I guess I could take that approach.
-Joe

On Monday 20 August 2012 20:51:32 Joe Hershberger wrote:
On Mon, Aug 20, 2012 at 7:24 PM, Mike Frysinger wrote:
On Monday 20 August 2012 19:40:45 Joe Hershberger wrote:
On Fri, Aug 17, 2012 at 6:35 PM, Mike Frysinger wrote:
On Friday 17 August 2012 16:34:40 Joe Hershberger wrote:
Designed to be able to access itb files on a filesystem or an mtd partition.
Supports print and list (like the fdt command) and also offset for finding the offset and size of a given property in an FDT file.
This is especially helpful when reading properties from an ITB file.
doesn't the ftdump utility from the dtc package cover your needs ?
No. The purpose is to use this utility e.g. in a Linux shell script to retrieve a property from the ITB. The two places I use it are to retrieve a version number from the ITB and to identify the offset and size of a data block (image) in the ITB.
From what I can see the ftdump utility in the dtc component just dumps the ITB as a single blob with no options. I'm looking at the dtc 1.2.0 source.
... so wouldn't the logical thing be to extend ftdump to support your needs and send a patch to the DTC authors rather than to write an entire tool from scratch and commit it to a tree that is merely a user of device trees ?
Yes it probably would have been, if I had noticed that the ftdump utility existed, then that is the approach I would have taken. I think it is of specific use to u-boot users, but if you think it's better to extend ftdump, I guess I could take that approach.
i think it has a better chance of being maintained and other people using it if it were merged into the canonical DTC project. i can see a more swiss army type tool being useful to people rather than having to pipe it all through awk.
git: git://git.jdl.com/software/dtc.git e-mail: devicetree-discuss@lists.ozlabs.org
they're friendly people :) -mike

Dear Mike Frysinger,
On Monday 20 August 2012 20:51:32 Joe Hershberger wrote:
On Mon, Aug 20, 2012 at 7:24 PM, Mike Frysinger wrote:
On Monday 20 August 2012 19:40:45 Joe Hershberger wrote:
On Fri, Aug 17, 2012 at 6:35 PM, Mike Frysinger wrote:
On Friday 17 August 2012 16:34:40 Joe Hershberger wrote:
Designed to be able to access itb files on a filesystem or an mtd partition.
Supports print and list (like the fdt command) and also offset for finding the offset and size of a given property in an FDT file.
This is especially helpful when reading properties from an ITB file.
doesn't the ftdump utility from the dtc package cover your needs ?
No. The purpose is to use this utility e.g. in a Linux shell script to retrieve a property from the ITB. The two places I use it are to retrieve a version number from the ITB and to identify the offset and size of a data block (image) in the ITB.
From what I can see the ftdump utility in the dtc component just dumps the ITB as a single blob with no options. I'm looking at the dtc 1.2.0 source.
... so wouldn't the logical thing be to extend ftdump to support your needs and send a patch to the DTC authors rather than to write an entire tool from scratch and commit it to a tree that is merely a user of device trees ?
Yes it probably would have been, if I had noticed that the ftdump utility existed, then that is the approach I would have taken. I think it is of specific use to u-boot users, but if you think it's better to extend ftdump, I guess I could take that approach.
i think it has a better chance of being maintained and other people using it if it were merged into the canonical DTC project. i can see a more swiss army type tool being useful to people rather than having to pipe it all through awk.
git: git://git.jdl.com/software/dtc.git e-mail: devicetree-discuss@lists.ozlabs.org
they're friendly people :)
Mostly :-)
Best regards, Marek Vasut

Hi Jerry,
On Fri, Aug 17, 2012 at 3:34 PM, Joe Hershberger joe.hershberger@ni.com wrote:
Before this patch, error codes returned from fdtlib were ignored and continued access would cause a crash. Now just check if the image is truncated and error if so.
Signed-off-by: Joe Hershberger joe.hershberger@ni.com
What's the progress on this series? I know Mike didn't like the last patch (6 of 6), but the first 5 should be good to go. I'd like them to be in the 2012.10 release.
Are you able to apply them through your branch? Or maybe ack and go through Tom?
Thanks, -Joe

Hi Joe, Tom,
On 10/04/2012 01:38 PM, Joe Hershberger wrote:
Hi Jerry,
On Fri, Aug 17, 2012 at 3:34 PM, Joe Hershberger joe.hershberger@ni.com wrote:
Before this patch, error codes returned from fdtlib were ignored and continued access would cause a crash. Now just check if the image is truncated and error if so.
Signed-off-by: Joe Hershberger joe.hershberger@ni.com
What's the progress on this series? I know Mike didn't like the last patch (6 of 6), but the first 5 should be good to go. I'd like them to be in the 2012.10 release.
Are you able to apply them through your branch? Or maybe ack and go through Tom?
The first 5 of the series look good to me. #1 and #5 touch image.c which is on the fringe of my FDT mandate.
Tom, do you want to pick the changes up? Unless you object, I'll apply them to the fdt subrepo and submit a pull request when the window opens.
Thanks, -Joe
Thanks, gvb

-----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1
On 10/08/12 16:45, Jerry Van Baren wrote:
Hi Joe, Tom,
On 10/04/2012 01:38 PM, Joe Hershberger wrote:
Hi Jerry,
On Fri, Aug 17, 2012 at 3:34 PM, Joe Hershberger joe.hershberger@ni.com wrote:
Before this patch, error codes returned from fdtlib were ignored and continued access would cause a crash. Now just check if the image is truncated and error if so.
Signed-off-by: Joe Hershberger joe.hershberger@ni.com ---
What's the progress on this series? I know Mike didn't like the last patch (6 of 6), but the first 5 should be good to go. I'd like them to be in the 2012.10 release.
Are you able to apply them through your branch? Or maybe ack and go through Tom?
The first 5 of the series look good to me. #1 and #5 touch image.c which is on the fringe of my FDT mandate.
Tom, do you want to pick the changes up? Unless you object, I'll apply them to the fdt subrepo and submit a pull request when the window opens.
Sounds fine with me so long as you're happy with the changes.
- -- Tom
participants (6)
-
Jerry Van Baren
-
Joe Hershberger
-
Joe Hershberger
-
Marek Vasut
-
Mike Frysinger
-
Tom Rini