Sergii Dmytruk has uploaded this change for review.
[RFC][OTP] dummyflasher: implement SCUR and OTP for MX25L6436
The chip has OTP mode, but state of OTP is stored in a security
register.
Additions:
* spi_scur parameter for dummyflasher to configure initial state of
security register
* commands for entering/leaving OTP mode (ENSO, EXSO)
* commands for reading/writing secure register (RDSCUR, WRSCUR)
Change-Id: I13716d597d305351ec27d532e9020615c397693a
Signed-off-by: Sergii Dmytruk <sergii.dmytruk@3mdeb.com>
---
M dummyflasher.c
M flashrom.8.tmpl
M spi.h
3 files changed, 84 insertions(+), 5 deletions(-)
git pull ssh://review.coreboot.org:29418/flashrom refs/changes/10/59710/1
diff --git a/dummyflasher.c b/dummyflasher.c
index e758075..31eb6db 100644
--- a/dummyflasher.c
+++ b/dummyflasher.c
@@ -34,7 +34,7 @@
EMULATE_ST_M25P10_RES, /* SR1 */
EMULATE_SST_SST25VF040_REMS, /* SR1 */
EMULATE_SST_SST25VF032B, /* SR1, SFDP */
- EMULATE_MACRONIX_MX25L6436, /* SR1 */
+ EMULATE_MACRONIX_MX25L6436, /* SR1, SCUR, OTP (mode) */
EMULATE_WINBOND_W25Q128FV, /* SR1-2, OTP (sec. regs) */
EMULATE_VARIABLE_SIZE, /* SR1 */
EMULATE_EON_EN25QH128, /* SR1, OTP (mode) */
@@ -49,6 +49,7 @@
uint8_t emu_status;
uint8_t emu_status2;
uint8_t emu_status_len; /* number of emulated status bytes */
+ uint8_t emu_scur; /* security register */
/* If "freq" parameter is passed in from command line, commands will delay
* for this period before returning. */
unsigned long int delay_us;
@@ -285,13 +286,19 @@
* allowed in current state. Returns zero if everything is fine. */
static int validate_otp_sector_op(struct emu_data *data, unsigned int offs, bool read_op)
{
- assert(data->emu_chip == EMULATE_EON_EN25QH128);
+ assert(data->emu_chip == EMULATE_EON_EN25QH128 ||
+ data->emu_chip == EMULATE_MACRONIX_MX25L6436);
if (!read_op && data->otp_locked) {
msg_perr("OTP is locked, cannot change contents of OTP sector anymore\n");
return 1;
}
- if ((offs & 0xfff) >= 0x200 && (offs >> 12) != 0xfff) {
+ if ((offs & 0xfff) >= 0x200) {
+ msg_perr("OTP address out of range: 0x%jx\n", (uintmax_t)offs);
+ return 1;
+ }
+ /* MX25L6436 doesn't care about the values of high 12 bits. */
+ if (data->emu_chip == EMULATE_EON_EN25QH128 && (offs >> 12) != 0xfff) {
msg_perr("OTP address out of range: 0x%jx\n", (uintmax_t)offs);
return 1;
}
@@ -852,6 +859,32 @@
data->otp_mode = true;
msg_pdbg("Entered OTP mode...\n");
break;
+ case JEDEC_ENSO: /* enter OTP for Macronix/Adesto chips */
+ if (data->emu_chip != EMULATE_MACRONIX_MX25L6436)
+ break;
+ data->otp_mode = true;
+ msg_pdbg("Entered OTP mode...\n");
+ break;
+ case JEDEC_EXSO: /* exit OTP for Macronix/Adesto chips */
+ if (data->emu_chip != EMULATE_MACRONIX_MX25L6436)
+ break;
+ data->otp_mode = false;
+ msg_pdbg("Left OTP mode...\n");
+ break;
+ case JEDEC_RDSCUR:
+ if (data->emu_chip != EMULATE_MACRONIX_MX25L6436)
+ break;
+ memset(readarr, data->emu_scur, readcnt);
+ break;
+ case JEDEC_WRSCUR:
+ if (data->emu_chip != EMULATE_MACRONIX_MX25L6436)
+ break;
+ /* Can't use this command in OTP mode. */
+ if (data->otp_mode)
+ break;
+ data->emu_scur |= 0x02; /* LDSO bit */
+ data->otp_locked = true;
+ break;
default:
/* No special response. */
break;
@@ -971,6 +1004,7 @@
unsigned int i;
char *endptr;
char *status = NULL;
+ char *scur = NULL;
int size = -1; /* size for VARIABLE_SIZE chip device */
bustext = extract_programmer_param("bus");
@@ -1217,8 +1251,10 @@
data->emu_jedec_be_d8_size = 64 * 1024;
data->emu_jedec_ce_60_size = data->emu_chip_size;
data->emu_jedec_ce_c7_size = data->emu_chip_size;
+ data->otp_region_count = 1;
+ data->otp_region_size = 512;
msg_pdbg("Emulating Macronix MX25L6436 SPI flash chip (RDID, "
- "SFDP)\n");
+ "SFDP, OTP)\n");
}
if (!strcmp(tmp, "W25Q128FV")) {
data->emu_chip = EMULATE_WINBOND_W25Q128FV;
@@ -1327,6 +1363,28 @@
}
}
+ scur = extract_programmer_param("spi_scur");
+ if (scur) {
+ uint8_t value;
+
+ errno = 0;
+ value = strtoul(scur, &endptr, 0);
+ if (errno != 0 || scur == endptr || *endptr != '\0') {
+ free(scur);
+ msg_perr("Error: initial security register specified, "
+ "but the value could not be converted.\n");
+ return 1;
+ }
+ free(scur);
+
+ data->emu_scur = value;
+ if (data->emu_chip == EMULATE_MACRONIX_MX25L6436)
+ data->otp_locked = ((value & 0x3) != 0);
+
+ msg_pdbg("Initial security register is set to 0x%02x.\n",
+ data->emu_scur);
+ }
+
data->flashchip_contents = malloc(data->emu_chip_size);
if (!data->flashchip_contents) {
msg_perr("Out of memory!\n");
diff --git a/flashrom.8.tmpl b/flashrom.8.tmpl
index a2433ca..cd2a9c9 100644
--- a/flashrom.8.tmpl
+++ b/flashrom.8.tmpl
@@ -735,7 +735,7 @@
.sp
.RB "* SST " SST25VF032B " SPI flash chip (4096 kB, RDID, AAI write)"
.sp
-.RB "* Macronix " MX25L6436 " SPI flash chip (8192 kB, RDID, SFDP)"
+.RB "* Macronix " MX25L6436 " SPI flash chip (8192 kB, RDID, SFDP, SCUR, OTP)"
.sp
.RB "* Winbond " W25Q128FV " SPI flash chip (16384 kB, RDID, OTP)"
.sp
@@ -839,6 +839,17 @@
is an 8-bit or 16-bit hexadecimal value.
.sp
.TP
+.B SPI security register (SCUR)
+.sp
+You can specify the initial content of the chip's security register with the
+.sp
+.B " flashrom -p dummy:spi_scur=content"
+.sp
+syntax where
+.B content
+is an 8-bit hexadecimal value.
+.sp
+.TP
.B Write protection
.sp
Chips with emulated WP: W25Q128FV.
diff --git a/spi.h b/spi.h
index 07d131d..267bd30 100644
--- a/spi.h
+++ b/spi.h
@@ -204,6 +204,16 @@
#define JEDEC_ENTER_OTP_OUTSIZE 0x01
#define JEDEC_ENTER_OTP_INSIZE 0x00
+/* Enter secured OTP mode (Macronix and Adesto chips) */
+#define JEDEC_ENSO 0xB1
+#define JEDEC_ENSO_OUTSIZE 0x01
+#define JEDEC_ENSO_INSIZE 0x00
+
+/* Exit secured OTP mode (Macronix and Adesto chips) */
+#define JEDEC_EXSO 0xC1
+#define JEDEC_EXSO_OUTSIZE 0x01
+#define JEDEC_EXSO_INSIZE 0x00
+
/* Read Security Register(s) (supported by most GigaDevice chips) */
#define JEDEC_READ_SEC_REG 0x48
#define JEDEC_READ_SEC_REG_OUTSIZE 0x05
To view, visit change 59710. To unsubscribe, or for help writing mail filters, visit settings.