* [0/10] Pending patches pull request
@ 2013-05-29 2:51 David Gibson
[not found] ` <1369795898-7631-1-git-send-email-david-xT8FGy+AXnRB3Ne2BGzF6laj5H9X9Tb+@public.gmane.org>
0 siblings, 1 reply; 12+ messages in thread
From: David Gibson @ 2013-05-29 2:51 UTC (permalink / raw)
To: jdl-CYoMK+44s/E; +Cc: devicetree-discuss-uLR06cmDAlY/bJ5BZ2RsiQ
Hi Jon,
Here's a batch of patches, a few from me, mostly from others, which I
think should go into dtc/libfdt. Please apply, or you can pull from:
git://github.com/dgibson/dtc.git (branch 'master')
^ permalink raw reply [flat|nested] 12+ messages in thread
* [PATCH 01/10] fdtdump: make usage a bit more friendly
[not found] ` <1369795898-7631-1-git-send-email-david-xT8FGy+AXnRB3Ne2BGzF6laj5H9X9Tb+@public.gmane.org>
@ 2013-05-29 2:51 ` David Gibson
2013-05-29 2:51 ` [PATCH 02/10] fdtdump: add a --scan option David Gibson
` (9 subsequent siblings)
10 siblings, 0 replies; 12+ messages in thread
From: David Gibson @ 2013-05-29 2:51 UTC (permalink / raw)
To: jdl-CYoMK+44s/E; +Cc: devicetree-discuss-uLR06cmDAlY/bJ5BZ2RsiQ
From: Mike Frysinger <vapier-aBrp7R+bbdUdnm+yROfE0A@public.gmane.org>
This starts a new usage framework and then cuts fdtdump over to it.
Now we can do `fdtdump -h` and get something useful back.
Signed-off-by: Mike Frysinger <vapier-aBrp7R+bbdUdnm+yROfE0A@public.gmane.org>
Signed-off-by: David Gibson <david-xT8FGy+AXnRB3Ne2BGzF6laj5H9X9Tb+@public.gmane.org>
---
fdtdump.c | 31 +++++++++++++++++++++++--------
util.c | 54 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
util.h | 61 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 138 insertions(+), 8 deletions(-)
diff --git a/fdtdump.c b/fdtdump.c
index 03ea429..a6e522c 100644
--- a/fdtdump.c
+++ b/fdtdump.c
@@ -117,21 +117,36 @@ static void dump_blob(void *blob)
}
}
+/* Usage related data. */
+static const char usage_synopsis[] = "fdtdump [options] <file>";
+static const char usage_short_opts[] = USAGE_COMMON_SHORT_OPTS;
+static struct option const usage_long_opts[] = {
+ USAGE_COMMON_LONG_OPTS
+};
+static const char * const usage_opts_help[] = {
+ USAGE_COMMON_OPTS_HELP
+};
int main(int argc, char *argv[])
{
+ int opt;
+ const char *file;
char *buf;
- if (argc < 2) {
- fprintf(stderr, "supply input filename\n");
- return 5;
+ while ((opt = util_getopt_long()) != EOF) {
+ switch (opt) {
+ case_USAGE_COMMON_FLAGS
+ }
}
+ if (optind != argc - 1)
+ long_usage("missing input filename");
+ file = argv[optind];
+
+ buf = utilfdt_read(file);
+ if (!buf)
+ die("could not read: %s\n", file);
- buf = utilfdt_read(argv[1]);
- if (buf)
- dump_blob(buf);
- else
- return 10;
+ dump_blob(buf);
return 0;
}
diff --git a/util.c b/util.c
index 350cf8b..d9a823a 100644
--- a/util.c
+++ b/util.c
@@ -392,3 +392,57 @@ void util_version(void)
printf("Version: %s\n", DTC_VERSION);
exit(0);
}
+
+void util_long_usage(const char *errmsg, const char *synopsis,
+ const char *short_opts, struct option const long_opts[],
+ const char * const opts_help[])
+{
+ FILE *fp = errmsg ? stderr : stdout;
+ const char a_arg[] = "<arg>";
+ size_t a_arg_len = strlen(a_arg) + 1;
+ size_t i;
+ int optlen;
+
+ fprintf(fp,
+ "Usage: %s\n"
+ "\n"
+ "Options: -[%s]\n", synopsis, short_opts);
+
+ /* prescan the --long opt length to auto-align */
+ optlen = 0;
+ for (i = 0; long_opts[i].name; ++i) {
+ /* +1 is for space between --opt and help text */
+ int l = strlen(long_opts[i].name) + 1;
+ if (long_opts[i].has_arg == a_argument)
+ l += a_arg_len;
+ if (optlen < l)
+ optlen = l;
+ }
+
+ for (i = 0; long_opts[i].name; ++i) {
+ /* helps when adding new applets or options */
+ assert(opts_help[i] != NULL);
+
+ /* first output the short flag if it has one */
+ if (long_opts[i].val > '~')
+ fprintf(fp, " ");
+ else
+ fprintf(fp, " -%c, ", long_opts[i].val);
+
+ /* then the long flag */
+ if (long_opts[i].has_arg == no_argument)
+ fprintf(fp, "--%-*s", optlen, long_opts[i].name);
+ else
+ fprintf(fp, "--%s %s%*s", long_opts[i].name, a_arg,
+ (int)(optlen - strlen(long_opts[i].name) - a_arg_len), "");
+
+ /* finally the help text */
+ fprintf(fp, "%s\n", opts_help[i]);
+ }
+
+ if (errmsg) {
+ fprintf(fp, "\nError: %s\n", errmsg);
+ exit(EXIT_FAILURE);
+ } else
+ exit(EXIT_SUCCESS);
+}
diff --git a/util.h b/util.h
index 95ae531..1da3bd3 100644
--- a/util.h
+++ b/util.h
@@ -2,6 +2,7 @@
#define _UTIL_H
#include <stdarg.h>
+#include <getopt.h>
/*
* Copyright 2011 The Chromium Authors, All Rights Reserved.
@@ -184,4 +185,64 @@ void utilfdt_print_data(const char *data, int len);
*/
void util_version(void) __attribute__((noreturn));
+/**
+ * Show usage and exit
+ *
+ * This helps standardize the output of various utils. You most likely want
+ * to use the long_usage() helper below rather than call this.
+ *
+ * @param errmsg If non-NULL, an error message to display
+ * @param synopsis The initial example usage text (and possible examples)
+ * @param short_opts The string of short options
+ * @param long_opts The structure of long options
+ * @param opts_help An array of help strings (should align with long_opts)
+ */
+void util_long_usage(const char *errmsg, const char *synopsis,
+ const char *short_opts, struct option const long_opts[],
+ const char * const opts_help[]) __attribute__((noreturn));
+
+/**
+ * Show usage and exit
+ *
+ * If you name all your usage variables with usage_xxx, then you can call this
+ * help macro rather than expanding all arguments yourself.
+ *
+ * @param errmsg If non-NULL, an error message to display
+ */
+#define long_usage(errmsg) \
+ util_long_usage(errmsg, usage_synopsis, usage_short_opts, \
+ usage_long_opts, usage_opts_help)
+
+/**
+ * Call getopt_long() with standard options
+ *
+ * Since all util code runs getopt in the same way, provide a helper.
+ */
+#define util_getopt_long() getopt_long(argc, argv, usage_short_opts, \
+ usage_long_opts, NULL)
+
+/* Helper for aligning long_opts array */
+#define a_argument required_argument
+
+/* Helper for usage_short_opts string constant */
+#define USAGE_COMMON_SHORT_OPTS "hV"
+
+/* Helper for usage_long_opts option array */
+#define USAGE_COMMON_LONG_OPTS \
+ {"help", no_argument, NULL, 'h'}, \
+ {"version", no_argument, NULL, 'V'}, \
+ {NULL, no_argument, NULL, 0x0}
+
+/* Helper for usage_opts_help array */
+#define USAGE_COMMON_OPTS_HELP \
+ "Print this help and exit", \
+ "Print version and exit", \
+ NULL
+
+/* Helper for getopt case statements */
+#define case_USAGE_COMMON_FLAGS \
+ case 'h': long_usage(NULL); \
+ case 'V': util_version(); \
+ case '?': long_usage("unknown option");
+
#endif /* _UTIL_H */
--
1.7.10.4
^ permalink raw reply related [flat|nested] 12+ messages in thread
* [PATCH 02/10] fdtdump: add a --scan option
[not found] ` <1369795898-7631-1-git-send-email-david-xT8FGy+AXnRB3Ne2BGzF6laj5H9X9Tb+@public.gmane.org>
2013-05-29 2:51 ` [PATCH 01/10] fdtdump: make usage a bit more friendly David Gibson
@ 2013-05-29 2:51 ` David Gibson
2013-05-29 2:51 ` [PATCH 03/10] dtc/fdt{get, put}/convert-dtsv0-lexer: convert to new usage helpers David Gibson
` (8 subsequent siblings)
10 siblings, 0 replies; 12+ messages in thread
From: David Gibson @ 2013-05-29 2:51 UTC (permalink / raw)
To: jdl-CYoMK+44s/E; +Cc: devicetree-discuss-uLR06cmDAlY/bJ5BZ2RsiQ
From: Mike Frysinger <vapier-aBrp7R+bbdUdnm+yROfE0A@public.gmane.org>
Often times, fdts get embedded in other larger files. Rather than force
people to `dd` the blob out themselves, make the fdtdump file smarter.
It can now scan the blob looking for the fdt magic. Once locate, it does
a little validation on the main struct to make sure we didn't hit random
binary data.
Signed-off-by: Mike Frysinger <vapier-aBrp7R+bbdUdnm+yROfE0A@public.gmane.org>
Signed-off-by: David Gibson <david-xT8FGy+AXnRB3Ne2BGzF6laj5H9X9Tb+@public.gmane.org>
---
fdtdump.c | 46 ++++++++++++++++++++++++++++++++++++++++++++--
1 file changed, 44 insertions(+), 2 deletions(-)
diff --git a/fdtdump.c b/fdtdump.c
index a6e522c..c8a3ee7 100644
--- a/fdtdump.c
+++ b/fdtdump.c
@@ -2,12 +2,14 @@
* fdtdump.c - Contributed by Pantelis Antoniou <pantelis.antoniou AT gmail.com>
*/
+#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
+#include <libfdt.h>
#include <libfdt_env.h>
#include <fdt.h>
@@ -119,11 +121,13 @@ static void dump_blob(void *blob)
/* Usage related data. */
static const char usage_synopsis[] = "fdtdump [options] <file>";
-static const char usage_short_opts[] = USAGE_COMMON_SHORT_OPTS;
+static const char usage_short_opts[] = "s" USAGE_COMMON_SHORT_OPTS;
static struct option const usage_long_opts[] = {
+ {"scan", no_argument, NULL, 's'},
USAGE_COMMON_LONG_OPTS
};
static const char * const usage_opts_help[] = {
+ "Scan for an embedded fdt in file",
USAGE_COMMON_OPTS_HELP
};
@@ -132,20 +136,58 @@ int main(int argc, char *argv[])
int opt;
const char *file;
char *buf;
+ bool scan = false;
+ off_t len;
while ((opt = util_getopt_long()) != EOF) {
switch (opt) {
case_USAGE_COMMON_FLAGS
+
+ case 's':
+ scan = true;
+ break;
}
}
if (optind != argc - 1)
long_usage("missing input filename");
file = argv[optind];
- buf = utilfdt_read(file);
+ buf = utilfdt_read_len(file, &len);
if (!buf)
die("could not read: %s\n", file);
+ /* try and locate an embedded fdt in a bigger blob */
+ if (scan) {
+ unsigned char smagic[4];
+ char *p = buf;
+ char *endp = buf + len;
+
+ fdt_set_magic(smagic, FDT_MAGIC);
+
+ /* poor man's memmem */
+ while (true) {
+ p = memchr(p, smagic[0], endp - p - 4);
+ if (!p)
+ break;
+ if (fdt_magic(p) == FDT_MAGIC) {
+ /* try and validate the main struct */
+ off_t this_len = endp - p;
+ fdt32_t max_version = 17;
+ if (fdt_version(p) <= max_version &&
+ fdt_last_comp_version(p) < max_version &&
+ fdt_totalsize(p) < this_len &&
+ fdt_off_dt_struct(p) < this_len &&
+ fdt_off_dt_strings(p) < this_len)
+ break;
+ }
+ ++p;
+ }
+ if (!p)
+ die("%s: could not locate fdt magic\n", file);
+ printf("%s: found fdt at offset %#zx\n", file, p - buf);
+ buf = p;
+ }
+
dump_blob(buf);
return 0;
--
1.7.10.4
^ permalink raw reply related [flat|nested] 12+ messages in thread
* [PATCH 03/10] dtc/fdt{get, put}/convert-dtsv0-lexer: convert to new usage helpers
[not found] ` <1369795898-7631-1-git-send-email-david-xT8FGy+AXnRB3Ne2BGzF6laj5H9X9Tb+@public.gmane.org>
2013-05-29 2:51 ` [PATCH 01/10] fdtdump: make usage a bit more friendly David Gibson
2013-05-29 2:51 ` [PATCH 02/10] fdtdump: add a --scan option David Gibson
@ 2013-05-29 2:51 ` David Gibson
2013-05-29 2:51 ` [PATCH 04/10] util: drop "long" from " David Gibson
` (7 subsequent siblings)
10 siblings, 0 replies; 12+ messages in thread
From: David Gibson @ 2013-05-29 2:51 UTC (permalink / raw)
To: jdl-CYoMK+44s/E; +Cc: devicetree-discuss-uLR06cmDAlY/bJ5BZ2RsiQ
From: Mike Frysinger <vapier-aBrp7R+bbdUdnm+yROfE0A@public.gmane.org>
This helps standardize the flag processing and the usage screens.
Only lightly tested; would be great if someone who uses these utils
could double check.
Signed-off-by: Mike Frysinger <vapier-aBrp7R+bbdUdnm+yROfE0A@public.gmane.org>
Signed-off-by: David Gibson <david-xT8FGy+AXnRB3Ne2BGzF6laj5H9X9Tb+@public.gmane.org>
---
convert-dtsv0-lexer.l | 22 +++++++---
dtc.c | 111 ++++++++++++++++++++++++++-----------------------
fdtget.c | 60 ++++++++++++--------------
fdtput.c | 63 +++++++++++++---------------
util.h | 2 +-
5 files changed, 131 insertions(+), 127 deletions(-)
diff --git a/convert-dtsv0-lexer.l b/convert-dtsv0-lexer.l
index 89d540a..e62d27a 100644
--- a/convert-dtsv0-lexer.l
+++ b/convert-dtsv0-lexer.l
@@ -194,11 +194,15 @@ const struct {
}
%%
-static void usage(void)
-{
- fprintf(stderr, "convert-dtsv0 <v0 dts file>...\n");
- exit(3);
-}
+/* Usage related data. */
+static const char usage_synopsis[] = "convert-dtsv0 [options] <v0 dts file>...";
+static const char usage_short_opts[] = "" USAGE_COMMON_SHORT_OPTS;
+static struct option const usage_long_opts[] = {
+ USAGE_COMMON_LONG_OPTS
+};
+static const char * const usage_opts_help[] = {
+ USAGE_COMMON_OPTS_HELP
+};
static void convert_file(const char *fname)
{
@@ -226,10 +230,16 @@ static void convert_file(const char *fname)
int main(int argc, char *argv[])
{
+ int opt;
int i;
+ while ((opt = util_getopt_long()) != EOF) {
+ switch (opt) {
+ case_USAGE_COMMON_FLAGS
+ }
+ }
if (argc < 2)
- usage();
+ long_usage("missing filename");
for (i = 1; i < argc; i++) {
fprintf(stderr, "Converting %s from dts v0 to dts v1\n", argv[i]);
diff --git a/dtc.c b/dtc.c
index e4e1b84..d0a1f2d 100644
--- a/dtc.c
+++ b/dtc.c
@@ -47,55 +47,60 @@ static void fill_fullpaths(struct node *tree, const char *prefix)
fill_fullpaths(child, tree->fullpath);
}
-static void __attribute__ ((noreturn)) usage(void)
-{
- fprintf(stderr, "Usage:\n");
- fprintf(stderr, "\tdtc [options] <input file>\n");
- fprintf(stderr, "\nOptions:\n");
- fprintf(stderr, "\t-h\n");
- fprintf(stderr, "\t\tThis help text\n");
- fprintf(stderr, "\t-q\n");
- fprintf(stderr, "\t\tQuiet: -q suppress warnings, -qq errors, -qqq all\n");
- fprintf(stderr, "\t-I <input format>\n");
- fprintf(stderr, "\t\tInput formats are:\n");
- fprintf(stderr, "\t\t\tdts - device tree source text\n");
- fprintf(stderr, "\t\t\tdtb - device tree blob\n");
- fprintf(stderr, "\t\t\tfs - /proc/device-tree style directory\n");
- fprintf(stderr, "\t-o <output file>\n");
- fprintf(stderr, "\t-O <output format>\n");
- fprintf(stderr, "\t\tOutput formats are:\n");
- fprintf(stderr, "\t\t\tdts - device tree source text\n");
- fprintf(stderr, "\t\t\tdtb - device tree blob\n");
- fprintf(stderr, "\t\t\tasm - assembler source\n");
- fprintf(stderr, "\t-V <output version>\n");
- fprintf(stderr, "\t\tBlob version to produce, defaults to %d (relevant for dtb\n\t\tand asm output only)\n", DEFAULT_FDT_VERSION);
- fprintf(stderr, "\t-d <output dependency file>\n");
- fprintf(stderr, "\t-R <number>\n");
- fprintf(stderr, "\t\tMake space for <number> reserve map entries (relevant for \n\t\tdtb and asm output only)\n");
- fprintf(stderr, "\t-S <bytes>\n");
- fprintf(stderr, "\t\tMake the blob at least <bytes> long (extra space)\n");
- fprintf(stderr, "\t-p <bytes>\n");
- fprintf(stderr, "\t\tAdd padding to the blob of <bytes> long (extra space)\n");
- fprintf(stderr, "\t-b <number>\n");
- fprintf(stderr, "\t\tSet the physical boot cpu\n");
- fprintf(stderr, "\t-f\n");
- fprintf(stderr, "\t\tForce - try to produce output even if the input tree has errors\n");
- fprintf(stderr, "\t-i\n");
- fprintf(stderr, "\t\tAdd a path to search for include files\n");
- fprintf(stderr, "\t-s\n");
- fprintf(stderr, "\t\tSort nodes and properties before outputting (only useful for\n\t\tcomparing trees)\n");
- fprintf(stderr, "\t-v\n");
- fprintf(stderr, "\t\tPrint DTC version and exit\n");
- fprintf(stderr, "\t-H <phandle format>\n");
- fprintf(stderr, "\t\tphandle formats are:\n");
- fprintf(stderr, "\t\t\tlegacy - \"linux,phandle\" properties only\n");
- fprintf(stderr, "\t\t\tepapr - \"phandle\" properties only\n");
- fprintf(stderr, "\t\t\tboth - Both \"linux,phandle\" and \"phandle\" properties\n");
- fprintf(stderr, "\t-W [no-]<checkname>\n");
- fprintf(stderr, "\t-E [no-]<checkname>\n");
- fprintf(stderr, "\t\t\tenable or disable warnings and errors\n");
- exit(3);
-}
+/* Usage related data. */
+static const char usage_synopsis[] = "dtc [options] <input file>";
+static const char usage_short_opts[] = "qI:O:o:V:d:R:S:p:fb:i:H:sW:E:hv";
+static struct option const usage_long_opts[] = {
+ {"quiet", no_argument, NULL, 'q'},
+ {"in-format", a_argument, NULL, 'I'},
+ {"out", a_argument, NULL, 'o'},
+ {"out-format", a_argument, NULL, 'O'},
+ {"out-version", a_argument, NULL, 'V'},
+ {"out-dependency", a_argument, NULL, 'd'},
+ {"reserve", a_argument, NULL, 'R'},
+ {"space", a_argument, NULL, 'S'},
+ {"pad", a_argument, NULL, 'p'},
+ {"boot-cpu", a_argument, NULL, 'b'},
+ {"force", no_argument, NULL, 'f'},
+ {"include", a_argument, NULL, 'i'},
+ {"sort", no_argument, NULL, 's'},
+ {"phandle", a_argument, NULL, 'H'},
+ {"warning", a_argument, NULL, 'W'},
+ {"error", a_argument, NULL, 'E'},
+ {"help", no_argument, NULL, 'h'},
+ {"version", no_argument, NULL, 'v'},
+ {NULL, no_argument, NULL, 0x0},
+};
+static const char * const usage_opts_help[] = {
+ "\n\tQuiet: -q suppress warnings, -qq errors, -qqq all",
+ "\n\tInput formats are:\n"
+ "\t\tdts - device tree source text\n"
+ "\t\tdtb - device tree blob\n"
+ "\t\tfs - /proc/device-tree style directory",
+ "\n\tOutput file",
+ "\n\tOutput formats are:\n"
+ "\t\tdts - device tree source text\n"
+ "\t\tdtb - device tree blob\n"
+ "\t\tasm - assembler source",
+ "\n\tBlob version to produce, defaults to %d (for dtb and asm output)", //, DEFAULT_FDT_VERSION);
+ "\n\tOutput dependency file",
+ "\n\ttMake space for <number> reserve map entries (for dtb and asm output)",
+ "\n\tMake the blob at least <bytes> long (extra space)",
+ "\n\tAdd padding to the blob of <bytes> long (extra space)",
+ "\n\tSet the physical boot cpu",
+ "\n\tTry to produce output even if the input tree has errors",
+ "\n\tAdd a path to search for include files",
+ "\n\tSort nodes and properties before outputting (useful for comparing trees)",
+ "\n\tValid phandle formats are:\n"
+ "\t\tlegacy - \"linux,phandle\" properties only\n"
+ "\t\tepapr - \"phandle\" properties only\n"
+ "\t\tboth - Both \"linux,phandle\" and \"phandle\" properties",
+ "\n\tEnable/disable warnings (prefix with \"no-\")",
+ "\n\tEnable/disable errors (prefix with \"no-\")",
+ "\n\tPrint this help and exit",
+ "\n\tPrint version and exit",
+ NULL,
+};
int main(int argc, char *argv[])
{
@@ -116,8 +121,7 @@ int main(int argc, char *argv[])
minsize = 0;
padsize = 0;
- while ((opt = getopt(argc, argv, "hI:O:o:V:d:R:S:p:fqb:i:vH:sW:E:"))
- != EOF) {
+ while ((opt = util_getopt_long()) != EOF) {
switch (opt) {
case 'I':
inform = optarg;
@@ -182,13 +186,14 @@ int main(int argc, char *argv[])
break;
case 'h':
+ long_usage(NULL);
default:
- usage();
+ long_usage("unknown option");
}
}
if (argc > (optind+1))
- usage();
+ long_usage("missing files");
else if (argc < (optind+1))
arg = "-";
else
diff --git a/fdtget.c b/fdtget.c
index c2fbab2..5008cc1 100644
--- a/fdtget.c
+++ b/fdtget.c
@@ -277,33 +277,33 @@ static int do_fdtget(struct display_info *disp, const char *filename,
return 0;
}
-static const char *usage_msg =
- "fdtget - read values from device tree\n"
- "\n"
- "Each value is printed on a new line.\n\n"
- "Usage:\n"
+/* Usage related data. */
+static const char usage_synopsis[] =
+ "read values from device tree\n"
" fdtget <options> <dt file> [<node> <property>]...\n"
" fdtget -p <options> <dt file> [<node> ]...\n"
- "Options:\n"
- "\t-t <type>\tType of data\n"
- "\t-p\t\tList properties for each node\n"
- "\t-l\t\tList subnodes for each node\n"
- "\t-d\t\tDefault value to display when the property is "
- "missing\n"
- "\t-h\t\tPrint this help\n\n"
+ "\n"
+ "Each value is printed on a new line.\n"
USAGE_TYPE_MSG;
-
-static void usage(const char *msg)
-{
- if (msg)
- fprintf(stderr, "Error: %s\n\n", msg);
-
- fprintf(stderr, "%s", usage_msg);
- exit(2);
-}
+static const char usage_short_opts[] = "t:pld:" USAGE_COMMON_SHORT_OPTS;
+static struct option const usage_long_opts[] = {
+ {"type", a_argument, NULL, 't'},
+ {"properties", no_argument, NULL, 'p'},
+ {"list", no_argument, NULL, 'l'},
+ {"default", a_argument, NULL, 'd'},
+ USAGE_COMMON_LONG_OPTS,
+};
+static const char * const usage_opts_help[] = {
+ "Type of data",
+ "List properties for each node",
+ "List subnodes for each node",
+ "Default value to display when the property is missing",
+ USAGE_COMMON_OPTS_HELP
+};
int main(int argc, char *argv[])
{
+ int opt;
char *filename = NULL;
struct display_info disp;
int args_per_step = 2;
@@ -312,20 +312,14 @@ int main(int argc, char *argv[])
memset(&disp, '\0', sizeof(disp));
disp.size = -1;
disp.mode = MODE_SHOW_VALUE;
- for (;;) {
- int c = getopt(argc, argv, "d:hlpt:");
- if (c == -1)
- break;
-
- switch (c) {
- case 'h':
- case '?':
- usage(NULL);
+ while ((opt = util_getopt_long()) != EOF) {
+ switch (opt) {
+ case_USAGE_COMMON_FLAGS
case 't':
if (utilfdt_decode_type(optarg, &disp.type,
&disp.size))
- usage("Invalid type string");
+ long_usage("invalid type string");
break;
case 'p':
@@ -347,7 +341,7 @@ int main(int argc, char *argv[])
if (optind < argc)
filename = argv[optind++];
if (!filename)
- usage("Missing filename");
+ long_usage("missing filename");
argv += optind;
argc -= optind;
@@ -358,7 +352,7 @@ int main(int argc, char *argv[])
/* Check for node, property arguments */
if (args_per_step == 2 && (argc % 2))
- usage("Must have an even number of arguments");
+ long_usage("must have an even number of arguments");
if (do_fdtget(&disp, filename, argv, argc, args_per_step))
return 1;
diff --git a/fdtput.c b/fdtput.c
index f2197f5..99eb05c 100644
--- a/fdtput.c
+++ b/fdtput.c
@@ -272,44 +272,40 @@ static int do_fdtput(struct display_info *disp, const char *filename,
return ret;
}
-static const char *usage_msg =
- "fdtput - write a property value to a device tree\n"
- "\n"
- "The command line arguments are joined together into a single value.\n"
- "\n"
- "Usage:\n"
+/* Usage related data. */
+static const char usage_synopsis[] =
+ "write a property value to a device tree\n"
" fdtput <options> <dt file> <node> <property> [<value>...]\n"
" fdtput -c <options> <dt file> [<node>...]\n"
- "Options:\n"
- "\t-c\t\tCreate nodes if they don't already exist\n"
- "\t-p\t\tAutomatically create nodes as needed for the node path\n"
- "\t-t <type>\tType of data\n"
- "\t-v\t\tVerbose: display each value decoded from command line\n"
- "\t-h\t\tPrint this help\n\n"
+ "\n"
+ "The command line arguments are joined together into a single value.\n"
USAGE_TYPE_MSG;
-
-static void usage(const char *msg)
-{
- if (msg)
- fprintf(stderr, "Error: %s\n\n", msg);
-
- fprintf(stderr, "%s", usage_msg);
- exit(2);
-}
+static const char usage_short_opts[] = "cpt:v" USAGE_COMMON_SHORT_OPTS;
+static struct option const usage_long_opts[] = {
+ {"create", no_argument, NULL, 'c'},
+ {"auto-path", no_argument, NULL, 'p'},
+ {"type", a_argument, NULL, 't'},
+ {"verbose", no_argument, NULL, 'v'},
+ USAGE_COMMON_LONG_OPTS,
+};
+static const char * const usage_opts_help[] = {
+ "Create nodes if they don't already exist",
+ "Automatically create nodes as needed for the node path",
+ "Type of data",
+ "Display each value decoded from command line",
+ USAGE_COMMON_OPTS_HELP
+};
int main(int argc, char *argv[])
{
+ int opt;
struct display_info disp;
char *filename = NULL;
memset(&disp, '\0', sizeof(disp));
disp.size = -1;
disp.oper = OPER_WRITE_PROP;
- for (;;) {
- int c = getopt(argc, argv, "chpt:v");
- if (c == -1)
- break;
-
+ while ((opt = util_getopt_long()) != EOF) {
/*
* TODO: add options to:
* - delete property
@@ -319,20 +315,19 @@ int main(int argc, char *argv[])
* - set amount of free space when writing
* - expand fdt if value doesn't fit
*/
- switch (c) {
+ switch (opt) {
+ case_USAGE_COMMON_FLAGS
+
case 'c':
disp.oper = OPER_CREATE_NODE;
break;
- case 'h':
- case '?':
- usage(NULL);
case 'p':
disp.auto_path = 1;
break;
case 't':
if (utilfdt_decode_type(optarg, &disp.type,
&disp.size))
- usage("Invalid type string");
+ long_usage("Invalid type string");
break;
case 'v':
@@ -344,16 +339,16 @@ int main(int argc, char *argv[])
if (optind < argc)
filename = argv[optind++];
if (!filename)
- usage("Missing filename");
+ long_usage("missing filename");
argv += optind;
argc -= optind;
if (disp.oper == OPER_WRITE_PROP) {
if (argc < 1)
- usage("Missing node");
+ long_usage("missing node");
if (argc < 2)
- usage("Missing property");
+ long_usage("missing property");
}
if (do_fdtput(&disp, filename, argv, argc))
diff --git a/util.h b/util.h
index 1da3bd3..439b2b3 100644
--- a/util.h
+++ b/util.h
@@ -164,7 +164,7 @@ int utilfdt_decode_type(const char *fmt, int *type, int *size);
#define USAGE_TYPE_MSG \
"<type>\ts=string, i=int, u=unsigned, x=hex\n" \
"\tOptional modifier prefix:\n" \
- "\t\thh or b=byte, h=2 byte, l=4 byte (default)\n";
+ "\t\thh or b=byte, h=2 byte, l=4 byte (default)";
/**
* Print property data in a readable format to stdout
--
1.7.10.4
^ permalink raw reply related [flat|nested] 12+ messages in thread
* [PATCH 04/10] util: drop "long" from usage helpers
[not found] ` <1369795898-7631-1-git-send-email-david-xT8FGy+AXnRB3Ne2BGzF6laj5H9X9Tb+@public.gmane.org>
` (2 preceding siblings ...)
2013-05-29 2:51 ` [PATCH 03/10] dtc/fdt{get, put}/convert-dtsv0-lexer: convert to new usage helpers David Gibson
@ 2013-05-29 2:51 ` David Gibson
2013-05-29 2:51 ` [PATCH 05/10] util: add common ARRAY_SIZE define David Gibson
` (6 subsequent siblings)
10 siblings, 0 replies; 12+ messages in thread
From: David Gibson @ 2013-05-29 2:51 UTC (permalink / raw)
To: jdl-CYoMK+44s/E; +Cc: devicetree-discuss-uLR06cmDAlY/bJ5BZ2RsiQ
From: Mike Frysinger <vapier-aBrp7R+bbdUdnm+yROfE0A@public.gmane.org>
Now that all utils have converted to the new usage framework, we can
rename to just plain "usage()" and avoid naming conflicts.
Signed-off-by: Mike Frysinger <vapier-aBrp7R+bbdUdnm+yROfE0A@public.gmane.org>
Signed-off-by: David Gibson <david-xT8FGy+AXnRB3Ne2BGzF6laj5H9X9Tb+@public.gmane.org>
---
convert-dtsv0-lexer.l | 2 +-
dtc.c | 6 +++---
fdtdump.c | 2 +-
fdtget.c | 6 +++---
fdtput.c | 8 ++++----
util.c | 6 +++---
util.h | 18 +++++++++---------
7 files changed, 24 insertions(+), 24 deletions(-)
diff --git a/convert-dtsv0-lexer.l b/convert-dtsv0-lexer.l
index e62d27a..8902648 100644
--- a/convert-dtsv0-lexer.l
+++ b/convert-dtsv0-lexer.l
@@ -239,7 +239,7 @@ int main(int argc, char *argv[])
}
}
if (argc < 2)
- long_usage("missing filename");
+ usage("missing filename");
for (i = 1; i < argc; i++) {
fprintf(stderr, "Converting %s from dts v0 to dts v1\n", argv[i]);
diff --git a/dtc.c b/dtc.c
index d0a1f2d..e3c9653 100644
--- a/dtc.c
+++ b/dtc.c
@@ -186,14 +186,14 @@ int main(int argc, char *argv[])
break;
case 'h':
- long_usage(NULL);
+ usage(NULL);
default:
- long_usage("unknown option");
+ usage("unknown option");
}
}
if (argc > (optind+1))
- long_usage("missing files");
+ usage("missing files");
else if (argc < (optind+1))
arg = "-";
else
diff --git a/fdtdump.c b/fdtdump.c
index c8a3ee7..c2f16ea 100644
--- a/fdtdump.c
+++ b/fdtdump.c
@@ -149,7 +149,7 @@ int main(int argc, char *argv[])
}
}
if (optind != argc - 1)
- long_usage("missing input filename");
+ usage("missing input filename");
file = argv[optind];
buf = utilfdt_read_len(file, &len);
diff --git a/fdtget.c b/fdtget.c
index 5008cc1..4377419 100644
--- a/fdtget.c
+++ b/fdtget.c
@@ -319,7 +319,7 @@ int main(int argc, char *argv[])
case 't':
if (utilfdt_decode_type(optarg, &disp.type,
&disp.size))
- long_usage("invalid type string");
+ usage("invalid type string");
break;
case 'p':
@@ -341,7 +341,7 @@ int main(int argc, char *argv[])
if (optind < argc)
filename = argv[optind++];
if (!filename)
- long_usage("missing filename");
+ usage("missing filename");
argv += optind;
argc -= optind;
@@ -352,7 +352,7 @@ int main(int argc, char *argv[])
/* Check for node, property arguments */
if (args_per_step == 2 && (argc % 2))
- long_usage("must have an even number of arguments");
+ usage("must have an even number of arguments");
if (do_fdtget(&disp, filename, argv, argc, args_per_step))
return 1;
diff --git a/fdtput.c b/fdtput.c
index 99eb05c..fbb283a 100644
--- a/fdtput.c
+++ b/fdtput.c
@@ -327,7 +327,7 @@ int main(int argc, char *argv[])
case 't':
if (utilfdt_decode_type(optarg, &disp.type,
&disp.size))
- long_usage("Invalid type string");
+ usage("Invalid type string");
break;
case 'v':
@@ -339,16 +339,16 @@ int main(int argc, char *argv[])
if (optind < argc)
filename = argv[optind++];
if (!filename)
- long_usage("missing filename");
+ usage("missing filename");
argv += optind;
argc -= optind;
if (disp.oper == OPER_WRITE_PROP) {
if (argc < 1)
- long_usage("missing node");
+ usage("missing node");
if (argc < 2)
- long_usage("missing property");
+ usage("missing property");
}
if (do_fdtput(&disp, filename, argv, argc))
diff --git a/util.c b/util.c
index d9a823a..3055c16 100644
--- a/util.c
+++ b/util.c
@@ -393,9 +393,9 @@ void util_version(void)
exit(0);
}
-void util_long_usage(const char *errmsg, const char *synopsis,
- const char *short_opts, struct option const long_opts[],
- const char * const opts_help[])
+void util_usage(const char *errmsg, const char *synopsis,
+ const char *short_opts, struct option const long_opts[],
+ const char * const opts_help[])
{
FILE *fp = errmsg ? stderr : stdout;
const char a_arg[] = "<arg>";
diff --git a/util.h b/util.h
index 439b2b3..7b9a840 100644
--- a/util.h
+++ b/util.h
@@ -189,7 +189,7 @@ void util_version(void) __attribute__((noreturn));
* Show usage and exit
*
* This helps standardize the output of various utils. You most likely want
- * to use the long_usage() helper below rather than call this.
+ * to use the usage() helper below rather than call this.
*
* @param errmsg If non-NULL, an error message to display
* @param synopsis The initial example usage text (and possible examples)
@@ -197,9 +197,9 @@ void util_version(void) __attribute__((noreturn));
* @param long_opts The structure of long options
* @param opts_help An array of help strings (should align with long_opts)
*/
-void util_long_usage(const char *errmsg, const char *synopsis,
- const char *short_opts, struct option const long_opts[],
- const char * const opts_help[]) __attribute__((noreturn));
+void util_usage(const char *errmsg, const char *synopsis,
+ const char *short_opts, struct option const long_opts[],
+ const char * const opts_help[]) __attribute__((noreturn));
/**
* Show usage and exit
@@ -209,9 +209,9 @@ void util_long_usage(const char *errmsg, const char *synopsis,
*
* @param errmsg If non-NULL, an error message to display
*/
-#define long_usage(errmsg) \
- util_long_usage(errmsg, usage_synopsis, usage_short_opts, \
- usage_long_opts, usage_opts_help)
+#define usage(errmsg) \
+ util_usage(errmsg, usage_synopsis, usage_short_opts, \
+ usage_long_opts, usage_opts_help)
/**
* Call getopt_long() with standard options
@@ -241,8 +241,8 @@ void util_long_usage(const char *errmsg, const char *synopsis,
/* Helper for getopt case statements */
#define case_USAGE_COMMON_FLAGS \
- case 'h': long_usage(NULL); \
+ case 'h': usage(NULL); \
case 'V': util_version(); \
- case '?': long_usage("unknown option");
+ case '?': usage("unknown option");
#endif /* _UTIL_H */
--
1.7.10.4
^ permalink raw reply related [flat|nested] 12+ messages in thread
* [PATCH 05/10] util: add common ARRAY_SIZE define
[not found] ` <1369795898-7631-1-git-send-email-david-xT8FGy+AXnRB3Ne2BGzF6laj5H9X9Tb+@public.gmane.org>
` (3 preceding siblings ...)
2013-05-29 2:51 ` [PATCH 04/10] util: drop "long" from " David Gibson
@ 2013-05-29 2:51 ` David Gibson
2013-05-29 2:51 ` [PATCH 06/10] fdtdump: add a debug mode David Gibson
` (5 subsequent siblings)
10 siblings, 0 replies; 12+ messages in thread
From: David Gibson @ 2013-05-29 2:51 UTC (permalink / raw)
To: jdl-CYoMK+44s/E; +Cc: devicetree-discuss-uLR06cmDAlY/bJ5BZ2RsiQ
From: Mike Frysinger <vapier-aBrp7R+bbdUdnm+yROfE0A@public.gmane.org>
I want to use this in more places, so put it in util.h rather than
copying & pasting it into another file.
Signed-off-by: Mike Frysinger <vapier-aBrp7R+bbdUdnm+yROfE0A@public.gmane.org>
Signed-off-by: David Gibson <david-xT8FGy+AXnRB3Ne2BGzF6laj5H9X9Tb+@public.gmane.org>
---
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.7.10.4
^ permalink raw reply related [flat|nested] 12+ messages in thread
* [PATCH 06/10] fdtdump: add a debug mode
[not found] ` <1369795898-7631-1-git-send-email-david-xT8FGy+AXnRB3Ne2BGzF6laj5H9X9Tb+@public.gmane.org>
` (4 preceding siblings ...)
2013-05-29 2:51 ` [PATCH 05/10] util: add common ARRAY_SIZE define David Gibson
@ 2013-05-29 2:51 ` David Gibson
2013-05-29 2:51 ` [PATCH 07/10] Use shorten_echo for wrap_tests David Gibson
` (4 subsequent siblings)
10 siblings, 0 replies; 12+ messages in thread
From: David Gibson @ 2013-05-29 2:51 UTC (permalink / raw)
To: jdl-CYoMK+44s/E; +Cc: devicetree-discuss-uLR06cmDAlY/bJ5BZ2RsiQ
From: Mike Frysinger <vapier-aBrp7R+bbdUdnm+yROfE0A@public.gmane.org>
When hacking raw fdt files, it's useful to know the actual offsets into
the file each node appears. Add a --debug mode that includes this.
Signed-off-by: Mike Frysinger <vapier-aBrp7R+bbdUdnm+yROfE0A@public.gmane.org>
Signed-off-by: David Gibson <david-xT8FGy+AXnRB3Ne2BGzF6laj5H9X9Tb+@public.gmane.org>
---
fdtdump.c | 41 +++++++++++++++++++++++++++++++++++++----
1 file changed, 37 insertions(+), 4 deletions(-)
diff --git a/fdtdump.c b/fdtdump.c
index c2f16ea..723770d 100644
--- a/fdtdump.c
+++ b/fdtdump.c
@@ -19,8 +19,29 @@
#define PALIGN(p, a) ((void *)(ALIGN((unsigned long)(p), (a))))
#define GET_CELL(p) (p += 4, *((const uint32_t *)(p-4)))
-static void dump_blob(void *blob)
+static const char *tagname(uint32_t tag)
{
+ static const char * const names[] = {
+#define TN(t) [t] #t
+ TN(FDT_BEGIN_NODE),
+ TN(FDT_END_NODE),
+ TN(FDT_PROP),
+ TN(FDT_NOP),
+ TN(FDT_END),
+#undef TN
+ };
+ if (tag < ARRAY_SIZE(names))
+ if (names[tag])
+ return names[tag];
+ return "FDT_???";
+}
+
+#define dumpf(fmt, args...) \
+ do { if (debug) printf("// " fmt, ## args); } while (0)
+
+static void dump_blob(void *blob, bool debug)
+{
+ uintptr_t blob_off = (uintptr_t)blob;
struct fdt_header *bph = blob;
uint32_t off_mem_rsvmap = fdt32_to_cpu(bph->off_mem_rsvmap);
uint32_t off_dt = fdt32_to_cpu(bph->off_dt_struct);
@@ -74,7 +95,8 @@ static void dump_blob(void *blob)
p = p_struct;
while ((tag = fdt32_to_cpu(GET_CELL(p))) != FDT_END) {
- /* printf("tag: 0x%08x (%d)\n", tag, p - p_struct); */
+ dumpf("%04zx: tag: 0x%08x (%s)\n",
+ (uintptr_t)p - blob_off - 4, tag, tagname(tag));
if (tag == FDT_BEGIN_NODE) {
s = p;
@@ -113,6 +135,8 @@ static void dump_blob(void *blob)
p = PALIGN(p + sz, 4);
+ dumpf("%04zx: string: %s\n", (uintptr_t)s - blob_off, s);
+ dumpf("%04zx: value\n", (uintptr_t)t - blob_off);
printf("%*s%s", depth * shift, "", s);
utilfdt_print_data(t, sz);
printf(";\n");
@@ -121,12 +145,14 @@ static void dump_blob(void *blob)
/* Usage related data. */
static const char usage_synopsis[] = "fdtdump [options] <file>";
-static const char usage_short_opts[] = "s" USAGE_COMMON_SHORT_OPTS;
+static const char usage_short_opts[] = "ds" USAGE_COMMON_SHORT_OPTS;
static struct option const usage_long_opts[] = {
+ {"debug", no_argument, NULL, 'd'},
{"scan", no_argument, NULL, 's'},
USAGE_COMMON_LONG_OPTS
};
static const char * const usage_opts_help[] = {
+ "Dump debug information while decoding the file",
"Scan for an embedded fdt in file",
USAGE_COMMON_OPTS_HELP
};
@@ -136,6 +162,7 @@ int main(int argc, char *argv[])
int opt;
const char *file;
char *buf;
+ bool debug = false;
bool scan = false;
off_t len;
@@ -143,6 +170,9 @@ int main(int argc, char *argv[])
switch (opt) {
case_USAGE_COMMON_FLAGS
+ case 'd':
+ debug = true;
+ break;
case 's':
scan = true;
break;
@@ -179,6 +209,9 @@ int main(int argc, char *argv[])
fdt_off_dt_struct(p) < this_len &&
fdt_off_dt_strings(p) < this_len)
break;
+ if (debug)
+ printf("%s: skipping fdt magic at offset %#zx\n",
+ file, p - buf);
}
++p;
}
@@ -188,7 +221,7 @@ int main(int argc, char *argv[])
buf = p;
}
- dump_blob(buf);
+ dump_blob(buf, debug);
return 0;
}
--
1.7.10.4
^ permalink raw reply related [flat|nested] 12+ messages in thread
* [PATCH 07/10] Use shorten_echo for wrap_tests
[not found] ` <1369795898-7631-1-git-send-email-david-xT8FGy+AXnRB3Ne2BGzF6laj5H9X9Tb+@public.gmane.org>
` (5 preceding siblings ...)
2013-05-29 2:51 ` [PATCH 06/10] fdtdump: add a debug mode David Gibson
@ 2013-05-29 2:51 ` David Gibson
2013-05-29 2:51 ` [PATCH 08/10] Remove some tests for misfeatures David Gibson
` (3 subsequent siblings)
10 siblings, 0 replies; 12+ messages in thread
From: David Gibson @ 2013-05-29 2:51 UTC (permalink / raw)
To: jdl-CYoMK+44s/E; +Cc: devicetree-discuss-uLR06cmDAlY/bJ5BZ2RsiQ
We have certain tests which generate extremely long command lines, which
are shortened in the testsuite output with the 'shorten_echo' function.
Currently that is used in run_fdtput_test and run_wrap_test, this patch
uses it for run_wrap_test as well, allowing more general tests with long
command lines.
Signed-off-by: David Gibson <david-xT8FGy+AXnRB3Ne2BGzF6laj5H9X9Tb+@public.gmane.org>
---
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.7.10.4
^ permalink raw reply related [flat|nested] 12+ messages in thread
* [PATCH 08/10] Remove some tests for misfeatures
[not found] ` <1369795898-7631-1-git-send-email-david-xT8FGy+AXnRB3Ne2BGzF6laj5H9X9Tb+@public.gmane.org>
` (6 preceding siblings ...)
2013-05-29 2:51 ` [PATCH 07/10] Use shorten_echo for wrap_tests David Gibson
@ 2013-05-29 2:51 ` David Gibson
2013-05-29 2:51 ` [PATCH 09/10] fdtput: expand fdt if value does not fit David Gibson
` (2 subsequent siblings)
10 siblings, 0 replies; 12+ messages in thread
From: David Gibson @ 2013-05-29 2:51 UTC (permalink / raw)
To: jdl-CYoMK+44s/E; +Cc: devicetree-discuss-uLR06cmDAlY/bJ5BZ2RsiQ
There are a couple of fdtput related tests which are rather pointless -
they explicitly test for the presence of an undesirable limitation in
fdtput, which will cause test failures when we fix it. This patch removes
the tests.
Signed-off-by: David Gibson <david-xT8FGy+AXnRB3Ne2BGzF6laj5H9X9Tb+@public.gmane.org>
---
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.7.10.4
^ permalink raw reply related [flat|nested] 12+ messages in thread
* [PATCH 09/10] fdtput: expand fdt if value does not fit
[not found] ` <1369795898-7631-1-git-send-email-david-xT8FGy+AXnRB3Ne2BGzF6laj5H9X9Tb+@public.gmane.org>
` (7 preceding siblings ...)
2013-05-29 2:51 ` [PATCH 08/10] Remove some tests for misfeatures David Gibson
@ 2013-05-29 2:51 ` David Gibson
2013-05-29 2:51 ` [PATCH 10/10] Add missing test binary to .gitignore David Gibson
2013-05-29 13:17 ` [0/10] Pending patches pull request Jon Loeliger
10 siblings, 0 replies; 12+ messages in thread
From: David Gibson @ 2013-05-29 2:51 UTC (permalink / raw)
To: jdl-CYoMK+44s/E
Cc: devicetree-discuss-uLR06cmDAlY/bJ5BZ2RsiQ, Srinivas Kandagatla
From: Srinivas Kandagatla <srinivas.kandagatla-qxv4g6HH51o@public.gmane.org>
If you try to insert a new node or extend a property with large value,
using fdtput you will notice that it always fails.
example:
fdtput -v -p -ts ./tst.dtb "/node-1" "property-1" "value-1
Error at 'node-1': FDT_ERR_NOSPACE
or
fdtput -v -c ./tst.dtb "/node-1"
Error at 'node-1': FDT_ERR_NOSPACE
or
fdtput -v -ts ./tst.dtb "/node" "property" "very big value"
Decoding value:
string: 'very big value'
Value size 15
Error at 'property': FDT_ERR_NOSPACE
All these error are returned from libfdt, as the size of the fdt passed
has no space to accomdate these new properties.
This patch adds realloc functions in fdtput to allocate new space in fdt
when it detects a shortage in space for new value or node. With this
patch, fdtput can insert a new node or property or extend a property
with new value greater than original size. Also it packs the final blob
to clean up any extra padding.
Without this patch fdtput tool complains with FDT_ERR_NOSPACE when we
try to add a node/property or extend the value of a property.
Testcases for the new behaviour added by David Gibson.
Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla-qxv4g6HH51o@public.gmane.org>
Signed-off-by: David Gibson <david-xT8FGy+AXnRB3Ne2BGzF6laj5H9X9Tb+@public.gmane.org>
---
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.7.10.4
^ permalink raw reply related [flat|nested] 12+ messages in thread
* [PATCH 10/10] Add missing test binary to .gitignore
[not found] ` <1369795898-7631-1-git-send-email-david-xT8FGy+AXnRB3Ne2BGzF6laj5H9X9Tb+@public.gmane.org>
` (8 preceding siblings ...)
2013-05-29 2:51 ` [PATCH 09/10] fdtput: expand fdt if value does not fit David Gibson
@ 2013-05-29 2:51 ` David Gibson
2013-05-29 13:17 ` [0/10] Pending patches pull request Jon Loeliger
10 siblings, 0 replies; 12+ messages in thread
From: David Gibson @ 2013-05-29 2:51 UTC (permalink / raw)
To: jdl-CYoMK+44s/E; +Cc: devicetree-discuss-uLR06cmDAlY/bJ5BZ2RsiQ
The subnode_iterate test binary was missing from .gitignore, this fixes it.
Signed-off-by: David Gibson <david-xT8FGy+AXnRB3Ne2BGzF6laj5H9X9Tb+@public.gmane.org>
---
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.7.10.4
^ permalink raw reply related [flat|nested] 12+ messages in thread
* Re: [0/10] Pending patches pull request
[not found] ` <1369795898-7631-1-git-send-email-david-xT8FGy+AXnRB3Ne2BGzF6laj5H9X9Tb+@public.gmane.org>
` (9 preceding siblings ...)
2013-05-29 2:51 ` [PATCH 10/10] Add missing test binary to .gitignore David Gibson
@ 2013-05-29 13:17 ` Jon Loeliger
10 siblings, 0 replies; 12+ messages in thread
From: Jon Loeliger @ 2013-05-29 13:17 UTC (permalink / raw)
To: David Gibson; +Cc: devicetree-discuss-uLR06cmDAlY/bJ5BZ2RsiQ
> Hi Jon,
>
> Here's a batch of patches, a few from me, mostly from others, which I
> think should go into dtc/libfdt. Please apply, or you can pull from:
> git://github.com/dgibson/dtc.git (branch 'master')
Pulled and pushed!
Thanks,
jdl
^ permalink raw reply [flat|nested] 12+ messages in thread
end of thread, other threads:[~2013-05-29 13:17 UTC | newest]
Thread overview: 12+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2013-05-29 2:51 [0/10] Pending patches pull request David Gibson
[not found] ` <1369795898-7631-1-git-send-email-david-xT8FGy+AXnRB3Ne2BGzF6laj5H9X9Tb+@public.gmane.org>
2013-05-29 2:51 ` [PATCH 01/10] fdtdump: make usage a bit more friendly David Gibson
2013-05-29 2:51 ` [PATCH 02/10] fdtdump: add a --scan option David Gibson
2013-05-29 2:51 ` [PATCH 03/10] dtc/fdt{get, put}/convert-dtsv0-lexer: convert to new usage helpers David Gibson
2013-05-29 2:51 ` [PATCH 04/10] util: drop "long" from " David Gibson
2013-05-29 2:51 ` [PATCH 05/10] util: add common ARRAY_SIZE define David Gibson
2013-05-29 2:51 ` [PATCH 06/10] fdtdump: add a debug mode David Gibson
2013-05-29 2:51 ` [PATCH 07/10] Use shorten_echo for wrap_tests David Gibson
2013-05-29 2:51 ` [PATCH 08/10] Remove some tests for misfeatures David Gibson
2013-05-29 2:51 ` [PATCH 09/10] fdtput: expand fdt if value does not fit David Gibson
2013-05-29 2:51 ` [PATCH 10/10] Add missing test binary to .gitignore David Gibson
2013-05-29 13:17 ` [0/10] Pending patches pull request Jon Loeliger
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).