Am 12.09.2011 20:12 schrieb Carl-Daniel Hailfinger:
Unlock ST M50FW002 correctly
Refactor ST M50 family unlocking
TODO: Unify write_lockbits_49fl00x() and unlock_block_stm50() and unlock_w39_fwh_block() and unlock_82802ab() and write_lockbits_block_49lfxxxc(). They all use exactly the same mechanism, but they don't share any code.
Refactor locking for all chips with locking at register space address +2
Unlock ST M50FW002 correctly. Refactor Winbond W39*, ST M50*, PMC Pm49*, SST 49LF00*, ... locking
Signed-off-by: Carl-Daniel Hailfinger c-d.hailfinger.devel.2006@gmx.net
Index: flashrom-82802ab_lock_refactor/w39.c =================================================================== --- flashrom-82802ab_lock_refactor/w39.c (Revision 1437) +++ flashrom-82802ab_lock_refactor/w39.c (Arbeitskopie) @@ -21,7 +21,10 @@
#include "flash.h"
-static int printlock_w39_fwh_block(struct flashchip *flash, int offset) +#define RWLOCK ((1 << 2) | (1 << 0)) +#define LOCKDOWN (1 << 1) + +static int printlock_regspace2_block(struct flashchip *flash, int offset) { chipaddr wrprotect = flash->virtual_registers + offset + 2; uint8_t locking; @@ -56,30 +59,67 @@ }
/* Read or write lock present? */ - return (locking & ((1 << 2) | (1 << 0))) ? -1 : 0; + return (locking & RWLOCK) ? -1 : 0; }
-static int unlock_w39_fwh_block(struct flashchip *flash, int offset) +int changelock_regspace2_block(struct flashchip *flash, int offset, uint8_t bits) { chipaddr wrprotect = flash->virtual_registers + offset + 2; uint8_t locking;
+ if (bits & 0xf8) { + msg_cerr("Invalid locking change 0x%02x requested at 0x%08x! " + "Please report a bug at flashrom@flashrom.org\n", + bits, offset); + return -1; + } locking = chip_readb(wrprotect); - /* Read or write lock present? */ - if (locking & ((1 << 2) | (1 << 0))) { + /* Did we request a change of read/write/lockdown? */ + if (((locking ^ bits) & (RWLOCK | LOCKDOWN)) == 0) { + msg_cdbg2("Locking status at 0x%08x not changed\n", offset); + return 0; + } + /* Change read or write lock? */ + if ((locking ^ bits) & RWLOCK) { /* Lockdown active? */ - if (locking & (1 << 1)) { - msg_cerr("Can't unlock block at 0x%08x!\n", offset); + if (locking & LOCKDOWN) { + msg_cerr("Can't change locking status at 0x%08x due to " + "lockdown!\n", offset); return -1; } else { - msg_cdbg("Unlocking block at 0x%08x\n", offset); - chip_writeb(0, wrprotect); + /* Do not lockdown yet. */ + msg_cdbg("Changing locking status at 0x%08x\n", offset); + chip_writeb(bits & RWLOCK, wrprotect); + if (chip_readb(wrprotect) != (bits & RWLOCK)) { + msg_cerr("Locking status change FAILED at " + "0x%08x!\n", offset); + return -1; + } } } + if ((locking & LOCKDOWN) && !(bits & LOCKDOWN)) { + msg_cerr("Lockdown can't be removed at 0x%08x!\n", offset); + /* FIXME: Is this really an error? */ + return -1; + } + if (!(locking & LOCKDOWN) && (bits & LOCKDOWN)) { + msg_cdbg("Enabling lockdown at 0x%08x\n", offset); + chip_writeb(bits, wrprotect); + if (chip_readb(wrprotect) != (bits)) { + msg_cerr("Lockdown status change FAILED at " + "0x%08x!\n", offset); + return -1; + } + }
return 0; }
+static int unlock_w39_fwh_block(struct flashchip *flash, int offset) +{ + return changelock_regspace2_block(flash, offset, 0x00); +} + static uint8_t w39_idmode_readb(struct flashchip *flash, int offset) { chipaddr bios = flash->virtual_memory; @@ -143,7 +183,7 @@ /* Print lock status of the complete chip */ for (i = 0; i < total_size; i += flash->page_size) - ret |= printlock_w39_fwh_block(flash, i); + ret |= printlock_regspace2_block(flash, i);
return ret; } Index: flashrom-82802ab_lock_refactor/sst49lfxxxc.c =================================================================== --- flashrom-82802ab_lock_refactor/sst49lfxxxc.c (Revision 1437) +++ flashrom-82802ab_lock_refactor/sst49lfxxxc.c (Arbeitskopie) @@ -23,15 +23,6 @@ #include "flash.h" #include "chipdrivers.h"
-static int write_lockbits_block_49lfxxxc(struct flashchip *flash, unsigned long address, unsigned char bits) -{ - unsigned long lock = flash->virtual_registers + address + 2; - msg_cdbg("lockbits at address=0x%08lx is 0x%01x\n", lock, chip_readb(lock)); - chip_writeb(bits, lock); - - return 0; -} - static int write_lockbits_49lfxxxc(struct flashchip *flash, unsigned char bits) { chipaddr registers = flash->virtual_registers; @@ -40,16 +31,16 @@
msg_cdbg("\nbios=0x%08lx\n", registers); for (i = 0; left > 65536; i++, left -= 65536) { - write_lockbits_block_49lfxxxc(flash, i * 65536, bits); + changelock_regspace2_block(flash, i * 65536, bits); } address = i * 65536; - write_lockbits_block_49lfxxxc(flash, address, bits); + changelock_regspace2_block(flash, address, bits); address += 32768; - write_lockbits_block_49lfxxxc(flash, address, bits); + changelock_regspace2_block(flash, address, bits); address += 8192; - write_lockbits_block_49lfxxxc(flash, address, bits); + changelock_regspace2_block(flash, address, bits); address += 8192; - write_lockbits_block_49lfxxxc(flash, address, bits); + changelock_regspace2_block(flash, address, bits);
return 0; } Index: flashrom-82802ab_lock_refactor/82802ab.c =================================================================== --- flashrom-82802ab_lock_refactor/82802ab.c (Revision 1437) +++ flashrom-82802ab_lock_refactor/82802ab.c (Arbeitskopie) @@ -110,10 +110,10 @@ int unlock_82802ab(struct flashchip *flash) { int i; - //chipaddr wrprotect = flash->virtual_registers + page + 2;
for (i = 0; i < flash->total_size * 1024; i+= flash->page_size) - chip_writeb(0, flash->virtual_registers + i + 2); + if (changelock_regspace2_block(flash, i, 0x00)) + return -1;
return 0; } Index: flashrom-82802ab_lock_refactor/pm49fl00x.c =================================================================== --- flashrom-82802ab_lock_refactor/pm49fl00x.c (Revision 1437) +++ flashrom-82802ab_lock_refactor/pm49fl00x.c (Arbeitskopie) @@ -21,29 +21,30 @@ */
#include "flash.h" +#include "chipdrivers.h"
-static void write_lockbits_49fl00x(chipaddr bios, int size, - unsigned char bits, int block_size) +static int write_lockbits_49fl00x(struct flashchip *flash, uint8_t bits, + int block_size) { - int i, left = size; + int i, left = flash->total_size * 1024;
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); + if (changelock_regspace2_block(flash, i * block_size, bits)) + return -1; } + return 0; }
int unlock_49fl00x(struct flashchip *flash) { - write_lockbits_49fl00x(flash->virtual_registers, flash->total_size * 1024, 0, flash->page_size); - return 0; + return write_lockbits_49fl00x(flash, 0, flash->page_size); }
int lock_49fl00x(struct flashchip *flash) { - write_lockbits_49fl00x(flash->virtual_registers, flash->total_size * 1024, 1, flash->page_size); - return 0; + return write_lockbits_49fl00x(flash, 1, flash->page_size); } Index: flashrom-82802ab_lock_refactor/flashchips.c =================================================================== --- flashrom-82802ab_lock_refactor/flashchips.c (Revision 1437) +++ flashrom-82802ab_lock_refactor/flashchips.c (Arbeitskopie) @@ -7523,9 +7523,9 @@ .total_size = 256, .page_size = 64 * 1024, .feature_bits = FEATURE_REGISTERMAP, - .tested = TEST_UNTESTED, + .tested = TEST_OK_PREW, .probe = probe_82802ab, - .probe_timing = TIMING_IGNORED, /* routine doesn't use probe_timing (sst49lfxxxc.c) */ + .probe_timing = TIMING_IGNORED, /* routine doesn't use probe_timing (82802ab.c) */ .block_erasers = { { @@ -7536,9 +7536,12 @@ {16 * 1024, 1}, }, .block_erase = erase_block_82802ab, + }, { + .eraseblocks = { {256 * 1024, 1}, }, + .block_erase = NULL, /* Only in A/A mux mode */ } }, - .unlock = unlock_stm50flw0x0x, + .unlock = unlock_stm50fw002, .write = write_82802ab, .read = read_memmapped, .voltage = {3000, 3600}, /* Also has 12V fast program & erase */ Index: flashrom-82802ab_lock_refactor/stm50flw0x0x.c =================================================================== --- flashrom-82802ab_lock_refactor/stm50flw0x0x.c (Revision 1437) +++ flashrom-82802ab_lock_refactor/stm50flw0x0x.c (Arbeitskopie) @@ -3,6 +3,7 @@ * * Copyright (C) 2008 Claus Gindhart claus.gindhart@kontron.com * Copyright (C) 2009 Sean Nelson audiohacked@gmail.com + * Copyright (C) 2011 Carl-Daniel Hailfinger * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -38,8 +39,6 @@ */ static int unlock_block_stm50flw0x0x(struct flashchip *flash, int offset) { - chipaddr wrprotect = flash->virtual_registers + 2; - static const uint8_t unlock_sector = 0x00; int j;
/* @@ -58,23 +57,11 @@ || (offset == 0xF0000)) {
// unlock each 4k-sector - for (j = 0; j < 0x10000; j += 0x1000) { - msg_cdbg("unlocking at 0x%x\n", offset + j); - chip_writeb(unlock_sector, wrprotect + offset + j); - if (chip_readb(wrprotect + offset + j) != unlock_sector) { - msg_cerr("Cannot unlock sector @ 0x%x\n", - offset + j); + for (j = 0; j < 0x10000; j += 0x1000) + if (changelock_regspace2_block(flash, offset + j, 0x00)) return -1; - } - } - } else { - msg_cdbg("unlocking at 0x%x\n", offset); - chip_writeb(unlock_sector, wrprotect + offset); - if (chip_readb(wrprotect + offset) != unlock_sector) { - msg_cerr("Cannot unlock sector @ 0x%x\n", offset); + } else if (changelock_regspace2_block(flash, offset, 0x00)) return -1; - } - }
return 0; } @@ -84,7 +71,7 @@ int i;
for (i = 0; i < flash->total_size * 1024; i+= flash->page_size) { - if(unlock_block_stm50flw0x0x(flash, i)) { + if (unlock_block_stm50flw0x0x(flash, i)) { msg_cerr("UNLOCK FAILED!\n"); return -1; } @@ -93,6 +80,27 @@ return 0; }
+/* FIXME: Should this be moved to a generic walk_unlockregions()? */ +int unlock_stm50fw002(struct flashchip *flash) +{ + static const struct eraseblock unlockregions[4] = { + {64 * 1024, 3}, + {32 * 1024, 1}, + {8 * 1024, 2}, + {16 * 1024, 1}}; + int i, j; + int addr = 0; + + for (i = 0; i < 4; i++) { + for (j = 0; j < unlockregions[i].count; j++) { + if (changelock_regspace2_block(flash, addr, 0x00)) + return 1; + addr += unlockregions[i].size; + } + } + return 0; +} + /* This function is unused. */ int erase_sector_stm50flw0x0x(struct flashchip *flash, unsigned int sector, unsigned int sectorsize) { Index: flashrom-82802ab_lock_refactor/chipdrivers.h =================================================================== --- flashrom-82802ab_lock_refactor/chipdrivers.h (Revision 1437) +++ flashrom-82802ab_lock_refactor/chipdrivers.h (Arbeitskopie) @@ -139,6 +139,8 @@ int printlock_w39v080fa_dual(struct flashchip *flash); int unlock_w39v040fb(struct flashchip *flash); int unlock_w39v080fa(struct flashchip *flash); +int printlock_regspace2_block(struct flashchip *flash, int offset); +int changelock_regspace2_block(struct flashchip *flash, int offset, uint8_t bits);
/* w29ee011.c */ int probe_w29ee011(struct flashchip *flash); @@ -146,5 +148,6 @@ /* stm50flw0x0x.c */ int erase_sector_stm50flw0x0x(struct flashchip *flash, unsigned int block, unsigned int blocksize); int unlock_stm50flw0x0x(struct flashchip *flash); +int unlock_stm50fw002(struct flashchip *flash);
#endif /* !__CHIPDRIVERS_H__ */