Add an optional sub-parameter to the -i parameter to allow building the image to be written from multiple files. This will also allow regions to be read from flash and written to separate image files in a later patch. Existing function read_buf_from_file() is refined and reused to read the file.
based on chromiumos' d0ea9ed71e7f86bb8e8db2ca7c32a96de25343d8 Signed-off-by: David Hendricks dhendrix@chromium.org Signed-off-by: Stefan Tauner stefan.tauner@student.tuwien.ac.at --- cli_classic.c | 9 ++++--- dummyflasher.c | 2 +- flash.h | 2 +- flashrom.c | 18 +++++++++----- layout.c | 78 ++++++++++++++++++++++++++++++++++++++++++++-------------- 5 files changed, 78 insertions(+), 31 deletions(-)
diff --git a/cli_classic.c b/cli_classic.c index a0c2d64..ed6d6aa 100644 --- a/cli_classic.c +++ b/cli_classic.c @@ -40,8 +40,8 @@ static void cli_classic_usage(const char *name) #if CONFIG_PRINT_WIKI == 1 "-z|" #endif - "-p <programmername>[:<parameters>] [-c <chipname>]\n" - "[-E|(-r|-w|-v) <file>] [-l <layoutfile> [-i <imagename>]...] [-n] [-f]]\n" + "-p <programmername>[:<parameter>[,<parameter>]...] [-c <chipname>]\n" + "[-E|(-r|-w|-v) <imagefile>] [-l <layoutfile> [-i <region>[:<regionfile>]...] [-n] [-f]]\n" "[-V[V[V]]] [-o <logfile>]\n\n", name);
printf(" -h | --help print this help text\n" @@ -54,8 +54,9 @@ static void cli_classic_usage(const char *name) " -c | --chip <chipname> probe only for specified flash chip\n" " -f | --force force specific operations (see man page)\n" " -n | --noverify don't auto-verify\n" - " -l | --layout <layoutfile> read ROM layout from <layoutfile>\n" - " -i | --image <name> only flash image <name> from flash layout\n" + " -l | --layout <layoutfile> read layout from <layoutfile>\n" + " -i | --include <region>[<:file>] only flash image <region> from layout \n" + " (optionally with data from <file>)\n" " -o | --output <logfile> log output to <logfile>\n" " -L | --list-supported print supported devices\n" #if CONFIG_PRINT_WIKI == 1 diff --git a/dummyflasher.c b/dummyflasher.c index 9c0d868..90d2261 100644 --- a/dummyflasher.c +++ b/dummyflasher.c @@ -389,7 +389,7 @@ int dummy_init(void) msg_pdbg("matches.\n"); msg_pdbg("Reading %s\n", emu_persistent_image); read_buf_from_file(flashchip_contents, emu_chip_size, - emu_persistent_image); + emu_persistent_image, NULL); } else { msg_pdbg("doesn't match.\n"); } diff --git a/flash.h b/flash.h index a942b9b..be5918b 100644 --- a/flash.h +++ b/flash.h @@ -261,7 +261,7 @@ void print_banner(void); void list_programmers_linebreak(int startcol, int cols, int paren); int selfcheck(void); int doit(struct flashctx *flash, int force, const char *filename, int read_it, int write_it, int erase_it, int verify_it); -int read_buf_from_file(unsigned char *buf, unsigned long size, const char *filename); +int read_buf_from_file(unsigned char *buf, unsigned long size, const char *filename, const char *size_msg); int write_buf_to_file(unsigned char *buf, unsigned long size, const char *filename);
/* helpers.c */ diff --git a/flashrom.c b/flashrom.c index afab57c..7db2696 100644 --- a/flashrom.c +++ b/flashrom.c @@ -1165,8 +1165,7 @@ notfound: return chip - flashchips; }
-int read_buf_from_file(unsigned char *buf, unsigned long size, - const char *filename) +int read_buf_from_file(unsigned char *buf, unsigned long size, const char *filename, const char *size_msg) { #ifdef __LIBPAYLOAD__ msg_gerr("Error: No file I/O support in libpayload\n"); @@ -1186,8 +1185,10 @@ int read_buf_from_file(unsigned char *buf, unsigned long size, return 1; } if (image_stat.st_size != size) { - msg_gerr("Error: Image size (%jd B) doesn't match the flash chip's size (%lu B)!\n", - (intmax_t)image_stat.st_size, size); + if (size_msg == NULL) + size_msg = "the expected size"; + msg_gerr("Error: Image size (%jd B) doesn't match %s (%lu B)!\n", + (intmax_t)image_stat.st_size, size_msg, size); fclose(image); return 1; } @@ -1968,7 +1969,7 @@ int doit(struct flashctx *flash, int force, const char *filename, int read_it, }
if (write_it || verify_it) { - if (read_buf_from_file(newcontents, size, filename)) { + if (read_buf_from_file(newcontents, size, filename, "the flash chip's size")) { ret = 1; goto out; } @@ -2002,7 +2003,12 @@ int doit(struct flashctx *flash, int force, const char *filename, int read_it, msg_cinfo("done.\n");
/* Build a new image taking the given layout into account. */ - build_new_image(flash, oldcontents, newcontents); + if (build_new_image(flash, oldcontents, newcontents)) { + msg_gerr("Could not prepare the data to be written due to problems with the layout,\n" + "aborting.\n"); + ret = 1; + goto out; + }
// ////////////////////////////////////////////////////////////
diff --git a/layout.c b/layout.c index 08cc776..7e2e904 100644 --- a/layout.c +++ b/layout.c @@ -33,6 +33,7 @@ typedef struct { chipoff_t end; unsigned int included; char name[256]; + char *file; } romentry_t;
/* rom_entries store the entries specified in a layout file and associated run-time data */ @@ -54,7 +55,7 @@ int read_romlayout(char *name) romlayout = fopen(name, "r");
if (!romlayout) { - msg_gerr("ERROR: Could not open ROM layout (%s).\n", + msg_gerr("ERROR: Could not open layout file (%s).\n", name); return -1; } @@ -63,8 +64,7 @@ int read_romlayout(char *name) char *tstr1, *tstr2;
if (num_rom_entries >= MAX_ROMLAYOUT) { - msg_gerr("Maximum number of ROM images (%i) in layout " - "file reached.\n", MAX_ROMLAYOUT); + msg_gerr("Maximum number of entries (%i) in layout file reached.\n", MAX_ROMLAYOUT); return 1; } if (2 != fscanf(romlayout, "%s %s\n", tempstr, rom_entries[num_rom_entries].name)) @@ -85,6 +85,7 @@ int read_romlayout(char *name) rom_entries[num_rom_entries].start = strtol(tstr1, (char **)NULL, 16); rom_entries[num_rom_entries].end = strtol(tstr2, (char **)NULL, 16); rom_entries[num_rom_entries].included = 0; + rom_entries[num_rom_entries].file = NULL; num_rom_entries++; }
@@ -138,14 +139,9 @@ int register_include_arg(char *name) static int find_romentry(char *name) { int i; - - if (num_rom_entries == 0) - return -1; - msg_gspew("Looking for region "%s"... ", name); for (i = 0; i < num_rom_entries; i++) { - if (!strcmp(rom_entries[i].name, name)) { - rom_entries[i].included = 1; + if (strcmp(rom_entries[i].name, name) == 0) { msg_gspew("found.\n"); return i; } @@ -165,27 +161,61 @@ int process_include_args(void) if (num_include_args == 0) return 0;
- /* User has specified an area, but no layout file is loaded. */ + /* User has specified an include argument, but no layout file is loaded. */ if (num_rom_entries == 0) { - msg_gerr("Region requested (with -i "%s"), " - "but no layout data is available.\n", + msg_gerr("Region requested (with -i/--include "%s"),\n" + "but no layout data is available. To include one use the -l/--layout syntax).\n", include_args[0]); return 1; }
for (i = 0; i < num_include_args; i++) { - if (find_romentry(include_args[i]) < 0) { - msg_gerr("Invalid region specified: "%s".\n", - include_args[i]); + char *file; + char *name = include_args[i]; + int ret = unquote_string(&name, &file, ":"); /* -i <region>[:<file>] */ + if (ret != 0) { + msg_gerr("Invalid include argument specified: "%s".\n", name); return 1; } + int idx = find_romentry(name); + if (idx < 0) { + msg_gerr("Invalid region name specified: "%s".\n", name); + return 1; + } + rom_entries[idx].included = 1; found++; + + if (file[0] != '\0') { + /* The remaining characters are interpreted as possible quoted filename. */ + ret = unquote_string(&file, NULL, NULL); + if (ret != 0) { + msg_gerr("Invalid region file name specified: "%s".\n", file); + return 1; + } +#ifdef __LIBPAYLOAD__ + msg_gerr("Error: No file I/O support in libpayload\n"); + return 1; +#else + file = strdup(file); + if (file == NULL) { + msg_gerr("Out of memory!\n"); + return 1; + } + rom_entries[idx].file = file; +#endif + } }
- 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("Using region%s: ", num_rom_entries > 1 ? "s" : ""); + bool first = true; + for (i = 0; i < num_rom_entries; i++) + if (rom_entries[i].included) { + if (first) + first = false; + else + msg_ginfo(", "); + msg_ginfo(""%s"", rom_entries[i].name); + } msg_ginfo(".\n"); return 0; } @@ -200,6 +230,8 @@ void layout_cleanup(void) num_include_args = 0;
for (i = 0; i < num_rom_entries; i++) { + free(rom_entries[i].file); + rom_entries[i].file = NULL; rom_entries[i].included = 0; } num_rom_entries = 0; @@ -283,6 +315,14 @@ int build_new_image(const struct flashctx *flash, uint8_t *oldcontents, uint8_t if (entry->start > start) memcpy(newcontents + start, oldcontents + start, entry->start - start); + /* If a file name is specified for this region, read the file contents and + * overwrite @newcontents in the range specified by @entry. */ + if (entry->file != NULL) { + if (read_buf_from_file(newcontents + entry->start, entry->end - entry->start + 1, + entry->file, "the region's size") != 0) + return 1; + } + /* Skip to location after current romentry. */ start = entry->end + 1; /* Catch overflow. */