Patchworkβ [3/3] Add support for generic SPI RES matching.

login
register
about
Submitter Stefan Tauner
Date 2012-08-25 20:35:31
Message ID <1345926931-18154-4-git-send-email-stefan.tauner@student.tuwien.ac.at>
Download mbox | patch
Permalink /patch/3726/
State Superseded
Headers show

Comments

Stefan Tauner - 2012-08-25 20:35:31
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(-)

Patch

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 };