1
0
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:
Matt DeVillier
2025-10-12 17:46:42 -05:00
committed by Anastasia Klimchuk
parent b0b975d0ea
commit bc3f2f84f9
4 changed files with 104 additions and 8 deletions

View File

@@ -33,6 +33,7 @@ enum {
OPTION_IFD = 0x0100,
OPTION_FMAP,
OPTION_FMAP_FILE,
OPTION_FMAP_VERIFY,
OPTION_FLASH_CONTENTS,
OPTION_FLASH_NAME,
OPTION_FLASH_SIZE,
@@ -65,7 +66,7 @@ struct cli_options {
const struct programmer_entry *prog;
char *pparam;
bool ifd, fmap;
bool ifd, fmap, fmap_verify;
struct flashrom_layout *layout;
struct layout_include_args *include_args;
char *layoutfile;
@@ -132,6 +133,7 @@ static void cli_classic_usage(const char *name)
" --flash-size read out the detected flash size\n"
" --fmap read ROM layout from fmap embedded in ROM\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"
" -i | --include <region>[:<file>] only read/write image <region> from layout\n"
" (optionally with data from <file>)\n"
@@ -847,7 +849,7 @@ static void parse_options(int argc, char **argv, const char *optstring,
break;
case OPTION_FMAP_FILE:
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");
if (options->ifd)
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;
case OPTION_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");
if (options->ifd)
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");
options->fmap = true;
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':
if (register_include_arg(&options->include_args, optarg))
cli_classic_abort_usage(NULL);
@@ -1060,6 +1075,7 @@ int main(int argc, char *argv[])
{"ifd", 0, NULL, OPTION_IFD},
{"fmap", 0, NULL, OPTION_FMAP},
{"fmap-file", 1, NULL, OPTION_FMAP_FILE},
{"fmap-verify", 0, NULL, OPTION_FMAP_VERIFY},
{"image", 1, NULL, 'i'}, // (deprecated): back compatibility.
{"include", 1, NULL, 'i'},
{"flash-contents", 1, NULL, OPTION_FLASH_CONTENTS},
@@ -1436,11 +1452,54 @@ int main(int argc, char *argv[])
goto out_shutdown;
}
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)) ||
process_include_args(options.layout, options.include_args))) {
ret = 1;
goto out_shutdown;
process_include_args(options.layout, options.include_args)) {
ret = 1;
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);

View File

@@ -15,7 +15,7 @@ SYNOPSIS
| -p <programmername>[:<parameters>] [-c <chipname>]
| (--flash-name|--flash-size|
| [-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>]]]
| [--wp-status] [--wp-list] [--wp-enable|--wp-disable]
| [--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
**--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**
Read ROM layout from Intel Firmware Descriptor.

View File

@@ -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
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
===============

View File

@@ -53,6 +53,7 @@ _flashrom()
--flash-size
--fmap
--fmap-file
--fmap-verify
--ifd
--include
--output