Edward O'Callaghan submitted this change.

View Change



5 is the latest approved patch-set.
No files were changed between the latest approved patch-set and the submitted one.

Approvals: build bot (Jenkins): Verified Angel Pons: Looks good to me, approved Anastasia Klimchuk: Looks good to me, approved
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>
---
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, 127 insertions(+), 47 deletions(-)

diff --git a/at45db.c b/at45db.c
index 53e15ec..7877330 100644
--- a/at45db.c
+++ b/at45db.c
@@ -80,9 +80,10 @@
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];
+ if (eraser->block_erase == 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 08e3969..815f489 100644
--- a/flashrom.c
+++ b/flashrom.c
@@ -336,6 +336,57 @@
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)
{
struct block_eraser eraser = flash->chip->block_erasers[k];
@@ -1099,7 +1150,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 470d1fe..3b07afe 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 03c1e2c..238d010 100644
--- a/include/flash.h
+++ b/include/flash.h
@@ -268,41 +268,44 @@
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 flashchip {
const char *vendor;
@@ -366,7 +369,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 579643c..1d9cdc9 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.

Gerrit-Project: flashrom
Gerrit-Branch: master
Gerrit-Change-Id: I02ae7e4c67c5bf34ec2fd7ffe4af8a2aba6fd5e5
Gerrit-Change-Number: 69133
Gerrit-PatchSet: 8
Gerrit-Owner: Edward O'Callaghan <quasisec@chromium.org>
Gerrit-Reviewer: Anastasia Klimchuk <aklm@chromium.org>
Gerrit-Reviewer: Angel Pons <th3fanbus@gmail.com>
Gerrit-Reviewer: Edward O'Callaghan <quasisec@chromium.org>
Gerrit-Reviewer: build bot (Jenkins) <no-reply@coreboot.org>
Gerrit-MessageType: merged