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(a)gmx.net>
Signed-off-by: Stefan Tauner <stefan.tauner(a)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(a)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(a)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(a)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(a)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 };
--
Kind regards, Stefan Tauner