Index: flash.h =================================================================== --- flash.h (revision 906) +++ flash.h (working copy) @@ -200,18 +200,20 @@ */ struct block_eraser { struct eraseblock{ unsigned int size; /* Eraseblock size */ unsigned int count; /* Number of contiguous blocks with that size */ } eraseblocks[NUM_ERASEREGIONS]; int (*block_erase) (struct flashchip *flash, unsigned int blockaddr, unsigned int blocklen); } block_erasers[NUM_ERASEFUNCTIONS]; + int (*printlock) (struct flashchip *flash); + int (*unlock) (struct flashchip *flash); int (*write) (struct flashchip *flash, uint8_t *buf); int (*read) (struct flashchip *flash, uint8_t *buf, int start, int len); /* Some flash devices have an additional register space. */ chipaddr virtual_memory; chipaddr virtual_registers; }; #define TEST_UNTESTED 0 Index: sst49lfxxxc.c =================================================================== --- sst49lfxxxc.c (revision 906) +++ sst49lfxxxc.c (working copy) @@ -76,18 +76,23 @@ address += 8192; printf_debug("lockbits at address=0x%08lx is 0x%01x\n", registers + address + 2, chip_readb(registers + address + 2)); chip_writeb(bits, registers + address + 2); return 0; } +int unlock_49lfxxxc(struct flashchip *flash) +{ + return write_lockbits_49lfxxxc(flash, 0); +} + int erase_sector_49lfxxxc(struct flashchip *flash, unsigned int address, unsigned int sector_size) { unsigned char status; chipaddr bios = flash->virtual_memory; chip_writeb(SECTOR_ERASE, bios); chip_writeb(ERASE, bios + address); do { Index: Makefile =================================================================== --- Makefile (revision 906) +++ Makefile (working copy) @@ -35,19 +35,19 @@ ifeq ($(OS_ARCH), Darwin) CPPFLAGS += -I/opt/local/include -I/usr/local/include LDFLAGS += -framework IOKit -framework DirectIO -L/opt/local/lib -L/usr/local/lib endif ifeq ($(OS_ARCH), FreeBSD) CPPFLAGS += -I/usr/local/include LDFLAGS += -L/usr/local/lib endif -CHIP_OBJS = jedec.o stm50flw0x0x.o w39v080fa.o sharplhf00l04.o w29ee011.o \ +CHIP_OBJS = jedec.o stm50flw0x0x.o w39v040c.o w39v080fa.o sharplhf00l04.o w29ee011.o \ sst28sf040.o m29f400bt.o 82802ab.o pm49fl00x.o \ sst49lfxxxc.o sst_fwhub.o flashchips.o spi.o LIB_OBJS = layout.o CLI_OBJS = flashrom.o cli_classic.o cli_output.o print.o PROGRAMMER_OBJS = udelay.o programmer.o Index: w39v040c.c =================================================================== --- w39v040c.c (revision 906) +++ w39v040c.c (working copy) @@ -44,18 +44,44 @@ programmer_delay(10); chip_writeb(0xF0, bios + 0x5555); programmer_delay(40); printf("%s: Boot block #TBL is %slocked, rest of chip #WP is %slocked.\n", __func__, lock & 0x4 ? "" : "un", lock & 0x8 ? "" : "un"); return 1; } +int printlock_w39v040c(struct flashchip *flash) +{ + chipaddr bios = flash->virtual_memory; + uint8_t lock; + + chip_writeb(0xAA, bios + 0x5555); + programmer_delay(10); + chip_writeb(0x55, bios + 0x2AAA); + programmer_delay(10); + chip_writeb(0x90, bios + 0x5555); + programmer_delay(10); + + lock = chip_readb(bios + 0xfff2); + + chip_writeb(0xAA, bios + 0x5555); + programmer_delay(10); + chip_writeb(0x55, bios + 0x2AAA); + programmer_delay(10); + chip_writeb(0xF0, bios + 0x5555); + programmer_delay(40); + + printf("%s: Boot block #TBL is %slocked, rest of chip #WP is %slocked.\n", + __func__, lock & 0x4 ? "" : "un", lock & 0x8 ? "" : "un"); + return 1; +} + int erase_w39v040c(struct flashchip *flash) { int i; unsigned int total_size = flash->total_size * 1024; for (i = 0; i < total_size; i += flash->page_size) { if (erase_sector_jedec(flash, i, flash->page_size)) { fprintf(stderr, "ERASE FAILED!\n"); return -1; Index: pm49fl00x.c =================================================================== --- pm49fl00x.c (revision 906) +++ pm49fl00x.c (working copy) @@ -30,18 +30,24 @@ for (i = 0; left >= block_size; i++, left -= block_size) { /* pm49fl002 */ if (block_size == 16384 && i % 2) continue; chip_writeb(bits, bios + (i * block_size) + 2); } } +int unlock_49fl00x(struct flashchip *flash) +{ + write_lockbits_49fl00x(flash->virtual_registers, flash->total_size * 1024, 0, flash->page_size); + return 0; +} + int erase_49fl00x(struct flashchip *flash) { int i; int total_size = flash->total_size * 1024; int page_size = flash->page_size; /* unprotected */ write_lockbits_49fl00x(flash->virtual_registers, total_size, 0, page_size); Index: flashchips.c =================================================================== --- flashchips.c (revision 906) +++ flashchips.c (working copy) @@ -43,18 +43,20 @@ * .page_size = Page or eraseblock(?) size in bytes * .tested = Test status * .probe = Probe function * .probe_timing = Probe function delay * .block_erasers[] = Array of erase layouts and erase functions * { * .eraseblocks[] = Array of { blocksize, blockcount } * .block_erase = Block erase function * } + * .printstatus = Chip lock status function + * .unlock = Chip unlock function * .write = Chip write function * .read = Chip read function */ { .vendor = "AMD", .name = "Am29F010A/B", .bustype = CHIP_BUSTYPE_PARALLEL, .manufacture_id = AMD_ID, @@ -3324,62 +3326,62 @@ .bustype = CHIP_BUSTYPE_LPC | CHIP_BUSTYPE_FWH, /* A/A Mux*/ .manufacture_id = PMC_ID_NOPREFIX, .model_id = PMC_49FL002, .total_size = 256, .page_size = 16 * 1024, .feature_bits = FEATURE_REGISTERMAP | FEATURE_EITHER_RESET, .tested = TEST_UNTESTED, .probe = probe_jedec, .probe_timing = TIMING_ZERO, /* routine is wrapper to probe_jedec (pm49fl00x.c) */ - /* .erase = NULL, Was: erase_49fl00x */ .block_erasers = { { .eraseblocks = { {4 * 1024, 64} }, .block_erase = erase_sector_jedec, }, { .eraseblocks = { {16 * 1024, 16} }, .block_erase = erase_block_jedec, }, { .eraseblocks = { {256 * 1024, 1} }, .block_erase = erase_chip_block_jedec, } }, + .unlock = unlock_49fl00x, .write = write_49fl00x, .read = read_memmapped, }, { .vendor = "PMC", .name = "Pm49FL004", .bustype = CHIP_BUSTYPE_LPC | CHIP_BUSTYPE_FWH, /* A/A Mux*/ .manufacture_id = PMC_ID_NOPREFIX, .model_id = PMC_49FL004, .total_size = 512, .page_size = 64 * 1024, .feature_bits = FEATURE_REGISTERMAP | FEATURE_EITHER_RESET, .tested = TEST_UNTESTED, .probe = probe_jedec, .probe_timing = TIMING_ZERO, /* routine is wrapper to probe_jedec (pm49fl00x.c) */ - /* .erase = NULL, Was: erase_49fl00x */ .block_erasers = { { .eraseblocks = { {4 * 1024, 128} }, .block_erase = erase_sector_jedec, }, { .eraseblocks = { {64 * 1024, 8} }, .block_erase = erase_block_jedec, }, { .eraseblocks = { {512 * 1024, 1} }, .block_erase = erase_chip_block_jedec, } }, + .unlock = unlock_49fl00x, .write = write_49fl00x, .read = read_memmapped, }, { .vendor = "Sanyo", .name = "LF25FW203A", .bustype = CHIP_BUSTYPE_SPI, .manufacture_id = SANYO_ID, @@ -4400,34 +4402,34 @@ .bustype = CHIP_BUSTYPE_LPC, .manufacture_id = SST_ID, .model_id = SST_49LF160C, .total_size = 2048, .page_size = 4 * 1024, .feature_bits = 0, .tested = TEST_OK_PRW, .probe = probe_49lfxxxc, .probe_timing = TIMING_IGNORED, /* routine don't use probe_timing (sst49lfxxxc.c) */ - /* .erase = NULL, Was: erase_49flxxxc */ .block_erasers = { { .eraseblocks = { {4 * 1024, 512} }, .block_erase = erase_sector_49lfxxxc, }, { .eraseblocks = { {64 * 1024, 31}, {32 * 1024, 1}, {8 * 1024, 2}, {16 * 1024, 1}, }, .block_erase = erase_block_49lfxxxc, } }, + .unlock = unlock_49lfxxxc, .write = write_49lfxxxc, .read = read_memmapped, }, { .vendor = "ST", .name = "M25P05-A", .bustype = CHIP_BUSTYPE_SPI, .manufacture_id = ST_ID, @@ -5734,29 +5736,29 @@ .bustype = CHIP_BUSTYPE_LPC, .manufacture_id = WINBOND_ID, .model_id = W_39V040C, .total_size = 512, .page_size = 64 * 1024, .feature_bits = FEATURE_EITHER_RESET, .tested = TEST_UNTESTED, .probe = probe_jedec, .probe_timing = TIMING_FIXME, - /* .erase = NULL, Was erase_w39v040c */ .block_erasers = { { .eraseblocks = { {64 * 1024, 8} }, .block_erase = erase_sector_jedec, }, { .eraseblocks = { {512 * 1024, 1} }, .block_erase = erase_chip_block_jedec, } }, + .printlock = printlock_w39v040c, .write = write_jedec_1, .read = read_memmapped, }, { .vendor = "Winbond", .name = "W39V040FA", .bustype = CHIP_BUSTYPE_FWH, .manufacture_id = WINBOND_ID, @@ -5909,56 +5911,56 @@ .bustype = CHIP_BUSTYPE_FWH, .manufacture_id = WINBOND_ID, .model_id = W_39V080FA, .total_size = 1024, .page_size = 64 * 1024, .feature_bits = FEATURE_REGISTERMAP | FEATURE_EITHER_RESET, .tested = TEST_UNTESTED, .probe = probe_jedec, .probe_timing = TIMING_FIXME, - /* .erase = NULL, Was erase_winbond_fwhub */ .block_erasers = { { .eraseblocks = { {64 * 1024, 16}, }, .block_erase = erase_sector_jedec, }, { .eraseblocks = { {1024 * 1024, 1} }, .block_erase = erase_chip_block_jedec, } }, + .unlock = unlock_winbond_fwhub, .write = write_jedec_1, .read = read_memmapped, }, { .vendor = "Winbond", .name = "W39V080FA (dual mode)", .bustype = CHIP_BUSTYPE_FWH, .manufacture_id = WINBOND_ID, .model_id = W_39V080FA_DM, .total_size = 512, .page_size = 64 * 1024, .feature_bits = FEATURE_REGISTERMAP | FEATURE_EITHER_RESET, .tested = TEST_UNTESTED, .probe = probe_jedec, .probe_timing = TIMING_FIXME, - /* .erase = NULL, Was erase_winbond_fwhub */ .block_erasers = { { .eraseblocks = { {64 * 1024, 8}, }, .block_erase = erase_sector_jedec, }, { .eraseblocks = { {512 * 1024, 1} }, .block_erase = erase_chip_block_jedec, } }, + .unlock = unlock_winbond_fwhub, .write = write_jedec_1, .read = read_memmapped, }, { .vendor = "Atmel", .name = "unknown Atmel SPI chip", .bustype = CHIP_BUSTYPE_SPI, .manufacture_id = ATMEL_ID, Index: flashrom.c =================================================================== --- flashrom.c (revision 906) +++ flashrom.c (working copy) @@ -832,18 +832,19 @@ } if (!flash || !flash->name) return NULL; printf("Found chip \"%s %s\" (%d KB, %s) at physical address 0x%lx.\n", flash->vendor, flash->name, flash->total_size, flashbuses_to_text(flash->bustype), base); + flash->printlock(flash); return flash; } int verify_flash(struct flashchip *flash, uint8_t *buf) { int ret; int total_size = flash->total_size * 1024; printf("Verifying flash... "); @@ -1130,18 +1131,20 @@ uint8_t *buf; unsigned long numbytes; FILE *image; int ret = 0; unsigned long size; size = flash->total_size * 1024; buf = (uint8_t *) calloc(size, sizeof(char)); + flash->unlock(flash); + if (erase_it) { if (flash->tested & TEST_BAD_ERASE) { fprintf(stderr, "Erase is not working on this chip. "); if (!force) { fprintf(stderr, "Aborting.\n"); programmer_shutdown(); return 1; } else { fprintf(stderr, "Continuing anyway.\n"); Index: chipdrivers.h =================================================================== --- chipdrivers.h (revision 906) +++ chipdrivers.h (working copy) @@ -111,18 +111,19 @@ int erase_29f002(struct flashchip *flash); int erase_chip_29f002(struct flashchip *flash, unsigned int addr, unsigned int blocklen); int erase_sector_29f002(struct flashchip *flash, unsigned int address, unsigned int blocklen); int write_29f002(struct flashchip *flash, uint8_t *buf); /* pm49fl00x.c */ int probe_49fl00x(struct flashchip *flash); int erase_49fl00x(struct flashchip *flash); int write_49fl00x(struct flashchip *flash, uint8_t *buf); +int unlock_49fl00x(struct flashchip *flash); /* sharplhf00l04.c */ int probe_lhf00l04(struct flashchip *flash); int erase_lhf00l04_block(struct flashchip *flash, unsigned int blockaddr, unsigned int blocklen); int write_lhf00l04(struct flashchip *flash, uint8_t *buf); void protect_lhf00l04(chipaddr bios); /* sst28sf040.c */ int probe_28sf040(struct flashchip *flash); @@ -139,35 +140,38 @@ int write_49lf040(struct flashchip *flash, uint8_t *buf); /* sst49lfxxxc.c */ int probe_49lfxxxc(struct flashchip *flash); int erase_49lfxxxc(struct flashchip *flash); int erase_sector_49lfxxxc(struct flashchip *flash, unsigned int address, unsigned int sector_size); int erase_block_49lfxxxc(struct flashchip *flash, unsigned int address, unsigned int sector_size); int erase_chip_49lfxxxc(struct flashchip *flash, unsigned int addr, unsigned int blocksize); int write_49lfxxxc(struct flashchip *flash, uint8_t *buf); +int unlock_49lfxxxc(struct flashchip *flash); /* sst_fwhub.c */ int probe_sst_fwhub(struct flashchip *flash); int erase_sst_fwhub(struct flashchip *flash); int erase_sst_fwhub_block(struct flashchip *flash, unsigned int offset, unsigned int page_size); int erase_sst_fwhub_sector(struct flashchip *flash, unsigned int offset, unsigned int page_size); int write_sst_fwhub(struct flashchip *flash, uint8_t *buf); /* w39v040c.c */ int probe_w39v040c(struct flashchip *flash); int erase_w39v040c(struct flashchip *flash); int write_w39v040c(struct flashchip *flash, uint8_t *buf); +int printlock_w39v040c(struct flashchip *flash); /* w39V080fa.c */ int probe_winbond_fwhub(struct flashchip *flash); int erase_winbond_fwhub(struct flashchip *flash); int write_winbond_fwhub(struct flashchip *flash, uint8_t *buf); +int unlock_winbond_fwhub(struct flashchip *flash); /* w29ee011.c */ int probe_w29ee011(struct flashchip *flash); /* w49f002u.c */ int write_49f002(struct flashchip *flash, uint8_t *buf); /* stm50flw0x0x.c */ int probe_stm50flw0x0x(struct flashchip *flash);