Sergii Dmytruk has uploaded this change for review. ( https://review.coreboot.org/c/flashrom/+/59710 )
Change subject: [RFC][OTP] dummyflasher: implement SCUR and OTP for MX25L6436 ......................................................................
[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