flashrom
Threads by month
- ----- 2025 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2024 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2023 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2022 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2021 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2020 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2019 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2018 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2017 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2016 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2015 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2014 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2013 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2012 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2011 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2010 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2009 -----
- December
- November
- October
- September
- August
- July
- June
October 2012
- 26 participants
- 89 discussions
Oct. 3, 2012
As long as a programmer's check_trans code does not rely on the previous
invocation of its init function one can trivially set that programmer's
check_trans function instead of the dummy's default one. This allows for
even better testing of the SPI infrastructure code under near realworld
conditions.
FIXME: add other programmers
FIXME: add manpage doc
Signed-off-by: Stefan Tauner <stefan.tauner(a)student.tuwien.ac.at>
---
dummyflasher.c | 15 ++++++++++++++-
programmer.h | 2 ++
wbsio_spi.c | 2 +-
3 files changed, 17 insertions(+), 2 deletions(-)
diff --git a/dummyflasher.c b/dummyflasher.c
index 4e08386..1d63b7a 100644
--- a/dummyflasher.c
+++ b/dummyflasher.c
@@ -119,7 +119,7 @@ static uint32_t dummy_chip_readl(const struct flashctx *flash,
static void dummy_chip_readn(const struct flashctx *flash, uint8_t *buf,
const chipaddr addr, size_t len);
-static const struct spi_programmer spi_programmer_dummyflasher = {
+static struct spi_programmer spi_programmer_dummyflasher = {
.type = SPI_CONTROLLER_DUMMY,
.max_data_read = MAX_DATA_READ_UNLIMITED,
.max_data_write = MAX_DATA_UNSPECIFIED,
@@ -373,6 +373,19 @@ int dummy_init(void)
msg_pdbg("Initial status register is set to 0x%02x.\n",
emu_status);
}
+ tmp = extract_programmer_param("spi_prog");
+ if (tmp) {
+ if (!strcmp(tmp, "wbsio")) {
+ spi_programmer_dummyflasher.check_trans = wbsio_spi_check_trans;
+ msg_pdbg("Using SPI payload limitations of the %s programmer.\n", tmp);
+ } else {
+ msg_perr("Error: emulation of a programmer requested, "
+ "but the programmer could not be parsed \"%s\".\n", tmp);
+ free(tmp);
+ return 1;
+ }
+ }
+ free(tmp);
#endif
msg_pdbg("Filling fake flash chip with 0xff, size %i\n", emu_chip_size);
diff --git a/programmer.h b/programmer.h
index bcd9547..c2373e6 100644
--- a/programmer.h
+++ b/programmer.h
@@ -585,6 +585,8 @@ int mcp6x_spi_init(int want_spi);
int sb600_probe_spi(struct pci_dev *dev);
/* wbsio_spi.c */
+int wbsio_spi_check_trans(struct flashctx *flash, unsigned int writecnt, unsigned int readcnt,
+ const unsigned char *writearr);
int wbsio_check_for_spi(void);
#endif
diff --git a/wbsio_spi.c b/wbsio_spi.c
index ec14c28..6164ae7 100644
--- a/wbsio_spi.c
+++ b/wbsio_spi.c
@@ -108,7 +108,7 @@ static uint8_t determine_mode(struct flashctx *flash, unsigned int writecnt, uns
return 0;
}
-static int wbsio_spi_check_trans(struct flashctx *flash, unsigned int writecnt, unsigned int readcnt,
+int wbsio_spi_check_trans(struct flashctx *flash, unsigned int writecnt, unsigned int readcnt,
const unsigned char *writearr)
{
if (determine_mode(flash, writecnt, readcnt, writearr) == 0)
--
Kind regards, Stefan Tauner
1
0
[PATCH 4/5] Generify probe_spi_rdid_generic() and add probe_spi_rdid_edi().
by Stefan Tauner Oct. 3, 2012
by Stefan Tauner Oct. 3, 2012
Oct. 3, 2012
Previously the "generic" function was working/used for exactly two
cases, namely for manufacturer IDs with 0 or 1 continuation bytes.
For this behavior it was overly complicated.
The new implementation handles up to 3 continuation bytes
automatically and allows for up to 4 model bytes which is directly
used to add support for an EDI probing function. The probe_spi_rdid4()
function is removed because it is no longer needed.
The new probe_spi_rdid_generic() tries to figure out the maximum
allowed read size by using the recently added check_trans() function
to reduce the request size if necessary. While this does not make
detection to succeed in all theoretical situations, it improves the
code and will hopefully work in all realworld situations.
Signed-off-by: Stefan Tauner <stefan.tauner(a)student.tuwien.ac.at>
---
flashchips.c | 24 +++++++--------
flashchips.h | 2 +-
spi25.c | 97 ++++++++++++++++++++++++++++++----------------------------
3 files changed, 63 insertions(+), 60 deletions(-)
diff --git a/flashchips.c b/flashchips.c
index e290e2f..a69d899 100644
--- a/flashchips.c
+++ b/flashchips.c
@@ -547,7 +547,7 @@ const struct flashchip flashchips[] = {
.page_size = 256,
.feature_bits = FEATURE_WRSR_WREN,
.tested = TEST_UNTESTED,
- .probe = probe_spi_rdid4,
+ .probe = probe_spi_rdid,
.probe_timing = TIMING_ZERO,
.block_erasers =
{
@@ -581,7 +581,7 @@ const struct flashchip flashchips[] = {
.page_size = 256,
.feature_bits = FEATURE_WRSR_WREN,
.tested = TEST_UNTESTED,
- .probe = probe_spi_rdid4,
+ .probe = probe_spi_rdid,
.probe_timing = TIMING_ZERO,
.block_erasers =
{
@@ -615,7 +615,7 @@ const struct flashchip flashchips[] = {
.page_size = 256,
.feature_bits = FEATURE_WRSR_WREN,
.tested = TEST_UNTESTED,
- .probe = probe_spi_rdid4,
+ .probe = probe_spi_rdid,
.probe_timing = TIMING_ZERO,
.block_erasers =
{
@@ -650,7 +650,7 @@ const struct flashchip flashchips[] = {
.page_size = 256,
.feature_bits = FEATURE_WRSR_WREN,
.tested = TEST_UNTESTED,
- .probe = probe_spi_rdid4,
+ .probe = probe_spi_rdid,
.probe_timing = TIMING_ZERO,
.block_erasers =
{
@@ -685,7 +685,7 @@ const struct flashchip flashchips[] = {
.page_size = 256,
.feature_bits = FEATURE_WRSR_WREN,
.tested = TEST_UNTESTED,
- .probe = probe_spi_rdid4,
+ .probe = probe_spi_rdid,
.probe_timing = TIMING_ZERO,
.block_erasers =
{
@@ -720,7 +720,7 @@ const struct flashchip flashchips[] = {
.page_size = 256,
.feature_bits = FEATURE_WRSR_WREN,
.tested = TEST_UNTESTED,
- .probe = probe_spi_rdid4,
+ .probe = probe_spi_rdid,
.probe_timing = TIMING_ZERO,
.block_erasers =
{
@@ -760,7 +760,7 @@ const struct flashchip flashchips[] = {
.page_size = 256,
.feature_bits = FEATURE_WRSR_WREN,
.tested = TEST_OK_PR,
- .probe = probe_spi_rdid4,
+ .probe = probe_spi_rdid,
.probe_timing = TIMING_ZERO,
.block_erasers =
{
@@ -795,7 +795,7 @@ const struct flashchip flashchips[] = {
.page_size = 256,
.feature_bits = FEATURE_WRSR_WREN,
.tested = TEST_OK_PR,
- .probe = probe_spi_rdid4,
+ .probe = probe_spi_rdid,
.probe_timing = TIMING_ZERO,
.block_erasers =
{
@@ -830,7 +830,7 @@ const struct flashchip flashchips[] = {
.page_size = 256,
.feature_bits = FEATURE_WRSR_WREN,
.tested = TEST_OK_PRE,
- .probe = probe_spi_rdid4,
+ .probe = probe_spi_rdid,
.probe_timing = TIMING_ZERO,
.block_erasers =
{
@@ -865,7 +865,7 @@ const struct flashchip flashchips[] = {
.page_size = 256,
.feature_bits = FEATURE_WRSR_WREN,
.tested = TEST_UNTESTED,
- .probe = probe_spi_rdid4,
+ .probe = probe_spi_rdid,
.probe_timing = TIMING_ZERO,
.block_erasers =
{
@@ -903,7 +903,7 @@ const struct flashchip flashchips[] = {
.page_size = 256,
.feature_bits = FEATURE_WRSR_WREN,
.tested = TEST_OK_PR,
- .probe = probe_spi_rdid4,
+ .probe = probe_spi_rdid,
.probe_timing = TIMING_ZERO,
.block_erasers =
{
@@ -9752,7 +9752,7 @@ const struct flashchip flashchips[] = {
.total_size = 0,
.page_size = 256,
.tested = TEST_BAD_PREW,
- .probe = probe_spi_rdid4,
+ .probe = probe_spi_rdid,
.probe_timing = TIMING_ZERO,
.write = NULL,
.read = NULL,
diff --git a/flashchips.h b/flashchips.h
index 8e51d35..d353b9e 100644
--- a/flashchips.h
+++ b/flashchips.h
@@ -91,7 +91,7 @@
#define AMD_AM29LV800BT 0xDA /* Same as Am29LV800DT */
#define AMIC_ID 0x7F37 /* AMIC */
-#define AMIC_ID_NOPREFIX 0x37 /* AMIC */
+#define AMIC_ID_NOPREFIX 0x37 /* not AMIC, but used nevertheless in some AMIC chips */
#define AMIC_A25L05PT 0x2020
#define AMIC_A25L05PU 0x2010
#define AMIC_A25L10PT 0x2021
diff --git a/spi25.c b/spi25.c
index a65f548..6310cf0 100644
--- a/spi25.c
+++ b/spi25.c
@@ -35,10 +35,13 @@ static int spi_rdid(struct flashctx *flash, unsigned char *readarr, int bytes)
int ret;
int i;
+ ret = flash->pgm->spi.check_trans(flash, sizeof(cmd), bytes, cmd);
+ if (ret)
+ return ret;
ret = spi_send_command(flash, sizeof(cmd), bytes, cmd, readarr);
if (ret)
return ret;
- msg_cspew("RDID returned");
+ msg_cspew("RDID returned %d bytes:", bytes);
for (i = 0; i < bytes; i++)
msg_cspew(" 0x%02x", readarr[i]);
msg_cspew(". ");
@@ -115,37 +118,54 @@ int spi_write_disable(struct flashctx *flash)
return spi_send_command(flash, sizeof(cmd), 0, cmd, NULL);
}
-static int probe_spi_rdid_generic(struct flashctx *flash, int bytes)
+/* The model_bytes parameter indicates the number of bytes of the model ID that have to match.
+ * The current implementation does work for manufacturer IDs with up to 3 continuation bytes and up to 4 bytes
+ * for the model identifier. */
+static int probe_spi_rdid_generic(struct flashctx *flash, int model_bytes)
{
+ int i, j;
const struct flashchip *chip = flash->chip;
- unsigned char readarr[4];
- uint32_t id1;
- uint32_t id2;
-
- if (spi_rdid(flash, readarr, bytes)) {
- return 0;
- }
-
- if (!oddparity(readarr[0]))
- msg_cdbg("RDID byte 0 parity violation. ");
-
- /* Check if this is a continuation vendor ID.
- * FIXME: Handle continuation device IDs.
- */
- if (readarr[0] == 0x7f) {
- if (!oddparity(readarr[1]))
- msg_cdbg("RDID byte 1 parity violation. ");
- id1 = (readarr[0] << 8) | readarr[1];
- id2 = readarr[2];
- if (bytes > 3) {
- id2 <<= 8;
- id2 |= readarr[3];
+ uint32_t id1 = 0;
+ uint32_t id2 = 0;
+
+ /* As of 2012-09 (JEP106AJ) there exist 8 banks, so we need at most 8 bytes to identify a manufacturer:
+ * 7x continuation indicators (0x7F) + one ID byte. The problem is that a number of programmers do not
+ * support arbitrary transaction lenghts. This implementation does not support more than 3 continuation
+ * bytes because we use 32 bits for the ID and currently do not need more than banks 1-2 anyway. */
+ const int MAX_RD = 4 + model_bytes;
+ uint8_t readarr[MAX_RD];
+ i = MAX_RD;
+ do {
+ int ret = spi_rdid(flash, readarr, i);
+ if (ret == 0)
+ break;
+ if (ret != SPI_INVALID_LENGTH)
+ return ret;
+ /* We need at least 1 vendor + n chip bytes, less does not make sense */
+ if (i <= 1 + model_bytes) {
+ msg_cinfo("%d byte RDID not supported on this SPI controller.\n", i);
+ return ret;
+ }
+ } while (i-- > 0);
+
+ i = 0;
+ while (i < MAX_RD) {
+ uint8_t tmp = readarr[i];
+ i++;
+ id1 = (id1 << 8) | tmp;
+ if (tmp != 0x7f) {
+ if (!oddparity(tmp)) {
+ msg_cdbg("Manufacturer ID parity violation at RDID byte %i. ID so far: 0x%x.\n",
+ i - 1, id1);
+ return 0;
+ }
+ break;
}
- } else {
- id1 = readarr[0];
- id2 = (readarr[1] << 8) | readarr[2];
}
+ for (j = 0; j < model_bytes; j++)
+ id2 = (id2 << 8) | readarr[i + j];
+
msg_cdbg("%s: id1 0x%02x, id2 0x%02x\n", __func__, id1, id2);
if (id1 == chip->manufacture_id && id2 == chip->model_id) {
@@ -170,29 +190,12 @@ static int probe_spi_rdid_generic(struct flashctx *flash, int bytes)
int probe_spi_rdid(struct flashctx *flash)
{
- return probe_spi_rdid_generic(flash, 3);
+ return probe_spi_rdid_generic(flash, 2);
}
-int probe_spi_rdid4(struct flashctx *flash)
+int probe_spi_rdid_edi(struct flashctx *flash)
{
- /* Some SPI controllers do not support commands with writecnt=1 and
- * readcnt=4.
- */
- switch (flash->pgm->spi.type) {
-#if CONFIG_INTERNAL == 1
-#if defined(__i386__) || defined(__x86_64__)
- case SPI_CONTROLLER_IT87XX:
- case SPI_CONTROLLER_WBSIO:
- msg_cinfo("4 byte RDID not supported on this SPI controller\n");
- return 0;
- break;
-#endif
-#endif
- default:
- return probe_spi_rdid_generic(flash, 4);
- }
-
- return 0;
+ return probe_spi_rdid_generic(flash, 4);
}
int probe_spi_rems(struct flashctx *flash)
--
Kind regards, Stefan Tauner
1
0
Adds the infrastructure parts that allow for sanity checks of
transactions without executing them. This includes new fields in
struct spi_programmer and default implementations as well as
concrete implementations for existing programmer where it makes sense.
Some additional cleanups are done as a bonus where i took the
opportunity, namely in sb600 and serprog.
Signed-off-by: Stefan Tauner <stefan.tauner(a)student.tuwien.ac.at>
---
bitbang_spi.c | 1 +
buspirate_spi.c | 14 +++++++++++++-
dediprog.c | 24 ++++++++++++++++--------
dummyflasher.c | 1 +
ft2232_spi.c | 14 +++++++++++++-
ichspi.c | 9 +++++++++
it85spi.c | 1 +
it87spi.c | 31 +++++++++++++++++++++++--------
linux_spi.c | 31 +++++++++++++++++++++++--------
programmer.h | 9 +++++++++
sb600spi.c | 51 ++++++++++++++++++++++++++++-----------------------
serprog.c | 32 +++++++++++++++++++++-----------
spi.c | 9 +++++++--
wbsio_spi.c | 10 ++++++++++
14 files changed, 175 insertions(+), 62 deletions(-)
diff --git a/bitbang_spi.c b/bitbang_spi.c
index 11d2de1..4b9f83a 100644
--- a/bitbang_spi.c
+++ b/bitbang_spi.c
@@ -67,6 +67,7 @@ static const struct spi_programmer spi_programmer_bitbang = {
.type = SPI_CONTROLLER_BITBANG,
.max_data_read = MAX_DATA_READ_UNLIMITED,
.max_data_write = MAX_DATA_WRITE_UNLIMITED,
+ .check_trans = default_spi_check_trans,
.command = bitbang_spi_send_command,
.multicommand = default_spi_send_multicommand,
.read = default_spi_read,
diff --git a/buspirate_spi.c b/buspirate_spi.c
index 054b4ff..340091c 100644
--- a/buspirate_spi.c
+++ b/buspirate_spi.c
@@ -129,6 +129,14 @@ static int buspirate_wait_for_string(unsigned char *buf, char *key)
return ret;
}
+static int buspirate_spi_check_trans(struct flashctx *flash, unsigned int writecnt, unsigned int readcnt,
+ const unsigned char *writearr)
+{
+ if (writecnt > 16 || readcnt > 16 || (readcnt + writecnt) > 16)
+ return SPI_INVALID_LENGTH;
+ return 0;
+}
+
static int buspirate_spi_send_command(struct flashctx *flash, unsigned int writecnt, unsigned int readcnt,
const unsigned char *writearr, unsigned char *readarr);
@@ -136,6 +144,7 @@ static const struct spi_programmer spi_programmer_buspirate = {
.type = SPI_CONTROLLER_BUSPIRATE,
.max_data_read = 12,
.max_data_write = 12,
+ .check_trans = buspirate_spi_check_trans,
.command = buspirate_spi_send_command,
.multicommand = default_spi_send_multicommand,
.read = default_spi_read,
@@ -421,8 +430,11 @@ static int buspirate_spi_send_command(struct flashctx *flash,
unsigned int i = 0;
int ret = 0;
- if (writecnt > 16 || readcnt > 16 || (readcnt + writecnt) > 16)
+ if (buspirate_spi_check_trans(flash, writecnt, readcnt, writearr) != 0) {
+ msg_pspew("%s called with an unsupported transaction layout: readcnt = %d, writecnt = %d.\n",
+ __func__, readcnt, writecnt);
return SPI_INVALID_LENGTH;
+ }
/* 3 bytes extra for CS#, len, CS#. */
if (buspirate_commbuf_grow(writecnt + readcnt + 3))
diff --git a/dediprog.c b/dediprog.c
index a81cf83..643b324 100644
--- a/dediprog.c
+++ b/dediprog.c
@@ -439,6 +439,18 @@ static int dediprog_spi_write_aai(struct flashctx *flash, uint8_t *buf, unsigned
return dediprog_spi_write(flash, buf, start, len, DEDI_SPI_CMD_AAIWRITE);
}
+static int dediprog_spi_check_trans(struct flashctx *flash, unsigned int writecnt, unsigned int readcnt,
+ const unsigned char *writearr)
+{
+ /* Paranoid, but I don't want to be blamed if anything explodes. */
+ if (writecnt > 16)
+ return 1;
+ /* 16 byte reads should work. */
+ if (readcnt > 16)
+ return -1;
+ return 0;
+}
+
static int dediprog_spi_send_command(struct flashctx *flash,
unsigned int writecnt,
unsigned int readcnt,
@@ -448,14 +460,9 @@ static int dediprog_spi_send_command(struct flashctx *flash,
int ret;
msg_pspew("%s, writecnt=%i, readcnt=%i\n", __func__, writecnt, readcnt);
- /* Paranoid, but I don't want to be blamed if anything explodes. */
- if (writecnt > 16) {
- msg_perr("Untested writecnt=%i, aborting.\n", writecnt);
- return 1;
- }
- /* 16 byte reads should work. */
- if (readcnt > 16) {
- msg_perr("Untested readcnt=%i, aborting.\n", readcnt);
+ if (dediprog_spi_check_trans(flash, writecnt, readcnt, writearr) != 0) {
+ msg_perr("%s called with an unsupported transaction layout: readcnt = %d, writecnt = %d.\n",
+ __func__, readcnt, writecnt);
return 1;
}
@@ -740,6 +747,7 @@ static const struct spi_programmer spi_programmer_dediprog = {
.type = SPI_CONTROLLER_DEDIPROG,
.max_data_read = MAX_DATA_UNSPECIFIED,
.max_data_write = MAX_DATA_UNSPECIFIED,
+ .check_trans = dediprog_spi_check_trans,
.command = dediprog_spi_send_command,
.multicommand = default_spi_send_multicommand,
.read = dediprog_spi_read,
diff --git a/dummyflasher.c b/dummyflasher.c
index 655b678..4e08386 100644
--- a/dummyflasher.c
+++ b/dummyflasher.c
@@ -123,6 +123,7 @@ static const struct spi_programmer spi_programmer_dummyflasher = {
.type = SPI_CONTROLLER_DUMMY,
.max_data_read = MAX_DATA_READ_UNLIMITED,
.max_data_write = MAX_DATA_UNSPECIFIED,
+ .check_trans = default_spi_check_trans, /* FIXME */
.command = dummy_spi_send_command,
.multicommand = default_spi_send_multicommand,
.read = default_spi_read,
diff --git a/ft2232_spi.c b/ft2232_spi.c
index 31a6c5c..d139886 100644
--- a/ft2232_spi.c
+++ b/ft2232_spi.c
@@ -139,6 +139,14 @@ static int get_buf(struct ftdi_context *ftdic, const unsigned char *buf,
return 0;
}
+static int ft2232_spi_check_trans(struct flashctx *flash, unsigned int writecnt, unsigned int readcnt,
+ const unsigned char *writearr)
+{
+ if (writecnt > 65536 || readcnt > 65536)
+ return SPI_INVALID_LENGTH;
+ return 0;
+}
+
static int ft2232_spi_send_command(struct flashctx *flash,
unsigned int writecnt, unsigned int readcnt,
const unsigned char *writearr,
@@ -148,6 +156,7 @@ static const struct spi_programmer spi_programmer_ft2232 = {
.type = SPI_CONTROLLER_FT2232,
.max_data_read = 64 * 1024,
.max_data_write = 256,
+ .check_trans = ft2232_spi_check_trans,
.command = ft2232_spi_send_command,
.multicommand = default_spi_send_multicommand,
.read = default_spi_read,
@@ -407,8 +416,11 @@ static int ft2232_spi_send_command(struct flashctx *flash,
int bufsize;
static int oldbufsize = 0;
- if (writecnt > 65536 || readcnt > 65536)
+ if (ft2232_spi_check_trans(flash, writecnt, readcnt, writearr) != 0) {
+ msg_pspew("%s called with an unsupported transaction layout: readcnt = %d, writecnt = %d.\n",
+ __func__, readcnt, writecnt);
return SPI_INVALID_LENGTH;
+ }
/* buf is not used for the response from the chip. */
bufsize = max(writecnt + 9, 260 + 9);
diff --git a/ichspi.c b/ichspi.c
index e60913c..0ce9dc2 100644
--- a/ichspi.c
+++ b/ichspi.c
@@ -1082,6 +1082,12 @@ static int prepare_opcode(struct flashctx *flash, unsigned int writecnt, unsigne
return 0;
}
+static int ich_spi_check_trans(struct flashctx *flash, unsigned int writecnt, unsigned int readcnt,
+ const unsigned char *writearr)
+{
+ return prepare_opcode(flash, writecnt, readcnt, writearr, true, NULL);
+}
+
static int ich_spi_send_command(struct flashctx *flash, unsigned int writecnt,
unsigned int readcnt,
const unsigned char *writearr,
@@ -1563,6 +1569,7 @@ static const struct spi_programmer spi_programmer_ich7 = {
.type = SPI_CONTROLLER_ICH7,
.max_data_read = 64,
.max_data_write = 64,
+ .check_trans = ich_spi_check_trans,
.command = ich_spi_send_command,
.multicommand = ich_spi_send_multicommand,
.read = default_spi_read,
@@ -1574,6 +1581,7 @@ static const struct spi_programmer spi_programmer_ich9 = {
.type = SPI_CONTROLLER_ICH9,
.max_data_read = 64,
.max_data_write = 64,
+ .check_trans = ich_spi_check_trans,
.command = ich_spi_send_command,
.multicommand = ich_spi_send_multicommand,
.read = default_spi_read,
@@ -1881,6 +1889,7 @@ static const struct spi_programmer spi_programmer_via = {
.type = SPI_CONTROLLER_VIA,
.max_data_read = 16,
.max_data_write = 16,
+ .check_trans = ich_spi_check_trans,
.command = ich_spi_send_command,
.multicommand = ich_spi_send_multicommand,
.read = default_spi_read,
diff --git a/it85spi.c b/it85spi.c
index 0b074eb..67c7185 100644
--- a/it85spi.c
+++ b/it85spi.c
@@ -280,6 +280,7 @@ static const struct spi_programmer spi_programmer_it85xx = {
.type = SPI_CONTROLLER_IT85XX,
.max_data_read = 64,
.max_data_write = 64,
+ .check_trans = default_spi_check_trans,
.command = it85xx_spi_send_command,
.multicommand = default_spi_send_multicommand,
.read = default_spi_read,
diff --git a/it87spi.c b/it87spi.c
index a35ddc0..f7b2a9e 100644
--- a/it87spi.c
+++ b/it87spi.c
@@ -104,6 +104,8 @@ void probe_superio_ite(void)
return;
}
+static int it8716f_spi_check_trans(struct flashctx *flash, unsigned int writecnt, unsigned int readcnt,
+ const unsigned char *writearr);
static int it8716f_spi_send_command(struct flashctx *flash,
unsigned int writecnt, unsigned int readcnt,
const unsigned char *writearr,
@@ -117,6 +119,7 @@ static const struct spi_programmer spi_programmer_it87xx = {
.type = SPI_CONTROLLER_IT87XX,
.max_data_read = MAX_DATA_UNSPECIFIED,
.max_data_write = MAX_DATA_UNSPECIFIED,
+ .check_trans = it8716f_spi_check_trans,
.command = it8716f_spi_send_command,
.multicommand = default_spi_send_multicommand,
.read = it8716f_spi_chip_read,
@@ -242,6 +245,18 @@ int init_superio_ite(void)
return ret;
}
+static int it8716f_spi_check_trans(struct flashctx *flash, unsigned int writecnt, unsigned int readcnt,
+ const unsigned char *writearr)
+{
+ if (readcnt > 3) {
+ return -1;
+ }
+ if (writecnt != 1 && writecnt != 2 && writecnt != 4 && writecnt != 5) {
+ return 1;
+ }
+ return 0;
+}
+
/*
* The IT8716F only supports commands with length 1,2,4,5 bytes including
* command byte and can not read more than 3 bytes from the device.
@@ -259,14 +274,16 @@ static int it8716f_spi_send_command(struct flashctx *flash,
uint8_t busy, writeenc;
int i;
+ if (it8716f_spi_check_trans(flash, writecnt, readcnt, writearr) != 0) {
+ msg_pspew("%s called with an unsupported transaction layout: readcnt = %d, writecnt = %d.\n",
+ __func__, readcnt, writecnt);
+ return SPI_INVALID_LENGTH;
+ }
+
do {
busy = INB(it8716f_flashport) & 0x80;
} while (busy);
- if (readcnt > 3) {
- msg_pinfo("%s called with unsupported readcnt %i.\n",
- __func__, readcnt);
- return SPI_INVALID_LENGTH;
- }
+
switch (writecnt) {
case 1:
OUTB(writearr[0], it8716f_flashport + 1);
@@ -292,9 +309,7 @@ static int it8716f_spi_send_command(struct flashctx *flash,
OUTB(writearr[4], it8716f_flashport + 7);
writeenc = 0x3;
break;
- default:
- msg_pinfo("%s called with unsupported writecnt %i.\n",
- __func__, writecnt);
+ default: /* Should never happen due to the checks in it8716f_spi_check_trans() */
return SPI_INVALID_LENGTH;
}
/*
diff --git a/linux_spi.c b/linux_spi.c
index 2f46463..2301b84 100644
--- a/linux_spi.c
+++ b/linux_spi.c
@@ -37,6 +37,8 @@
static int fd = -1;
static int linux_spi_shutdown(void *data);
+static int linux_spi_check_trans(struct flashctx *flash, unsigned int writecnt, unsigned int readcnt,
+ const unsigned char *writearr);
static int linux_spi_send_command(struct flashctx *flash, unsigned int writecnt,
unsigned int readcnt,
const unsigned char *txbuf,
@@ -50,6 +52,7 @@ static const struct spi_programmer spi_programmer_linux = {
.type = SPI_CONTROLLER_LINUX,
.max_data_read = MAX_DATA_UNSPECIFIED, /* TODO? */
.max_data_write = MAX_DATA_UNSPECIFIED, /* TODO? */
+ .check_trans = linux_spi_check_trans,
.command = linux_spi_send_command,
.multicommand = default_spi_send_multicommand,
.read = linux_spi_read,
@@ -129,29 +132,41 @@ static int linux_spi_shutdown(void *data)
return 0;
}
+static int linux_spi_check_trans(struct flashctx *flash, unsigned int writecnt, unsigned int readcnt,
+ const unsigned char *writearr)
+{
+ /* The implementation currently does not support requests that
+ don't start with sending a command. */
+ if (writecnt == 0)
+ return SPI_INVALID_LENGTH;
+ return 0;
+}
+
static int linux_spi_send_command(struct flashctx *flash, unsigned int writecnt,
unsigned int readcnt,
- const unsigned char *txbuf,
- unsigned char *rxbuf)
+ const unsigned char *writearr,
+ unsigned char *readarr)
{
int iocontrol_code;
struct spi_ioc_transfer msg[2] = {
{
- .tx_buf = (uint64_t)(ptrdiff_t)txbuf,
+ .tx_buf = (uint64_t)(ptrdiff_t)writearr,
.len = writecnt,
},
{
- .rx_buf = (uint64_t)(ptrdiff_t)rxbuf,
+ .rx_buf = (uint64_t)(ptrdiff_t)readarr,
.len = readcnt,
},
};
+ int ret = linux_spi_check_trans(flash, writecnt, readcnt, writearr);
+ if (ret != 0)
+ msg_perr("%s called with an unsupported transaction layout: readcnt = %d, writecnt = %d.\n",
+ __func__, readcnt, writecnt);
+ return ret;
+
if (fd == -1)
return -1;
- /* The implementation currently does not support requests that
- don't start with sending a command. */
- if (writecnt == 0)
- return SPI_INVALID_LENGTH;
/* Just submit the first (write) request in case there is nothing
to read. Otherwise submit both requests. */
diff --git a/programmer.h b/programmer.h
index dedec67..bcd9547 100644
--- a/programmer.h
+++ b/programmer.h
@@ -529,9 +529,18 @@ struct spi_programmer {
int (*read)(struct flashctx *flash, uint8_t *buf, unsigned int start, unsigned int len);
int (*write_256)(struct flashctx *flash, uint8_t *buf, unsigned int start, unsigned int len);
int (*write_aai)(struct flashctx *flash, uint8_t *buf, unsigned int start, unsigned int len);
+ /* Returns 0 if the supplied data can be sent by this programmer. Possible error codes include:
+ * SPI_INVALID_LENGTH if readcnt, writecnt or their combination is not allowed
+ * negative values if readcnt is too big
+ * positive values if writecnt is too big */
+ int (*check_trans)(struct flashctx *flash, unsigned int writecnt, unsigned int readcnt,
+ const unsigned char *writearr);
+ int (*check_transs)(struct flashctx *flash, struct spi_command *cmds);
const void *data;
};
+int default_spi_check_trans(struct flashctx *flash, unsigned int writecnt, unsigned int readcnt,
+ const unsigned char *writearr);
int default_spi_send_command(struct flashctx *flash, unsigned int writecnt, unsigned int readcnt,
const unsigned char *writearr, unsigned char *readarr);
int default_spi_send_multicommand(struct flashctx *flash, struct spi_command *cmds);
diff --git a/sb600spi.c b/sb600spi.c
index fe60aa9..9acf476 100644
--- a/sb600spi.c
+++ b/sb600spi.c
@@ -89,33 +89,37 @@ static void execute_command(void)
;
}
+static int sb600_spi_check_trans(struct flashctx *flash, unsigned int writecnt, unsigned int readcnt,
+ const unsigned char *writearr)
+{
+ /* We expect 1 opcode byte plus up to 8 data bytes (in any direction):
+ * the opcode has its own register, the data bytes are sent via an 8 byte FIFO. */
+ if ((writecnt == 0) || (writecnt - 1 + readcnt > 8)) {
+ return SPI_INVALID_LENGTH;
+ }
+ return 0;
+}
+
+
static int sb600_spi_send_command(struct flashctx *flash, unsigned int writecnt,
unsigned int readcnt,
const unsigned char *writearr,
unsigned char *readarr)
{
int count;
- /* First byte is cmd which can not being sent through FIFO. */
- unsigned char cmd = *writearr++;
+ unsigned char cmd = *writearr;
unsigned int readoffby1;
unsigned char readwrite;
- writecnt--;
-
- msg_pspew("%s, cmd=%x, writecnt=%x, readcnt=%x\n",
- __func__, cmd, writecnt, readcnt);
-
- if (readcnt > 8) {
- msg_pinfo("%s, SB600 SPI controller can not receive %d bytes, "
- "it is limited to 8 bytes\n", __func__, readcnt);
+ if (sb600_spi_check_trans(flash, writecnt, readcnt, writearr) != 0) {
+ msg_perr("%s called with an unsupported transaction layout: readcnt = %d, writecnt = %d.\n",
+ __func__, readcnt, writecnt);
return SPI_INVALID_LENGTH;
}
- if (writecnt > 8) {
- msg_pinfo("%s, SB600 SPI controller can not send %d bytes, "
- "it is limited to 8 bytes\n", __func__, writecnt);
- return SPI_INVALID_LENGTH;
- }
+ /* First byte is cmd which can not be sent through FIFO. */
+ writecnt--;
+ writearr++;
/* This is a workaround for a bug in SB600 and SB700. If we only send
* an opcode and no additional data/address, the SPI controller will
@@ -123,7 +127,7 @@ static int sb600_spi_send_command(struct flashctx *flash, unsigned int writecnt,
* the chip response is discarded and will not end up in the FIFO.
* It is unclear if the CS# line is set high too early as well.
*/
- readoffby1 = (writecnt) ? 0 : 1;
+ readoffby1 = (writecnt == 0) ? 1 : 0;
readwrite = (readcnt + readoffby1) << 4 | (writecnt);
mmio_writeb(readwrite, sb600_spibar + 1);
mmio_writeb(cmd, sb600_spibar + 0);
@@ -196,13 +200,14 @@ static int sb600_spi_send_command(struct flashctx *flash, unsigned int writecnt,
static const struct spi_programmer spi_programmer_sb600 = {
.type = SPI_CONTROLLER_SB600,
- .max_data_read = 8,
- .max_data_write = 5,
- .command = sb600_spi_send_command,
- .multicommand = default_spi_send_multicommand,
- .read = default_spi_read,
- .write_256 = default_spi_write_256,
- .write_aai = default_spi_write_aai,
+ .max_data_read = 8,
+ .max_data_write = 5,
+ .check_trans = sb600_spi_check_trans,
+ .command = sb600_spi_send_command,
+ .multicommand = default_spi_send_multicommand,
+ .read = default_spi_read,
+ .write_256 = default_spi_write_256,
+ .write_aai = default_spi_write_aai,
};
int sb600_probe_spi(struct pci_dev *dev)
diff --git a/serprog.c b/serprog.c
index b179ea4..4b0dc19 100644
--- a/serprog.c
+++ b/serprog.c
@@ -234,31 +234,31 @@ err_out:
return 1;
}
-static int sp_check_commandavail(uint8_t command)
+static int sp_check_commandavail(uint8_t cmd)
{
int byteoffs, bitoffs;
- byteoffs = command / 8;
- bitoffs = command % 8;
+ byteoffs = cmd / 8;
+ bitoffs = cmd % 8;
return (sp_cmdmap[byteoffs] & (1 << bitoffs)) ? 1 : 0;
}
static int sp_automatic_cmdcheck(uint8_t cmd)
{
- if ((sp_check_avail_automatic) && (sp_check_commandavail(cmd) == 0)) {
- msg_pdbg("Warning: Automatic command availability check failed "
- "for cmd 0x%x - won't execute cmd\n", cmd);
+ if ((sp_check_avail_automatic) && (sp_check_commandavail(cmd) == 0))
return 1;
- }
return 0;
}
-static int sp_docommand(uint8_t command, uint32_t parmlen,
+static int sp_docommand(uint8_t cmd, uint32_t parmlen,
uint8_t *params, uint32_t retlen, void *retparms)
{
unsigned char c;
- if (sp_automatic_cmdcheck(command))
+ if (sp_automatic_cmdcheck(cmd)) {
+ msg_pdbg("Warning: Automatic command availability check failed "
+ "for cmd 0x%x - won't execute cmd\n", cmd);
return 1;
- if (write(sp_fd, &command, 1) != 1) {
+ }
+ if (write(sp_fd, &cmd, 1) != 1) {
msg_perr("Error: cannot write op code: %s\n", strerror(errno));
return 1;
}
@@ -316,8 +316,11 @@ static void sp_flush_stream(void)
static int sp_stream_buffer_op(uint8_t cmd, uint32_t parmlen, uint8_t * parms)
{
uint8_t *sp;
- if (sp_automatic_cmdcheck(cmd))
+ if (sp_automatic_cmdcheck(cmd)) {
+ msg_pdbg("Warning: Automatic command availability check failed "
+ "for cmd 0x%x - won't execute cmd\n", cmd);
return 1;
+ }
sp = malloc(1 + parmlen);
if (!sp) sp_die("Error: cannot malloc command buffer");
sp[0] = cmd;
@@ -332,6 +335,12 @@ static int sp_stream_buffer_op(uint8_t cmd, uint32_t parmlen, uint8_t * parms)
return 0;
}
+static int serprog_spi_check_trans(struct flashctx *flash, unsigned int writecnt, unsigned int readcnt,
+ const unsigned char *writearr)
+{
+ return sp_automatic_cmdcheck(S_CMD_O_SPIOP);
+}
+
static int serprog_spi_send_command(struct flashctx *flash,
unsigned int writecnt, unsigned int readcnt,
const unsigned char *writearr,
@@ -342,6 +351,7 @@ static struct spi_programmer spi_programmer_serprog = {
.type = SPI_CONTROLLER_SERPROG,
.max_data_read = MAX_DATA_READ_UNLIMITED,
.max_data_write = MAX_DATA_WRITE_UNLIMITED,
+ .check_trans = serprog_spi_check_trans,
.command = serprog_spi_send_command,
.multicommand = default_spi_send_multicommand,
.read = serprog_spi_read,
diff --git a/spi.c b/spi.c
index 94a76a7..046d095 100644
--- a/spi.c
+++ b/spi.c
@@ -30,12 +30,17 @@
#include "programmer.h"
#include "spi.h"
+int default_spi_check_trans(struct flashctx *flash, unsigned int writecnt, unsigned int readcnt,
+ const unsigned char *writearr)
+{
+ return 0;
+}
+
int spi_send_command(struct flashctx *flash, unsigned int writecnt,
unsigned int readcnt, const unsigned char *writearr,
unsigned char *readarr)
{
- return flash->pgm->spi.command(flash, writecnt, readcnt, writearr,
- readarr);
+ return flash->pgm->spi.command(flash, writecnt, readcnt, writearr, readarr);
}
int spi_send_multicommand(struct flashctx *flash, struct spi_command *cmds)
diff --git a/wbsio_spi.c b/wbsio_spi.c
index 778b983..ec14c28 100644
--- a/wbsio_spi.c
+++ b/wbsio_spi.c
@@ -108,6 +108,15 @@ static uint8_t determine_mode(struct flashctx *flash, unsigned int writecnt, uns
return 0;
}
+static int wbsio_spi_check_trans(struct flashctx *flash, unsigned int writecnt, unsigned int readcnt,
+ const unsigned char *writearr)
+{
+ if (determine_mode(flash, writecnt, readcnt, writearr) == 0)
+ return SPI_INVALID_LENGTH;
+
+ return 0;
+}
+
static int wbsio_spi_send_command(struct flashctx *flash, unsigned int writecnt,
unsigned int readcnt,
const unsigned char *writearr,
@@ -119,6 +128,7 @@ static const struct spi_programmer spi_programmer_wbsio = {
.type = SPI_CONTROLLER_WBSIO,
.max_data_read = MAX_DATA_UNSPECIFIED,
.max_data_write = MAX_DATA_UNSPECIFIED,
+ .check_trans = wbsio_spi_check_trans,
.command = wbsio_spi_send_command,
.multicommand = default_spi_send_multicommand,
.read = wbsio_spi_read,
--
Kind regards, Stefan Tauner
1
0
Introduce determine_mode() which contains the extracted bits of the init
function that do sanity checks but without altering the hardware state.
Signed-off-by: Stefan Tauner <stefan.tauner(a)student.tuwien.ac.at>
---
wbsio_spi.c | 136 +++++++++++++++++++++++++++++++++--------------------------
1 file changed, 77 insertions(+), 59 deletions(-)
diff --git a/wbsio_spi.c b/wbsio_spi.c
index 7d4bb2a..778b983 100644
--- a/wbsio_spi.c
+++ b/wbsio_spi.c
@@ -61,6 +61,53 @@ done:
return flashport;
}
+/* W83627DHG has 11 command modes:
+ * 1=1 command only
+ * 2=1 command+1 data write
+ * 3=1 command+2 data read
+ * 4=1 command+3 address
+ * 5=1 command+3 address+1 data write
+ * 6=1 command+3 address+4 data write
+ * 7=1 command+3 address+1 dummy address inserted by wbsio+4 data read
+ * 8=1 command+3 address+1 data read
+ * 9=1 command+3 address+2 data read
+ * a=1 command+3 address+3 data read
+ * b=1 command+3 address+4 data read
+ *
+ * mode[7:4] holds the command mode
+ * mode[3:0] holds SPI address bits [19:16]
+ *
+ * The Winbond SPI master only supports 20 bit addresses on the SPI bus. :\
+ * Would one more byte of RAM in the chip (to get all 24 bits) really make
+ * such a big difference?
+ */
+static uint8_t determine_mode(struct flashctx *flash, unsigned int writecnt, unsigned int readcnt,
+ const unsigned char *writearr)
+{
+ if (1 == writecnt && 0 == readcnt) {
+ return 0x10;
+ } else if (2 == writecnt && 0 == readcnt) {
+ return 0x20;
+ } else if (1 == writecnt && 2 == readcnt) {
+ return 0x30;
+ } else if (4 == writecnt && 0 == readcnt) {
+ return 0x40 | (writearr[1] & 0x0f);
+ } else if (5 == writecnt && 0 == readcnt) {
+ return 0x50 | (writearr[1] & 0x0f);
+ } else if (8 == writecnt && 0 == readcnt) {
+ return 0x60 | (writearr[1] & 0x0f);
+ } else if (5 == writecnt && 4 == readcnt) {
+ /* XXX: TODO not supported by flashrom infrastructure!
+ * This mode, 7, discards the fifth byte in writecnt,
+ * but since we can not express that in flashrom, fail
+ * the operation for now.
+ */;
+ } else if (4 == writecnt && readcnt >= 1 && readcnt <= 4) {
+ return ((7 + readcnt) << 4) | (writearr[1] & 0x0f);
+ }
+ return 0;
+}
+
static int wbsio_spi_send_command(struct flashctx *flash, unsigned int writecnt,
unsigned int readcnt,
const unsigned char *writearr,
@@ -95,52 +142,37 @@ int wbsio_check_for_spi(void)
return 0;
}
-/* W83627DHG has 11 command modes:
- * 1=1 command only
- * 2=1 command+1 data write
- * 3=1 command+2 data read
- * 4=1 command+3 address
- * 5=1 command+3 address+1 data write
- * 6=1 command+3 address+4 data write
- * 7=1 command+3 address+1 dummy address inserted by wbsio+4 data read
- * 8=1 command+3 address+1 data read
- * 9=1 command+3 address+2 data read
- * a=1 command+3 address+3 data read
- * b=1 command+3 address+4 data read
- *
- * mode[7:4] holds the command mode
- * mode[3:0] holds SPI address bits [19:16]
- *
- * The Winbond SPI master only supports 20 bit addresses on the SPI bus. :\
- * Would one more byte of RAM in the chip (to get all 24 bits) really make
- * such a big difference?
- */
static int wbsio_spi_send_command(struct flashctx *flash, unsigned int writecnt,
unsigned int readcnt,
const unsigned char *writearr,
unsigned char *readarr)
{
int i;
- uint8_t mode = 0;
+ uint8_t mode = determine_mode(flash, writecnt, readcnt, writearr);
- msg_pspew("%s:", __func__);
+ if (!mode) {
+ msg_perr("%s: unsupported command type wr=%d rd=%d\n",
+ __func__, writecnt, readcnt);
+ /* Command type refers to the number of bytes read/written. */
+ return SPI_INVALID_LENGTH;
+ }
- if (1 == writecnt && 0 == readcnt) {
- mode = 0x10;
- } else if (2 == writecnt && 0 == readcnt) {
+ msg_pspew(" cmd=%02x mode=%02x\n", writearr[0], mode);
+ switch (mode & 0xF0) {
+ case 0x10: break;
+ case 0x20:
OUTB(writearr[1], wbsio_spibase + 4);
msg_pspew(" data=0x%02x", writearr[1]);
- mode = 0x20;
- } else if (1 == writecnt && 2 == readcnt) {
- mode = 0x30;
- } else if (4 == writecnt && 0 == readcnt) {
+ break;
+ case 0x30: break;
+ case 0x40:
msg_pspew(" addr=0x%02x", (writearr[1] & 0x0f));
for (i = 2; i < writecnt; i++) {
OUTB(writearr[i], wbsio_spibase + i);
msg_pspew("%02x", writearr[i]);
}
- mode = 0x40 | (writearr[1] & 0x0f);
- } else if (5 == writecnt && 0 == readcnt) {
+ break;
+ case 0x50:
msg_pspew(" addr=0x%02x", (writearr[1] & 0x0f));
for (i = 2; i < 4; i++) {
OUTB(writearr[i], wbsio_spibase + i);
@@ -148,8 +180,8 @@ static int wbsio_spi_send_command(struct flashctx *flash, unsigned int writecnt,
}
OUTB(writearr[i], wbsio_spibase + i);
msg_pspew(" data=0x%02x", writearr[i]);
- mode = 0x50 | (writearr[1] & 0x0f);
- } else if (8 == writecnt && 0 == readcnt) {
+ break;
+ case 0x60:
msg_pspew(" addr=0x%02x", (writearr[1] & 0x0f));
for (i = 2; i < 4; i++) {
OUTB(writearr[i], wbsio_spibase + i);
@@ -160,44 +192,30 @@ static int wbsio_spi_send_command(struct flashctx *flash, unsigned int writecnt,
OUTB(writearr[i], wbsio_spibase + i);
msg_pspew("%02x", writearr[i]);
}
- mode = 0x60 | (writearr[1] & 0x0f);
- } else if (5 == writecnt && 4 == readcnt) {
- /* XXX: TODO not supported by flashrom infrastructure!
- * This mode, 7, discards the fifth byte in writecnt,
- * but since we can not express that in flashrom, fail
- * the operation for now.
- */
- ;
- } else if (4 == writecnt && readcnt >= 1 && readcnt <= 4) {
+ break;
+ case 0x70: /* unimplemented */
+ break;
+ default:
msg_pspew(" addr=0x%02x", (writearr[1] & 0x0f));
for (i = 2; i < writecnt; i++) {
OUTB(writearr[i], wbsio_spibase + i);
msg_pspew("%02x", writearr[i]);
}
- mode = ((7 + readcnt) << 4) | (writearr[1] & 0x0f);
- }
- msg_pspew(" cmd=%02x mode=%02x\n", writearr[0], mode);
-
- if (!mode) {
- msg_perr("%s: unsupported command type wr=%d rd=%d\n",
- __func__, writecnt, readcnt);
- /* Command type refers to the number of bytes read/written. */
- return SPI_INVALID_LENGTH;
+ break;
}
OUTB(writearr[0], wbsio_spibase);
OUTB(mode, wbsio_spibase + 1);
programmer_delay(10);
- if (!readcnt)
- return 0;
-
- msg_pspew("%s: returning data =", __func__);
- for (i = 0; i < readcnt; i++) {
- readarr[i] = INB(wbsio_spibase + 4 + i);
- msg_pspew(" 0x%02x", readarr[i]);
+ if (readcnt > 0) {
+ msg_pspew("%s: returning data =", __func__);
+ for (i = 0; i < readcnt; i++) {
+ readarr[i] = INB(wbsio_spibase + 4 + i);
+ msg_pspew(" 0x%02x", readarr[i]);
+ }
+ msg_pspew("\n");
}
- msg_pspew("\n");
return 0;
}
--
Kind regards, Stefan Tauner
1
0
Oct. 3, 2012
- Introduce prepare_opcode() which does:
* find the offset of an opcode or reprogram the OPMENU as necessary
* check if the writecnt and readcnt are legit for the transaction type
* ensure that the allowed BBAR is obeyed.
- Merge lookup_spi_type() and parts of reprogram_opcode_on_the_fly()
into determine_spitype().
- Verify the writes in program_opcodes() and use it in error handling.
- Refactor ich_spi_send_multicommand() to utilize above changes.
- General cleanup of variable and constant names, among others:
* opcode_index -> oppos everywhere
* shortening of SPI_OPCODE_TYPE_*
Signed-off-by: Stefan Tauner <stefan.tauner(a)student.tuwien.ac.at>
---
flash.h | 1 +
ichspi.c | 347 +++++++++++++++++++++++++++++++++++---------------------------
2 files changed, 196 insertions(+), 152 deletions(-)
diff --git a/flash.h b/flash.h
index 4913536..3230849 100644
--- a/flash.h
+++ b/flash.h
@@ -24,6 +24,7 @@
#ifndef __FLASH_H__
#define __FLASH_H__ 1
+#include <stdbool.h>
#include <stdint.h>
#include <stddef.h>
#ifdef _WIN32
diff --git a/ichspi.c b/ichspi.c
index 8dd1893..e60913c 100644
--- a/ichspi.c
+++ b/ichspi.c
@@ -135,10 +135,10 @@
#define FPB_FPBA (0x1FFF << FPB_FPBA_OFF)
// ICH9R SPI commands
-#define SPI_OPCODE_TYPE_READ_NO_ADDRESS 0
-#define SPI_OPCODE_TYPE_WRITE_NO_ADDRESS 1
-#define SPI_OPCODE_TYPE_READ_WITH_ADDRESS 2
-#define SPI_OPCODE_TYPE_WRITE_WITH_ADDRESS 3
+#define READING_OP_NO_ADDR 0
+#define WRITING_OP_NO_ADDR 1
+#define READING_OP_WITH_ADDR 2
+#define WRITING_OP_WITH_ADDR 3
// ICH7 registers
#define ICH7_REG_SPIS 0x00 /* 16 Bits */
@@ -261,14 +261,14 @@ static OPCODES O_ST_M25P = {
JEDEC_EWSR,
},
{
- {JEDEC_BYTE_PROGRAM, SPI_OPCODE_TYPE_WRITE_WITH_ADDRESS, 0}, // Write Byte
- {JEDEC_READ, SPI_OPCODE_TYPE_READ_WITH_ADDRESS, 0}, // Read Data
- {JEDEC_BE_D8, SPI_OPCODE_TYPE_WRITE_WITH_ADDRESS, 0}, // Erase Sector
- {JEDEC_RDSR, SPI_OPCODE_TYPE_READ_NO_ADDRESS, 0}, // Read Device Status Reg
- {JEDEC_REMS, SPI_OPCODE_TYPE_READ_WITH_ADDRESS, 0}, // Read Electronic Manufacturer Signature
- {JEDEC_WRSR, SPI_OPCODE_TYPE_WRITE_NO_ADDRESS, 0}, // Write Status Register
- {JEDEC_RDID, SPI_OPCODE_TYPE_READ_NO_ADDRESS, 0}, // Read JDEC ID
- {JEDEC_CE_C7, SPI_OPCODE_TYPE_WRITE_NO_ADDRESS, 0}, // Bulk erase
+ {JEDEC_BYTE_PROGRAM, WRITING_OP_WITH_ADDR, 0}, // Write Byte
+ {JEDEC_READ, READING_OP_WITH_ADDR, 0}, // Read Data
+ {JEDEC_BE_D8, WRITING_OP_WITH_ADDR, 0}, // Erase Sector
+ {JEDEC_RDSR, READING_OP_NO_ADDR, 0}, // Read Device Status Reg
+ {JEDEC_REMS, READING_OP_WITH_ADDR, 0}, // Read Electronic Manufacturer Signature
+ {JEDEC_WRSR, WRITING_OP_NO_ADDR, 0}, // Write Status Register
+ {JEDEC_RDID, READING_OP_NO_ADDR, 0}, // Read JDEC ID
+ {JEDEC_CE_C7, WRITING_OP_NO_ADDR, 0}, // Bulk erase
}
};
@@ -277,17 +277,17 @@ static OPCODES O_ST_M25P = {
* is needed which is currently not in the chipset OPCODE table
*/
static OPCODE POSSIBLE_OPCODES[] = {
- {JEDEC_BYTE_PROGRAM, SPI_OPCODE_TYPE_WRITE_WITH_ADDRESS, 0}, // Write Byte
- {JEDEC_READ, SPI_OPCODE_TYPE_READ_WITH_ADDRESS, 0}, // Read Data
- {JEDEC_BE_D8, SPI_OPCODE_TYPE_WRITE_WITH_ADDRESS, 0}, // Erase Sector
- {JEDEC_RDSR, SPI_OPCODE_TYPE_READ_NO_ADDRESS, 0}, // Read Device Status Reg
- {JEDEC_REMS, SPI_OPCODE_TYPE_READ_WITH_ADDRESS, 0}, // Read Electronic Manufacturer Signature
- {JEDEC_WRSR, SPI_OPCODE_TYPE_WRITE_NO_ADDRESS, 0}, // Write Status Register
- {JEDEC_RDID, SPI_OPCODE_TYPE_READ_NO_ADDRESS, 0}, // Read JDEC ID
- {JEDEC_CE_C7, SPI_OPCODE_TYPE_WRITE_NO_ADDRESS, 0}, // Bulk erase
- {JEDEC_SE, SPI_OPCODE_TYPE_WRITE_WITH_ADDRESS, 0}, // Sector erase
- {JEDEC_BE_52, SPI_OPCODE_TYPE_WRITE_WITH_ADDRESS, 0}, // Block erase
- {JEDEC_AAI_WORD_PROGRAM, SPI_OPCODE_TYPE_WRITE_NO_ADDRESS, 0}, // Auto Address Increment
+ {JEDEC_BYTE_PROGRAM, WRITING_OP_WITH_ADDR, 0}, // Write Byte
+ {JEDEC_READ, READING_OP_WITH_ADDR, 0}, // Read Data
+ {JEDEC_BE_D8, WRITING_OP_WITH_ADDR, 0}, // Erase Sector
+ {JEDEC_RDSR, READING_OP_NO_ADDR, 0}, // Read Device Status Reg
+ {JEDEC_REMS, READING_OP_WITH_ADDR, 0}, // Read Electronic Manufacturer Signature
+ {JEDEC_WRSR, WRITING_OP_NO_ADDR, 0}, // Write Status Register
+ {JEDEC_RDID, READING_OP_NO_ADDR, 0}, // Read JDEC ID
+ {JEDEC_CE_C7, WRITING_OP_NO_ADDR, 0}, // Bulk erase
+ {JEDEC_SE, WRITING_OP_WITH_ADDR, 0}, // Sector erase
+ {JEDEC_BE_52, WRITING_OP_WITH_ADDR, 0}, // Block erase
+ {JEDEC_AAI_WORD_PROGRAM, WRITING_OP_NO_ADDR, 0}, // Auto Address Increment
};
static OPCODES O_EXISTING = {};
@@ -370,66 +370,61 @@ static void prettyprint_ich9_reg_ssfc(uint32_t reg_val)
pprint_reg(SSFC, SCF, reg_val, "\n");
}
-static uint8_t lookup_spi_type(uint8_t opcode)
+static uint8_t determine_spitype(uint8_t opcode, unsigned int writecnt, unsigned int readcnt)
{
- int a;
-
- for (a = 0; a < ARRAY_SIZE(POSSIBLE_OPCODES); a++) {
- if (POSSIBLE_OPCODES[a].opcode == opcode)
- return POSSIBLE_OPCODES[a].spi_type;
+ int i;
+ for (i = 0; i < ARRAY_SIZE(POSSIBLE_OPCODES); i++) {
+ if (POSSIBLE_OPCODES[i].opcode == opcode)
+ return POSSIBLE_OPCODES[i].spi_type;
}
- return 0xFF;
+ /* Try to guess spi type from read/write sizes.
+ * The following valid writecnt/readcnt combinations exist:
+ * writecnt = 4, readcnt >= 0
+ * writecnt = 1, readcnt >= 0
+ * writecnt >= 4, readcnt = 0
+ * writecnt >= 1, readcnt = 0
+ * writecnt >= 1 is guaranteed for all commands.
+ */
+ msg_pspew("Need to guess spitype from payload lengths.\n");
+ if (readcnt == 0)
+ /* if readcnt=0 and writecount >= 4, we don't know if it is WRITE_NO_ADDRESS
+ * or WRITE_WITH_ADDRESS. But if we use WRITE_NO_ADDRESS and the first 3 data
+ * bytes are actual the address, they go to the bus anyhow
+ */
+ return WRITING_OP_NO_ADDR;
+ else if (writecnt == 1) // and readcnt is > 0
+ return READING_OP_NO_ADDR;
+ else if (writecnt == 4) // and readcnt is > 0
+ return READING_OP_WITH_ADDR;
+ else // we have an invalid case
+ return 0xFF;
}
-static int reprogram_opcode_on_the_fly(uint8_t opcode, unsigned int writecnt, unsigned int readcnt)
+static int reprogram_opcode_on_the_fly(uint8_t opcode, uint8_t spi_type, unsigned int writecnt, unsigned int readcnt)
{
- uint8_t spi_type;
-
- spi_type = lookup_spi_type(opcode);
- if (spi_type > 3) {
- /* Try to guess spi type from read/write sizes.
- * The following valid writecnt/readcnt combinations exist:
- * writecnt = 4, readcnt >= 0
- * writecnt = 1, readcnt >= 0
- * writecnt >= 4, readcnt = 0
- * writecnt >= 1, readcnt = 0
- * writecnt >= 1 is guaranteed for all commands.
- */
- if (readcnt == 0)
- /* if readcnt=0 and writecount >= 4, we don't know if it is WRITE_NO_ADDRESS
- * or WRITE_WITH_ADDRESS. But if we use WRITE_NO_ADDRESS and the first 3 data
- * bytes are actual the address, they go to the bus anyhow
- */
- spi_type = SPI_OPCODE_TYPE_WRITE_NO_ADDRESS;
- else if (writecnt == 1) // and readcnt is > 0
- spi_type = SPI_OPCODE_TYPE_READ_NO_ADDRESS;
- else if (writecnt == 4) // and readcnt is > 0
- spi_type = SPI_OPCODE_TYPE_READ_WITH_ADDRESS;
- else // we have an invalid case
- return SPI_INVALID_LENGTH;
- }
- int oppos = 2; // use original JEDEC_BE_D8 offset
+ int ret;
+ const int oppos = 2; // use original JEDEC_BE_D8 offset
curopcodes->opcode[oppos].opcode = opcode;
curopcodes->opcode[oppos].spi_type = spi_type;
- program_opcodes(curopcodes, 0);
- oppos = find_opcode(curopcodes, opcode);
- msg_pdbg2("on-the-fly OPCODE (0x%02X) re-programmed, op-pos=%d\n", opcode, oppos);
- return oppos;
+ ret = program_opcodes(curopcodes, 0);
+ if (ret == 0)
+ msg_pdbg2("OPCODE (0x%02X) re-programmed on-the-fly, op-pos=%d\n", opcode, oppos);
+ return ret;
}
static int find_opcode(OPCODES *op, uint8_t opcode)
{
- int a;
+ int i;
if (op == NULL) {
msg_perr("\n%s: null OPCODES pointer!\n", __func__);
return -1;
}
- for (a = 0; a < 8; a++) {
- if (op->opcode[a].opcode == opcode)
- return a;
+ for (i = 0; i < 8; i++) {
+ if (op->opcode[i].opcode == opcode)
+ return i;
}
return -1;
@@ -549,6 +544,14 @@ static int program_opcodes(OPCODES *op, int enable_undo)
mmio_writew(optype, ich_spibar + ICH7_REG_OPTYPE);
mmio_writel(opmenu[0], ich_spibar + ICH7_REG_OPMENU);
mmio_writel(opmenu[1], ich_spibar + ICH7_REG_OPMENU + 4);
+
+ if ((preop != mmio_readw(ich_spibar + ICH7_REG_PREOP)) ||
+ (optype != mmio_readw(ich_spibar + ICH7_REG_OPTYPE)) ||
+ (opmenu[0] != mmio_readl(ich_spibar + ICH7_REG_OPMENU)) ||
+ (opmenu[1] != mmio_readl(ich_spibar + ICH7_REG_OPMENU + 4))) {
+ msg_perr("Programming opcodes failed.\n");
+ return 1;
+ }
break;
case CHIPSET_ICH8:
default: /* Future version might behave the same */
@@ -563,6 +566,13 @@ static int program_opcodes(OPCODES *op, int enable_undo)
mmio_writew(optype, ich_spibar + ICH9_REG_OPTYPE);
mmio_writel(opmenu[0], ich_spibar + ICH9_REG_OPMENU);
mmio_writel(opmenu[1], ich_spibar + ICH9_REG_OPMENU + 4);
+ if ((preop != mmio_readw(ich_spibar + ICH9_REG_PREOP)) ||
+ (optype != mmio_readw(ich_spibar + ICH9_REG_OPTYPE)) ||
+ (opmenu[0] != mmio_readl(ich_spibar + ICH9_REG_OPMENU)) ||
+ (opmenu[1] != mmio_readl(ich_spibar + ICH9_REG_OPMENU + 4))) {
+ msg_perr("Programming opcodes failed.\n");
+ return 1;
+ }
break;
}
@@ -720,11 +730,11 @@ static int ich7_run_opcode(OPCODE op, uint32_t offset,
uint32_t temp32;
uint16_t temp16;
uint64_t opmenu;
- int opcode_index;
+ int oppos;
/* Is it a write command? */
- if ((op.spi_type == SPI_OPCODE_TYPE_WRITE_NO_ADDRESS)
- || (op.spi_type == SPI_OPCODE_TYPE_WRITE_WITH_ADDRESS)) {
+ if ((op.spi_type == WRITING_OP_NO_ADDR)
+ || (op.spi_type == WRITING_OP_WITH_ADDR)) {
write_cmd = 1;
}
@@ -765,17 +775,17 @@ static int ich7_run_opcode(OPCODE op, uint32_t offset,
opmenu = REGREAD32(ICH7_REG_OPMENU);
opmenu |= ((uint64_t)REGREAD32(ICH7_REG_OPMENU + 4)) << 32;
- for (opcode_index = 0; opcode_index < 8; opcode_index++) {
+ for (oppos = 0; oppos < 8; oppos++) {
if ((opmenu & 0xff) == op.opcode) {
break;
}
opmenu >>= 8;
}
- if (opcode_index == 8) {
+ if (oppos == 8) {
msg_pdbg("Opcode %x not found.\n", op.opcode);
return 1;
}
- temp16 |= ((uint16_t) (opcode_index & 0x07)) << 4;
+ temp16 |= ((uint16_t) (oppos & 0x07)) << 4;
timeout = 100 * 60; /* 60 ms are 9.6 million cycles at 16 MHz. */
/* Handle Atomic. Atomic commands include three steps:
@@ -837,11 +847,10 @@ static int ich9_run_opcode(OPCODE op, uint32_t offset,
int timeout;
uint32_t temp32;
uint64_t opmenu;
- int opcode_index;
+ int oppos;
/* Is it a write command? */
- if ((op.spi_type == SPI_OPCODE_TYPE_WRITE_NO_ADDRESS)
- || (op.spi_type == SPI_OPCODE_TYPE_WRITE_WITH_ADDRESS)) {
+ if ((op.spi_type == WRITING_OP_NO_ADDR) || (op.spi_type == WRITING_OP_WITH_ADDR)) {
write_cmd = 1;
}
@@ -887,17 +896,17 @@ static int ich9_run_opcode(OPCODE op, uint32_t offset,
opmenu = REGREAD32(ICH9_REG_OPMENU);
opmenu |= ((uint64_t)REGREAD32(ICH9_REG_OPMENU + 4)) << 32;
- for (opcode_index = 0; opcode_index < 8; opcode_index++) {
+ for (oppos = 0; oppos < 8; oppos++) {
if ((opmenu & 0xff) == op.opcode) {
break;
}
opmenu >>= 8;
}
- if (opcode_index == 8) {
+ if (oppos == 8) {
msg_pdbg("Opcode %x not found.\n", op.opcode);
return 1;
}
- temp32 |= ((uint32_t) (opcode_index & 0x07)) << (8 + 4);
+ temp32 |= ((uint32_t) (oppos & 0x07)) << (8 + 4);
timeout = 100 * 60; /* 60 ms are 9.6 million cycles at 16 MHz. */
/* Handle Atomic. Atomic commands include three steps:
@@ -982,86 +991,114 @@ static int run_opcode(const struct flashctx *flash, OPCODE op, uint32_t offset,
}
}
-static int ich_spi_send_command(struct flashctx *flash, unsigned int writecnt,
- unsigned int readcnt,
- const unsigned char *writearr,
- unsigned char *readarr)
+/* Check command and prepare the appropriate opcode.
+ * The selected OPCODE will be returned in opcodep if it can be determined.
+ * If the dryrun flag is set, try do determine opcode sanity and availability only, do not change hw state
+ * (i.e. do not touch OPMENU). In that case opcodep is unused. */
+static int prepare_opcode(struct flashctx *flash, unsigned int writecnt, unsigned int readcnt,
+ const unsigned char *writearr, bool dryrun, OPCODE **opcodep)
{
- int result;
- int opcode_index = -1;
- const unsigned char cmd = *writearr;
- OPCODE *opcode;
- uint32_t addr = 0;
- uint8_t *data;
- int count;
+ OPCODE *opcode = NULL;
+ OPCODE emu_op = {0};
+ if (writecnt == 0)
+ return SPI_INVALID_LENGTH;
- /* find cmd in opcodes-table */
- opcode_index = find_opcode(curopcodes, cmd);
- if (opcode_index == -1) {
- if (!ichspi_lock)
- opcode_index = reprogram_opcode_on_the_fly(cmd, writecnt, readcnt);
- if (opcode_index == SPI_INVALID_LENGTH) {
- msg_pdbg("OPCODE 0x%02x has unsupported length, will not execute.\n", cmd);
+ /* ensure that the requested opcode is available */
+ int oppos = find_opcode(curopcodes, writearr[0]);
+ if (oppos >= 0) {
+ opcode = &(curopcodes->opcode[oppos]);
+ } else {
+ uint8_t spi_type = determine_spitype(writearr[0], writecnt, readcnt);
+ if (spi_type == 0xFF) {
+ if (!dryrun)
+ msg_pdbg("Could not determine spitype for opcode 0x%02x.\n", writearr[0]);
return SPI_INVALID_LENGTH;
- } else if (opcode_index == -1) {
- msg_pdbg("Invalid OPCODE 0x%02x, will not execute.\n",
- cmd);
+ }
+ if (ichspi_lock) {
+ if (!dryrun)
+ msg_pdbg("OPCODES locked down and do not contain 0x%02x, can not execute.\n",
+ writearr[0]);
return SPI_INVALID_OPCODE;
+ } else {
+ /* In a dryrun we expect that reprogramming works successfully, but we need to create
+ * an OPCODE object for the tests below. */
+ if (dryrun) {
+ emu_op.opcode = writearr[0];
+ emu_op.spi_type = spi_type;
+ opcode = &emu_op;
+ } else {
+ if (reprogram_opcode_on_the_fly(writearr[0], spi_type, writecnt, readcnt) != 0)
+ return SPI_GENERIC_ERROR;
+ oppos = find_opcode(curopcodes, writearr[0]);
+ opcode = &(curopcodes->opcode[oppos]);
+ }
}
}
- opcode = &(curopcodes->opcode[opcode_index]);
-
/* The following valid writecnt/readcnt combinations exist:
* writecnt = 4, readcnt >= 0
* writecnt = 1, readcnt >= 0
* writecnt >= 4, readcnt = 0
* writecnt >= 1, readcnt = 0
- * writecnt >= 1 is guaranteed for all commands.
- */
- if ((opcode->spi_type == SPI_OPCODE_TYPE_READ_WITH_ADDRESS) &&
- (writecnt != 4)) {
- msg_perr("%s: Internal command size error for opcode "
- "0x%02x, got writecnt=%i, want =4\n", __func__, cmd,
- writecnt);
+ * writecnt >= 1 is guaranteed for all commands. */
+ if ((opcode->spi_type == READING_OP_WITH_ADDR) && (writecnt != 4)) {
+ if (!dryrun)
+ msg_perr("%s: Reading command requires an opcode (0x%02x) and exactly 3 address bytes, "
+ "but writecnt=%i.\n", __func__, writearr[0], writecnt);
return SPI_INVALID_LENGTH;
}
- if ((opcode->spi_type == SPI_OPCODE_TYPE_READ_NO_ADDRESS) &&
- (writecnt != 1)) {
- msg_perr("%s: Internal command size error for opcode "
- "0x%02x, got writecnt=%i, want =1\n", __func__, cmd,
- writecnt);
+ if ((opcode->spi_type == READING_OP_NO_ADDR) && (writecnt != 1)) {
+ if (!dryrun)
+ msg_perr("%s: Reading command requires an opcode (0x%02x) without address bytes, "
+ "but writecnt=%i.\n", __func__, writearr[0], writecnt);
return SPI_INVALID_LENGTH;
}
- if ((opcode->spi_type == SPI_OPCODE_TYPE_WRITE_WITH_ADDRESS) &&
- (writecnt < 4)) {
- msg_perr("%s: Internal command size error for opcode "
- "0x%02x, got writecnt=%i, want >=4\n", __func__, cmd,
- writecnt);
+ if ((opcode->spi_type == WRITING_OP_WITH_ADDR) && (writecnt < 4)) {
+ if (!dryrun)
+ msg_perr("%s: Writing command requires at least an opcode (0x%02x) and exactly "
+ "3 address bytes, but writecnt=%i.\n", __func__, writearr[0], writecnt);
return SPI_INVALID_LENGTH;
}
- if (((opcode->spi_type == SPI_OPCODE_TYPE_WRITE_WITH_ADDRESS) ||
- (opcode->spi_type == SPI_OPCODE_TYPE_WRITE_NO_ADDRESS)) &&
- (readcnt)) {
- msg_perr("%s: Internal command size error for opcode "
- "0x%02x, got readcnt=%i, want =0\n", __func__, cmd,
- readcnt);
+ if (((opcode->spi_type == WRITING_OP_WITH_ADDR) || (opcode->spi_type == WRITING_OP_NO_ADDR)) &&
+ (readcnt > 0)) {
+ if (!dryrun)
+ msg_perr("%s: Writing command with opcode (0x%02x) can read not bytes, "
+ "but readcnt=%i.\n", __func__, writearr[0], readcnt);
return SPI_INVALID_LENGTH;
}
- /* if opcode-type requires an address */
- if (opcode->spi_type == SPI_OPCODE_TYPE_READ_WITH_ADDRESS ||
- opcode->spi_type == SPI_OPCODE_TYPE_WRITE_WITH_ADDRESS) {
- addr = (writearr[1] << 16) |
- (writearr[2] << 8) | (writearr[3] << 0);
+ /* If the opcode type requires an address we check if it is below the allowed base. */
+ if (opcode->spi_type == READING_OP_WITH_ADDR || opcode->spi_type == WRITING_OP_WITH_ADDR) {
+ uint32_t addr = (writearr[1] << 16) | (writearr[2] << 8) | (writearr[3] << 0);
if (addr < ichspi_bbar) {
- msg_perr("%s: Address 0x%06x below allowed "
- "range 0x%06x-0xffffff\n", __func__,
- addr, ichspi_bbar);
+ msg_perr("%s: Address 0x%06x below allowed range 0x%06x-0xffffff\n",
+ __func__, addr, ichspi_bbar);
return SPI_INVALID_ADDRESS;
}
}
+ if (opcodep != NULL)
+ *opcodep = opcode;
+ return 0;
+}
+
+static int ich_spi_send_command(struct flashctx *flash, unsigned int writecnt,
+ unsigned int readcnt,
+ const unsigned char *writearr,
+ unsigned char *readarr)
+{
+ OPCODE *opcode;
+ uint32_t addr;
+ uint8_t *data;
+ int count;
+
+ int result = prepare_opcode(flash, writecnt, readcnt, writearr, false, &opcode);
+ if (result != 0) {
+ msg_pspew("%s called with an unsupported transaction layout: readcnt = %d, writecnt = %d.\n",
+ __func__, readcnt, writecnt);
+ return result;
+ }
+
/* Translate read/write array/count.
* The maximum data length is identical for the maximum read length and
* for the maximum write length excluding opcode and address. Opcode and
@@ -1069,10 +1106,10 @@ static int ich_spi_send_command(struct flashctx *flash, unsigned int writecnt,
* and are thus not counted towards data length. The only exception
* applies if the opcode definition (un)intentionally classifies said
* opcode incorrectly as non-address opcode or vice versa. */
- if (opcode->spi_type == SPI_OPCODE_TYPE_WRITE_NO_ADDRESS) {
+ if (opcode->spi_type == WRITING_OP_NO_ADDR) {
data = (uint8_t *) (writearr + 1);
count = writecnt - 1;
- } else if (opcode->spi_type == SPI_OPCODE_TYPE_WRITE_WITH_ADDRESS) {
+ } else if (opcode->spi_type == WRITING_OP_WITH_ADDR) {
data = (uint8_t *) (writearr + 4);
count = writecnt - 4;
} else {
@@ -1080,11 +1117,11 @@ static int ich_spi_send_command(struct flashctx *flash, unsigned int writecnt,
count = readcnt;
}
+ addr = (writearr[1] << 16) | (writearr[2] << 8) | (writearr[3] << 0);
result = run_opcode(flash, *opcode, addr, count, data);
if (result) {
msg_pdbg("Running OPCODE 0x%02x failed ", opcode->opcode);
- if ((opcode->spi_type == SPI_OPCODE_TYPE_WRITE_WITH_ADDRESS) ||
- (opcode->spi_type == SPI_OPCODE_TYPE_READ_WITH_ADDRESS)) {
+ if ((opcode->spi_type == WRITING_OP_WITH_ADDR) || (opcode->spi_type == READING_OP_WITH_ADDR)) {
msg_pdbg("at address 0x%06x ", addr);
}
msg_pdbg("(payload length was %d).\n", count);
@@ -1092,8 +1129,7 @@ static int ich_spi_send_command(struct flashctx *flash, unsigned int writecnt,
/* Print out the data array if it contains data to write.
* Errors are detected before the received data is read back into
* the array so it won't make sense to print it then. */
- if ((opcode->spi_type == SPI_OPCODE_TYPE_WRITE_WITH_ADDRESS) ||
- (opcode->spi_type == SPI_OPCODE_TYPE_WRITE_NO_ADDRESS)) {
+ if ((opcode->spi_type == WRITING_OP_WITH_ADDR) || (opcode->spi_type == WRITING_OP_NO_ADDR)) {
int i;
msg_pspew("The data was:\n");
for (i = 0; i < count; i++){
@@ -1358,17 +1394,17 @@ static int ich_hwseq_write(struct flashctx *flash, uint8_t *buf,
return 0;
}
-static int ich_spi_send_multicommand(struct flashctx *flash,
- struct spi_command *cmds)
+static int ich_spi_send_multicommand(struct flashctx *flash, struct spi_command *cmds)
{
int ret = 0;
int i;
int oppos, preoppos;
for (; (cmds->writecnt || cmds->readcnt) && !ret; cmds++) {
- if ((cmds + 1)->writecnt || (cmds + 1)->readcnt) {
+ struct spi_command *cmd_nxt = cmds + 1;
+ if (cmd_nxt->writecnt || cmd_nxt->readcnt) {
/* Next command is valid. */
preoppos = find_preop(curopcodes, cmds->writearr[0]);
- oppos = find_opcode(curopcodes, (cmds + 1)->writearr[0]);
+ oppos = find_opcode(curopcodes, cmd_nxt->writearr[0]);
if ((oppos == -1) && (preoppos != -1)) {
/* Current command is listed as preopcode in
* ICH struct OPCODES, but next command is not
@@ -1376,13 +1412,10 @@ static int ich_spi_send_multicommand(struct flashctx *flash,
* Check for command sanity, then
* try to reprogram the ICH opcode list.
*/
- if (find_preop(curopcodes,
- (cmds + 1)->writearr[0]) != -1) {
- msg_perr("%s: Two subsequent "
- "preopcodes 0x%02x and 0x%02x, "
+ if (find_preop(curopcodes, cmd_nxt->writearr[0]) != -1) {
+ msg_perr("%s: Two subsequent preopcodes 0x%02x and 0x%02x, "
"ignoring the first.\n",
- __func__, cmds->writearr[0],
- (cmds + 1)->writearr[0]);
+ __func__, cmds->writearr[0], cmd_nxt->writearr[0]);
continue;
}
/* If the chipset is locked down, we'll fail
@@ -1390,7 +1423,19 @@ static int ich_spi_send_multicommand(struct flashctx *flash,
* No need to bother with fixups.
*/
if (!ichspi_lock) {
- oppos = reprogram_opcode_on_the_fly((cmds + 1)->writearr[0], (cmds + 1)->writecnt, (cmds + 1)->readcnt);
+ uint8_t spi_type = determine_spitype(cmd_nxt->writearr[0],
+ cmd_nxt->writecnt,
+ cmd_nxt->readcnt);
+ if (spi_type == 0xFF) {
+ msg_pdbg("Could not determine spitype for opcode 0x%02x.\n",
+ cmd_nxt->writearr[0]);
+ return SPI_INVALID_LENGTH;
+ }
+ ret = reprogram_opcode_on_the_fly(cmd_nxt->writearr[0], spi_type,
+ cmd_nxt->writecnt, cmd_nxt->readcnt);
+ if (ret == -1)
+ continue;
+ oppos = find_opcode(curopcodes, cmd_nxt->writearr[0]);
if (oppos == -1)
continue;
curopcodes->opcode[oppos].atomic = preoppos + 1;
@@ -1793,10 +1838,8 @@ int ich_init_spi(struct pci_dev *dev, uint32_t base, void *rcrb,
}
}
- if (ich_spi_mode == ich_auto && ichspi_lock &&
- ich_missing_opcodes()) {
- msg_pinfo("Enabling hardware sequencing because "
- "some important opcode is locked.\n");
+ if (ich_spi_mode == ich_auto && ichspi_lock && ich_missing_opcodes()) {
+ msg_pinfo("Enabling hardware sequencing because an important opcode is unavailable.\n");
ich_spi_mode = ich_hwseq;
}
--
Kind regards, Stefan Tauner
1
0
This patch set enables us to figure out if transactions will succeed
without executing them, which allows for a refactoring of
probe_spi_rdid_generic() which in consequence makes it possible to add
probe_spi_rdid_edi().
The infrastructure code as a whole, but especially the ichspi code
is heavily modified. Please be aware of that if you test it on
mainboards.
Antonio: please rebase your Spansion patch on this one and extend it
to add actually two chips by using the full 32 bit model IDs
(0x20184d00, 0x20184d01) and .probe = probe_spi_rdid_edi.
Stefan Tauner (5):
Refactor ichspi and prepare it for check_trans().
Prepare wbsio_spi.c for check_trans().
Introduce check_trans().
Generify probe_spi_rdid_generic() and add probe_spi_rdid_edi().
Let the dummy programmer emulate SPI payload limitations.
bitbang_spi.c | 1 +
buspirate_spi.c | 14 ++-
dediprog.c | 24 ++--
dummyflasher.c | 16 ++-
flash.h | 1 +
flashchips.c | 24 ++--
flashchips.h | 2 +-
ft2232_spi.c | 14 ++-
ichspi.c | 356 +++++++++++++++++++++++++++++++------------------------
it85spi.c | 1 +
it87spi.c | 31 +++--
linux_spi.c | 31 +++--
programmer.h | 11 ++
sb600spi.c | 51 ++++----
serprog.c | 32 +++--
spi.c | 9 +-
spi25.c | 97 +++++++--------
wbsio_spi.c | 146 ++++++++++++++---------
18 files changed, 527 insertions(+), 334 deletions(-)
This is the output of the dummy programmer to show the new behavior:
flashrom v0.9.6.1-r1611 on Linux 3.2.0-31-generic (x86_64)
flashrom is free software, get the source code at http://www.flashrom.org
flashrom was built with libpci 3.1.8, GCC 4.6.3, little endian
Command line (3 args): ./flashrom -p dummy:bus=SPI,spi_prog=wbsio,emulate=M25P10.RES -V
Calibrating delay loop... OS timer resolution is 1 usecs, 1456M loops per second, 10 myus = 10 us, 100 myus = 127 us, 1000 myus = 1023 us, 10000 myus = 10024 us, 4 myus = 10 us, OK.
Initializing dummy programmer
Requested buses are: SPI
Enabling support for SPI flash.
Emulating ST M25P10.RES SPI flash chip (RES, page write)
Using SPI payload limitations of the wbsio programmer.
Filling fake flash chip with 0xff, size 131072
The following protocols are supported: SPI.
Probing for AMIC A25L05PT, 64 kB: 3 byte RDID not supported on this SPI controller.
Probing for AMIC A25L05PU, 64 kB: 3 byte RDID not supported on this SPI controller.
Probing for AMIC A25L10PT, 128 kB: 3 byte RDID not supported on this SPI controller.
Probing for AMIC A25L10PU, 128 kB: 3 byte RDID not supported on this SPI controller.
Probing for AMIC A25L20PT, 256 kB: 3 byte RDID not supported on this SPI controller.
Probing for AMIC A25L20PU, 256 kB: 3 byte RDID not supported on this SPI controller.
Probing for AMIC A25L40PT, 512 kB: 3 byte RDID not supported on this SPI controller.
Probing for AMIC A25L40PU, 512 kB: 3 byte RDID not supported on this SPI controller.
Probing for AMIC A25L80P, 1024 kB: 3 byte RDID not supported on this SPI controller.
Probing for AMIC A25L16PT, 2048 kB: 3 byte RDID not supported on this SPI controller.
Probing for AMIC A25L16PU, 2048 kB: 3 byte RDID not supported on this SPI controller.
Probing for AMIC A25L512, 64 kB: 3 byte RDID not supported on this SPI controller.
Probing for AMIC A25L010, 128 kB: 3 byte RDID not supported on this SPI controller.
Probing for AMIC A25L020, 256 kB: 3 byte RDID not supported on this SPI controller.
Probing for AMIC A25L040, 512 kB: 3 byte RDID not supported on this SPI controller.
Probing for AMIC A25L080, 1024 kB: 3 byte RDID not supported on this SPI controller.
Probing for AMIC A25L016, 2048 kB: 3 byte RDID not supported on this SPI controller.
Probing for AMIC A25L032, 4096 kB: 3 byte RDID not supported on this SPI controller.
Probing for AMIC A25LQ032, 4096 kB: 3 byte RDID not supported on this SPI controller.
Probing for Atmel AT25DF021, 256 kB: 3 byte RDID not supported on this SPI controller.
Probing for Atmel AT25DF041A, 512 kB: 3 byte RDID not supported on this SPI controller.
Probing for Atmel AT25DF081, 1024 kB: 3 byte RDID not supported on this SPI controller.
Probing for Atmel AT25DF081A, 1024 kB: 3 byte RDID not supported on this SPI controller.
Probing for Atmel AT25DF161, 2048 kB: 3 byte RDID not supported on this SPI controller.
Probing for Atmel AT25DF321, 4096 kB: 3 byte RDID not supported on this SPI controller.
Probing for Atmel AT25DF321A, 4096 kB: 3 byte RDID not supported on this SPI controller.
Probing for Atmel AT25DF641(A), 8192 kB: 3 byte RDID not supported on this SPI controller.
Probing for Atmel AT25DQ161, 2048 kB: 3 byte RDID not supported on this SPI controller.
Probing for Atmel AT25F512B, 64 kB: 3 byte RDID not supported on this SPI controller.
Probing for Atmel AT25FS010, 128 kB: 3 byte RDID not supported on this SPI controller.
Probing for Atmel AT25FS040, 512 kB: 3 byte RDID not supported on this SPI controller.
Probing for Atmel AT26DF041, 512 kB: 3 byte RDID not supported on this SPI controller.
Probing for Atmel AT26DF081A, 1024 kB: 3 byte RDID not supported on this SPI controller.
Probing for Atmel AT26DF161, 2048 kB: 3 byte RDID not supported on this SPI controller.
Probing for Atmel AT26DF161A, 2048 kB: 3 byte RDID not supported on this SPI controller.
Probing for Atmel AT26F004, 512 kB: 3 byte RDID not supported on this SPI controller.
Probing for Atmel AT45CS1282, 16896 kB: 3 byte RDID not supported on this SPI controller.
Probing for Atmel AT45DB011D, 128 kB: 3 byte RDID not supported on this SPI controller.
Probing for Atmel AT45DB021D, 256 kB: 3 byte RDID not supported on this SPI controller.
Probing for Atmel AT45DB041D, 512 kB: 3 byte RDID not supported on this SPI controller.
Probing for Atmel AT45DB081D, 1024 kB: 3 byte RDID not supported on this SPI controller.
Probing for Atmel AT45DB161D, 2048 kB: 3 byte RDID not supported on this SPI controller.
Probing for Atmel AT45DB321C, 4224 kB: 3 byte RDID not supported on this SPI controller.
Probing for Atmel AT45DB321D, 4096 kB: 3 byte RDID not supported on this SPI controller.
Probing for Atmel AT45DB642D, 8192 kB: 3 byte RDID not supported on this SPI controller.
Probing for EMST F25L008A, 1024 kB: 3 byte RDID not supported on this SPI controller.
Probing for Eon EN25B05, 64 kB: 3 byte RDID not supported on this SPI controller.
Probing for Eon EN25B05T, 64 kB: 3 byte RDID not supported on this SPI controller.
Probing for Eon EN25B10, 128 kB: 3 byte RDID not supported on this SPI controller.
Probing for Eon EN25B10T, 128 kB: 3 byte RDID not supported on this SPI controller.
Probing for Eon EN25B20, 256 kB: 3 byte RDID not supported on this SPI controller.
Probing for Eon EN25B20T, 256 kB: 3 byte RDID not supported on this SPI controller.
Probing for Eon EN25B40, 512 kB: 3 byte RDID not supported on this SPI controller.
Probing for Eon EN25B40T, 512 kB: 3 byte RDID not supported on this SPI controller.
Probing for Eon EN25B80, 1024 kB: 3 byte RDID not supported on this SPI controller.
Probing for Eon EN25B80T, 1024 kB: 3 byte RDID not supported on this SPI controller.
Probing for Eon EN25B16, 2048 kB: 3 byte RDID not supported on this SPI controller.
Probing for Eon EN25B16T, 2048 kB: 3 byte RDID not supported on this SPI controller.
Probing for Eon EN25B32, 4096 kB: 3 byte RDID not supported on this SPI controller.
Probing for Eon EN25B32T, 4096 kB: 3 byte RDID not supported on this SPI controller.
Probing for Eon EN25B64, 8192 kB: 3 byte RDID not supported on this SPI controller.
Probing for Eon EN25B64T, 8192 kB: 3 byte RDID not supported on this SPI controller.
Probing for Eon EN25F05, 64 kB: 3 byte RDID not supported on this SPI controller.
Probing for Eon EN25F10, 128 kB: 3 byte RDID not supported on this SPI controller.
Probing for Eon EN25F20, 256 kB: 3 byte RDID not supported on this SPI controller.
Probing for Eon EN25F40, 512 kB: 3 byte RDID not supported on this SPI controller.
Probing for Eon EN25F80, 1024 kB: 3 byte RDID not supported on this SPI controller.
Probing for Eon EN25F16, 2048 kB: 3 byte RDID not supported on this SPI controller.
Probing for Eon EN25F32, 4096 kB: 3 byte RDID not supported on this SPI controller.
Probing for Eon EN25F64, 8192 kB: 3 byte RDID not supported on this SPI controller.
Probing for Eon EN25Q40, 512 kB: 3 byte RDID not supported on this SPI controller.
Probing for Eon EN25Q80(A), 1024 kB: 3 byte RDID not supported on this SPI controller.
Probing for Eon EN25Q16, 2048 kB: 3 byte RDID not supported on this SPI controller.
Probing for Eon EN25Q32(A/B), 4096 kB: 3 byte RDID not supported on this SPI controller.
Probing for Eon EN25Q64, 8192 kB: 3 byte RDID not supported on this SPI controller.
Probing for Eon EN25Q128, 16384 kB: 3 byte RDID not supported on this SPI controller.
Probing for Eon EN25QH16, 2048 kB: 3 byte RDID not supported on this SPI controller.
Probing for Eon EN25QH32, 4096 kB: 3 byte RDID not supported on this SPI controller.
Probing for GigaDevice GD25Q20, 256 kB: 3 byte RDID not supported on this SPI controller.
Probing for GigaDevice GD25Q40, 512 kB: 3 byte RDID not supported on this SPI controller.
Probing for GigaDevice GD25Q80, 1024 kB: 3 byte RDID not supported on this SPI controller.
Probing for GigaDevice GD25Q16, 2048 kB: 3 byte RDID not supported on this SPI controller.
Probing for GigaDevice GD25Q32, 4096 kB: 3 byte RDID not supported on this SPI controller.
Probing for GigaDevice GD25Q64, 8192 kB: 3 byte RDID not supported on this SPI controller.
Probing for GigaDevice GD25Q128, 16384 kB: 3 byte RDID not supported on this SPI controller.
Probing for GigaDevice GD25LQ32, 4096 kB: 3 byte RDID not supported on this SPI controller.
Probing for Macronix MX25L512, 64 kB: 3 byte RDID not supported on this SPI controller.
Probing for Macronix MX25L1005, 128 kB: 3 byte RDID not supported on this SPI controller.
Probing for Macronix MX25L2005, 256 kB: 3 byte RDID not supported on this SPI controller.
Probing for Macronix MX25L4005, 512 kB: 3 byte RDID not supported on this SPI controller.
Probing for Macronix MX25L8005, 1024 kB: 3 byte RDID not supported on this SPI controller.
Probing for Macronix MX25L1605, 2048 kB: 3 byte RDID not supported on this SPI controller.
Probing for Macronix MX25L1635D, 2048 kB: 3 byte RDID not supported on this SPI controller.
Probing for Macronix MX25L1635E, 2048 kB: 3 byte RDID not supported on this SPI controller.
Probing for Macronix MX25L3205, 4096 kB: 3 byte RDID not supported on this SPI controller.
Probing for Macronix MX25L3235D, 4096 kB: 3 byte RDID not supported on this SPI controller.
Probing for Macronix MX25L6405, 8192 kB: 3 byte RDID not supported on this SPI controller.
Probing for Macronix MX25L12805, 16384 kB: 3 byte RDID not supported on this SPI controller.
Probing for Numonyx M25PE10, 128 kB: 3 byte RDID not supported on this SPI controller.
Probing for Numonyx M25PE20, 256 kB: 3 byte RDID not supported on this SPI controller.
Probing for Numonyx M25PE40, 512 kB: 3 byte RDID not supported on this SPI controller.
Probing for Numonyx M25PE80, 1024 kB: 3 byte RDID not supported on this SPI controller.
Probing for Numonyx M25PE16, 2048 kB: 3 byte RDID not supported on this SPI controller.
Probing for Numonyx N25Q064, 8192 kB: 3 byte RDID not supported on this SPI controller.
Probing for PMC Pm25LV010, 128 kB: 3 byte RDID not supported on this SPI controller.
Probing for PMC Pm25LV016B, 2048 kB: 3 byte RDID not supported on this SPI controller.
Probing for PMC Pm25LV020, 256 kB: 3 byte RDID not supported on this SPI controller.
Probing for PMC Pm25LV040, 512 kB: 3 byte RDID not supported on this SPI controller.
Probing for PMC Pm25LV080B, 1024 kB: 3 byte RDID not supported on this SPI controller.
Probing for PMC Pm25LV512, 64 kB: 3 byte RDID not supported on this SPI controller.
Probing for Sanyo LF25FW203A, 2048 kB: 3 byte RDID not supported on this SPI controller.
Probing for Spansion S25FL004A, 512 kB: 3 byte RDID not supported on this SPI controller.
Probing for Spansion S25FL008A, 1024 kB: 3 byte RDID not supported on this SPI controller.
Probing for Spansion S25FL016A, 2048 kB: 3 byte RDID not supported on this SPI controller.
Probing for Spansion S25FL032A, 4096 kB: 3 byte RDID not supported on this SPI controller.
Probing for Spansion S25FL064A, 8192 kB: 3 byte RDID not supported on this SPI controller.
Probing for SST SST25LF040A, 512 kB: probe_spi_res2: id1 0x10, id2 0x10
Probing for SST SST25LF080A, 1024 kB: probe_spi_res2: id1 0x10, id2 0x10
Probing for SST SST25VF010, 128 kB: probe_spi_rems: id1 0xff, id2 0xff
Probing for SST SST25VF016B, 2048 kB: 3 byte RDID not supported on this SPI controller.
Probing for SST SST25VF032B, 4096 kB: 3 byte RDID not supported on this SPI controller.
Probing for SST SST25VF064C, 8192 kB: 3 byte RDID not supported on this SPI controller.
Probing for SST SST25VF040, 512 kB: probe_spi_rems: id1 0xff, id2 0xff
Probing for SST SST25VF040B, 512 kB: 3 byte RDID not supported on this SPI controller.
Probing for SST SST25VF040B.REMS, 512 kB: probe_spi_rems: id1 0xff, id2 0xff
Probing for SST SST25VF080B, 1024 kB: 3 byte RDID not supported on this SPI controller.
Probing for SST SST25WF512, 64 kB: 3 byte RDID not supported on this SPI controller.
Probing for SST SST25WF010, 128 kB: 3 byte RDID not supported on this SPI controller.
Probing for SST SST25WF020, 256 kB: 3 byte RDID not supported on this SPI controller.
Probing for SST SST25WF040, 512 kB: 3 byte RDID not supported on this SPI controller.
Probing for ST M25P05-A, 64 kB: 3 byte RDID not supported on this SPI controller.
Probing for ST M25P05, 64 kB: probe_spi_res1: id 0x10
Chip status register is 00
Found ST flash chip "M25P05" (64 kB, SPI) on dummy.
Probing for ST M25P10-A, 128 kB: 3 byte RDID not supported on this SPI controller.
Probing for ST M25P10, 128 kB: probe_spi_res1: id 0x10
Chip status register is 00
Found ST flash chip "M25P10" (128 kB, SPI) on dummy.
Probing for ST M25P20, 256 kB: 3 byte RDID not supported on this SPI controller.
Probing for ST M25P40, 512 kB: 3 byte RDID not supported on this SPI controller.
Probing for ST M25P40-old, 512 kB: probe_spi_res1: id 0x10
Probing for ST M25P80, 1024 kB: 3 byte RDID not supported on this SPI controller.
Probing for ST M25P16, 2048 kB: 3 byte RDID not supported on this SPI controller.
Probing for ST M25P32, 4096 kB: 3 byte RDID not supported on this SPI controller.
Probing for ST M25P64, 8192 kB: 3 byte RDID not supported on this SPI controller.
Probing for ST M25P128, 16384 kB: 3 byte RDID not supported on this SPI controller.
Probing for ST M25PX16, 2048 kB: 3 byte RDID not supported on this SPI controller.
Probing for ST M25PX32, 4096 kB: 3 byte RDID not supported on this SPI controller.
Probing for ST M25PX64, 8192 kB: 3 byte RDID not supported on this SPI controller.
Probing for Winbond W25Q80, 1024 kB: 3 byte RDID not supported on this SPI controller.
Probing for Winbond W25Q16, 2048 kB: 3 byte RDID not supported on this SPI controller.
Probing for Winbond W25Q32, 4096 kB: 3 byte RDID not supported on this SPI controller.
Probing for Winbond W25Q64, 8192 kB: 3 byte RDID not supported on this SPI controller.
Probing for Winbond W25Q128, 16384 kB: 3 byte RDID not supported on this SPI controller.
Probing for Winbond W25X10, 128 kB: 3 byte RDID not supported on this SPI controller.
Probing for Winbond W25X20, 256 kB: 3 byte RDID not supported on this SPI controller.
Probing for Winbond W25X40, 512 kB: 3 byte RDID not supported on this SPI controller.
Probing for Winbond W25X80, 1024 kB: 3 byte RDID not supported on this SPI controller.
Probing for Winbond W25X16, 2048 kB: 3 byte RDID not supported on this SPI controller.
Probing for Winbond W25X32, 4096 kB: 3 byte RDID not supported on this SPI controller.
Probing for Winbond W25X64, 8192 kB: 3 byte RDID not supported on this SPI controller.
Probing for Unknown SFDP-capable chip, 0 kB: No SFDP signature found.
Probing for AMIC unknown AMIC SPI chip, 0 kB: 3 byte RDID not supported on this SPI controller.
Probing for Atmel unknown Atmel SPI chip, 0 kB: 3 byte RDID not supported on this SPI controller.
Probing for Eon unknown Eon SPI chip, 0 kB: 3 byte RDID not supported on this SPI controller.
Probing for Macronix unknown Macronix SPI chip, 0 kB: 3 byte RDID not supported on this SPI controller.
Probing for PMC unknown PMC SPI chip, 0 kB: 3 byte RDID not supported on this SPI controller.
Probing for SST unknown SST SPI chip, 0 kB: 3 byte RDID not supported on this SPI controller.
Probing for ST unknown ST SPI chip, 0 kB: 3 byte RDID not supported on this SPI controller.
Probing for Sanyo unknown Sanyo SPI chip, 0 kB: 3 byte RDID not supported on this SPI controller.
Probing for Winbond unknown Winbond (ex Nexcom) SPI chip, 0 kB: 3 byte RDID not supported on this SPI controller.
Probing for Generic unknown SPI chip (RDID), 0 kB: 3 byte RDID not supported on this SPI controller.
Probing for Generic unknown SPI chip (REMS), 0 kB: probe_spi_rems: id1 0xff, id2 0xff
Multiple flash chips were detected: "M25P05", "M25P10"
Please specify which chip to use with the -c <chipname> option.
--
Kind regards, Stefan Tauner
1
0
On Tue, 2 Oct 2012 18:02:12 +0400
Владислав Быков <vladislavbyk1(a)gmail.com> wrote:
> No problem :3
Thanks a lot! This proves that the register contents of the locking
registers are indeed altered by the pin and that flashrom will
automatically pick that information up and just works. I'll add a note
to the entry of your board and will change the lock message accordingly.
> Btw, maybe you have jabber or icq? :) It would be convenient)
I am somewhat flattered, but i prefer public communication by mail.
This way it gets archived and can help other people in the future. If
you want to chat with me/us, you are welcomed to join our IRC channel
(#flashrom) on freenode (chat.freenode.net)
--
Kind regards/Mit freundlichen Grüßen, Stefan Tauner
2
1
2012/10/2 Владислав Быков <vladislavbyk1(a)gmail.com>:
> No problem :3
> Default jumper position (enabled):
>>
>> >> sudo flashrom -p internal -VV
>> [sudo] password for vladislavbyk:
>> flashrom v0.9.6.1-r1564 on Linux 3.5.4-1-ARCH (i686)
>> flashrom is free software, get the source code at http://www.flashrom.org
>>
>> flashrom was built with libpci 3.1.10, GCC 4.7.1 20120721 (prerelease),
>> little endian
>> Command line (3 args): flashrom -p internal -VV
>> Calibrating delay loop... OS timer resolution is 1 usecs, 1355M loops per
>> second, 10 myus = 10 us, 100 myus = 97 us, 1000 myus = 1126 us, 10000 myus =
>> 9925 us, 4 myus = 4 us, OK.
>>
>> Initializing internal programmer
>> No coreboot table found.
>> DMI string system-manufacturer: "To Be Filled By O.E.M."
>> DMI string system-product-name: "To Be Filled By O.E.M."
>> DMI string system-version: "To Be Filled By O.E.M."
>> DMI string baseboard-manufacturer: "Foxconn"
>> DMI string baseboard-product-name: "H55MX-S Series"
>> DMI string baseboard-version: "1.1"
>> DMI string chassis-type: "Desktop"
>> Found ITE Super I/O, ID 0x8720 on port 0x2e
>> Found chipset "Intel H55" with PCI ID 8086:3b06. Enabling flash write...
>> 0xfff80000/0xffb80000 FWH IDSEL: 0x0
>> 0xfff00000/0xffb00000 FWH IDSEL: 0x0
>> 0xffe80000/0xffa80000 FWH IDSEL: 0x1
>> 0xffe00000/0xffa00000 FWH IDSEL: 0x1
>> 0xffd80000/0xff980000 FWH IDSEL: 0x2
>> 0xffd00000/0xff900000 FWH IDSEL: 0x2
>> 0xffc80000/0xff880000 FWH IDSEL: 0x3
>> 0xffc00000/0xff800000 FWH IDSEL: 0x3
>> 0xff700000/0xff300000 FWH IDSEL: 0x4
>> 0xff600000/0xff200000 FWH IDSEL: 0x5
>> 0xff500000/0xff100000 FWH IDSEL: 0x6
>> 0xff400000/0xff000000 FWH IDSEL: 0x7
>> 0xfff80000/0xffb80000 FWH decode enabled
>> 0xfff00000/0xffb00000 FWH decode enabled
>> 0xffe80000/0xffa80000 FWH decode disabled
>> 0xffe00000/0xffa00000 FWH decode disabled
>> 0xffd80000/0xff980000 FWH decode disabled
>> 0xffd00000/0xff900000 FWH decode disabled
>> 0xffc80000/0xff880000 FWH decode disabled
>> 0xffc00000/0xff800000 FWH decode disabled
>> 0xff700000/0xff300000 FWH decode disabled
>> 0xff600000/0xff200000 FWH decode disabled
>> 0xff500000/0xff100000 FWH decode disabled
>> 0xff400000/0xff000000 FWH decode disabled
>> Maximum FWH chip size: 0x100000 bytes
>> BIOS Lock Enable: disabled, BIOS Write Enable: disabled, BIOS_CNTL is 0x8
>> Root Complex Register Block address = 0xfed1c000
>> GCS = 0xc64: BIOS Interface Lock-Down: disabled, Boot BIOS Straps: 0x3
>> (SPI)
>> Top Swap : not enabled
>> SPIBAR = 0xfed1c000 + 0x3800
>> 0x04: 0x6008 (HSFS)
>> HSFS: FDONE=0, FCERR=0, AEL=0, BERASE=1, SCIP=0, FDOPSS=1, FDV=1,
>> FLOCKDN=0
>> Programming OPCODES...
>> program_opcodes: preop=5006 optype=463b opmenu=05d80302c79f0190
>> done
>> OP Type Pre-OP
>> op[0]: 0x02, write w/ addr, none
>> op[1]: 0x03, read w/ addr, none
>> op[2]: 0xd8, write w/ addr, none
>> op[3]: 0x05, read w/o addr, none
>> op[4]: 0x90, read w/ addr, none
>> op[5]: 0x01, write w/o addr, none
>> op[6]: 0x9f, read w/o addr, none
>> op[7]: 0xc7, write w/o addr, none
>> Pre-OP 0: 0x06, Pre-OP 1: 0x50
>>
>> 0x06: 0x0000 (HSFC)
>> HSFC: FGO=0, FCYCLE=0, FDBC=0, SME=0
>> 0x08: 0x00000000 (FADDR)
>> 0x50: 0x00000a0b (FRAP)
>> BMWAG 0x00, BMRAG 0x00, BRWA 0x0a, BRRA 0x0b
>> 0x54: 0x00000000 FREG0: WARNING: Flash Descriptor region
>> (0x00000000-0x00000fff) is read-only.
>>
>> 0x58: 0x07ff0700 FREG1: BIOS region (0x00700000-0x007fffff) is read-write.
>> 0x5C: 0x06ff0001 FREG2: WARNING: Management Engine region
>> (0x00001000-0x006fffff) is locked.
>> 0x60: 0x00001fff FREG3: Gigabit Ethernet region is unused.
>> 0x64: 0x00001fff FREG4: Platform Data region is unused.
>> 0x74: 0x00000000 (PR0 is unused)
>> 0x78: 0x00000000 (PR1 is unused)
>> 0x7C: 0x00000000 (PR2 is unused)
>> 0x80: 0x00000000 (PR3 is unused)
>> 0x84: 0x00000000 (PR4 is unused)
>> Please send a verbose log to flashrom(a)flashrom.org if this board is not
>> listed on
>> http://flashrom.org/Supported_hardware#Supported_mainboards yet.
>> Writes have been disabled. You can enforce write support with the
>> ich_spi_force programmer option, but it will most likely harm your
>> hardware!
>> If you force flashrom you will get no support if something breaks.
>>
>> 0x90: 0x00 (SSFS)
>> SSFS: SCIP=0, FDONE=0, FCERR=0, AEL=0
>> 0x91: 0xf84200 (SSFC)
>> SSFC: SCGO=0, ACS=0, SPOP=0, COP=0, DBC=2, SME=0, SCF=0
>> 0x94: 0x5006 (PREOP)
>> 0x96: 0x463b (OPTYPE)
>> 0x98: 0x05d80302 (OPMENU)
>> 0x9C: 0xc79f0190 (OPMENU+4)
>> 0xA0: 0x00000000 (BBAR)
>> 0xC4: 0x00000000 (LVSCC)
>> LVSCC: BES=0x0, WG=0, WSR=0, WEWS=0, EO=0x0, VCL=0
>> 0xC8: 0x00002001 (UVSCC)
>> UVSCC: BES=0x1, WG=0, WSR=0, WEWS=0, EO=0x20, VCL=0
>> 0xD0: 0x00000000 (FPB)
>>
>> Reading flash descriptors mapped by the chipset via FDOC/FDOD... done.
>> === Content Section ===
>> FLVALSIG 0x0ff0a55a
>> FLMAP0 0x02040102
>> FLMAP1 0x10100206
>> FLMAP2 0x00000020
>>
>> --- Details ---
>> NR (Number of Regions): 3
>> FRBA (Flash Region Base Address): 0x040
>> NC (Number of Components): 2
>> FCBA (Flash Component Base Address): 0x020
>> ISL (ICH/PCH Strap Length): 16
>> FISBA/FPSBA (Flash ICH/PCH Strap Base Address): 0x100
>> NM (Number of Masters): 3
>> FMBA (Flash Master Base Address): 0x060
>> MSL/PSL (MCH/PROC Strap Length): 0
>> FMSBA (Flash MCH/PROC Strap Base Address): 0x200
>>
>> === Component Section ===
>> FLCOMP 0x0930001b
>> FLILL 0x00000000
>>
>> --- Details ---
>> Component 1 density: 4 MB
>> Component 2 density: 4 MB
>> Read Clock Frequency: 20 MHz
>> Read ID and Status Clock Freq.: 33 MHz
>> Write and Erase Clock Freq.: 33 MHz
>> Fast Read is supported.
>> Fast Read Clock Frequency: 33 MHz
>> No forbidden opcodes.
>>
>> === Region Section ===
>> FLREG0 0x00000000
>> FLREG1 0x07ff0700
>> FLREG2 0x06ff0001
>> FLREG3 0x00001fff
>>
>> --- Details ---
>> Region 0 (Descr.) 0x00000000 - 0x00000fff
>> Region 1 (BIOS ) 0x00700000 - 0x007fffff
>> Region 2 (ME ) 0x00001000 - 0x006fffff
>> Region 3 (GbE ) is unused.
>>
>> === Master Section ===
>> FLMSTR1 0x0a0b0000
>> FLMSTR2 0x0c0d0000
>> FLMSTR3 0x08080118
>>
>> --- Details ---
>> Descr. BIOS ME GbE Platf.
>> BIOS r rw rw
>> ME r rw rw
>> GbE rw
>>
>> Enabling hardware sequencing due to multiple flash chips detected.
>> SPI Read Configuration: prefetching enabled, caching enabled, OK.
>> No IT87* serial flash segment enabled.
>> The following protocols are supported: FWH, Programmer-specific.
>> Probing for Programmer Opaque flash chip, 0 kB: Found 2 attached SPI flash
>> chips with a combined density of 8192 kB.
>> There is only one partition containing the whole address space (0x000000 -
>> 0x7fffff).
>> There are 2048 erase blocks with 4096 B each.
>> Found Programmer flash chip "Opaque flash chip" (8192 kB,
>> Programmer-specific) at physical address 0x0.
>> Probing for Atmel AT49LH002, 256 kB: probe_82802ab: id1 0x41, id2 0x4d,
>> id1 parity violation, id1 is normal flash content, id2 is normal flash
>> content
>> Probing for Intel 82802AB, 512 kB: probe_82802ab: id1 0x14, id2 0x8c, id1
>> parity violation, id1 is normal flash content, id2 is normal flash content
>>
>> Probing for Intel 82802AC, 1024 kB: probe_82802ab: id1 0x4e, id2 0x56, id1
>> parity violation, id1 is normal flash content, id2 is normal flash content
>> Probing for PMC Pm49FL002, 256 kB: probe_jedec_common: id1 0x41, id2 0x4d,
>> id1 parity violation, id1 is normal flash content, id2 is normal flash
>> content
>> Probing for PMC Pm49FL004, 512 kB: probe_jedec_common: id1 0x14, id2 0x8c,
>> id1 parity violation, id1 is normal flash content, id2 is normal flash
>> content
>>
>> Probing for Sharp LHF00L04, 1024 kB: probe_82802ab: id1 0x4e, id2 0x56,
>> id1 parity violation, id1 is normal flash content, id2 is normal flash
>> content
>> Probing for SST SST49LF002A/B, 256 kB: probe_jedec_common: id1 0x41, id2
>> 0x4d, id1 parity violation, id1 is normal flash content, id2 is normal flash
>> content
>> Probing for SST SST49LF003A/B, 384 kB: probe_jedec_common: id1 0x02, id2
>> 0x00, id1 is normal flash content, id2 is normal flash content
>> Probing for SST SST49LF004A/B, 512 kB: probe_jedec_common: id1 0x14, id2
>> 0x8c, id1 parity violation, id1 is normal flash content, id2 is normal flash
>> content
>> Probing for SST SST49LF004C, 512 kB: probe_82802ab: id1 0x14, id2 0x8c,
>> id1 parity violation, id1 is normal flash content, id2 is normal flash
>> content
>>
>> Probing for SST SST49LF008A, 1024 kB: probe_jedec_common: id1 0x4e, id2
>> 0x56, id1 parity violation, id1 is normal flash content, id2 is normal flash
>> content
>> Probing for SST SST49LF008C, 1024 kB: probe_82802ab: id1 0x4e, id2 0x56,
>> id1 parity violation, id1 is normal flash content, id2 is normal flash
>> content
>> Probing for SST SST49LF016C, 2048 kB: Chip size 2048 kB is bigger than
>> supported size 1024 kB of chipset/board/programmer for FWH interface,
>> probe/read/erase/write may fail. probe_82802ab: id1 0xff, id2 0xff, id1
>> parity violation, id1 is normal flash content, id2 is normal flash content
>> Probing for ST M50FLW040A, 512 kB: probe_82802ab: id1 0x14, id2 0x8c, id1
>> parity violation, id1 is normal flash content, id2 is normal flash content
>> Probing for ST M50FLW040B, 512 kB: probe_82802ab: id1 0x14, id2 0x8c, id1
>> parity violation, id1 is normal flash content, id2 is normal flash content
>>
>> Probing for ST M50FLW080A, 1024 kB: probe_82802ab: id1 0x4e, id2 0x56, id1
>> parity violation, id1 is normal flash content, id2 is normal flash content
>> Probing for ST M50FLW080B, 1024 kB: probe_82802ab: id1 0x4e, id2 0x56, id1
>> parity violation, id1 is normal flash content, id2 is normal flash content
>> Probing for ST M50FW002, 256 kB: probe_82802ab: id1 0x41, id2 0x4d, id1
>> parity violation, id1 is normal flash content, id2 is normal flash content
>> Probing for ST M50FW016, 2048 kB: Chip size 2048 kB is bigger than
>> supported size 1024 kB of chipset/board/programmer for FWH interface,
>> probe/read/erase/write may fail. probe_82802ab: id1 0xff, id2 0xff, id1
>> parity violation, id1 is normal flash content, id2 is normal flash content
>> Probing for ST M50FW040, 512 kB: probe_82802ab: id1 0x14, id2 0x8c, id1
>> parity violation, id1 is normal flash content, id2 is normal flash content
>>
>> Probing for ST M50FW080, 1024 kB: probe_82802ab: id1 0x4e, id2 0x56, id1
>> parity violation, id1 is normal flash content, id2 is normal flash content
>> Probing for Winbond W39V040FA, 512 kB: probe_jedec_common: id1 0x14, id2
>> 0x8c, id1 parity violation, id1 is normal flash content, id2 is normal flash
>> content
>> Probing for Winbond W39V040FB, 512 kB: probe_jedec_common: id1 0x14, id2
>> 0x8c, id1 parity violation, id1 is normal flash content, id2 is normal flash
>> content
>> Probing for Winbond W39V040FC, 512 kB: probe_jedec_common: id1 0x14, id2
>> 0x8c, id1 parity violation, id1 is normal flash content, id2 is normal flash
>> content
>>
>> Probing for Winbond W49V002FA, 256 kB: probe_jedec_common: id1 0x41, id2
>> 0x4d, id1 parity violation, id1 is normal flash content, id2 is normal flash
>> content
>> Probing for Winbond W39V080FA, 1024 kB: probe_jedec_common: id1 0x4e, id2
>> 0x56, id1 parity violation, id1 is normal flash content, id2 is normal flash
>> content
>> Probing for Winbond W39V080FA (dual mode), 512 kB: probe_jedec_common: id1
>> 0x14, id2 0x8c, id1 parity violation, id1 is normal flash content, id2 is
>> normal flash content
>>
>> Found Programmer flash chip "Opaque flash chip" (8192 kB,
>> Programmer-specific).
>> No operations were specified.
>> Restoring MMIO space at 0xb77908a0
>> Restoring MMIO space at 0xb779089c
>> Restoring MMIO space at 0xb7790898
>> Restoring MMIO space at 0xb7790896
>> Restoring MMIO space at 0xb7790894
>>
>> Restoring PCI config space for 00:1f:0 reg 0xdc
>> >>
>
>
> Disabled:
>>
>> ^[[A%
>> >> sudo flashrom -p internal -VV
>> [sudo] password for vladislavbyk:
>> flashrom v0.9.6.1-r1564 on Linux 3.5.4-1-ARCH (i686)
>> flashrom is free software, get the source code at http://www.flashrom.org
>>
>> flashrom was built with libpci 3.1.10, GCC 4.7.1 20120721 (prerelease),
>> little endian
>> Command line (3 args): flashrom -p internal -VV
>> Calibrating delay loop... OS timer resolution is 1 usecs, 1328M loops per
>> second, 10 myus = 9 us, 100 myus = 96 us, 1000 myus = 1083 us, 10000 myus =
>> 9907 us, 4 myus = 3 us, OK.
>>
>> Initializing internal programmer
>> No coreboot table found.
>> DMI string system-manufacturer: "To Be Filled By O.E.M."
>> DMI string system-product-name: "To Be Filled By O.E.M."
>> DMI string system-version: "To Be Filled By O.E.M."
>> DMI string baseboard-manufacturer: "Foxconn"
>> DMI string baseboard-product-name: "H55MX-S Series"
>> DMI string baseboard-version: "1.1"
>> DMI string chassis-type: "Desktop"
>> Found ITE Super I/O, ID 0x8720 on port 0x2e
>> Found chipset "Intel H55" with PCI ID 8086:3b06. Enabling flash write...
>> 0xfff80000/0xffb80000 FWH IDSEL: 0x0
>> 0xfff00000/0xffb00000 FWH IDSEL: 0x0
>> 0xffe80000/0xffa80000 FWH IDSEL: 0x1
>> 0xffe00000/0xffa00000 FWH IDSEL: 0x1
>> 0xffd80000/0xff980000 FWH IDSEL: 0x2
>> 0xffd00000/0xff900000 FWH IDSEL: 0x2
>> 0xffc80000/0xff880000 FWH IDSEL: 0x3
>> 0xffc00000/0xff800000 FWH IDSEL: 0x3
>> 0xff700000/0xff300000 FWH IDSEL: 0x4
>> 0xff600000/0xff200000 FWH IDSEL: 0x5
>> 0xff500000/0xff100000 FWH IDSEL: 0x6
>> 0xff400000/0xff000000 FWH IDSEL: 0x7
>> 0xfff80000/0xffb80000 FWH decode enabled
>> 0xfff00000/0xffb00000 FWH decode enabled
>> 0xffe80000/0xffa80000 FWH decode disabled
>> 0xffe00000/0xffa00000 FWH decode disabled
>> 0xffd80000/0xff980000 FWH decode disabled
>> 0xffd00000/0xff900000 FWH decode disabled
>> 0xffc80000/0xff880000 FWH decode disabled
>> 0xffc00000/0xff800000 FWH decode disabled
>> 0xff700000/0xff300000 FWH decode disabled
>> 0xff600000/0xff200000 FWH decode disabled
>> 0xff500000/0xff100000 FWH decode disabled
>> 0xff400000/0xff000000 FWH decode disabled
>> Maximum FWH chip size: 0x100000 bytes
>> BIOS Lock Enable: disabled, BIOS Write Enable: disabled, BIOS_CNTL is 0x8
>> Root Complex Register Block address = 0xfed1c000
>> GCS = 0xc64: BIOS Interface Lock-Down: disabled, Boot BIOS Straps: 0x3
>> (SPI)
>> Top Swap : not enabled
>> SPIBAR = 0xfed1c000 + 0x3800
>> 0x04: 0x4008 (HSFS)
>> HSFS: FDONE=0, FCERR=0, AEL=0, BERASE=1, SCIP=0, FDOPSS=0, FDV=1,
>> FLOCKDN=0
>> The Flash Descriptor Security Override Strap-Pin is set. Restrictions
>> implied
>> by the FRAP and FREG registers are NOT in effect. Please note that
>> Protected
>> Range (PR) restrictions still apply.
>> Programming OPCODES...
>> program_opcodes: preop=5006 optype=463b opmenu=05d80302c79f0190
>> done
>> OP Type Pre-OP
>> op[0]: 0x02, write w/ addr, none
>> op[1]: 0x03, read w/ addr, none
>> op[2]: 0xd8, write w/ addr, none
>> op[3]: 0x05, read w/o addr, none
>> op[4]: 0x90, read w/ addr, none
>> op[5]: 0x01, write w/o addr, none
>> op[6]: 0x9f, read w/o addr, none
>> op[7]: 0xc7, write w/o addr, none
>> Pre-OP 0: 0x06, Pre-OP 1: 0x50
>>
>> 0x06: 0x0000 (HSFC)
>> HSFC: FGO=0, FCYCLE=0, FDBC=0, SME=0
>> 0x08: 0x00000000 (FADDR)
>> 0x50: 0x0000ffff (FRAP)
>> BMWAG 0x00, BMRAG 0x00, BRWA 0xff, BRRA 0xff
>> 0x54: 0x00000000 FREG0: Flash Descriptor region (0x00000000-0x00000fff) is
>> read-write.
>> 0x58: 0x07ff0700 FREG1: BIOS region (0x00700000-0x007fffff) is read-write.
>> 0x5C: 0x06ff0001 FREG2: Management Engine region (0x00001000-0x006fffff)
>> is read-write.
>> 0x60: 0x00001fff FREG3: Gigabit Ethernet region is unused.
>> 0x64: 0x00001fff FREG4: Platform Data region is unused.
>> 0x74: 0x00000000 (PR0 is unused)
>> 0x78: 0x00000000 (PR1 is unused)
>> 0x7C: 0x00000000 (PR2 is unused)
>> 0x80: 0x00000000 (PR3 is unused)
>> 0x84: 0x00000000 (PR4 is unused)
>>
>> 0x90: 0x00 (SSFS)
>> SSFS: SCIP=0, FDONE=0, FCERR=0, AEL=0
>> 0x91: 0xf84200 (SSFC)
>> SSFC: SCGO=0, ACS=0, SPOP=0, COP=0, DBC=2, SME=0, SCF=0
>> 0x94: 0x5006 (PREOP)
>> 0x96: 0x463b (OPTYPE)
>> 0x98: 0x05d80302 (OPMENU)
>> 0x9C: 0xc79f0190 (OPMENU+4)
>> 0xA0: 0x00000000 (BBAR)
>> 0xC4: 0x00000000 (LVSCC)
>> LVSCC: BES=0x0, WG=0, WSR=0, WEWS=0, EO=0x0, VCL=0
>> 0xC8: 0x00002001 (UVSCC)
>> UVSCC: BES=0x1, WG=0, WSR=0, WEWS=0, EO=0x20, VCL=0
>> 0xD0: 0x00000000 (FPB)
>>
>> Reading flash descriptors mapped by the chipset via FDOC/FDOD... done.
>> === Content Section ===
>> FLVALSIG 0x0ff0a55a
>> FLMAP0 0x02040102
>> FLMAP1 0x10100206
>> FLMAP2 0x00000020
>>
>> --- Details ---
>> NR (Number of Regions): 3
>> FRBA (Flash Region Base Address): 0x040
>> NC (Number of Components): 2
>> FCBA (Flash Component Base Address): 0x020
>> ISL (ICH/PCH Strap Length): 16
>> FISBA/FPSBA (Flash ICH/PCH Strap Base Address): 0x100
>> NM (Number of Masters): 3
>> FMBA (Flash Master Base Address): 0x060
>> MSL/PSL (MCH/PROC Strap Length): 0
>> FMSBA (Flash MCH/PROC Strap Base Address): 0x200
>>
>> === Component Section ===
>> FLCOMP 0x0930001b
>> FLILL 0x00000000
>>
>> --- Details ---
>> Component 1 density: 4 MB
>> Component 2 density: 4 MB
>> Read Clock Frequency: 20 MHz
>> Read ID and Status Clock Freq.: 33 MHz
>> Write and Erase Clock Freq.: 33 MHz
>> Fast Read is supported.
>> Fast Read Clock Frequency: 33 MHz
>> No forbidden opcodes.
>>
>> === Region Section ===
>> FLREG0 0x00000000
>> FLREG1 0x07ff0700
>> FLREG2 0x06ff0001
>> FLREG3 0x00001fff
>>
>> --- Details ---
>> Region 0 (Descr.) 0x00000000 - 0x00000fff
>> Region 1 (BIOS ) 0x00700000 - 0x007fffff
>> Region 2 (ME ) 0x00001000 - 0x006fffff
>> Region 3 (GbE ) is unused.
>>
>> === Master Section ===
>> FLMSTR1 0x0a0b0000
>> FLMSTR2 0x0c0d0000
>> FLMSTR3 0x08080118
>>
>> --- Details ---
>> Descr. BIOS ME GbE Platf.
>> BIOS r rw rw
>> ME r rw rw
>> GbE rw
>>
>> Enabling hardware sequencing due to multiple flash chips detected.
>> SPI Read Configuration: prefetching enabled, caching enabled, OK.
>> No IT87* serial flash segment enabled.
>> The following protocols are supported: FWH, Programmer-specific.
>> Probing for Programmer Opaque flash chip, 0 kB: Found 2 attached SPI flash
>> chips with a combined density of 8192 kB.
>> There is only one partition containing the whole address space (0x000000 -
>> 0x7fffff).
>> There are 2048 erase blocks with 4096 B each.
>> Found Programmer flash chip "Opaque flash chip" (8192 kB,
>> Programmer-specific) at physical address 0x0.
>> Probing for Atmel AT49LH002, 256 kB: probe_82802ab: id1 0x41, id2 0x4d,
>> id1 parity violation, id1 is normal flash content, id2 is normal flash
>> content
>> Probing for Intel 82802AB, 512 kB: probe_82802ab: id1 0x14, id2 0x8c, id1
>> parity violation, id1 is normal flash content, id2 is normal flash content
>>
>> Probing for Intel 82802AC, 1024 kB: probe_82802ab: id1 0x4e, id2 0x56, id1
>> parity violation, id1 is normal flash content, id2 is normal flash content
>> Probing for PMC Pm49FL002, 256 kB: probe_jedec_common: id1 0x41, id2 0x4d,
>> id1 parity violation, id1 is normal flash content, id2 is normal flash
>> content
>> Probing for PMC Pm49FL004, 512 kB: probe_jedec_common: id1 0x14, id2 0x8c,
>> id1 parity violation, id1 is normal flash content, id2 is normal flash
>> content
>>
>> Probing for Sharp LHF00L04, 1024 kB: probe_82802ab: id1 0x4e, id2 0x56,
>> id1 parity violation, id1 is normal flash content, id2 is normal flash
>> content
>> Probing for SST SST49LF002A/B, 256 kB: probe_jedec_common: id1 0x41, id2
>> 0x4d, id1 parity violation, id1 is normal flash content, id2 is normal flash
>> content
>> Probing for SST SST49LF003A/B, 384 kB: probe_jedec_common: id1 0x02, id2
>> 0x00, id1 is normal flash content, id2 is normal flash content
>> Probing for SST SST49LF004A/B, 512 kB: probe_jedec_common: id1 0x14, id2
>> 0x8c, id1 parity violation, id1 is normal flash content, id2 is normal flash
>> content
>> Probing for SST SST49LF004C, 512 kB: probe_82802ab: id1 0x14, id2 0x8c,
>> id1 parity violation, id1 is normal flash content, id2 is normal flash
>> content
>>
>> Probing for SST SST49LF008A, 1024 kB: probe_jedec_common: id1 0x4e, id2
>> 0x56, id1 parity violation, id1 is normal flash content, id2 is normal flash
>> content
>> Probing for SST SST49LF008C, 1024 kB: probe_82802ab: id1 0x4e, id2 0x56,
>> id1 parity violation, id1 is normal flash content, id2 is normal flash
>> content
>> Probing for SST SST49LF016C, 2048 kB: Chip size 2048 kB is bigger than
>> supported size 1024 kB of chipset/board/programmer for FWH interface,
>> probe/read/erase/write may fail. probe_82802ab: id1 0xff, id2 0xff, id1
>> parity violation, id1 is normal flash content, id2 is normal flash content
>> Probing for ST M50FLW040A, 512 kB: probe_82802ab: id1 0x14, id2 0x8c, id1
>> parity violation, id1 is normal flash content, id2 is normal flash content
>> Probing for ST M50FLW040B, 512 kB: probe_82802ab: id1 0x14, id2 0x8c, id1
>> parity violation, id1 is normal flash content, id2 is normal flash content
>>
>> Probing for ST M50FLW080A, 1024 kB: probe_82802ab: id1 0x4e, id2 0x56, id1
>> parity violation, id1 is normal flash content, id2 is normal flash content
>> Probing for ST M50FLW080B, 1024 kB: probe_82802ab: id1 0x4e, id2 0x56, id1
>> parity violation, id1 is normal flash content, id2 is normal flash content
>> Probing for ST M50FW002, 256 kB: probe_82802ab: id1 0x41, id2 0x4d, id1
>> parity violation, id1 is normal flash content, id2 is normal flash content
>> Probing for ST M50FW016, 2048 kB: Chip size 2048 kB is bigger than
>> supported size 1024 kB of chipset/board/programmer for FWH interface,
>> probe/read/erase/write may fail. probe_82802ab: id1 0xff, id2 0xff, id1
>> parity violation, id1 is normal flash content, id2 is normal flash content
>> Probing for ST M50FW040, 512 kB: probe_82802ab: id1 0x14, id2 0x8c, id1
>> parity violation, id1 is normal flash content, id2 is normal flash content
>>
>> Probing for ST M50FW080, 1024 kB: probe_82802ab: id1 0x4e, id2 0x56, id1
>> parity violation, id1 is normal flash content, id2 is normal flash content
>> Probing for Winbond W39V040FA, 512 kB: probe_jedec_common: id1 0x14, id2
>> 0x8c, id1 parity violation, id1 is normal flash content, id2 is normal flash
>> content
>> Probing for Winbond W39V040FB, 512 kB: probe_jedec_common: id1 0x14, id2
>> 0x8c, id1 parity violation, id1 is normal flash content, id2 is normal flash
>> content
>> Probing for Winbond W39V040FC, 512 kB: probe_jedec_common: id1 0x14, id2
>> 0x8c, id1 parity violation, id1 is normal flash content, id2 is normal flash
>> content
>>
>> Probing for Winbond W49V002FA, 256 kB: probe_jedec_common: id1 0x41, id2
>> 0x4d, id1 parity violation, id1 is normal flash content, id2 is normal flash
>> content
>> Probing for Winbond W39V080FA, 1024 kB: probe_jedec_common: id1 0x4e, id2
>> 0x56, id1 parity violation, id1 is normal flash content, id2 is normal flash
>> content
>> Probing for Winbond W39V080FA (dual mode), 512 kB: probe_jedec_common: id1
>> 0x14, id2 0x8c, id1 parity violation, id1 is normal flash content, id2 is
>> normal flash content
>>
>> Found Programmer flash chip "Opaque flash chip" (8192 kB,
>> Programmer-specific).
>> No operations were specified.
>> Restoring MMIO space at 0xb77438a0
>> Restoring MMIO space at 0xb774389c
>> Restoring MMIO space at 0xb7743898
>> Restoring MMIO space at 0xb7743896
>> Restoring MMIO space at 0xb7743894
>>
>> Restoring PCI config space for 00:1f:0 reg 0xdc
>
>
> Btw, maybe you have jabber or icq? :) It would be convenient)
No, but you are welcome to join #flashrom on irc.freenode.net
http://flashrom.org/IRC
> 2012/10/2 Stefan Tauner <stefan.tauner(a)student.tuwien.ac.at>
>>
>> On Tue, 2 Oct 2012 17:41:21 +0400
>> Владислав Быков <vladislavbyk1(a)gmail.com> wrote:
>>
>> > Yep, i toggle jumper, it's named MFG. It's should be disable (writed to
>> > mainboard manual) until i start flash.
>>
>> Ok, thanks, can you please run "flashrom -p internal -VV" with the
>> jumper in the previous/untoggled/default position and send us the
>> output? I would like to know if/how the contents of the registers
>> change by this exactly. This is not clearly documented publicly by
>> Intel but might be helpful to us in the future.
>>
>> --
>> Kind regards/Mit freundlichen Grüßen, Stefan Tauner
>
>
>
> _______________________________________________
> flashrom mailing list
> flashrom(a)flashrom.org
> http://www.flashrom.org/mailman/listinfo/flashrom
1
0
On Tue, 2 Oct 2012 17:41:21 +0400
Владислав Быков <vladislavbyk1(a)gmail.com> wrote:
> Yep, i toggle jumper, it's named MFG. It's should be disable (writed to
> mainboard manual) until i start flash.
Ok, thanks, can you please run "flashrom -p internal -VV" with the
jumper in the previous/untoggled/default position and send us the
output? I would like to know if/how the contents of the registers
change by this exactly. This is not clearly documented publicly by
Intel but might be helpful to us in the future.
--
Kind regards/Mit freundlichen Grüßen, Stefan Tauner
2
1
On Tue, 2 Oct 2012 06:49:30 +0400
Владислав Быков <vladislavbyk1(a)gmail.com> wrote:
> Yiiiha! 996F1P07 work! Thank you very-very-very much! :)
Great, i hope it does also boot afterwards ;)
I have added your board to our list of supported boards and will commit
this later together with other small changes.
just one additional question…
> Found chipset "Intel H55". Enabling flash write... The Flash Descriptor
> Security Override Strap-Pin is set. Restrictions implied
> by the FRAP and FREG registers are NOT in effect. Please note that Protected
> Range (PR) restrictions still apply.
This "Flash Descriptor Security Override Strap" setting caught my
interest. This is configured by a physical pin of the chipset and
Intel's documentation very clearly recommends that there is no way to
enable it on shipped consumer boards (not to speak of making it the
default), it is just for debugging. My question is: did you notice a
jumper on the board that might influence this (maybe labelled "write
protection" or similar) or is there an option in the "BIOS" setup to
change this?
--
Kind regards/Mit freundlichen Grüßen, Stefan Tauner
2
1