summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--flash.h1
-rw-r--r--flashchips.c69
-rw-r--r--flashrom.813
-rw-r--r--flashrom.c7
4 files changed, 62 insertions, 28 deletions
diff --git a/flash.h b/flash.h
index e51b6d4..20db343 100644
--- a/flash.h
+++ b/flash.h
@@ -83,6 +83,7 @@ enum chipbustype {
#define FEATURE_ADDR_SHIFTED (1 << 5)
#define FEATURE_WRSR_EWSR (1 << 6)
#define FEATURE_WRSR_WREN (1 << 7)
+#define FEATURE_OTP (1 << 8)
#define FEATURE_WRSR_EITHER (FEATURE_WRSR_EWSR | FEATURE_WRSR_WREN)
struct flashctx;
diff --git a/flashchips.c b/flashchips.c
index ca1c57f..c6bff8d 100644
--- a/flashchips.c
+++ b/flashchips.c
@@ -1120,7 +1120,8 @@ const struct flashchip flashchips[] = {
.model_id = AMIC_A25L032,
.total_size = 4096,
.page_size = 256,
- .feature_bits = FEATURE_WRSR_WREN,
+ /* OTP: 64B total; read 0x4B, 0x48; write 0x42 */
+ .feature_bits = FEATURE_WRSR_WREN | FEATURE_OTP,
.tested = TEST_UNTESTED,
.probe = probe_spi_rdid,
.probe_timing = TIMING_ZERO,
@@ -1158,7 +1159,8 @@ const struct flashchip flashchips[] = {
.model_id = AMIC_A25LQ032,
.total_size = 4096,
.page_size = 256,
- .feature_bits = FEATURE_WRSR_WREN,
+ /* OTP: 64B total; read 0x4B, 0x48; write 0x42 */
+ .feature_bits = FEATURE_WRSR_WREN | FEATURE_OTP,
.tested = TEST_UNTESTED,
.probe = probe_spi_rdid,
.probe_timing = TIMING_ZERO,
@@ -1315,7 +1317,8 @@ const struct flashchip flashchips[] = {
.model_id = ATMEL_AT25DF021,
.total_size = 256,
.page_size = 256,
- .feature_bits = FEATURE_WRSR_WREN,
+ /* OTP: 128B total, 64B pre-programmed; read 0x77; write 0x9B */
+ .feature_bits = FEATURE_WRSR_WREN | FEATURE_OTP,
.tested = TEST_UNTESTED,
.probe = probe_spi_rdid,
.probe_timing = TIMING_ZERO,
@@ -1543,7 +1546,8 @@ const struct flashchip flashchips[] = {
.model_id = ATMEL_AT25DF321A,
.total_size = 4096,
.page_size = 256,
- .feature_bits = FEATURE_WRSR_WREN,
+ /* OTP: 128B total, 64B pre-programmed; read 0x77; write 0x9B */
+ .feature_bits = FEATURE_WRSR_WREN | FEATURE_OTP,
.tested = TEST_OK_PROBE,
.probe = probe_spi_rdid,
.probe_timing = TIMING_ZERO,
@@ -1619,7 +1623,8 @@ const struct flashchip flashchips[] = {
.model_id = ATMEL_AT25DQ161,
.total_size = 2048,
.page_size = 256,
- .feature_bits = FEATURE_WRSR_WREN,
+ /* OTP: 128B total, 64B pre-programmed; read 0x77; write 0x9B */
+ .feature_bits = FEATURE_WRSR_WREN | FEATURE_OTP,
.tested = TEST_UNTESTED,
.probe = probe_spi_rdid,
.probe_timing = TIMING_ZERO,
@@ -1657,7 +1662,8 @@ const struct flashchip flashchips[] = {
.model_id = ATMEL_AT25F512B,
.total_size = 64,
.page_size = 256,
- .feature_bits = FEATURE_WRSR_WREN,
+ /* OTP: 128B total, 64B pre-programmed; read 0x77; write 0x9B */
+ .feature_bits = FEATURE_WRSR_WREN | FEATURE_OTP,
.tested = TEST_UNTESTED,
.probe = probe_spi_rdid,
.probe_timing = TIMING_ZERO,
@@ -2168,6 +2174,8 @@ const struct flashchip flashchips[] = {
.model_id = ATMEL_AT45DB321D,
.total_size = 4096 /* Size can only be determined from status register */,
.page_size = 512 /* Size can only be determined from status register */,
+ /* OTP: 128B total, 64B pre-programmed; read 0x77; write 0x9B */
+ .feature_bits = FEATURE_OTP,
.tested = TEST_BAD_READ,
.probe = probe_spi_rdid,
.probe_timing = TIMING_ZERO,
@@ -3236,8 +3244,8 @@ const struct flashchip flashchips[] = {
.model_id = EON_EN25Q40,
.total_size = 512,
.page_size = 256,
- /* TODO: chip features 256-byte one-time programmable region */
- .feature_bits = FEATURE_WRSR_WREN,
+ /* OTP: 256B total; enter 0x3A */
+ .feature_bits = FEATURE_WRSR_WREN | FEATURE_OTP,
.tested = TEST_UNTESTED,
.probe = probe_spi_rdid,
.probe_timing = TIMING_ZERO,
@@ -3271,8 +3279,8 @@ const struct flashchip flashchips[] = {
.model_id = EON_EN25Q80,
.total_size = 1024,
.page_size = 256,
- /* TODO: chip features 256-byte one-time programmable region */
- .feature_bits = FEATURE_WRSR_WREN,
+ /* OTP: 256B total; enter 0x3A */
+ .feature_bits = FEATURE_WRSR_WREN | FEATURE_OTP,
.tested = TEST_UNTESTED,
.probe = probe_spi_rdid,
.probe_timing = TIMING_ZERO,
@@ -3308,9 +3316,8 @@ const struct flashchip flashchips[] = {
.model_id = EON_EN25Q16,
.total_size = 2048,
.page_size = 256,
- /* TODO: EN25D16 features 512-byte one-time programmable region,
- * EN25Q16 features a 128-byte one-time programmable region */
- .feature_bits = FEATURE_WRSR_WREN,
+ /* OTP: D16 512B/Q16 128B total; enter 0x3A */
+ .feature_bits = FEATURE_WRSR_WREN | FEATURE_OTP,
.tested = TEST_UNTESTED,
.probe = probe_spi_rdid,
.probe_timing = TIMING_ZERO,
@@ -3348,8 +3355,8 @@ const struct flashchip flashchips[] = {
.model_id = EON_EN25Q32,
.total_size = 4096,
.page_size = 256,
- /* TODO: chip features 512-byte one-time programmable region */
- .feature_bits = FEATURE_WRSR_WREN,
+ /* OTP: 512B total; enter 0x3A */
+ .feature_bits = FEATURE_WRSR_WREN | FEATURE_OTP,
.tested = TEST_UNTESTED,
.probe = probe_spi_rdid,
.probe_timing = TIMING_ZERO,
@@ -3383,8 +3390,8 @@ const struct flashchip flashchips[] = {
.model_id = EON_EN25Q64,
.total_size = 8192,
.page_size = 256,
- /* TODO: chip features 512-byte one-time programmable region */
- .feature_bits = FEATURE_WRSR_WREN,
+ /* OTP: 512B total; enter 0x3A */
+ .feature_bits = FEATURE_WRSR_WREN | FEATURE_OTP,
.tested = TEST_UNTESTED,
.probe = probe_spi_rdid,
.probe_timing = TIMING_ZERO,
@@ -3418,8 +3425,8 @@ const struct flashchip flashchips[] = {
.model_id = EON_EN25Q128,
.total_size = 16384,
.page_size = 256,
- /* TODO: chip features 512-byte one-time programmable region */
- .feature_bits = FEATURE_WRSR_WREN,
+ /* OTP: 512B total; enter 0x3A */
+ .feature_bits = FEATURE_WRSR_WREN | FEATURE_OTP,
.tested = TEST_UNTESTED,
.probe = probe_spi_rdid,
.probe_timing = TIMING_ZERO,
@@ -3452,10 +3459,9 @@ const struct flashchip flashchips[] = {
.model_id = EON_EN25QH16,
.total_size = 2048,
.page_size = 256,
- /* TODO: chip features 512-byte one-time programmable region
- * and supports SFDP.
- */
- .feature_bits = FEATURE_WRSR_WREN,
+ /* supports SFDP */
+ /* OTP: 512B total; enter 0x3A */
+ .feature_bits = FEATURE_WRSR_WREN | FEATURE_OTP,
.tested = TEST_UNTESTED,
.probe = probe_spi_rdid,
.probe_timing = TIMING_ZERO,
@@ -7092,6 +7098,8 @@ const struct flashchip flashchips[] = {
.model_id = ST_M25PX16,
.total_size = 2048,
.page_size = 256,
+ /* OTP: 64B total; read 0x4B; write 0x42 */
+ .feature_bits = FEATURE_OTP,
.tested = TEST_OK_PREW,
.probe = probe_spi_rdid,
.probe_timing = TIMING_ZERO,
@@ -7960,7 +7968,8 @@ const struct flashchip flashchips[] = {
.model_id = WINBOND_NEX_W25Q80,
.total_size = 1024,
.page_size = 256,
- .feature_bits = FEATURE_WRSR_WREN,
+ /* OTP: 1024B total, 256B reserved; read 0x48; write 0x42 */
+ .feature_bits = FEATURE_WRSR_WREN | FEATURE_OTP,
.tested = TEST_OK_PREW,
.probe = probe_spi_rdid,
.probe_timing = TIMING_ZERO,
@@ -7997,7 +8006,8 @@ const struct flashchip flashchips[] = {
.model_id = WINBOND_NEX_W25Q16,
.total_size = 2048,
.page_size = 256,
- .feature_bits = FEATURE_WRSR_WREN,
+ /* OTP: 1024B total, 256B reserved; read 0x48; write 0x42 */
+ .feature_bits = FEATURE_WRSR_WREN | FEATURE_OTP,
.tested = TEST_OK_PREW,
.probe = probe_spi_rdid,
.probe_timing = TIMING_ZERO,
@@ -8034,7 +8044,8 @@ const struct flashchip flashchips[] = {
.model_id = WINBOND_NEX_W25Q32,
.total_size = 4096,
.page_size = 256,
- .feature_bits = FEATURE_WRSR_WREN,
+ /* OTP: 1024B total, 256B reserved; read 0x48; write 0x42 */
+ .feature_bits = FEATURE_WRSR_WREN | FEATURE_OTP,
.tested = TEST_OK_PREW,
.probe = probe_spi_rdid,
.probe_timing = TIMING_ZERO,
@@ -8071,7 +8082,8 @@ const struct flashchip flashchips[] = {
.model_id = WINBOND_NEX_W25Q64,
.total_size = 8192,
.page_size = 256,
- .feature_bits = FEATURE_WRSR_WREN,
+ /* OTP: 1024B total, 256B reserved; read 0x48; write 0x42 */
+ .feature_bits = FEATURE_WRSR_WREN | FEATURE_OTP,
.tested = TEST_OK_PREW,
.probe = probe_spi_rdid,
.probe_timing = TIMING_ZERO,
@@ -8107,7 +8119,8 @@ const struct flashchip flashchips[] = {
.model_id = WINBOND_NEX_W25Q128,
.total_size = 16384,
.page_size = 256,
- .feature_bits = FEATURE_WRSR_WREN,
+ /* OTP: 1024B total, 256B reserved; read 0x48; write 0x42 */
+ .feature_bits = FEATURE_WRSR_WREN | FEATURE_OTP,
.tested = TEST_OK_PROBE,
.probe = probe_spi_rdid,
.probe_timing = TIMING_ZERO,
diff --git a/flashrom.8 b/flashrom.8
index 2f23cb8..e5f9a29 100644
--- a/flashrom.8
+++ b/flashrom.8
@@ -670,6 +670,19 @@ and flashrom will attempt to detect it and abort immediately for safety reasons.
More information about flashrom on laptops is available from
.sp
.B " http://www.flashrom.org/Laptops"
+.SS
+One-time programmable (OTP) memory and unique IDs
+.sp
+Some flash chips contain OTP memory often denoted as "security registers".
+They usually have a capacity in the range of some bytes to a few hundred
+bytes and can be used to give devices unique IDs etc. flashrom is not able
+to read or write these memories and may therefore not be able to duplicate a
+chip completely. For chip types known to include OTP memories a warning is
+printed when they are detected.
+.sp
+Similar to OTP memories are unique, factory programmed, unforgeable IDs.
+They are not modifiable by the user at all.
+.RE
.SH LICENSE
.B flashrom
is covered by the GNU General Public License (GPL), version 2. Some files are
diff --git a/flashrom.c b/flashrom.c
index ee68344..a378e51 100644
--- a/flashrom.c
+++ b/flashrom.c
@@ -1560,6 +1560,13 @@ int selfcheck(void)
void check_chip_supported(const struct flashctx *flash)
{
+ if (flash->feature_bits & FEATURE_OTP) {
+ msg_cdbg("This chip may contain one-time programmable memory. "
+ "flashrom cannot read\nand may never be able to write "
+ "it, hence it may not be able to completely\n"
+ "clone the contents of this chip (see man page for "
+ "details).\n");
+ }
if (TEST_OK_MASK != (flash->tested & TEST_OK_MASK)) {
msg_cinfo("===\n");
if (flash->tested & TEST_BAD_MASK) {
OpenPOWER on IntegriCloud