Edward O'Callaghan has uploaded this change for review.
tree/: Convert flashchip erase_block func ptr to enumerate [ALT]
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>
---
M at45db.c
M flashrom.c
M include/chipdrivers.h
M include/flash.h
M sfdp.c
M spi25.c
M tests/chip.c
7 files changed, 135 insertions(+), 50 deletions(-)
git pull ssh://review.coreboot.org:29418/flashrom refs/changes/33/69133/1
diff --git a/at45db.c b/at45db.c
index 53e15ec..eeebf49 100644
--- a/at45db.c
+++ b/at45db.c
@@ -80,9 +80,11 @@
unsigned int i, j;
unsigned int cnt = 0;
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];
+ erasefunc_t *erase_func = lookup_erase_func_ptr_(eraser);
+ if (erase_func == &spi_erase_at45db_sector) {
for (j = 0; j < NUM_ERASEREGIONS; j++) {
- cnt += flash->chip->block_erasers[i].eraseblocks[j].count;
+ cnt += eraser->eraseblocks[j].count;
}
}
}
diff --git a/flashrom.c b/flashrom.c
index cf6a59d..1f36d45 100644
--- a/flashrom.c
+++ b/flashrom.c
@@ -337,22 +337,79 @@
return extract_param(&cfg->params, param_name, ",");
}
+/* special unit-test hook */
+erasefunc_t *g_test_erase_injector;
+
+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 erasefunc_t *lookup_erase_func_ptr(const struct flashchip *chip, int idx)
+{
+ const struct block_eraser *const eraser = &chip->block_erasers[idx];
+ return lookup_erase_func_ptr_(eraser);
+}
+
static int check_block_eraser(const struct flashctx *flash, int k, int log)
{
struct block_eraser eraser = flash->chip->block_erasers[k];
+ erasefunc_t *erase_func = lookup_erase_func_ptr(flash->chip, k);
- if (eraser.block_erase == NO_BLOCK_ERASE_FUNC && !eraser.eraseblocks[0].count) {
+ if (erase_func == NO_BLOCK_ERASE_FUNC && !eraser.eraseblocks[0].count) {
if (log)
msg_cdbg("not defined. ");
return 1;
}
- if (eraser.block_erase == NO_BLOCK_ERASE_FUNC && eraser.eraseblocks[0].count) {
+ if (erase_func == NO_BLOCK_ERASE_FUNC && eraser.eraseblocks[0].count) {
if (log)
msg_cdbg("eraseblock layout is known, but matching "
"block erase function is not implemented. ");
return 1;
}
- if (eraser.block_erase != NO_BLOCK_ERASE_FUNC && !eraser.eraseblocks[0].count) {
+ if (erase_func != NO_BLOCK_ERASE_FUNC && !eraser.eraseblocks[0].count) {
if (log)
msg_cdbg("block erase function found, but "
"eraseblock layout is not defined. ");
@@ -1096,7 +1153,8 @@
msg_cdbg(", ");
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)
return ret;
}
diff --git a/include/chipdrivers.h b/include/chipdrivers.h
index 61d43c9..fc8e6ed 100644
--- a/include/chipdrivers.h
+++ b/include/chipdrivers.h
@@ -52,8 +52,8 @@
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_dc(struct flashctx *flash, unsigned int addr, unsigned int blocklen);
-erasefunc_t *spi_get_erasefn_from_opcode(uint8_t opcode);
-uint8_t spi_get_opcode_from_erasefn(erasefunc_t *func);
+enum block_erase_func spi_get_erasefn_from_opcode(uint8_t opcode);
+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_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);
diff --git a/include/flash.h b/include/flash.h
index 8639cd3..ce7ed81 100644
--- a/include/flash.h
+++ b/include/flash.h
@@ -268,41 +268,46 @@
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);
-#define NO_BLOCK_ERASE_FUNC NULL
-#define SPI_BLOCK_ERASE_EMULATION &spi_block_erase_emulation
-#define SPI_BLOCK_ERASE_20 &spi_block_erase_20
-#define SPI_BLOCK_ERASE_21 &spi_block_erase_21
-#define SPI_BLOCK_ERASE_40 &spi_block_erase_40
-#define SPI_BLOCK_ERASE_50 &spi_block_erase_50
-#define SPI_BLOCK_ERASE_52 &spi_block_erase_52
-#define SPI_BLOCK_ERASE_53 &spi_block_erase_53
-#define SPI_BLOCK_ERASE_5C &spi_block_erase_5c
-#define SPI_BLOCK_ERASE_60 &spi_block_erase_60
-#define SPI_BLOCK_ERASE_62 &spi_block_erase_62
-#define SPI_BLOCK_ERASE_81 &spi_block_erase_81
-#define SPI_BLOCK_ERASE_C4 &spi_block_erase_c4
-#define SPI_BLOCK_ERASE_C7 &spi_block_erase_c7
-#define SPI_BLOCK_ERASE_D7 &spi_block_erase_d7
-#define SPI_BLOCK_ERASE_D8 &spi_block_erase_d8
-#define SPI_BLOCK_ERASE_DB &spi_block_erase_db
-#define SPI_BLOCK_ERASE_DC &spi_block_erase_dc
-#define S25FL_BLOCK_ERASE &s25fl_block_erase
-#define S25FS_BLOCK_ERASE_D8 &s25fs_block_erase_d8
-#define JEDEC_SECTOR_ERASE &erase_sector_jedec
-#define JEDEC_BLOCK_ERASE &erase_block_jedec
-#define JEDEC_CHIP_BLOCK_ERASE &erase_chip_block_jedec
-#define OPAQUE_ERASE &erase_opaque
-#define SPI_ERASE_AT45CS_SECTOR &spi_erase_at45cs_sector
-#define SPI_ERASE_AT45DB_BLOCK &spi_erase_at45db_block
-#define SPI_ERASE_AT45DB_CHIP &spi_erase_at45db_chip
-#define SPI_ERASE_AT45DB_PAGE &spi_erase_at45db_page
-#define SPI_ERASE_AT45DB_SECTOR &spi_erase_at45db_sector
-#define ERASE_CHIP_28SF040 &erase_chip_28sf040
-#define ERASE_SECTOR_28SF040 &erase_sector_28sf040
-#define ERASE_BLOCK_82802AB &erase_block_82802ab
-#define ERASE_SECTOR_49LFXXXC &erase_sector_49lfxxxc
-#define STM50_SECTOR_ERASE &erase_sector_stm50
-#define EDI_CHIP_BLOCK_ERASE &edi_chip_block_erase
+enum block_erase_func {
+ NO_BLOCK_ERASE_FUNC = 0, /* 0 indicates no block erase function set. */
+ SPI_BLOCK_ERASE_EMULATION = 1,
+ SPI_BLOCK_ERASE_20,
+ SPI_BLOCK_ERASE_21,
+ SPI_BLOCK_ERASE_40,
+ SPI_BLOCK_ERASE_50,
+ SPI_BLOCK_ERASE_52,
+ SPI_BLOCK_ERASE_53,
+ SPI_BLOCK_ERASE_5C,
+ SPI_BLOCK_ERASE_60,
+ SPI_BLOCK_ERASE_62,
+ SPI_BLOCK_ERASE_81,
+ SPI_BLOCK_ERASE_C4,
+ SPI_BLOCK_ERASE_C7,
+ SPI_BLOCK_ERASE_D7,
+ SPI_BLOCK_ERASE_D8,
+ SPI_BLOCK_ERASE_DB,
+ SPI_BLOCK_ERASE_DC,
+ S25FL_BLOCK_ERASE,
+ S25FS_BLOCK_ERASE_D8,
+ JEDEC_SECTOR_ERASE,
+ JEDEC_BLOCK_ERASE,
+ JEDEC_CHIP_BLOCK_ERASE,
+ OPAQUE_ERASE,
+ SPI_ERASE_AT45CS_SECTOR,
+ SPI_ERASE_AT45DB_BLOCK,
+ SPI_ERASE_AT45DB_CHIP,
+ SPI_ERASE_AT45DB_PAGE,
+ SPI_ERASE_AT45DB_SECTOR,
+ ERASE_CHIP_28SF040,
+ ERASE_SECTOR_28SF040,
+ ERASE_BLOCK_82802AB,
+ ERASE_SECTOR_49LFXXXC,
+ STM50_SECTOR_ERASE,
+ EDI_CHIP_BLOCK_ERASE,
+ TEST_ERASE_INJECTOR, /* special case must come last. */
+};
+struct block_eraser;
+erasefunc_t *lookup_erase_func_ptr_(const struct block_eraser *const eraser);
struct flashchip {
const char *vendor;
@@ -366,7 +371,7 @@
} eraseblocks[NUM_ERASEREGIONS];
/* a block_erase function should try to erase one block of size
* '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];
int (*printlock) (struct flashctx *flash);
diff --git a/sfdp.c b/sfdp.c
index a09827d..ccf840f 100644
--- a/sfdp.c
+++ b/sfdp.c
@@ -81,7 +81,7 @@
{
int i;
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 ||
total_size % block_size != 0) {
diff --git a/spi25.c b/spi25.c
index fb94748..da870be 100644
--- a/spi25.c
+++ b/spi25.c
@@ -619,7 +619,7 @@
}
static const struct {
- erasefunc_t *func;
+ enum block_erase_func func;
uint8_t opcode;
} function_opcode_list[] = {
{SPI_BLOCK_ERASE_20, 0x20},
@@ -639,7 +639,7 @@
{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;
for (i = 0; i < ARRAY_SIZE(function_opcode_list); i++) {
@@ -651,14 +651,14 @@
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;
for (i = 0; i < ARRAY_SIZE(function_opcode_list); i++) {
if (function_opcode_list[i].func == func)
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);
return 0x00; //Assuming 0x00 is not a erase function opcode
}
diff --git a/tests/chip.c b/tests/chip.c
index f09c020..d9f5bfb 100644
--- a/tests/chip.c
+++ b/tests/chip.c
@@ -148,6 +148,7 @@
extern write_func_t *g_test_write_injector;
extern read_func_t *g_test_read_injector;
+extern erasefunc_t *g_test_erase_injector;
static const struct flashchip chip_8MiB = {
.vendor = "aklm",
@@ -160,7 +161,7 @@
{{
/* All blocks within total size of the chip. */
.eraseblocks = { {2 * MiB, 4} },
- .block_erase = block_erase_chip,
+ .block_erase = TEST_ERASE_INJECTOR,
}},
};
@@ -208,6 +209,7 @@
g_test_write_injector = write_chip;
g_test_read_injector = read_chip;
+ g_test_erase_injector = block_erase_chip;
struct flashrom_flashctx flashctx = { 0 };
struct flashrom_layout *layout;
struct flashchip mock_chip = chip_8MiB;
@@ -268,6 +270,7 @@
g_test_write_injector = write_chip;
g_test_read_injector = read_chip;
+ g_test_erase_injector = block_erase_chip;
struct flashrom_flashctx flashctx = { 0 };
struct flashrom_layout *layout;
struct flashchip mock_chip = chip_8MiB;
@@ -341,6 +344,7 @@
g_test_write_injector = write_chip;
g_test_read_injector = read_chip;
+ g_test_erase_injector = block_erase_chip;
struct flashrom_flashctx flashctx = { 0 };
struct flashrom_layout *layout;
struct flashchip mock_chip = chip_8MiB;
@@ -440,6 +444,7 @@
g_test_write_injector = write_chip;
g_test_read_injector = read_chip;
+ g_test_erase_injector = block_erase_chip;
struct flashrom_flashctx flashctx = { 0 };
struct flashrom_layout *layout;
struct flashchip mock_chip = chip_8MiB;
To view, visit change 69133. To unsubscribe, or for help writing mail filters, visit settings.