summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorCarl-Daniel Hailfinger <c-d.hailfinger.devel.2006@gmx.net>2009-05-11 14:01:17 +0000
committerCarl-Daniel Hailfinger <c-d.hailfinger.devel.2006@gmx.net>2009-05-11 14:01:17 +0000
commitbf3c90962f49ddc070f632aacc30ee4970162f14 (patch)
treea0e8389cfb6d9bbb8ec7710858dff2bbd8d678b8
parent86815600d9b51687621410c75b863cf82519750d (diff)
downloadflashrom-bf3c90962f49ddc070f632aacc30ee4970162f14.zip
flashrom-bf3c90962f49ddc070f632aacc30ee4970162f14.tar.gz
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. Corresponding to flashrom svn r492. Signed-off-by: Carl-Daniel Hailfinger <c-d.hailfinger.devel.2006@gmx.net> Acked-by: Uwe Hermann <uwe@hermann-uwe.de>
-rw-r--r--flashrom.c1
-rw-r--r--sst_fwhub.c64
2 files changed, 62 insertions, 3 deletions
diff --git a/flashrom.c b/flashrom.c
index d7f4479..981d835 100644
--- a/flashrom.c
+++ b/flashrom.c
@@ -65,6 +65,7 @@ const struct programmer_entry programmer_table[] = {
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);
}
diff --git a/sst_fwhub.c b/sst_fwhub.c
index ab541e4..0bf2d4d 100644
--- a/sst_fwhub.c
+++ b/sst_fwhub.c
@@ -35,23 +35,75 @@ void print_sst_fwhub_status(uint8_t status)
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);
+ printf_debug("%s\n", (blockstatus) ? "failed" : "OK");
+ }
+
+ 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 +137,7 @@ int write_sst_fwhub(struct flashchip *flash, uint8_t *buf)
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 +146,11 @@ int write_sst_fwhub(struct flashchip *flash, uint8_t *buf)
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");
OpenPOWER on IntegriCloud