Add lock bit handling (printing, setting and checking) to SST FWH chips and abort any writes to locked sectors. Verbose mode gives you all the info. Normal mode only tells you of unlocking failed, but gives enough details to debug.
Add a comment about flash register placement to flashrom.c.
Thanks to Uwe for testing multiple iterations of this patch.
Signed-off-by: Carl-Daniel Hailfinger c-d.hailfinger.devel.2006@gmx.net
Index: flashrom-sst_fwhub_lockbits/sst_fwhub.c =================================================================== --- flashrom-sst_fwhub_lockbits/sst_fwhub.c (Revision 491) +++ flashrom-sst_fwhub_lockbits/sst_fwhub.c (Arbeitskopie) @@ -35,23 +35,79 @@ printf("%s", status & 0x2 ? "WP|TBL#|WP#,ABORT:" : "UNLOCK:"); }
+int check_sst_fwhub_block_lock(struct flashchip *flash, int offset) +{ + volatile uint8_t *registers = flash->virtual_registers; + uint8_t blockstatus; + + blockstatus = chip_readb(registers + offset + 2); + printf_debug("Lock status for 0x%06x (size 0x%06x) is %02x, ", + offset, flash->page_size, blockstatus); + switch (blockstatus & 0x3) { + case 0x0: + printf_debug("full access\n"); + break; + case 0x1: + printf_debug("write locked\n"); + break; + case 0x2: + printf_debug("locked open\n"); + break; + case 0x3: + printf_debug("write locked down\n"); + break; + } + /* Return content of the write_locked bit */ + return blockstatus & 0x1; +} + +int clear_sst_fwhub_block_lock(struct flashchip *flash, int offset) +{ + volatile uint8_t *registers = flash->virtual_registers; + uint8_t blockstatus; + + blockstatus = check_sst_fwhub_block_lock(flash, offset); + + if (blockstatus) { + printf_debug("Trying to clear lock for 0x%06x... ", offset) + chip_writeb(0, registers + offset + 2); + + blockstatus = check_sst_fwhub_block_lock(flash, offset); + if (blockstatus) { + printf_debug("failed\n"); + } else { + printf_debug("OK\n"); + } + } + + return blockstatus; +} + /* probe_jedec works fine for probing */ int probe_sst_fwhub(struct flashchip *flash) { + int i; + if (probe_jedec(flash) == 0) return 0;
map_flash_registers(flash);
+ for (i = 0; i < flash->total_size * 1024; i += flash->page_size) + check_sst_fwhub_block_lock(flash, i); + return 1; }
int erase_sst_fwhub_block(struct flashchip *flash, int offset) { - volatile uint8_t *wrprotect = flash->virtual_registers + offset + 2; + uint8_t blockstatus = clear_sst_fwhub_block_lock(flash, offset);
- // clear write protect - chip_writeb(0, wrprotect); + if (blockstatus) { + printf("Block lock clearing failed, not erasing block " + "at 0x%06x\n", offset); + return 1; + }
erase_block_jedec(flash->virtual_memory, offset); toggle_ready_jedec(flash->virtual_memory); @@ -85,6 +141,7 @@ int total_size = flash->total_size * 1024; int page_size = flash->page_size; volatile uint8_t *bios = flash->virtual_memory; + uint8_t blockstatus;
// FIXME: We want block wide erase instead of ironing the whole chip if (erase_sst_fwhub(flash)) @@ -93,6 +150,11 @@ printf("Programming page: "); for (i = 0; i < total_size / page_size; i++) { printf("%04d at address: 0x%08x", i, i * page_size); + blockstatus = clear_sst_fwhub_block_lock(flash, i * page_size); + if (blockstatus) { + printf(" is locked down permanently, aborting\n"); + return 1; + } write_sector_jedec(bios, buf + i * page_size, bios + i * page_size, page_size); printf("\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b"); Index: flashrom-sst_fwhub_lockbits/flashrom.c =================================================================== --- flashrom-sst_fwhub_lockbits/flashrom.c (Revision 491) +++ flashrom-sst_fwhub_lockbits/flashrom.c (Arbeitskopie) @@ -65,6 +65,7 @@ void map_flash_registers(struct flashchip *flash) { size_t size = flash->total_size * 1024; + /* Flash registers live 4 MByte below the flash. */ flash->virtual_registers = physmap("flash chip registers", (0xFFFFFFFF - 0x400000 - size + 1), size); }
nice. I have no way to test -- can you verify this has worked on real hardware?
Thanks
ron
On Mon, May 11, 2009 at 04:56:05AM +0200, Carl-Daniel Hailfinger wrote:
Add lock bit handling (printing, setting and checking) to SST FWH chips and abort any writes to locked sectors. Verbose mode gives you all the info. Normal mode only tells you of unlocking failed, but gives enough details to debug.
Add a comment about flash register placement to flashrom.c.
Thanks to Uwe for testing multiple iterations of this patch.
Signed-off-by: Carl-Daniel Hailfinger c-d.hailfinger.devel.2006@gmx.net
Acked-by: Uwe Hermann uwe@hermann-uwe.de
As noted above, I've tested this on my hardware.
+int clear_sst_fwhub_block_lock(struct flashchip *flash, int offset) +{
- volatile uint8_t *registers = flash->virtual_registers;
- uint8_t blockstatus;
- blockstatus = check_sst_fwhub_block_lock(flash, offset);
- if (blockstatus) {
printf_debug("Trying to clear lock for 0x%06x... ", offset)
chip_writeb(0, registers + offset + 2);
blockstatus = check_sst_fwhub_block_lock(flash, offset);
if (blockstatus) {
printf_debug("failed\n");
} else {
printf_debug("OK\n");
}
I find this nicer for short and simple if's like this one:
printf_debug("%s\n", (blockstatus) ? "failed" : "OK");
Either is fine though, if you prefer the 5-line version.
Uwe.
On 11.05.2009 15:53, Uwe Hermann wrote:
On Mon, May 11, 2009 at 04:56:05AM +0200, Carl-Daniel Hailfinger wrote:
Add lock bit handling (printing, setting and checking) to SST FWH chips and abort any writes to locked sectors. Verbose mode gives you all the info. Normal mode only tells you of unlocking failed, but gives enough details to debug.
Add a comment about flash register placement to flashrom.c.
Thanks to Uwe for testing multiple iterations of this patch.
Signed-off-by: Carl-Daniel Hailfinger c-d.hailfinger.devel.2006@gmx.net
Acked-by: Uwe Hermann uwe@hermann-uwe.de
As noted above, I've tested this on my hardware.
Thanks, committed in r492.
+int clear_sst_fwhub_block_lock(struct flashchip *flash, int offset) +{
- volatile uint8_t *registers = flash->virtual_registers;
- uint8_t blockstatus;
- blockstatus = check_sst_fwhub_block_lock(flash, offset);
- if (blockstatus) {
printf_debug("Trying to clear lock for 0x%06x... ", offset)
chip_writeb(0, registers + offset + 2);
blockstatus = check_sst_fwhub_block_lock(flash, offset);
if (blockstatus) {
printf_debug("failed\n");
} else {
printf_debug("OK\n");
}
I find this nicer for short and simple if's like this one:
printf_debug("%s\n", (blockstatus) ? "failed" : "OK");
Either is fine though, if you prefer the 5-line version.
Ah yes, that was a remainder from earlier versions of the patch. Thanks for noticing. I changed it.
Regards, Carl-Daniel