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

tree/: Convert flashchip read func ptr to enumerate

This forges the way for flashchips.c to be pure declarative
data and lookup functions for dispatch to be pure. This
means that the flashchips data could be extracted out to
be agnostic data of the flashrom code and algorithms.

TEST='R|W|E && --flash-name' on ARM, AMD & Intel DUT's.

Change-Id: I612d46fefedf2b69e7e2064aa857fa0756efb4e7
Signed-off-by: Edward O'Callaghan <quasisec@google.com>
Reviewed-on: https://review.coreboot.org/c/flashrom/+/66788
Reviewed-by: Nikolai Artemiev <nartemiev@google.com>
Reviewed-by: Felix Singer <felixsinger@posteo.net>
Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
This commit is contained in:
Edward O'Callaghan 2022-08-16 18:23:33 +10:00 committed by Felix Singer
parent 985ad5623f
commit 594d3357b6
7 changed files with 654 additions and 607 deletions

File diff suppressed because it is too large Load Diff

View File

@ -411,6 +411,35 @@ static int check_erased_range(struct flashctx *flash, unsigned int start, unsign
return ret;
}
/* special unit-test hook */
read_func_t *g_test_read_injector;
static read_func_t *lookup_read_func_ptr(const struct flashchip *chip)
{
switch (chip->read) {
case SPI_CHIP_READ: return &spi_chip_read;
case READ_OPAQUE: return &read_opaque;
case READ_MEMMAPPED: return &read_memmapped;
case EDI_CHIP_READ: return &edi_chip_read;
case SPI_READ_AT45DB: return spi_read_at45db;
case SPI_READ_AT45DB_E8: return spi_read_at45db_e8;
case TEST_READ_INJECTOR: return g_test_read_injector;
/* default: total function, 0 indicates no read function set.
* We explicitly do not want a default catch-all case in the switch
* to ensure unhandled enum's are compiler warnings.
*/
case NO_READ_FUNC: return NULL;
};
return NULL;
}
int read_flash(struct flashctx *flash, uint8_t *buf, unsigned int start, unsigned int len)
{
read_func_t *read_func = lookup_read_func_ptr(flash->chip);
return read_func(flash, buf, start, len);
}
/*
* @cmpbuf buffer to compare against, cmpbuf[0] is expected to match the
* flash content at location start
@ -430,7 +459,7 @@ int verify_range(struct flashctx *flash, const uint8_t *cmpbuf, unsigned int sta
return -1;
}
if (!flash->chip->read) {
if (!lookup_read_func_ptr(flash->chip)) {
msg_cerr("ERROR: flashrom has no read function for this flash chip.\n");
return -1;
}
@ -441,7 +470,7 @@ int verify_range(struct flashctx *flash, const uint8_t *cmpbuf, unsigned int sta
return -1;
}
int ret = flash->chip->read(flash, readbuf, start, len);
int ret = read_flash(flash, readbuf, start, len);
if (ret) {
msg_gerr("Verification impossible because read failed "
"at 0x%x (len 0x%x)\n", start, len);
@ -930,7 +959,7 @@ static int read_by_layout(struct flashctx *const flashctx, uint8_t *const buffer
const chipoff_t region_start = entry->start;
const chipsize_t region_len = entry->end - entry->start + 1;
if (flashctx->chip->read(flashctx, buffer + region_start, region_start, region_len))
if (read_flash(flashctx, buffer + region_start, region_start, region_len))
return 1;
}
return 0;
@ -1159,7 +1188,7 @@ static int erase_block(struct flashctx *const flashctx,
if (info->region_start > info->erase_start) {
const chipoff_t start = info->erase_start;
const chipsize_t len = info->region_start - info->erase_start;
if (flashctx->chip->read(flashctx, backup_contents, start, len)) {
if (read_flash(flashctx, backup_contents, start, len)) {
msg_cerr("Can't read! Aborting.\n");
goto _free_ret;
}
@ -1169,7 +1198,7 @@ static int erase_block(struct flashctx *const flashctx,
const chipoff_t start = info->region_end + 1;
const chipoff_t rel_start = start - info->erase_start; /* within this erase block */
const chipsize_t len = info->erase_end - info->region_end;
if (flashctx->chip->read(flashctx, backup_contents + rel_start, start, len)) {
if (read_flash(flashctx, backup_contents + rel_start, start, len)) {
msg_cerr("Can't read! Aborting.\n");
goto _free_ret;
}
@ -1256,7 +1285,7 @@ static int read_erase_write_block(struct flashctx *const flashctx,
if (info->region_start > info->erase_start) {
const chipoff_t start = info->erase_start;
const chipsize_t len = info->region_start - info->erase_start;
if (flashctx->chip->read(flashctx, newc, start, len)) {
if (read_flash(flashctx, newc, start, len)) {
msg_cerr("Can't read! Aborting.\n");
goto _free_ret;
}
@ -1267,7 +1296,7 @@ static int read_erase_write_block(struct flashctx *const flashctx,
const chipoff_t start = info->region_end + 1;
const chipoff_t rel_start = start - info->erase_start; /* within this erase block */
const chipsize_t len = info->erase_end - info->region_end;
if (flashctx->chip->read(flashctx, newc + rel_start, start, len)) {
if (read_flash(flashctx, newc + rel_start, start, len)) {
msg_cerr("Can't read! Aborting.\n");
goto _free_ret;
}
@ -1367,7 +1396,7 @@ static int verify_by_layout(
const chipoff_t region_start = entry->start;
const chipsize_t region_len = entry->end - entry->start + 1;
if (flashctx->chip->read(flashctx, curcontents + region_start, region_start, region_len))
if (read_flash(flashctx, curcontents + region_start, region_start, region_len))
return 1;
if (compare_range(newcontents + region_start, curcontents + region_start,
region_start, region_len))
@ -1554,7 +1583,7 @@ static int chip_safety_check(const struct flashctx *flash, int force,
return 1;
msg_cerr("Continuing anyway.\n");
}
if (!chip->read) {
if (!lookup_read_func_ptr(chip)) {
msg_cerr("flashrom has no read function for this "
"flash chip.\n");
return 1;
@ -1775,7 +1804,7 @@ int flashrom_image_write(struct flashctx *const flashctx, void *const buffer, co
*/
msg_cinfo("Reading old flash chip contents... ");
if (verify_all) {
if (flashctx->chip->read(flashctx, oldcontents, 0, flash_size)) {
if (read_flash(flashctx, oldcontents, 0, flash_size)) {
msg_cinfo("FAILED.\n");
goto _finalize_ret;
}
@ -1795,7 +1824,7 @@ int flashrom_image_write(struct flashctx *const flashctx, void *const buffer, co
if (verify_all) {
msg_cerr("Checking if anything has changed.\n");
msg_cinfo("Reading current flash chip contents... ");
if (!flashctx->chip->read(flashctx, curcontents, 0, flash_size)) {
if (!read_flash(flashctx, curcontents, 0, flash_size)) {
msg_cinfo("done.\n");
if (!memcmp(oldcontents, curcontents, flash_size)) {
nonfatal_help_message();

8
fmap.c
View File

@ -167,7 +167,7 @@ static int fmap_lsearch_rom(struct fmap **fmap_out,
goto _finalize_ret;
}
ret = flashctx->chip->read(flashctx, buf + rom_offset, rom_offset, len);
ret = read_flash(flashctx, buf + rom_offset, rom_offset, len);
if (ret) {
msg_pdbg("Cannot read ROM contents.\n");
goto _free_ret;
@ -232,7 +232,7 @@ static int fmap_bsearch_rom(struct fmap **fmap_out, struct flashctx *const flash
/* Read errors are considered non-fatal since we may
* encounter locked regions and want to continue. */
if (flashctx->chip->read(flashctx, (uint8_t *)fmap, offset, sig_len)) {
if (read_flash(flashctx, (uint8_t *)fmap, offset, sig_len)) {
/*
* Print in verbose mode only to avoid excessive
* messages for benign errors. Subsequent error
@ -245,7 +245,7 @@ static int fmap_bsearch_rom(struct fmap **fmap_out, struct flashctx *const flash
if (memcmp(fmap, FMAP_SIGNATURE, sig_len) != 0)
continue;
if (flashctx->chip->read(flashctx, (uint8_t *)fmap + sig_len,
if (read_flash(flashctx, (uint8_t *)fmap + sig_len,
offset + sig_len, sizeof(*fmap) - sig_len)) {
msg_cerr("Cannot read %zu bytes at offset %06zx\n",
sizeof(*fmap) - sig_len, offset + sig_len);
@ -277,7 +277,7 @@ static int fmap_bsearch_rom(struct fmap **fmap_out, struct flashctx *const flash
goto _free_ret;
}
if (flashctx->chip->read(flashctx, (uint8_t *)fmap + sizeof(*fmap),
if (read_flash(flashctx, (uint8_t *)fmap + sizeof(*fmap),
offset + sizeof(*fmap), fmap_len - sizeof(*fmap))) {
msg_cerr("Cannot read %zu bytes at offset %06zx\n",
fmap_len - sizeof(*fmap), offset + sizeof(*fmap));

View File

@ -255,6 +255,19 @@ enum write_func {
};
typedef int (write_func_t)(struct flashctx *flash, const uint8_t *buf, unsigned int start, unsigned int len);
enum read_func {
NO_READ_FUNC = 0, /* 0 indicates no read function set. */
SPI_CHIP_READ = 1,
READ_OPAQUE,
READ_MEMMAPPED,
EDI_CHIP_READ,
SPI_READ_AT45DB,
SPI_READ_AT45DB_E8,
TEST_READ_INJECTOR, /* special case must come last. */
};
typedef int (read_func_t)(struct flashctx *flash, uint8_t *buf, unsigned int start, unsigned int len);
int read_flash(struct flashctx *flash, uint8_t *buf, unsigned int start, unsigned int len);
struct flashchip {
const char *vendor;
const char *name;
@ -323,7 +336,7 @@ struct flashchip {
int (*printlock) (struct flashctx *flash);
int (*unlock) (struct flashctx *flash);
enum write_func write;
int (*read) (struct flashctx *flash, uint8_t *buf, unsigned int start, unsigned int len);
enum read_func read;
struct voltage {
uint16_t min;
uint16_t max;

View File

@ -299,7 +299,7 @@ int flashrom_layout_read_from_ifd(struct flashrom_layout **const layout, struct
goto _free_ret;
msg_cinfo("Reading ich descriptor... ");
if (flashctx->chip->read(flashctx, desc, 0, 0x1000)) {
if (read_flash(flashctx, desc, 0, 0x1000)) {
msg_cerr("Read operation failed!\n");
msg_cinfo("FAILED.\n");
ret = 2;

View File

@ -147,12 +147,13 @@ static void teardown(struct flashrom_layout **layout)
}
extern write_func_t *g_test_write_injector;
extern read_func_t *g_test_read_injector;
static const struct flashchip chip_8MiB = {
.vendor = "aklm",
.total_size = MOCK_CHIP_SIZE / KiB,
.tested = TEST_OK_PREW,
.read = read_chip,
.read = TEST_READ_INJECTOR,
.write = TEST_WRITE_INJECTOR,
.unlock = unlock_chip,
.block_erasers =
@ -168,7 +169,7 @@ static const struct flashchip chip_W25Q128_V = {
.vendor = "aklm&dummyflasher",
.total_size = 16 * 1024,
.tested = TEST_OK_PREW,
.read = spi_chip_read,
.read = SPI_CHIP_READ,
.write = SPI_CHIP_WRITE256,
.unlock = spi_disable_blockprotect,
.page_size = 256,
@ -206,6 +207,7 @@ void erase_chip_test_success(void **state)
};
g_test_write_injector = write_chip;
g_test_read_injector = read_chip;
struct flashrom_flashctx flashctx = { 0 };
struct flashrom_layout *layout;
struct flashchip mock_chip = chip_8MiB;
@ -265,6 +267,7 @@ void read_chip_test_success(void **state)
};
g_test_write_injector = write_chip;
g_test_read_injector = read_chip;
struct flashrom_flashctx flashctx = { 0 };
struct flashrom_layout *layout;
struct flashchip mock_chip = chip_8MiB;
@ -337,6 +340,7 @@ void write_chip_test_success(void **state)
};
g_test_write_injector = write_chip;
g_test_read_injector = read_chip;
struct flashrom_flashctx flashctx = { 0 };
struct flashrom_layout *layout;
struct flashchip mock_chip = chip_8MiB;
@ -435,6 +439,7 @@ void verify_chip_test_success(void **state)
};
g_test_write_injector = write_chip;
g_test_read_injector = read_chip;
struct flashrom_flashctx flashctx = { 0 };
struct flashrom_layout *layout;
struct flashchip mock_chip = chip_8MiB;

View File

@ -64,7 +64,7 @@ static const struct flashchip chip_W25Q128_V = {
.vendor = "aklm&dummyflasher",
.total_size = 16 * 1024,
.tested = TEST_OK_PREW,
.read = spi_chip_read,
.read = SPI_CHIP_READ,
.write = SPI_CHIP_WRITE256,
.unlock = spi_disable_blockprotect,
.feature_bits = FEATURE_WRSR_WREN | FEATURE_OTP | FEATURE_WRSR_EXT2 | FEATURE_WRSR2 | FEATURE_WRSR3,