1
0
mirror of https://review.coreboot.org/flashrom.git synced 2025-04-26 22:52:34 +02:00

cli_classic.c: Make -r/-w/-v argument optional when using -i

Make the filename parameter directly following -r/-w/-v optional, since
the -i parameter allows the image to be written to be sourced from
multiple files, regions to be read from flash and written to separate
image files, and regions to be verified using an image file only
containing that region.

Since the filename parameter following -w/-v was ignored when a
filename was specified following `-i <region>:<filename>`, this patch
essentially removes the requirement to provide an unused parameter.

Based on https://review.coreboot.org/c/flashrom/+/52362.

TEST=run the following commands on a supported board:
flashrom -p internal -r /tmp/coreboot.rom
flashrom -p internal -r --ifd -i bios:/tmp/coreboot.rom
flashrom -p internal -r /tmp/coreboot.rom --ifd -i bios:/tmp/bios.bin
flashrom -p internal -w /tmp/coreboot.rom
flashrom -p internal -w --ifd -i bios:/tmp/coreboot.rom
flashrom -p internal -w /tmp/coreboot.rom --ifd -i bios:/tmp/bios.bin
flashrom -p internal -v /tmp/coreboot.rom
flashrom -p internal -v --ifd -i bios:/tmp/coreboot.rom
flashrom -p internal -v /tmp/coreboot.rom --ifd -i bios:/tmp/bios.bin

Change-Id: I6eba095d478f1a7bdbc3854627a656f93dd9e452
Signed-off-by: Matt DeVillier <matt.devillier@gmail.com>
Reviewed-on: https://review.coreboot.org/c/flashrom/+/85159
Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
Reviewed-by: Anastasia Klimchuk <aklm@chromium.org>
This commit is contained in:
Matt DeVillier 2024-11-15 09:33:01 -06:00 committed by Anastasia Klimchuk
parent d07cd9f515
commit b9e0a3ce70
4 changed files with 176 additions and 38 deletions

View File

@ -108,17 +108,17 @@ static void cli_classic_usage(const char *name)
printf("Usage: %s [-h|-R|-L|"
"\n\t-p <programmername>[:<parameters>] [-c <chipname>]\n"
"\t\t(--flash-name|--flash-size|\n"
"\t\t [-E|-x|(-r|-w|-v) <file>]\n"
"\t\t [-E|-x|(-r|-w|-v) [<file>]]\n"
"\t\t [(-l <layoutfile>|--ifd| --fmap|--fmap-file <file>) [-i <region>[:<file>]]...]\n"
"\t\t [-n] [-N] [-f])]\n"
"\t[-V[V[V]]] [-o <logfile>]\n\n", name);
printf(" -h | --help print this help text\n"
" -R | --version print version (release)\n"
" -r | --read <file> read flash and save to <file>\n"
" -w | --write (<file>|-) write <file> or the content provided\n"
" -r | --read [<file>] read flash and save to <file>\n"
" -w | --write [<file>|-] write <file> or the content provided\n"
" on the standard input to flash\n"
" -v | --verify (<file>|-) verify flash against <file>\n"
" -v | --verify [<file>|-] verify flash against <file>\n"
" or the content provided on the standard input\n"
" -E | --erase erase flash memory\n"
" -V | --verbose more verbose output\n"
@ -616,6 +616,23 @@ static int write_buf_to_include_args(const struct flashrom_layout *const layout,
return 0;
}
static char *get_optional_filename(char *argv[])
{
char *filename = NULL;
/* filename was supplied in optarg (i.e. -rfilename) */
if (optarg != NULL)
filename = strdup(optarg);
/* filename is on optind if it is not another flag (i.e. -r filename)
* - is treated as stdin, so we still strdup in this case
*/
else if (optarg == NULL && argv[optind] != NULL &&
(argv[optind][0] != '-' || argv[optind][1] == '\0'))
filename = strdup(argv[optind++]);
return filename;
}
static int do_read(struct flashctx *const flash, const char *const filename)
{
int ret;
@ -663,8 +680,10 @@ static int do_write(struct flashctx *const flash, const char *const filename, co
}
/* Read '-w' argument first... */
if (filename) {
if (read_buf_from_file(newcontents, flash_size, filename))
goto _free_ret;
}
/*
* ... then update newcontents with contents from files provided to '-i'
* args if needed.
@ -697,8 +716,10 @@ static int do_verify(struct flashctx *const flash, const char *const filename)
}
/* Read '-v' argument first... */
if (filename) {
if (read_buf_from_file(newcontents, flash_size, filename))
goto _free_ret;
}
/*
* ... then update newcontents with contents from files provided to '-i'
* args if needed.
@ -773,12 +794,12 @@ static void parse_options(int argc, char **argv, const char *optstring,
switch (opt) {
case 'r':
cli_classic_validate_singleop(&operation_specified);
options->filename = strdup(optarg);
options->filename = get_optional_filename(argv);
options->read_it = true;
break;
case 'w':
cli_classic_validate_singleop(&operation_specified);
options->filename = strdup(optarg);
options->filename = get_optional_filename(argv);
options->write_it = true;
break;
case 'v':
@ -787,7 +808,7 @@ static void parse_options(int argc, char **argv, const char *optstring,
if (options->dont_verify_it) {
cli_classic_abort_usage("--verify and --noverify are mutually exclusive. Aborting.\n");
}
options->filename = strdup(optarg);
options->filename = get_optional_filename(argv);
options->verify_it = true;
break;
case 'n':
@ -1033,12 +1054,12 @@ int main(int argc, char *argv[])
int ret = 0;
struct cli_options options = { 0 };
static const char optstring[] = "r:Rw:v:nNVEfc:l:i:p:Lzho:x";
static const char optstring[] = "r::Rw::v::nNVEfc:l:i:p:Lzho:x";
static const struct option long_options[] = {
{"read", 1, NULL, 'r'},
{"write", 1, NULL, 'w'},
{"read", 2, NULL, 'r'},
{"write", 2, NULL, 'w'},
{"erase", 0, NULL, 'E'},
{"verify", 1, NULL, 'v'},
{"verify", 2, NULL, 'v'},
{"noverify", 0, NULL, 'n'},
{"noverify-all", 0, NULL, 'N'},
{"extract", 0, NULL, 'x'},
@ -1098,7 +1119,7 @@ int main(int argc, char *argv[])
parse_options(argc, argv, optstring, long_options, &options);
if ((options.read_it | options.write_it | options.verify_it) && check_filename(options.filename, "image"))
if (options.filename && check_filename(options.filename, "image"))
cli_classic_abort_usage(NULL);
if (options.layoutfile && check_filename(options.layoutfile, "layout"))
cli_classic_abort_usage(NULL);
@ -1316,6 +1337,57 @@ int main(int argc, char *argv[])
goto out_shutdown;
}
/*
* Common rules for -r/-w/-v syntax parsing:
*
* - If no filename is specified at all, quit.
*
* - If a file is specified for -r/-w/-v and no files are specified with
* -i args (or -i is not used), then that file will be used for reading/
* writing/verifying the entire ROM.
*
* - If no filename is specified for -r/-w/-v, but files are specified
* for -i, then the number of file arguments for -i options must be
* equal to the total number of -i options.
*
* Rules for reading:
*
* - If files are specified for -i args but not -r, do partial reads for
* each -i arg, creating a new file for each region. Each -i option
* must specify a filename.
*
* - If filenames are specified for -r and -i args, then:
* - Do partial read for each -i arg, creating a new file for
* each region where a filename is provided (-i region:filename).
* - Create a ROM-sized file with partially filled content. For each
* -i arg, fill the corresponding offset with content from ROM.
*
* Rules for writing and verifying:
*
* - If files are specified for both -w/-v and -i args, -i files take
* priority (files specified for -w/-v are unused).
*
* - If files are specified for -i args but not -w, do partial writes
* for each -i arg. Likewise for -v and -i args. All -i args must
* supply a filename. Any omission is considered ambiguous.
*
* - Regions with a filename associated must not overlap. This is also
* considered ambiguous. Note: This is checked later since it requires
* processing the layout/fmap first.
*/
if ((options.read_it | options.write_it | options.verify_it) && !options.filename) {
if (!options.include_args) {
msg_gerr("Error: No image file specified.\n");
ret = 1;
goto out_shutdown;
}
if (check_include_args_filename(options.include_args)) {
ret = 1;
goto out_shutdown;
}
}
if (options.flash_name) {
if (fill_flash->chip->vendor && fill_flash->chip->name) {
printf("vendor=\"%s\" name=\"%s\"\n",

View File

@ -14,7 +14,7 @@ SYNOPSIS
| **flashrom** [-h|-R|-L|
| -p <programmername>[:<parameters>] [-c <chipname>]
| (--flash-name|--flash-size|
| [-E|-x|-r <file>|-w <file>|-v <file>]
| [-E|-x|-r [<file>]|-w [<file>]|-v [<file>]]
| [(-l <file>|--ifd|--fmap|--fmap-file <file>)
| [-i <include>[:<file>]]]
| [--wp-status] [--wp-list] [--wp-enable|--wp-disable]
@ -50,10 +50,13 @@ Also you are advised to make a backup of your current ROM contents with ``-r`` b
All operations involving any chip access (probe/read/write/...) require the ``-p/--programmer`` option to be used (please see below).
**-r, --read <file>**
**-r, --read [<file>]**
Read flash ROM contents and save them into the given **<file>**.
If the file already exists, it will be overwritten.
The **<file>** parameter is required here unless reading is restricted to one or more flash regions via the ``-i/--include`` parameter
and the file is specified there. See the ``--include`` section below for examples.
**-w, --write (<file>|-)**
Write **<file>** into flash ROM. If **-** is provided instead, contents will be read from stdin.
@ -64,6 +67,9 @@ All operations involving any chip access (probe/read/write/...) require the ``-p
This copy is updated along with the write operation. In case of erase errors it is even re-read completely.
After writing has finished and if verification is enabled, the whole flash chip is read out and compared with the input image.
The **<file>** parameter is required here unless writing is restricted to one or more flash regions via the ``-i/--include`` parameter
and the file is specified there. See the ``--include`` section below for examples.
**-n, --noverify**
Skip the automatic verification of flash ROM contents after writing. Using this option is **not** recommended,
@ -91,6 +97,9 @@ All operations involving any chip access (probe/read/write/...) require the ``-p
Verify the flash ROM contents against the given **<file>**.
If **-** is provided instead, contents will be written to the stdout.
The **<file>** parameter is required here unless verification is restricted to one or more flash regions via the ``-i/--include`` parameter
and the file is specified there. See the ``--include`` section below for examples.
**-E, --erase**
Erase the flash ROM chip.
@ -187,23 +196,66 @@ All operations involving any chip access (probe/read/write/...) require the ``-p
**-i, --include <region>[:<file>]**
Read or write only **<region>** to or from ROM.
The **-i** option may be used multiple times if the user wishes to read or write multiple regions using a single command.
Read, write, or verify only **<region>** to or from ROM.
The **-i** option may be used multiple times if the user wishes to read, write, or verify multiple regions using a single command.
The user may optionally specify a corresponding **<file>** for any region they wish to read or write.
A read operation will read the corresponding regions from ROM and write individual files for each one.
A write option will read file(s) and write to the corresponding region(s) in ROM.
For write operations, files specified using ``-i`` take precedence over content from the argument to ``-w``.
For all read/write/verify operations, the **<file>** parameter following those operations becomes optional and will be ignored
if present whenever the <file> is specified following the region.
Common rules for -r/-w/-v syntax parsing:
- If no filename is specified at all, quit.
- If a file is specified for -r/-w/-v and no files are specified with
-i args (or -i is not used), then that file will be used for reading/
writing/verifying the entire ROM.
- If no filename is specified for -r/-w/-v, but files are specified
for -i, then the number of file arguments for -i options must be
equal to the total number of -i options.
Rules for reading:
- If files are specified for -i args but not -r, do partial reads for
each -i arg, creating a new file for each region. Each -i option
must specify a filename.
- If filenames are specified for -r and -i args, then:
- Do partial read for each -i arg, creating a new file for
each region where a filename is provided (-i region:filename).
- Create a ROM-sized file with partially filled content. For each
-i arg, fill the corresponding offset with content from ROM.
Rules for writing and verifying:
- If files are specified for both -w/-v and -i args, -i files take
priority (files specified for -w/-v are unused).
- If files are specified for -i args but not -w, do partial writes
for each -i arg. Likewise for -v and -i args. All -i args must
supply a filename. Any omission is considered ambiguous.
- Regions with a filename associated must not overlap. This is also
considered ambiguous. Note: This is checked later since it requires
processing the layout/fmap first.
Examples:
To read regions named **foo** and **bar** in layout file **<layout>** into region-sized files **foo.bin** and **bar.bin**, run::
flashrom -p prog -l <layout> -i foo:foo.bin -i bar:bar.bin -r rom.bin
flashrom -p prog -r -l <layout> -i foo:foo.bin -i bar:bar.bin
To write files **foo.bin** and **bar.bin** into regions named **foo** and **bar** in layout file **<layout>** to the ROM, run::
flashrom -p prog -l <layout> -i foo:foo.bin -i bar:bar.bin -w rom.bin
flashrom -p prog -w -l <layout> -i foo:foo.bin -i bar:bar.bin
To verify regions named **foo** and **bar** using layout file **<layout>** and files **foo.bin** and **bar.bin**, run::
flashrom -p prog -v -l <layout> -i foo:foo.bin -i bar:bar.bin
**--wp-status**

View File

@ -69,6 +69,7 @@ int layout_from_file(struct flashrom_layout **, const char *name);
int register_include_arg(struct layout_include_args **, const char *arg);
int process_include_args(struct flashrom_layout *, const struct layout_include_args *);
int check_include_args_filename(const struct layout_include_args *);
void cleanup_include_args(struct layout_include_args **);
const struct romentry *layout_next_included_region(const struct flashrom_layout *, chipoff_t);

View File

@ -288,6 +288,19 @@ int process_include_args(struct flashrom_layout *l, const struct layout_include_
return 0;
}
int check_include_args_filename(const struct layout_include_args *include_args)
{
const struct layout_include_args *arg;
for (arg = include_args; arg; arg = arg->next) {
if (!arg->file || (arg->file[0] == '\0')) {
fprintf(stderr, "Error: No region file specified for -i/--include option.\n");
return 1;
}
}
return 0;
}
/* returns boolean 1 if any regions overlap, 0 otherwise */
int included_regions_overlap(const struct flashrom_layout *const l)
{