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 <[email protected]>

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 [email protected]\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 <[email protected]>
  * Copyright (C) 2009 Sean Nelson <[email protected]>
+ * 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__ */


-- 
http://www.hailfinger.org/


_______________________________________________
flashrom mailing list
[email protected]
http://www.flashrom.org/mailman/listinfo/flashrom

Reply via email to