The general idea and most of the code is stolen from chromiumos:
8fc0740356ca15d02fb1c65ab43b10844f148c3b bb9049c66ca55e0dc621dd2c70b5d2cb6e5179bf Signed-off-by: Louis Yung-Chieh Lo yjlou@chromium.org
and the main part: d0ea9ed71e7f86bb8e8db2ca7c32a96de25343d8 Signed-off-by: David Hendricks dhendrix@chromium.org
My implementation does not defer the processing until doit(), but after the argument parsing loop only (doit() should not contain argument checks).
This allows to specify -i and -l parameters in any order.
Signed-off-by: Stefan Tauner stefan.tauner@student.tuwien.ac.at Acked-by: David Hendricks dhendrix@google.com --- cli_classic.c | 10 +++---- flash.h | 3 +- layout.c | 85 ++++++++++++++++++++++++++++++++++++++++++++++++--------- 3 files changed, 78 insertions(+), 20 deletions(-)
diff --git a/cli_classic.c b/cli_classic.c index a931de8..3928ded 100644 --- a/cli_classic.c +++ b/cli_classic.c @@ -295,14 +295,9 @@ int main(int argc, char *argv[]) cli_classic_abort_usage(); break; case 'i': - /* FIXME: -l has to be specified before -i. */ tempstr = strdup(optarg); - if (find_romentry(tempstr) < 0) { - fprintf(stderr, "Error: image %s not found in " - "layout file or -i specified before " - "-l\n", tempstr); + if (register_include_arg(tempstr)) cli_classic_abort_usage(); - } break; case 'L': if (++operation_specified > 1) { @@ -395,6 +390,9 @@ int main(int argc, char *argv[]) cli_classic_abort_usage(); }
+ if (process_include_args()) + cli_classic_abort_usage(); + /* FIXME: Print the actions flashrom will take. */
if (list_supported) { diff --git a/flash.h b/flash.h index e21a986..e51b6d4 100644 --- a/flash.h +++ b/flash.h @@ -289,8 +289,9 @@ int print(int type, const char *fmt, ...) __attribute__((format(printf, 2, 3))); #define msg_cspew(...) print(MSG_BARF, __VA_ARGS__) /* chip debug barf */
/* layout.c */ +int register_include_arg(char *name); +int process_include_args(void); int read_romlayout(char *name); -int find_romentry(char *name); int handle_romentries(struct flashctx *flash, uint8_t *oldcontents, uint8_t *newcontents);
/* spi.c */ diff --git a/layout.c b/layout.c index 68d05fd..3928699 100644 --- a/layout.c +++ b/layout.c @@ -41,6 +41,12 @@ typedef struct { char name[256]; } romlayout_t;
+/* include_args lists arguments specified at the command line with -i. They + * must be processed at some point so that desired regions are marked as + * "included" in the rom_entries list. + */ +static char *include_args[MAX_ROMLAYOUT]; +static int num_include_args = 0; /* the number of valid entries. */ static romlayout_t rom_entries[MAX_ROMLAYOUT];
#if CONFIG_INTERNAL == 1 /* FIXME: Move the whole block to cbtable.c? */ @@ -156,10 +162,8 @@ int read_romlayout(char *name)
if (romimages >= MAX_ROMLAYOUT) { msg_gerr("Maximum number of ROM images (%i) in layout " - "file reached before end of layout file.\n", - MAX_ROMLAYOUT); - msg_gerr("Ignoring the rest of the layout file.\n"); - break; + "file reached.\n", MAX_ROMLAYOUT); + return 1; } if (2 != fscanf(romlayout, "%s %s\n", tempstr, rom_entries[romimages].name)) continue; @@ -194,27 +198,80 @@ int read_romlayout(char *name) } #endif
-int find_romentry(char *name) +/* register an include argument (-i) for later processing */ +int register_include_arg(char *name) +{ + if (num_include_args >= MAX_ROMLAYOUT) { + msg_gerr("Too many regions included (%i).\n", num_include_args); + return 1; + } + + if (name == NULL) { + msg_gerr("<NULL> is a bad region name.\n"); + return 1; + } + + include_args[num_include_args] = name; + num_include_args++; + return 0; +} + +/* returns the index of the entry (or a negative value if it is not found) */ +static int find_romentry(char *name) { int i;
if (!romimages) return -1;
- msg_ginfo("Looking for "%s"... ", name); - + msg_gspew("Looking for region "%s"... ", name); for (i = 0; i < romimages; i++) { if (!strcmp(rom_entries[i].name, name)) { rom_entries[i].included = 1; - msg_ginfo("found.\n"); + msg_gspew("found.\n"); return i; } } - msg_ginfo("not found.\n"); // Not found. Error. - + msg_gspew("not found.\n"); return -1; }
+/* process -i arguments + * returns 0 to indicate success, >0 to indicate failure + */ +int process_include_args(void) +{ + int i; + unsigned int found = 0; + + if (num_include_args == 0) + return 0; + + for (i = 0; i < num_include_args; i++) { + /* User has specified an area, but no layout file is loaded. */ + if (!romimages) { + msg_gerr("Region requested (with -i "%s"), " + "but no layout data is available.\n", + include_args[i]); + return 1; + } + + if (find_romentry(include_args[i]) < 0) { + msg_gerr("Invalid region specified: "%s"\n", + include_args[i]); + return 1; + } + found++; + } + + msg_ginfo("Using region%s: "%s"", num_include_args > 1 ? "s" : "", + include_args[0]); + for (i = 1; i < num_include_args; i++) + msg_ginfo(", "%s"", include_args[i]); + msg_ginfo(".\n"); + return 0; +} + romlayout_t *get_next_included_romentry(unsigned int start) { int i; @@ -248,11 +305,12 @@ int handle_romentries(struct flashctx *flash, uint8_t *oldcontents, uint8_t *new romlayout_t *entry; unsigned int size = flash->total_size * 1024;
- /* If no layout file was specified or the layout file was empty, assume - * that the user wants to flash the complete new image. + /* If no regions were specified for inclusion, assume + * that the user wants to write the complete new image. */ - if (!romimages) + if (num_include_args == 0) return 0; + /* Non-included romentries are ignored. * The union of all included romentries is used from the new image. */ @@ -264,6 +322,7 @@ int handle_romentries(struct flashctx *flash, uint8_t *oldcontents, uint8_t *new size - start); break; } + /* For non-included region, copy from old content. */ if (entry->start > start) memcpy(newcontents + start, oldcontents + start, entry->start - start);