mirror of
https://review.coreboot.org/flashrom.git
synced 2025-11-05 15:40:41 +01:00
cli-classic: Add new '--fmap-verify' option
Add a new layout option, --fmap-verify, to be used when writing to flash, which will compare the FMAP on the flash chip to the one in the file being flashed, and abort if there are any differences. The comparison ensures that number of regions and start/end addresses are all identical. Add documentation for the new option as well. TEST: tested with the following commands: flashrom -p internal -r coreboot.rom --fmap-verify -i COREBOOT (fails w/error) flashrom -p internal -v coreboot.rom --fmap-verify -i COREBOOT (fails w/error) flashrom -p internal -r coreboot.rom --fmap -i COREBOOT (ok) flashrom -p internal -w coreboot.rom --fmap-verify -i COREBOOT (fails w/error - no FMAP) flashrom -p internal -r coreboot.rom (fails w/error, active ME) flashrom -p internal -r coreboot.rom --ifd -i bios (ok) flashrom -p internal -w coreboot.rom --fmap-verify -i COREBOOT -N (ok) Change-Id: I34f69d848869cf236b7e57cf8f60c2aaad79c385 Signed-off-by: Matt DeVillier <matt.devillier@gmail.com> Reviewed-on: https://review.coreboot.org/c/flashrom/+/89536 Tested-by: build bot (Jenkins) <no-reply@coreboot.org> Reviewed-by: Anastasia Klimchuk <aklm@chromium.org>
This commit is contained in:
committed by
Anastasia Klimchuk
parent
b0b975d0ea
commit
bc3f2f84f9
@@ -33,6 +33,7 @@ enum {
|
|||||||
OPTION_IFD = 0x0100,
|
OPTION_IFD = 0x0100,
|
||||||
OPTION_FMAP,
|
OPTION_FMAP,
|
||||||
OPTION_FMAP_FILE,
|
OPTION_FMAP_FILE,
|
||||||
|
OPTION_FMAP_VERIFY,
|
||||||
OPTION_FLASH_CONTENTS,
|
OPTION_FLASH_CONTENTS,
|
||||||
OPTION_FLASH_NAME,
|
OPTION_FLASH_NAME,
|
||||||
OPTION_FLASH_SIZE,
|
OPTION_FLASH_SIZE,
|
||||||
@@ -65,7 +66,7 @@ struct cli_options {
|
|||||||
const struct programmer_entry *prog;
|
const struct programmer_entry *prog;
|
||||||
char *pparam;
|
char *pparam;
|
||||||
|
|
||||||
bool ifd, fmap;
|
bool ifd, fmap, fmap_verify;
|
||||||
struct flashrom_layout *layout;
|
struct flashrom_layout *layout;
|
||||||
struct layout_include_args *include_args;
|
struct layout_include_args *include_args;
|
||||||
char *layoutfile;
|
char *layoutfile;
|
||||||
@@ -132,6 +133,7 @@ static void cli_classic_usage(const char *name)
|
|||||||
" --flash-size read out the detected flash size\n"
|
" --flash-size read out the detected flash size\n"
|
||||||
" --fmap read ROM layout from fmap embedded in ROM\n"
|
" --fmap read ROM layout from fmap embedded in ROM\n"
|
||||||
" --fmap-file <fmapfile> read ROM layout from fmap in <fmapfile>\n"
|
" --fmap-file <fmapfile> read ROM layout from fmap in <fmapfile>\n"
|
||||||
|
" --fmap-verify read ROM layout from fmap and verify it matches file fmap\n"
|
||||||
" --ifd read layout from an Intel Firmware Descriptor\n"
|
" --ifd read layout from an Intel Firmware Descriptor\n"
|
||||||
" -i | --include <region>[:<file>] only read/write image <region> from layout\n"
|
" -i | --include <region>[:<file>] only read/write image <region> from layout\n"
|
||||||
" (optionally with data from <file>)\n"
|
" (optionally with data from <file>)\n"
|
||||||
@@ -847,7 +849,7 @@ static void parse_options(int argc, char **argv, const char *optstring,
|
|||||||
break;
|
break;
|
||||||
case OPTION_FMAP_FILE:
|
case OPTION_FMAP_FILE:
|
||||||
if (options->fmap)
|
if (options->fmap)
|
||||||
cli_classic_abort_usage("Error: --fmap or --fmap-file specified "
|
cli_classic_abort_usage("Error: --fmap, --fmap-file, or --fmap-verify specified "
|
||||||
"more than once. Aborting.\n");
|
"more than once. Aborting.\n");
|
||||||
if (options->ifd)
|
if (options->ifd)
|
||||||
cli_classic_abort_usage("Error: --fmap-file and --ifd both specified. Aborting.\n");
|
cli_classic_abort_usage("Error: --fmap-file and --ifd both specified. Aborting.\n");
|
||||||
@@ -858,7 +860,7 @@ static void parse_options(int argc, char **argv, const char *optstring,
|
|||||||
break;
|
break;
|
||||||
case OPTION_FMAP:
|
case OPTION_FMAP:
|
||||||
if (options->fmap)
|
if (options->fmap)
|
||||||
cli_classic_abort_usage("Error: --fmap or --fmap-file specified "
|
cli_classic_abort_usage("Error: --fmap, --fmap-file, or --fmap-verify specified "
|
||||||
"more than once. Aborting.\n");
|
"more than once. Aborting.\n");
|
||||||
if (options->ifd)
|
if (options->ifd)
|
||||||
cli_classic_abort_usage("Error: --fmap and --ifd both specified. Aborting.\n");
|
cli_classic_abort_usage("Error: --fmap and --ifd both specified. Aborting.\n");
|
||||||
@@ -866,6 +868,19 @@ static void parse_options(int argc, char **argv, const char *optstring,
|
|||||||
cli_classic_abort_usage("Error: --layout and --fmap both specified. Aborting.\n");
|
cli_classic_abort_usage("Error: --layout and --fmap both specified. Aborting.\n");
|
||||||
options->fmap = true;
|
options->fmap = true;
|
||||||
break;
|
break;
|
||||||
|
case OPTION_FMAP_VERIFY:
|
||||||
|
if (options->fmap)
|
||||||
|
cli_classic_abort_usage("Error: --fmap, --fmap-file, or --fmap-verify specified "
|
||||||
|
"more than once. Aborting.\n");
|
||||||
|
if (options->ifd)
|
||||||
|
cli_classic_abort_usage("Error: --fmap-verify and --ifd both specified. Aborting.\n");
|
||||||
|
if (options->layoutfile)
|
||||||
|
cli_classic_abort_usage("Error: --fmap-verify and --layout both specified. Aborting.\n");
|
||||||
|
if (options->read_it || options->verify_it)
|
||||||
|
cli_classic_abort_usage("Error: --fmap-verify cannot be used with read or verify operations. Aborting.\n");
|
||||||
|
options->fmap = true;
|
||||||
|
options->fmap_verify = true;
|
||||||
|
break;
|
||||||
case 'i':
|
case 'i':
|
||||||
if (register_include_arg(&options->include_args, optarg))
|
if (register_include_arg(&options->include_args, optarg))
|
||||||
cli_classic_abort_usage(NULL);
|
cli_classic_abort_usage(NULL);
|
||||||
@@ -1060,6 +1075,7 @@ int main(int argc, char *argv[])
|
|||||||
{"ifd", 0, NULL, OPTION_IFD},
|
{"ifd", 0, NULL, OPTION_IFD},
|
||||||
{"fmap", 0, NULL, OPTION_FMAP},
|
{"fmap", 0, NULL, OPTION_FMAP},
|
||||||
{"fmap-file", 1, NULL, OPTION_FMAP_FILE},
|
{"fmap-file", 1, NULL, OPTION_FMAP_FILE},
|
||||||
|
{"fmap-verify", 0, NULL, OPTION_FMAP_VERIFY},
|
||||||
{"image", 1, NULL, 'i'}, // (deprecated): back compatibility.
|
{"image", 1, NULL, 'i'}, // (deprecated): back compatibility.
|
||||||
{"include", 1, NULL, 'i'},
|
{"include", 1, NULL, 'i'},
|
||||||
{"flash-contents", 1, NULL, OPTION_FLASH_CONTENTS},
|
{"flash-contents", 1, NULL, OPTION_FLASH_CONTENTS},
|
||||||
@@ -1436,11 +1452,54 @@ int main(int argc, char *argv[])
|
|||||||
goto out_shutdown;
|
goto out_shutdown;
|
||||||
}
|
}
|
||||||
free(fmapfile_buffer);
|
free(fmapfile_buffer);
|
||||||
} else if (options.fmap && (flashrom_layout_read_fmap_from_rom(&options.layout, &context, 0,
|
} else if (options.fmap) {
|
||||||
|
/* Read layout from ROM fmap */
|
||||||
|
if (flashrom_layout_read_fmap_from_rom(&options.layout, &context, 0,
|
||||||
flashrom_flash_getsize(&context)) ||
|
flashrom_flash_getsize(&context)) ||
|
||||||
process_include_args(options.layout, options.include_args))) {
|
process_include_args(options.layout, options.include_args)) {
|
||||||
ret = 1;
|
ret = 1;
|
||||||
goto out_shutdown;
|
goto out_shutdown;
|
||||||
|
}
|
||||||
|
if (options.fmap_verify) {
|
||||||
|
struct flashrom_layout *file_layout = NULL;
|
||||||
|
struct stat s;
|
||||||
|
if (stat(options.filename, &s) != 0) {
|
||||||
|
msg_gerr("Failed to stat the file \"%s\"\n", options.filename);
|
||||||
|
ret = 1;
|
||||||
|
goto out_release;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t fmapfile_size = s.st_size;
|
||||||
|
uint8_t *file_buffer = malloc(fmapfile_size);
|
||||||
|
if (!file_buffer) {
|
||||||
|
ret = 1;
|
||||||
|
goto out_release;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (read_buf_from_file(file_buffer, fmapfile_size, options.filename)) {
|
||||||
|
ret = 1;
|
||||||
|
free(file_buffer);
|
||||||
|
goto out_release;
|
||||||
|
}
|
||||||
|
/* Read layout from file fmap */
|
||||||
|
if (flashrom_layout_read_fmap_from_buffer(&file_layout, &context, file_buffer,
|
||||||
|
flashrom_flash_getsize(&context)) ||
|
||||||
|
process_include_args(file_layout, options.include_args)) {
|
||||||
|
ret = 1;
|
||||||
|
free(file_buffer);
|
||||||
|
goto out_release;
|
||||||
|
}
|
||||||
|
free(file_buffer);
|
||||||
|
/* compare the two layouts */
|
||||||
|
if (flashrom_layout_compare(options.layout, file_layout)) {
|
||||||
|
msg_cerr("FMAP layouts do not match! Aborting.\n");
|
||||||
|
flashrom_layout_release(file_layout);
|
||||||
|
ret = 1;
|
||||||
|
goto out_release;
|
||||||
|
}
|
||||||
|
flashrom_layout_release(file_layout);
|
||||||
|
msg_cinfo("FMAP layouts match.\n");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
flashrom_layout_set(&context, options.layout);
|
flashrom_layout_set(&context, options.layout);
|
||||||
|
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ SYNOPSIS
|
|||||||
| -p <programmername>[:<parameters>] [-c <chipname>]
|
| -p <programmername>[:<parameters>] [-c <chipname>]
|
||||||
| (--flash-name|--flash-size|
|
| (--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>)
|
| [(-l <file>|--ifd|--fmap|--fmap-file <file>|--fmap-verify)
|
||||||
| [-i <include>[:<file>]]]
|
| [-i <include>[:<file>]]]
|
||||||
| [--wp-status] [--wp-list] [--wp-enable|--wp-disable]
|
| [--wp-status] [--wp-list] [--wp-enable|--wp-disable]
|
||||||
| [--wp-range <start>,<length>|--wp-region <region>]
|
| [--wp-range <start>,<length>|--wp-region <region>]
|
||||||
@@ -179,6 +179,21 @@ All operations involving any chip access (probe/read/write/...) require the ``-p
|
|||||||
flashrom -p prog --fmap-file some.rom --image COREBOOT -w some.rom
|
flashrom -p prog --fmap-file some.rom --image COREBOOT -w some.rom
|
||||||
|
|
||||||
|
|
||||||
|
**--fmap-verify**
|
||||||
|
Read ROM layout from fmap embedded in the ROM and verify that it matches the fmap in the file to be written.
|
||||||
|
|
||||||
|
This option is mutually exclusive with **--fmap**, **--fmap-file**, **--layout**, and **--ifd**.
|
||||||
|
It can only be used with write operations, as it does not make sense otherwise. Before writing, **flashrom**
|
||||||
|
will read the fmap from both the flash chip and the file to be written, then compare them. If the fmaps do
|
||||||
|
not match, the write operation will be aborted.
|
||||||
|
|
||||||
|
This is useful to prevent accidentally writing a ROM image with an incompatible layout to a flash chip.
|
||||||
|
|
||||||
|
If you only want to update the **COREBOOT** region defined in the fmap, and verify that the fmap matches, run::
|
||||||
|
|
||||||
|
flashrom -p prog --fmap-verify -w new.rom --image COREBOOT
|
||||||
|
|
||||||
|
|
||||||
**--ifd**
|
**--ifd**
|
||||||
Read ROM layout from Intel Firmware Descriptor.
|
Read ROM layout from Intel Firmware Descriptor.
|
||||||
|
|
||||||
|
|||||||
@@ -38,6 +38,27 @@ If you are flashing multiple regions or ones that partially overlap with
|
|||||||
read-only parts then that could result in flashrom failing in the
|
read-only parts then that could result in flashrom failing in the
|
||||||
middle, leaving you in unknown state.
|
middle, leaving you in unknown state.
|
||||||
|
|
||||||
|
FMAP verification support
|
||||||
|
--------------------------
|
||||||
|
|
||||||
|
A new ``--fmap-verify`` option has been added that allows verification of FMAP
|
||||||
|
(Flash Map) layout compatibility before performing write operations. This option
|
||||||
|
reads the FMAP layout from both the flash ROM and the file to be written, then
|
||||||
|
compares them to ensure they match before proceeding with the write.
|
||||||
|
|
||||||
|
This is particularly useful when updating specific regions (e.g., COREBOOT) to
|
||||||
|
prevent accidentally writing a ROM image with an incompatible layout that could
|
||||||
|
result in a bricked system. The ``--fmap-verify`` option is mutually exclusive
|
||||||
|
with ``--fmap``, ``--fmap-file``, ``--layout``, and ``--ifd`` options, and can
|
||||||
|
only be used with write operations (``-w``).
|
||||||
|
|
||||||
|
Example usage::
|
||||||
|
|
||||||
|
flashrom -p programmer --fmap-verify -w newimage.rom --image COREBOOT
|
||||||
|
|
||||||
|
If the FMAP layouts don't match, the operation will abort with a detailed error
|
||||||
|
message showing which regions differ.
|
||||||
|
|
||||||
New programmers
|
New programmers
|
||||||
===============
|
===============
|
||||||
|
|
||||||
|
|||||||
@@ -53,6 +53,7 @@ _flashrom()
|
|||||||
--flash-size
|
--flash-size
|
||||||
--fmap
|
--fmap
|
||||||
--fmap-file
|
--fmap-file
|
||||||
|
--fmap-verify
|
||||||
--ifd
|
--ifd
|
||||||
--include
|
--include
|
||||||
--output
|
--output
|
||||||
|
|||||||
Reference in New Issue
Block a user