diff --git a/82802ab.c b/82802ab.c index 1316939..3aa76b4 100644 --- a/82802ab.c +++ b/82802ab.c @@ -195,13 +195,62 @@ int write_82802ab(struct flashchip *flash, uint8_t *buf) /* erase block by block and write block by block; this is the most secure way */ if (erase_block_82802ab(flash, i * page_size, page_size)) { fprintf(stderr, "ERASE FAILED!\n"); return -1; } write_page_82802ab(bios, buf + i * page_size, bios + i * page_size, page_size); } printf("\n"); free(tmpbuf); return 0; } + +int unlock_28f004s5(struct flashrom *flash) +{ + chipaddr bios = flash->virtual_memory; + uint8_t mcfg, bcfg, need_unlock = 0, can_unlock = 0; + + /* Clear status register */ + chip_writeb(0x50, bios); + + /* Read identifier codes */ + chip_writeb(0x90, bios); + + /* Read master lock-bit */ + mcfg = chip_readb(bios + 0x3); + msg_cinfo("master lock is "); + if (mcfg) { + msg_cdbg("locked!\n"); + } else { + msg_cdbg("unlocked!\n"); + can_unlock = 1; + } + + /* Read block lock-bits */ + for (i = 0; i < flash->total_size * 1024; i+= (64 * 1024)) { + bcfg = chip_readb(bios + i + 2); // read block lock config + msg_cdbg("block lock at %06x is %slocked!\n", i, bcfg ? "" : "un"); + if (bcfg) { + need_unlock = 1; + } + } + + /* Reset chip */ + chip_writeb(0xFF, bios); + + /* Unlock: clear block lock-bits, if needed */ + if (can_unlock && need_unlock) { + chip_writeb(0x60, bios); + chip_writeb(0xD0, bios); + chip_writeb(0xFF, bios); + } + + /* Error: master locked or a block is locked */ + if (!can_unlock && need_unlock) { + msg_cerr("At least one block is locked and lockdown is active!\n"); + return -1; + } + + return 0; +} diff --git a/flashchips.c b/flashchips.c index 35f75a6..802f51a 100644 --- a/flashchips.c +++ b/flashchips.c @@ -2306,90 +2306,89 @@ struct flashchip flashchips[] = { }, .write = write_coreboot_m29f400bt, .read = read_memmapped, }, { .vendor = "Intel", .name = "28F001BX-B", .bustype = CHIP_BUSTYPE_PARALLEL, .manufacture_id = INTEL_ID, .model_id = P28F001BXB, .total_size = 128, .page_size = 128 * 1024, /* 8k + 2x4k + 112k */ - .tested = TEST_BAD_WRITE, + .tested = TEST_UNTESTED, .probe = probe_jedec, .probe_timing = TIMING_ZERO, /* Datasheet has no timing info specified */ .block_erasers = { { .eraseblocks = { {8 * 1024, 1}, {4 * 1024, 2}, {112 * 1024, 1}, }, .block_erase = erase_block_82802ab, }, }, - .write = NULL, + .write = write_82802ab, .read = read_memmapped, }, { .vendor = "Intel", .name = "28F001BX-T", .bustype = CHIP_BUSTYPE_PARALLEL, .manufacture_id = INTEL_ID, .model_id = P28F001BXT, .total_size = 128, .page_size = 128 * 1024, /* 112k + 2x4k + 8k */ - .tested = TEST_BAD_WRITE, + .tested = TEST_UNTESTED, .probe = probe_jedec, .probe_timing = TIMING_ZERO, /* Datasheet has no timing info specified */ .block_erasers = { { .eraseblocks = { {112 * 1024, 1}, {4 * 1024, 2}, {8 * 1024, 1}, }, .block_erase = erase_block_82802ab, }, }, - .write = NULL, + .write = write_82802ab, .read = read_memmapped, }, { .vendor = "Intel", .name = "28F004S5", .bustype = CHIP_BUSTYPE_PARALLEL, .manufacture_id = INTEL_ID, .model_id = E_28F004S5, .total_size = 512, .page_size = 256, - .feature_bits = FEATURE_REGISTERMAP, .tested = TEST_UNTESTED, .probe = probe_82802ab, .probe_timing = TIMING_ZERO, /* Datasheet has no timing info specified */ .block_erasers = { { .eraseblocks = { {64 * 1024, 8} }, .block_erase = erase_block_82802ab, }, }, - .unlock = unlock_82802ab, + .unlock = unlock_28f004s5, .write = write_82802ab, .read = read_memmapped, }, { .vendor = "Intel", .name = "82802AB", .bustype = CHIP_BUSTYPE_FWH, .manufacture_id = INTEL_ID, .model_id = I_82802AB, .total_size = 512, .page_size = 64 * 1024, .feature_bits = FEATURE_REGISTERMAP,