Support generic 1-byte SPI RES matching (low match quality). Support generic 2-byte SPI RES matching (high match quality).
Signed-off-by: Carl-Daniel Hailfinger c-d.hailfinger.devel.2006@gmx.net Signed-off-by: Stefan Tauner stefan.tauner@student.tuwien.ac.at --- chipdrivers.h | 2 + flashchips.c | 31 +++++++++++++++ flashrom.c | 4 +- sfdp.c | 48 +---------------------- spi25.c | 117 +++++++++++++++++++++++++++++++++++++++++++++++++++------ 5 files changed, 143 insertions(+), 59 deletions(-)
diff --git a/chipdrivers.h b/chipdrivers.h index 56a4c8a..c4b798a 100644 --- a/chipdrivers.h +++ b/chipdrivers.h @@ -37,6 +37,7 @@ int probe_spi_rdid4(struct flashctx *flash); int probe_spi_rems(struct flashctx *flash); int probe_spi_res1(struct flashctx *flash); int probe_spi_res2(struct flashctx *flash); +int probe_spi_automagic_res1(struct flashctx *flash); int spi_write_enable(struct flashctx *flash); int spi_write_disable(struct flashctx *flash); int spi_block_erase_20(struct flashctx *flash, unsigned int addr, unsigned int blocklen); @@ -46,6 +47,7 @@ int spi_block_erase_d8(struct flashctx *flash, unsigned int addr, unsigned int b int spi_block_erase_60(struct flashctx *flash, unsigned int addr, unsigned int blocklen); int spi_block_erase_c7(struct flashctx *flash, unsigned int addr, unsigned int blocklen); erasefunc_t *spi_get_erasefn_from_opcode(uint8_t opcode); +int spi_add_uniform_eraser(struct flashchip *chip, uint8_t opcode, uint32_t block_size); int spi_chip_write_1(struct flashctx *flash, uint8_t *buf, unsigned int start, unsigned int len); uint8_t spi_read_status_register(struct flashctx *flash); int spi_write_status_register(struct flashctx *flash, int status); diff --git a/flashchips.c b/flashchips.c index 789f17f..4b78f7f 100644 --- a/flashchips.c +++ b/flashchips.c @@ -9673,5 +9673,36 @@ const struct flashchip flashchips[] = { .write = NULL, },
+ { + .vendor = "Generic", + .name = "unknown SPI chip (RES2)", + .bustype = BUS_SPI, + .manufacture_id = GENERIC_MANUF_ID, + .model_id = GENERIC_DEVICE_ID, + .total_size = 0, + .page_size = 256, + .tested = TEST_BAD_PREW, + .probe = probe_spi_res2, + .write = NULL, + }, + + { + .vendor = "Generic", + .name = "unknown SPI chip (RES1)", + .bustype = BUS_SPI, + .manufacture_id = GENERIC_MANUF_ID, + .model_id = GENERIC_DEVICE_ID, + .total_size = 0, + .page_size = 256, + .tested = TEST_BAD_PREW, + .probe = probe_spi_automagic_res1, + .probe_timing = TIMING_ZERO, + .block_erasers = {}, + .unlock = spi_disable_blockprotect, + .write = NULL, + .read = spi_chip_read, + .voltage = {}, + }, + { NULL } }; diff --git a/flashrom.c b/flashrom.c index 44a3eba..c39abf6 100644 --- a/flashrom.c +++ b/flashrom.c @@ -1029,7 +1029,9 @@ int probe_flash(struct registered_programmer *pgm, int startchip, struct flashct if (startchip == 0) break; /* Not the first flash chip detected on this bus, but not a generic match either. */ - if ((flash->chip->model_id != GENERIC_DEVICE_ID) && (flash->chip->model_id != SFDP_DEVICE_ID)) + if ((flash->chip->manufacture_id != GENERIC_MANUF_ID) && + (flash->chip->model_id != GENERIC_DEVICE_ID) && + (flash->chip->model_id != SFDP_DEVICE_ID)) break; /* Not the first flash chip detected on this bus, and it's just a generic match. Ignore it. */ notfound: diff --git a/sfdp.c b/sfdp.c index bc69dd0..1d3669c 100644 --- a/sfdp.c +++ b/sfdp.c @@ -81,50 +81,6 @@ struct sfdp_tbl_hdr { uint32_t ptp; /* 24b pointer */ };
-static int sfdp_add_uniform_eraser(struct flashchip *chip, uint8_t opcode, uint32_t block_size) -{ - int i; - uint32_t total_size = chip->total_size * 1024; - erasefunc_t *erasefn = spi_get_erasefn_from_opcode(opcode); - - if (erasefn == NULL || total_size == 0 || block_size == 0 || - total_size % block_size != 0) { - msg_cdbg("%s: invalid input, please report to " - "flashrom@flashrom.org\n", __func__); - return 1; - } - - for (i = 0; i < NUM_ERASEFUNCTIONS; i++) { - struct block_eraser *eraser = &chip->block_erasers[i]; - /* Check for duplicates (including (some) non-uniform ones). */ - if (eraser->eraseblocks[0].size == block_size && - eraser->block_erase == erasefn) { - msg_cdbg2(" Tried to add a duplicate block eraser: " - "%d x %d B with opcode 0x%02x.\n", - total_size/block_size, block_size, opcode); - return 1; - } - if (eraser->eraseblocks[0].size != 0 || - eraser->block_erase != NULL) { - msg_cspew(" Block Eraser %d is already occupied.\n", - i); - continue; - } - - eraser->block_erase = erasefn; - eraser->eraseblocks[0].size = block_size; - eraser->eraseblocks[0].count = total_size/block_size; - msg_cdbg2(" Block eraser %d: %d x %d B with opcode " - "0x%02x\n", i, total_size/block_size, block_size, - opcode); - return 0; - } - msg_cinfo("%s: Not enough space to store another eraser (i=%d)." - " Please report this at flashrom@flashrom.org\n", - __func__, i); - return 1; -} - static int sfdp_fill_flash(struct flashchip *chip, uint8_t *buf, uint16_t len) { uint8_t opcode_4k_erase = 0xFF; @@ -221,7 +177,7 @@ static int sfdp_fill_flash(struct flashchip *chip, uint8_t *buf, uint16_t len) }
if (opcode_4k_erase != 0xFF) - sfdp_add_uniform_eraser(chip, opcode_4k_erase, 4 * 1024); + spi_add_uniform_eraser(chip, opcode_4k_erase, 4 * 1024);
/* FIXME: double words 3-7 contain unused fast read information */
@@ -252,7 +208,7 @@ static int sfdp_fill_flash(struct flashchip *chip, uint8_t *buf, uint16_t len) tmp8 = buf[(4 * 7) + (j * 2) + 1]; msg_cspew(" Erase Sector Type %d Opcode: 0x%02x\n", j + 1, tmp8); - sfdp_add_uniform_eraser(chip, tmp8, block_size); + spi_add_uniform_eraser(chip, tmp8, block_size); }
done: diff --git a/spi25.c b/spi25.c index 914b821..9ea04ef 100644 --- a/spi25.c +++ b/spi25.c @@ -22,6 +22,7 @@ * Contains the common SPI chip driver functions */
+#include <stdio.h> #include <string.h> #include "flash.h" #include "flashchips.h" @@ -232,6 +233,7 @@ int probe_spi_rems(struct flashctx *flash)
int probe_spi_res1(struct flashctx *flash) { + const struct flashchip *chip = flash->chip; static const unsigned char allff[] = {0xff, 0xff, 0xff}; static const unsigned char all00[] = {0x00, 0x00, 0x00}; unsigned char readarr[3]; @@ -265,18 +267,23 @@ int probe_spi_res1(struct flashctx *flash)
msg_cdbg("%s: id 0x%x\n", __func__, id2);
- if (id2 != flash->chip->model_id) - return 0; + if (id2 == flash->chip->model_id) { + /* Print the status register to tell the user about possible write protection. */ + spi_prettyprint_status_register(flash);
- /* Print the status register to tell the - * user about possible write protection. - */ - spi_prettyprint_status_register(flash); - return 1; + return 1; + } + + /* Test if there is any device ID. */ + if (GENERIC_MANUF_ID == chip->manufacture_id && id2 == chip->model_id) + return 1; + + return 0; }
int probe_spi_res2(struct flashctx *flash) { + const struct flashchip *chip = flash->chip; unsigned char readarr[2]; uint32_t id1, id2;
@@ -289,13 +296,55 @@ int probe_spi_res2(struct flashctx *flash)
msg_cdbg("%s: id1 0x%x, id2 0x%x\n", __func__, id1, id2);
- if (id1 != flash->chip->manufacture_id || id2 != flash->chip->model_id) + if (id1 == chip->manufacture_id && id2 == chip->model_id) { + /* Print the status register to tell the + * user about possible write protection. + */ + spi_prettyprint_status_register(flash); + + return 1; + } + + /* Test if this is a pure vendor match. */ + if (id1 == chip->manufacture_id && GENERIC_DEVICE_ID == chip->model_id) + return 1; + + /* Test if there is any vendor ID and if this is indeed a two-byte RES. */ + if (GENERIC_MANUF_ID == chip->manufacture_id && id1 != 0xff && id1 != id2) + return 1; + + return 0; +} + +int probe_spi_automagic_res1(struct flashctx *flash) +{ + unsigned char readarr[1]; + unsigned int total_size; + + if (spi_res(flash, readarr, 1)) return 0;
- /* Print the status register to tell the - * user about possible write protection. - */ - spi_prettyprint_status_register(flash); + msg_cdbg("%s: id1 0x%x\n", __func__, readarr[0]); + if (readarr[0] < 0x10 || readarr[0] > 0x17) { + msg_cdbg("RES ID out of bounds: 0x%x\n", readarr[0]); + return 0; + } + total_size = (2 << readarr[0]) / 1024; + + //if (!force) { + //blablabla + //return 0; + //} + flash->chip->total_size = total_size; + + spi_add_uniform_eraser(flash->chip, 0x60, total_size * 1024); + spi_add_uniform_eraser(flash->chip, 0xc7, total_size * 1024); + /* This does not help users of locked-down thinkpads because there is only the 0xd8 erase op available. + * But since that one is used with various erase block sizes (non-uniform, 4k, 32k, 64k, 256k), we + * can not just add that too. */ + // gather (uniform) 0xd8 block size from command line argument? + flash->chip->write = spi_chip_write_1; + flash->chip->tested = TEST_OK_PREW; return 1; }
@@ -748,6 +797,50 @@ erasefunc_t *spi_get_erasefn_from_opcode(uint8_t opcode) } }
+int spi_add_uniform_eraser(struct flashchip *chip, uint8_t opcode, uint32_t block_size) +{ + int i; + uint32_t total_size = chip->total_size * 1024; + erasefunc_t *erasefn = spi_get_erasefn_from_opcode(opcode); + + if (erasefn == NULL || total_size == 0 || block_size == 0 || + total_size % block_size != 0) { + msg_cdbg("%s: invalid input, please report to " + "flashrom@flashrom.org\n", __func__); + return 1; + } + + for (i = 0; i < NUM_ERASEFUNCTIONS; i++) { + struct block_eraser *eraser = &chip->block_erasers[i]; + /* Check for duplicates (including (some) non-uniform ones). */ + if (eraser->eraseblocks[0].size == block_size && + eraser->block_erase == erasefn) { + msg_cdbg2(" Tried to add a duplicate block eraser: " + "%d x %d B with opcode 0x%02x.\n", + total_size/block_size, block_size, opcode); + return 1; + } + if (eraser->eraseblocks[0].size != 0 || + eraser->block_erase != NULL) { + msg_cspew(" Block Eraser %d is already occupied.\n", + i); + continue; + } + + eraser->block_erase = erasefn; + eraser->eraseblocks[0].size = block_size; + eraser->eraseblocks[0].count = total_size/block_size; + msg_cdbg2(" Block eraser %d: %d x %d B with opcode " + "0x%02x\n", i, total_size/block_size, block_size, + opcode); + return 0; + } + msg_cinfo("%s: Not enough space to store another eraser (i=%d)." + " Please report this at flashrom@flashrom.org\n", + __func__, i); + return 1; +} + int spi_write_status_enable(struct flashctx *flash) { static const unsigned char cmd[JEDEC_EWSR_OUTSIZE] = { JEDEC_EWSR };