1
0
mirror of https://review.coreboot.org/flashrom.git synced 2025-07-01 06:01:16 +02:00

tree/: Convert flashchip erase_block 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.

Change-Id: I02ae7e4c67c5bf34ec2fd7ffe4af8a2aba6fd5e5
Signed-off-by: Edward O'Callaghan <quasisec@google.com>
Reviewed-on: https://review.coreboot.org/c/flashrom/+/69133
Reviewed-by: Angel Pons <th3fanbus@gmail.com>
Reviewed-by: Anastasia Klimchuk <aklm@chromium.org>
Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
This commit is contained in:
Edward O'Callaghan
2022-08-29 10:36:21 +10:00
committed by Edward O'Callaghan
parent 3c44e12a28
commit 3bba710d98
7 changed files with 108 additions and 47 deletions

View File

@ -80,9 +80,10 @@ static unsigned int at45db_get_sector_count(struct flashctx *flash)
unsigned int i, j; unsigned int i, j;
unsigned int cnt = 0; unsigned int cnt = 0;
for (i = 0; i < NUM_ERASEFUNCTIONS; i++) { for (i = 0; i < NUM_ERASEFUNCTIONS; i++) {
if (flash->chip->block_erasers[i].block_erase == SPI_ERASE_AT45DB_SECTOR) { const struct block_eraser *const eraser = &flash->chip->block_erasers[i];
if (eraser->block_erase == SPI_ERASE_AT45DB_SECTOR) {
for (j = 0; j < NUM_ERASEREGIONS; j++) { for (j = 0; j < NUM_ERASEREGIONS; j++) {
cnt += flash->chip->block_erasers[i].eraseblocks[j].count; cnt += eraser->eraseblocks[j].count;
} }
} }
} }

View File

@ -336,6 +336,57 @@ char *extract_programmer_param_str(const struct programmer_cfg *cfg, const char
return extract_param(&cfg->params, param_name, ","); return extract_param(&cfg->params, param_name, ",");
} }
/* special unit-test hook */
erasefunc_t *g_test_erase_injector;
static erasefunc_t *lookup_erase_func_ptr(const struct block_eraser *const eraser)
{
switch (eraser->block_erase) {
case SPI_BLOCK_ERASE_EMULATION: return &spi_block_erase_emulation;
case SPI_BLOCK_ERASE_20: return &spi_block_erase_20;
case SPI_BLOCK_ERASE_21: return &spi_block_erase_21;
case SPI_BLOCK_ERASE_40: return NULL; // FIXME unhandled &spi_block_erase_40;
case SPI_BLOCK_ERASE_50: return &spi_block_erase_50;
case SPI_BLOCK_ERASE_52: return &spi_block_erase_52;
case SPI_BLOCK_ERASE_53: return &spi_block_erase_53;
case SPI_BLOCK_ERASE_5C: return &spi_block_erase_5c;
case SPI_BLOCK_ERASE_60: return &spi_block_erase_60;
case SPI_BLOCK_ERASE_62: return &spi_block_erase_62;
case SPI_BLOCK_ERASE_81: return &spi_block_erase_81;
case SPI_BLOCK_ERASE_C4: return &spi_block_erase_c4;
case SPI_BLOCK_ERASE_C7: return &spi_block_erase_c7;
case SPI_BLOCK_ERASE_D7: return &spi_block_erase_d7;
case SPI_BLOCK_ERASE_D8: return &spi_block_erase_d8;
case SPI_BLOCK_ERASE_DB: return &spi_block_erase_db;
case SPI_BLOCK_ERASE_DC: return &spi_block_erase_dc;
case S25FL_BLOCK_ERASE: return &s25fl_block_erase;
case S25FS_BLOCK_ERASE_D8: return &s25fs_block_erase_d8;
case JEDEC_SECTOR_ERASE: return &erase_sector_jedec; // TODO rename to &jedec_sector_erase;
case JEDEC_BLOCK_ERASE: return &erase_block_jedec; // TODO rename to &jedec_block_erase;
case JEDEC_CHIP_BLOCK_ERASE: return &erase_chip_block_jedec; // TODO rename to &jedec_chip_block_erase;
case OPAQUE_ERASE: return &erase_opaque; // TODO rename to &opqaue_erase;
case SPI_ERASE_AT45CS_SECTOR: return &spi_erase_at45cs_sector;
case SPI_ERASE_AT45DB_BLOCK: return &spi_erase_at45db_block;
case SPI_ERASE_AT45DB_CHIP: return &spi_erase_at45db_chip;
case SPI_ERASE_AT45DB_PAGE: return &spi_erase_at45db_page;
case SPI_ERASE_AT45DB_SECTOR: return &spi_erase_at45db_sector;
case ERASE_CHIP_28SF040: return &erase_chip_28sf040;
case ERASE_SECTOR_28SF040: return &erase_sector_28sf040;
case ERASE_BLOCK_82802AB: return &erase_block_82802ab;
case ERASE_SECTOR_49LFXXXC: return &erase_sector_49lfxxxc;
case STM50_SECTOR_ERASE: return &erase_sector_stm50; // TODO rename to &stm50_sector_erase;
case EDI_CHIP_BLOCK_ERASE: return &edi_chip_block_erase;
case TEST_ERASE_INJECTOR: return g_test_erase_injector;
/* default: total function, 0 indicates no erase 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_BLOCK_ERASE_FUNC: return NULL;
};
return NULL;
}
static int check_block_eraser(const struct flashctx *flash, int k, int log) static int check_block_eraser(const struct flashctx *flash, int k, int log)
{ {
struct block_eraser eraser = flash->chip->block_erasers[k]; struct block_eraser eraser = flash->chip->block_erasers[k];
@ -1099,7 +1150,8 @@ static int walk_eraseblocks(struct flashctx *const flashctx,
msg_cdbg(", "); msg_cdbg(", ");
msg_cdbg("0x%06x-0x%06x:", info->erase_start, info->erase_end); msg_cdbg("0x%06x-0x%06x:", info->erase_start, info->erase_end);
ret = per_blockfn(flashctx, info, eraser->block_erase); erasefunc_t *erase_func = lookup_erase_func_ptr(eraser);
ret = per_blockfn(flashctx, info, erase_func);
if (ret) if (ret)
return ret; return ret;
} }

View File

@ -52,8 +52,8 @@ int spi_block_erase_d7(struct flashctx *flash, unsigned int addr, unsigned int b
int spi_block_erase_d8(struct flashctx *flash, unsigned int addr, unsigned int blocklen); int spi_block_erase_d8(struct flashctx *flash, unsigned int addr, unsigned int blocklen);
int spi_block_erase_db(struct flashctx *flash, unsigned int addr, unsigned int blocklen); int spi_block_erase_db(struct flashctx *flash, unsigned int addr, unsigned int blocklen);
int spi_block_erase_dc(struct flashctx *flash, unsigned int addr, unsigned int blocklen); int spi_block_erase_dc(struct flashctx *flash, unsigned int addr, unsigned int blocklen);
erasefunc_t *spi_get_erasefn_from_opcode(uint8_t opcode); enum block_erase_func spi_get_erasefn_from_opcode(uint8_t opcode);
uint8_t spi_get_opcode_from_erasefn(erasefunc_t *func); uint8_t spi_get_opcode_from_erasefn(enum block_erase_func func);
int spi_chip_write_1(struct flashctx *flash, const uint8_t *buf, unsigned int start, unsigned int len); int spi_chip_write_1(struct flashctx *flash, const uint8_t *buf, unsigned int start, unsigned int len);
int spi_nbyte_read(struct flashctx *flash, unsigned int addr, uint8_t *bytes, unsigned int len); int spi_nbyte_read(struct flashctx *flash, unsigned int addr, uint8_t *bytes, unsigned int len);
int spi_read_chunked(struct flashctx *flash, uint8_t *buf, unsigned int start, unsigned int len, unsigned int chunksize); int spi_read_chunked(struct flashctx *flash, uint8_t *buf, unsigned int start, unsigned int len, unsigned int chunksize);

View File

@ -268,41 +268,44 @@ enum read_func {
typedef int (read_func_t)(struct flashctx *flash, uint8_t *buf, unsigned int start, unsigned int len); 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); int read_flash(struct flashctx *flash, uint8_t *buf, unsigned int start, unsigned int len);
#define NO_BLOCK_ERASE_FUNC NULL enum block_erase_func {
#define SPI_BLOCK_ERASE_EMULATION &spi_block_erase_emulation NO_BLOCK_ERASE_FUNC = 0, /* 0 indicates no block erase function set. */
#define SPI_BLOCK_ERASE_20 &spi_block_erase_20 SPI_BLOCK_ERASE_EMULATION = 1,
#define SPI_BLOCK_ERASE_21 &spi_block_erase_21 SPI_BLOCK_ERASE_20,
#define SPI_BLOCK_ERASE_40 &spi_block_erase_40 SPI_BLOCK_ERASE_21,
#define SPI_BLOCK_ERASE_50 &spi_block_erase_50 SPI_BLOCK_ERASE_40,
#define SPI_BLOCK_ERASE_52 &spi_block_erase_52 SPI_BLOCK_ERASE_50,
#define SPI_BLOCK_ERASE_53 &spi_block_erase_53 SPI_BLOCK_ERASE_52,
#define SPI_BLOCK_ERASE_5C &spi_block_erase_5c SPI_BLOCK_ERASE_53,
#define SPI_BLOCK_ERASE_60 &spi_block_erase_60 SPI_BLOCK_ERASE_5C,
#define SPI_BLOCK_ERASE_62 &spi_block_erase_62 SPI_BLOCK_ERASE_60,
#define SPI_BLOCK_ERASE_81 &spi_block_erase_81 SPI_BLOCK_ERASE_62,
#define SPI_BLOCK_ERASE_C4 &spi_block_erase_c4 SPI_BLOCK_ERASE_81,
#define SPI_BLOCK_ERASE_C7 &spi_block_erase_c7 SPI_BLOCK_ERASE_C4,
#define SPI_BLOCK_ERASE_D7 &spi_block_erase_d7 SPI_BLOCK_ERASE_C7,
#define SPI_BLOCK_ERASE_D8 &spi_block_erase_d8 SPI_BLOCK_ERASE_D7,
#define SPI_BLOCK_ERASE_DB &spi_block_erase_db SPI_BLOCK_ERASE_D8,
#define SPI_BLOCK_ERASE_DC &spi_block_erase_dc SPI_BLOCK_ERASE_DB,
#define S25FL_BLOCK_ERASE &s25fl_block_erase SPI_BLOCK_ERASE_DC,
#define S25FS_BLOCK_ERASE_D8 &s25fs_block_erase_d8 S25FL_BLOCK_ERASE,
#define JEDEC_SECTOR_ERASE &erase_sector_jedec S25FS_BLOCK_ERASE_D8,
#define JEDEC_BLOCK_ERASE &erase_block_jedec JEDEC_SECTOR_ERASE,
#define JEDEC_CHIP_BLOCK_ERASE &erase_chip_block_jedec JEDEC_BLOCK_ERASE,
#define OPAQUE_ERASE &erase_opaque JEDEC_CHIP_BLOCK_ERASE,
#define SPI_ERASE_AT45CS_SECTOR &spi_erase_at45cs_sector OPAQUE_ERASE,
#define SPI_ERASE_AT45DB_BLOCK &spi_erase_at45db_block SPI_ERASE_AT45CS_SECTOR,
#define SPI_ERASE_AT45DB_CHIP &spi_erase_at45db_chip SPI_ERASE_AT45DB_BLOCK,
#define SPI_ERASE_AT45DB_PAGE &spi_erase_at45db_page SPI_ERASE_AT45DB_CHIP,
#define SPI_ERASE_AT45DB_SECTOR &spi_erase_at45db_sector SPI_ERASE_AT45DB_PAGE,
#define ERASE_CHIP_28SF040 &erase_chip_28sf040 SPI_ERASE_AT45DB_SECTOR,
#define ERASE_SECTOR_28SF040 &erase_sector_28sf040 ERASE_CHIP_28SF040,
#define ERASE_BLOCK_82802AB &erase_block_82802ab ERASE_SECTOR_28SF040,
#define ERASE_SECTOR_49LFXXXC &erase_sector_49lfxxxc ERASE_BLOCK_82802AB,
#define STM50_SECTOR_ERASE &erase_sector_stm50 ERASE_SECTOR_49LFXXXC,
#define EDI_CHIP_BLOCK_ERASE &edi_chip_block_erase STM50_SECTOR_ERASE,
EDI_CHIP_BLOCK_ERASE,
TEST_ERASE_INJECTOR, /* special case must come last. */
};
struct flashchip { struct flashchip {
const char *vendor; const char *vendor;
@ -366,7 +369,7 @@ struct flashchip {
} eraseblocks[NUM_ERASEREGIONS]; } eraseblocks[NUM_ERASEREGIONS];
/* a block_erase function should try to erase one block of size /* a block_erase function should try to erase one block of size
* 'blocklen' at address 'blockaddr' and return 0 on success. */ * 'blocklen' at address 'blockaddr' and return 0 on success. */
int (*block_erase) (struct flashctx *flash, unsigned int blockaddr, unsigned int blocklen); enum block_erase_func block_erase;
} block_erasers[NUM_ERASEFUNCTIONS]; } block_erasers[NUM_ERASEFUNCTIONS];
int (*printlock) (struct flashctx *flash); int (*printlock) (struct flashctx *flash);

2
sfdp.c
View File

@ -81,7 +81,7 @@ static int sfdp_add_uniform_eraser(struct flashchip *chip, uint8_t opcode, uint3
{ {
int i; int i;
uint32_t total_size = chip->total_size * 1024; uint32_t total_size = chip->total_size * 1024;
erasefunc_t *erasefn = spi_get_erasefn_from_opcode(opcode); enum block_erase_func erasefn = spi_get_erasefn_from_opcode(opcode);
if (erasefn == NO_BLOCK_ERASE_FUNC || total_size == 0 || block_size == 0 || if (erasefn == NO_BLOCK_ERASE_FUNC || total_size == 0 || block_size == 0 ||
total_size % block_size != 0) { total_size % block_size != 0) {

View File

@ -619,7 +619,7 @@ int spi_block_erase_dc(struct flashctx *flash, unsigned int addr, unsigned int b
} }
static const struct { static const struct {
erasefunc_t *func; enum block_erase_func func;
uint8_t opcode; uint8_t opcode;
} function_opcode_list[] = { } function_opcode_list[] = {
{SPI_BLOCK_ERASE_20, 0x20}, {SPI_BLOCK_ERASE_20, 0x20},
@ -639,7 +639,7 @@ static const struct {
{SPI_BLOCK_ERASE_DC, 0xdc}, {SPI_BLOCK_ERASE_DC, 0xdc},
}; };
erasefunc_t *spi_get_erasefn_from_opcode(uint8_t opcode) enum block_erase_func spi_get_erasefn_from_opcode(uint8_t opcode)
{ {
size_t i; size_t i;
for (i = 0; i < ARRAY_SIZE(function_opcode_list); i++) { for (i = 0; i < ARRAY_SIZE(function_opcode_list); i++) {
@ -651,14 +651,14 @@ erasefunc_t *spi_get_erasefn_from_opcode(uint8_t opcode)
return NO_BLOCK_ERASE_FUNC; return NO_BLOCK_ERASE_FUNC;
} }
uint8_t spi_get_opcode_from_erasefn(erasefunc_t *func) uint8_t spi_get_opcode_from_erasefn(enum block_erase_func func)
{ {
size_t i; size_t i;
for (i = 0; i < ARRAY_SIZE(function_opcode_list); i++) { for (i = 0; i < ARRAY_SIZE(function_opcode_list); i++) {
if (function_opcode_list[i].func == func) if (function_opcode_list[i].func == func)
return function_opcode_list[i].opcode; return function_opcode_list[i].opcode;
} }
msg_cinfo("%s: unknown erase function (0x%p). Please report " msg_cinfo("%s: unknown erase function (0x%d). Please report "
"this at flashrom@flashrom.org\n", __func__, func); "this at flashrom@flashrom.org\n", __func__, func);
return 0x00; //Assuming 0x00 is not a erase function opcode return 0x00; //Assuming 0x00 is not a erase function opcode
} }

View File

@ -148,6 +148,7 @@ static void teardown(struct flashrom_layout **layout)
extern write_func_t *g_test_write_injector; extern write_func_t *g_test_write_injector;
extern read_func_t *g_test_read_injector; extern read_func_t *g_test_read_injector;
extern erasefunc_t *g_test_erase_injector;
static const struct flashchip chip_8MiB = { static const struct flashchip chip_8MiB = {
.vendor = "aklm", .vendor = "aklm",
@ -160,7 +161,7 @@ static const struct flashchip chip_8MiB = {
{{ {{
/* All blocks within total size of the chip. */ /* All blocks within total size of the chip. */
.eraseblocks = { {2 * MiB, 4} }, .eraseblocks = { {2 * MiB, 4} },
.block_erase = block_erase_chip, .block_erase = TEST_ERASE_INJECTOR,
}}, }},
}; };
@ -208,6 +209,7 @@ void erase_chip_test_success(void **state)
g_test_write_injector = write_chip; g_test_write_injector = write_chip;
g_test_read_injector = read_chip; g_test_read_injector = read_chip;
g_test_erase_injector = block_erase_chip;
struct flashrom_flashctx flashctx = { 0 }; struct flashrom_flashctx flashctx = { 0 };
struct flashrom_layout *layout; struct flashrom_layout *layout;
struct flashchip mock_chip = chip_8MiB; struct flashchip mock_chip = chip_8MiB;
@ -268,6 +270,7 @@ void read_chip_test_success(void **state)
g_test_write_injector = write_chip; g_test_write_injector = write_chip;
g_test_read_injector = read_chip; g_test_read_injector = read_chip;
g_test_erase_injector = block_erase_chip;
struct flashrom_flashctx flashctx = { 0 }; struct flashrom_flashctx flashctx = { 0 };
struct flashrom_layout *layout; struct flashrom_layout *layout;
struct flashchip mock_chip = chip_8MiB; struct flashchip mock_chip = chip_8MiB;
@ -341,6 +344,7 @@ void write_chip_test_success(void **state)
g_test_write_injector = write_chip; g_test_write_injector = write_chip;
g_test_read_injector = read_chip; g_test_read_injector = read_chip;
g_test_erase_injector = block_erase_chip;
struct flashrom_flashctx flashctx = { 0 }; struct flashrom_flashctx flashctx = { 0 };
struct flashrom_layout *layout; struct flashrom_layout *layout;
struct flashchip mock_chip = chip_8MiB; struct flashchip mock_chip = chip_8MiB;
@ -440,6 +444,7 @@ void verify_chip_test_success(void **state)
g_test_write_injector = write_chip; g_test_write_injector = write_chip;
g_test_read_injector = read_chip; g_test_read_injector = read_chip;
g_test_erase_injector = block_erase_chip;
struct flashrom_flashctx flashctx = { 0 }; struct flashrom_flashctx flashctx = { 0 };
struct flashrom_layout *layout; struct flashrom_layout *layout;
struct flashchip mock_chip = chip_8MiB; struct flashchip mock_chip = chip_8MiB;