Commit ef3ac8ac authored by Carl-Daniel Hailfinger's avatar Carl-Daniel Hailfinger Committed by Stefan Tauner
Browse files

Refactor unlocking of many chips with locking at register space address +2


This includes PMC Pm49*, SST 49LF00*, ST M50* and Winbond W39* families.
The erase and write test status bits of all affected chips have been reset.

Corresponding to flashrom svn r1833.
Signed-off-by: default avatarCarl-Daniel Hailfinger <c-d.hailfinger.devel.2006@gmx.net>
Signed-off-by: default avatarStefan Tauner <stefan.tauner@alumni.tuwien.ac.at>
Acked-by: default avatarStefan Tauner <stefan.tauner@alumni.tuwien.ac.at>
parent 2a41f0a2
......@@ -108,17 +108,6 @@ uint8_t wait_82802ab(struct flashctx *flash)
return status;
}
int unlock_82802ab(struct flashctx *flash)
{
int i;
//chipaddr wrprotect = flash->virtual_registers + page + 2;
for (i = 0; i < flash->chip->total_size * 1024; i+= flash->chip->page_size)
chip_writeb(flash, 0, flash->virtual_registers + i + 2);
return 0;
}
int erase_block_82802ab(struct flashctx *flash, unsigned int page,
unsigned int pagesize)
{
......
......@@ -351,7 +351,7 @@ endif
# Flash chip drivers and bus support infrastructure.
CHIP_OBJS = jedec.o stm50.o w39.o w29ee011.o \
sst28sf040.o m29f400bt.o 82802ab.o pm49fl00x.o \
sst28sf040.o m29f400bt.o 82802ab.o \
sst49lfxxxc.o sst_fwhub.o flashchips.o spi.o spi25.o spi25_statusreg.o \
opaque.o sfdp.o en29lv640b.o at45db.o
......
......@@ -131,7 +131,6 @@ int probe_82802ab(struct flashctx *flash);
int erase_block_82802ab(struct flashctx *flash, unsigned int page, unsigned int pagesize);
int write_82802ab(struct flashctx *flash, const uint8_t *buf, unsigned int start, unsigned int len);
void print_status_82802ab(uint8_t status);
int unlock_82802ab(struct flashctx *flash);
int unlock_28f004s5(struct flashctx *flash);
int unlock_lh28f008bjt(struct flashctx *flash);
......@@ -146,15 +145,20 @@ int erase_sector_jedec(struct flashctx *flash, unsigned int page, unsigned int p
int erase_block_jedec(struct flashctx *flash, unsigned int page, unsigned int blocksize);
int erase_chip_block_jedec(struct flashctx *flash, unsigned int page, unsigned int blocksize);
int unlock_regspace2_uniform_32k(struct flashctx *flash);
int unlock_regspace2_uniform_64k(struct flashctx *flash);
int unlock_regspace2_block_eraser_0(struct flashctx *flash);
int unlock_regspace2_block_eraser_1(struct flashctx *flash);
int unlock_regspace2_block(const struct flashctx *flash, chipaddr off);
int printlock_regspace2_uniform_64k(struct flashctx *flash);
int printlock_regspace2_block_eraser_0(struct flashctx *flash);
int printlock_regspace2_block_eraser_1(struct flashctx *flash);
/* m29f400bt.c */
int probe_m29f400bt(struct flashctx *flash);
int write_m29f400bt(struct flashctx *flash, const uint8_t *buf, unsigned int start, unsigned int len);
void protect_m29f400bt(struct flashctx *flash, chipaddr bios);
/* pm49fl00x.c */
int unlock_49fl00x(struct flashctx *flash);
int lock_49fl00x(struct flashctx *flash);
/* sst28sf040.c */
int erase_chip_28sf040(struct flashctx *flash, unsigned int addr, unsigned int blocklen);
int erase_sector_28sf040(struct flashctx *flash, unsigned int address, unsigned int sector_size);
......@@ -164,7 +168,6 @@ int protect_28sf040(struct flashctx *flash);
/* sst49lfxxxc.c */
int erase_sector_49lfxxxc(struct flashctx *flash, unsigned int address, unsigned int sector_size);
int unlock_49lfxxxc(struct flashctx *flash);
/* sst_fwhub.c */
int printlock_sst_fwhub(struct flashctx *flash);
......@@ -184,8 +187,6 @@ int printlock_w39v040fc(struct flashctx *flash);
int printlock_w39v080a(struct flashctx *flash);
int printlock_w39v080fa(struct flashctx *flash);
int printlock_w39v080fa_dual(struct flashctx *flash);
int unlock_w39v040fb(struct flashctx *flash);
int unlock_w39v080fa(struct flashctx *flash);
int printlock_at49f(struct flashctx *flash);
/* w29ee011.c */
......@@ -193,8 +194,6 @@ int probe_w29ee011(struct flashctx *flash);
/* stm50.c */
int erase_sector_stm50(struct flashctx *flash, unsigned int block, unsigned int blocksize);
int unlock_stm50_uniform(struct flashctx *flash);
int unlock_stm50_nonuniform(struct flashctx *flash);
/* en29lv640b.c */
int probe_en29lv640b(struct flashctx *flash);
......
......@@ -1382,7 +1382,7 @@ const struct flashchip flashchips[] = {
.total_size = 512,
.page_size = 64 * 1024,
.feature_bits = FEATURE_REGISTERMAP | FEATURE_EITHER_RESET,
.tested = TEST_OK_PREW,
.tested = TEST_OK_PR,
.probe = probe_jedec,
.probe_timing = TIMING_ZERO, /* routine is wrapper to probe_jedec (pm49fl00x.c) */
.block_erasers =
......@@ -1395,7 +1395,7 @@ const struct flashchip flashchips[] = {
.block_erase = erase_chip_block_jedec,
}
},
.unlock = unlock_49fl00x,
.unlock = unlock_regspace2_uniform_64k,
.write = write_jedec_1,
.read = read_memmapped,
.voltage = {3000, 3600},
......@@ -5979,7 +5979,7 @@ const struct flashchip flashchips[] = {
.total_size = 512,
.page_size = 64 * 1024,
.feature_bits = FEATURE_REGISTERMAP,
.tested = TEST_OK_PREW,
.tested = TEST_OK_PR,
.probe = probe_82802ab,
.probe_timing = TIMING_IGNORED, /* routine does not use probe_timing (82802ab.c) */
.block_erasers =
......@@ -5989,7 +5989,7 @@ const struct flashchip flashchips[] = {
.block_erase = erase_block_82802ab,
},
},
.unlock = unlock_82802ab,
.unlock = unlock_regspace2_uniform_64k,
.write = write_82802ab,
.read = read_memmapped,
.voltage = {3000, 3600},
......@@ -6014,7 +6014,7 @@ const struct flashchip flashchips[] = {
.block_erase = erase_block_82802ab,
},
},
.unlock = unlock_82802ab,
.unlock = unlock_regspace2_uniform_64k,
.write = write_82802ab,
.read = read_memmapped,
.voltage = {3000, 3600},
......@@ -9202,7 +9202,7 @@ const struct flashchip flashchips[] = {
.total_size = 256,
.page_size = 16 * 1024,
.feature_bits = FEATURE_REGISTERMAP | FEATURE_EITHER_RESET,
.tested = TEST_OK_PREW,
.tested = TEST_OK_PR,
.probe = probe_jedec,
.probe_timing = TIMING_ZERO, /* routine is wrapper to probe_jedec (pm49fl00x.c) */
.block_erasers =
......@@ -9218,7 +9218,7 @@ const struct flashchip flashchips[] = {
.block_erase = erase_chip_block_jedec,
}
},
.unlock = unlock_49fl00x,
.unlock = unlock_regspace2_uniform_32k,
.write = write_jedec_1,
.read = read_memmapped,
.voltage = {3000, 3600},
......@@ -9233,7 +9233,7 @@ const struct flashchip flashchips[] = {
.total_size = 512,
.page_size = 64 * 1024,
.feature_bits = FEATURE_REGISTERMAP | FEATURE_EITHER_RESET,
.tested = TEST_OK_PREW,
.tested = TEST_OK_PR,
.probe = probe_jedec,
.probe_timing = TIMING_ZERO, /* routine is wrapper to probe_jedec (pm49fl00x.c) */
.block_erasers =
......@@ -9249,7 +9249,7 @@ const struct flashchip flashchips[] = {
.block_erase = erase_chip_block_jedec,
}
},
.unlock = unlock_49fl00x,
.unlock = unlock_regspace2_uniform_64k,
.write = write_jedec_1,
.read = read_memmapped,
.voltage = {3000, 3600},
......@@ -9562,7 +9562,7 @@ const struct flashchip flashchips[] = {
.block_erase = NULL, /* 30 D0, only in A/A mux mode */
},
},
.unlock = unlock_82802ab,
.unlock = unlock_regspace2_uniform_64k,
.write = write_82802ab,
.read = read_memmapped,
.voltage = {3000, 3600},
......@@ -11104,7 +11104,8 @@ const struct flashchip flashchips[] = {
.block_erase = erase_block_82802ab,
}
},
.unlock = unlock_49lfxxxc,
.printlock = printlock_regspace2_block_eraser_1,
.unlock = unlock_regspace2_block_eraser_1,
.write = write_82802ab,
.read = read_memmapped,
.voltage = {3000, 3600},
......@@ -11169,7 +11170,8 @@ const struct flashchip flashchips[] = {
.block_erase = erase_block_82802ab,
}
},
.unlock = unlock_49lfxxxc,
.printlock = printlock_regspace2_block_eraser_1,
.unlock = unlock_regspace2_block_eraser_1,
.write = write_82802ab,
.read = read_memmapped,
.voltage = {3000, 3600},
......@@ -11184,7 +11186,7 @@ const struct flashchip flashchips[] = {
.total_size = 2048,
.page_size = 4 * 1024,
.feature_bits = FEATURE_REGISTERMAP,
.tested = TEST_OK_PREW,
.tested = TEST_OK_PR,
.probe = probe_82802ab,
.probe_timing = TIMING_IGNORED, /* routine doesn't use probe_timing (sst49lfxxxc.c) */
.block_erasers =
......@@ -11202,7 +11204,8 @@ const struct flashchip flashchips[] = {
.block_erase = erase_block_82802ab,
}
},
.unlock = unlock_49lfxxxc,
.printlock = printlock_regspace2_block_eraser_1,
.unlock = unlock_regspace2_block_eraser_1,
.write = write_82802ab,
.read = read_memmapped,
.voltage = {3000, 3600},
......@@ -11307,7 +11310,7 @@ const struct flashchip flashchips[] = {
.total_size = 512,
.page_size = 64 * 1024,
.feature_bits = FEATURE_EITHER_RESET | FEATURE_REGISTERMAP,
.tested = TEST_OK_PREW,
.tested = TEST_OK_PR,
.probe = probe_jedec,
.probe_timing = 1, /* 150ns */
.block_erasers =
......@@ -11323,7 +11326,7 @@ const struct flashchip flashchips[] = {
.block_erase = NULL,
}
},
.unlock = unlock_82802ab,
.unlock = unlock_regspace2_uniform_64k,
.write = write_jedec_1,
.read = read_memmapped,
.voltage = {3000, 3600},
......@@ -11368,7 +11371,7 @@ const struct flashchip flashchips[] = {
.total_size = 2048,
.page_size = 4 * 1024,
.feature_bits = FEATURE_REGISTERMAP,
.tested = TEST_OK_PRE,
.tested = TEST_OK_PR,
.probe = probe_82802ab,
.probe_timing = TIMING_IGNORED, /* routine doesn't use probe_timing (sst49lfxxxc.c) */
.block_erasers =
......@@ -11386,7 +11389,8 @@ const struct flashchip flashchips[] = {
.block_erase = erase_block_82802ab,
}
},
.unlock = unlock_49lfxxxc,
.printlock = printlock_regspace2_block_eraser_1,
.unlock = unlock_regspace2_block_eraser_1,
.write = write_82802ab,
.read = read_memmapped,
.voltage = {3000, 3600},
......@@ -11654,7 +11658,7 @@ const struct flashchip flashchips[] = {
}
},
.write = write_82802ab,
.unlock = unlock_stm50_uniform,
.unlock = unlock_regspace2_uniform_64k,
.read = read_memmapped,
.voltage = {3000, 3600}, /* Also has 12V fast program & erase */
},
......@@ -11687,7 +11691,7 @@ const struct flashchip flashchips[] = {
}
},
.write = write_82802ab,
.unlock = unlock_stm50_uniform,
.unlock = unlock_regspace2_uniform_64k,
.read = read_memmapped,
.voltage = {3000, 3600}, /* Also has 12V fast program & erase */
},
......@@ -11701,7 +11705,7 @@ const struct flashchip flashchips[] = {
.total_size = 1024,
.page_size = 0,
.feature_bits = FEATURE_REGISTERMAP,
.tested = TEST_OK_PRE,
.tested = TEST_OK_PR,
.probe = probe_82802ab,
.probe_timing = TIMING_FIXME,
.block_erasers =
......@@ -11719,7 +11723,8 @@ const struct flashchip flashchips[] = {
.block_erase = erase_block_82802ab,
}
},
.unlock = unlock_stm50_nonuniform,
.printlock = printlock_regspace2_block_eraser_0,
.unlock = unlock_regspace2_block_eraser_0,
.write = write_82802ab,
.read = read_memmapped,
.voltage = {3000, 3600}, /* Also has 12V fast program & erase */
......@@ -11752,7 +11757,8 @@ const struct flashchip flashchips[] = {
.block_erase = erase_block_82802ab,
}
},
.unlock = unlock_stm50_nonuniform,
.printlock = printlock_regspace2_block_eraser_0,
.unlock = unlock_regspace2_block_eraser_0,
.write = write_82802ab,
.read = read_memmapped,
.voltage = {3000, 3600}, /* Also has 12V fast program & erase */
......@@ -11767,9 +11773,9 @@ const struct flashchip flashchips[] = {
.total_size = 256,
.page_size = 0,
.feature_bits = FEATURE_REGISTERMAP,
.tested = TEST_UNTESTED,
.tested = TEST_OK_PR,
.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 =
{
{
......@@ -11780,9 +11786,13 @@ const struct flashchip flashchips[] = {
{16 * 1024, 1},
},
.block_erase = erase_block_82802ab,
}, {
.eraseblocks = { {256 * 1024, 1}, },
.block_erase = NULL, /* Only in A/A mux mode */
}
},
.unlock = unlock_stm50_nonuniform,
.printlock = printlock_regspace2_block_eraser_0,
.unlock = unlock_regspace2_block_eraser_0,
.write = write_82802ab,
.read = read_memmapped,
.voltage = {3000, 3600}, /* Also has 12V fast program & erase */
......@@ -11807,7 +11817,7 @@ const struct flashchip flashchips[] = {
.block_erase = erase_block_82802ab,
}
},
.unlock = unlock_stm50_uniform,
.unlock = unlock_regspace2_uniform_64k,
.write = write_82802ab,
.read = read_memmapped,
.voltage = {3000, 3600}, /* Also has 12V fast program & erase */
......@@ -11832,7 +11842,7 @@ const struct flashchip flashchips[] = {
.block_erase = erase_block_82802ab,
}
},
.unlock = unlock_stm50_uniform,
.unlock = unlock_regspace2_uniform_64k,
.write = write_82802ab,
.read = read_memmapped,
.voltage = {3000, 3600}, /* Also has 12V fast program & erase */
......@@ -11847,7 +11857,7 @@ const struct flashchip flashchips[] = {
.total_size = 1024,
.page_size = 0,
.feature_bits = FEATURE_REGISTERMAP,
.tested = TEST_OK_PREW,
.tested = TEST_OK_PR,
.probe = probe_82802ab,
.probe_timing = TIMING_IGNORED, /* routine doesn't use probe_timing (82802ab.c) */
.block_erasers =
......@@ -11857,7 +11867,7 @@ const struct flashchip flashchips[] = {
.block_erase = erase_block_82802ab,
}
},
.unlock = unlock_stm50_uniform,
.unlock = unlock_regspace2_uniform_64k,
.write = write_82802ab,
.read = read_memmapped,
.voltage = {3000, 3600}, /* Also has 12V fast program & erase */
......@@ -11882,7 +11892,7 @@ const struct flashchip flashchips[] = {
.block_erase = erase_block_82802ab,
}
},
.unlock = unlock_stm50_uniform,
.unlock = unlock_regspace2_uniform_64k,
.write = write_82802ab,
.read = read_memmapped,
.voltage = {3000, 3600}, /* Also has 12V fast program & erase */
......@@ -11913,7 +11923,8 @@ const struct flashchip flashchips[] = {
.block_erase = erase_block_82802ab,
}
},
.unlock = unlock_stm50_nonuniform,
.printlock = printlock_regspace2_block_eraser_0,
.unlock = unlock_regspace2_block_eraser_0,
.write = write_82802ab,
.read = read_memmapped,
.voltage = {3000, 3600}, /* Also has 12V fast program & erase */
......@@ -13181,7 +13192,7 @@ const struct flashchip flashchips[] = {
.total_size = 512,
.page_size = 64 * 1024,
.feature_bits = FEATURE_REGISTERMAP | FEATURE_EITHER_RESET,
.tested = TEST_OK_PREW,
.tested = TEST_OK_PR,
.probe = probe_jedec,
.probe_timing = 10,
.block_erasers =
......@@ -13198,7 +13209,7 @@ const struct flashchip flashchips[] = {
}
},
.printlock = printlock_w39v040fa,
.unlock = unlock_sst_fwhub,
.unlock = unlock_regspace2_uniform_64k,
.write = write_jedec_1,
.read = read_memmapped,
.voltage = {3000, 3600},
......@@ -13213,7 +13224,7 @@ const struct flashchip flashchips[] = {
.total_size = 512,
.page_size = 64 * 1024,
.feature_bits = FEATURE_REGISTERMAP | FEATURE_EITHER_RESET,
.tested = TEST_OK_PREW,
.tested = TEST_OK_PR,
.probe = probe_jedec,
.probe_timing = 10,
.block_erasers =
......@@ -13227,7 +13238,7 @@ const struct flashchip flashchips[] = {
}
},
.printlock = printlock_w39v040fb,
.unlock = unlock_w39v040fb,
.unlock = unlock_regspace2_uniform_64k,
.write = write_jedec_1,
.read = read_memmapped,
.voltage = {3000, 3600}, /* Also has 12V fast program */
......@@ -13418,7 +13429,7 @@ const struct flashchip flashchips[] = {
.total_size = 1024,
.page_size = 64 * 1024,
.feature_bits = FEATURE_REGISTERMAP | FEATURE_EITHER_RESET,
.tested = TEST_OK_PREW,
.tested = TEST_OK_PR,
.probe = probe_jedec,
.probe_timing = 10,
.block_erasers =
......@@ -13432,7 +13443,7 @@ const struct flashchip flashchips[] = {
}
},
.printlock = printlock_w39v080fa,
.unlock = unlock_w39v080fa,
.unlock = unlock_regspace2_uniform_64k,
.write = write_jedec_1,
.read = read_memmapped,
.voltage = {3000, 3600}, /* Also has 12V fast program */
......
......@@ -4,8 +4,9 @@
* Copyright (C) 2000 Silicon Integrated System Corporation
* Copyright (C) 2006 Giampiero Giancipoli <gianci@email.it>
* Copyright (C) 2006 coresystems GmbH <info@coresystems.de>
* Copyright (C) 2007 Carl-Daniel Hailfinger
* Copyright (C) 2007, 2011 Carl-Daniel Hailfinger
* Copyright (C) 2009 Sean Nelson <audiohacked@gmail.com>
* Copyright (C) 2014 Stefan Tauner
*
* 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
......@@ -510,3 +511,185 @@ int erase_chip_jedec(struct flashctx *flash)
mask = getaddrmask(flash->chip);
return erase_chip_jedec_common(flash, mask);
}
struct unlockblock {
unsigned int size;
unsigned int count;
};
typedef int (*unlockblock_func)(const struct flashctx *flash, chipaddr offset);
static int regspace2_walk_unlockblocks(const struct flashctx *flash, const struct unlockblock *block, unlockblock_func func)
{
chipaddr off = flash->virtual_registers + 2;
while (block->count != 0) {
unsigned int j;
for (j = 0; j < block->count; j++) {
if (func(flash, off))
return -1;
off += block->size;
}
block++;
}
return 0;
}
#define REG2_RWLOCK ((1 << 2) | (1 << 0))
#define REG2_LOCKDOWN (1 << 1)
#define REG2_MASK (REG2_RWLOCK | REG2_LOCKDOWN)
static int printlock_regspace2_block(const struct flashctx *flash, chipaddr offset)
{
chipaddr wrprotect = flash->virtual_registers + offset + 2;
uint8_t state = chip_readb(flash, wrprotect);
msg_cdbg("Lock status of block at 0x%0*" PRIxPTR " is ", PRIxPTR_WIDTH, offset);
switch (state & REG2_MASK) {
case 0:
msg_cdbg("Full Access.\n");
break;
case 1:
msg_cdbg("Write Lock (Default State).\n");
break;
case 2:
msg_cdbg("Locked Open (Full Access, Locked Down).\n");
break;
case 3:
msg_cdbg("Write Lock, Locked Down.\n");
break;
case 4:
msg_cdbg("Read Lock.\n");
break;
case 5:
msg_cdbg("Read/Write Lock.\n");
break;
case 6:
msg_cdbg("Read Lock, Locked Down.\n");
break;
case 7:
msg_cdbg("Read/Write Lock, Locked Down.\n");
break;
}
return 0;
}
int printlock_regspace2_blocks(const struct flashctx *flash, const struct unlockblock *blocks)
{
return regspace2_walk_unlockblocks(flash, blocks, &printlock_regspace2_block);
}
static int printlock_regspace2_uniform(struct flashctx *flash, unsigned long block_size)
{
const unsigned int elems = flash->chip->total_size * 1024 / block_size;
struct unlockblock blocks[2] = {{.size = block_size, .count = elems}};
return regspace2_walk_unlockblocks(flash, blocks, &printlock_regspace2_block);
}
int printlock_regspace2_uniform_64k(struct flashctx *flash)
{
return printlock_regspace2_uniform(flash, 64 * 1024);
}
int printlock_regspace2_block_eraser_0(struct flashctx *flash)
{
// FIXME: this depends on the eraseblocks not to be filled up completely (i.e. to be null-terminated).
const struct unlockblock *unlockblocks =
(const struct unlockblock *)flash->chip->block_erasers[0].eraseblocks;
return regspace2_walk_unlockblocks(flash, unlockblocks, &printlock_regspace2_block);
}
int printlock_regspace2_block_eraser_1(struct flashctx *flash)
{
// FIXME: this depends on the eraseblocks not to be filled up completely (i.e. to be null-terminated).
const struct unlockblock *unlockblocks =
(const struct unlockblock *)flash->chip->block_erasers[1].eraseblocks;
return regspace2_walk_unlockblocks(flash, unlockblocks, &printlock_regspace2_block);
}
static int changelock_regspace2_block(const struct flashctx *flash, chipaddr offset, uint8_t new_bits)
{
chipaddr wrprotect = flash->virtual_registers + offset + 2;
uint8_t old;
if (new_bits & ~REG2_MASK) {
msg_cerr("Invalid locking change 0x%02x requested at 0x%0*" PRIxPTR "! "
"Please report a bug at flashrom@flashrom.org\n",
new_bits, PRIxPTR_WIDTH, offset);
return -1;
}
old = chip_readb(flash, wrprotect);
/* Early exist if no change (of read/write/lockdown) was requested. */
if (((old ^ new_bits) & REG2_MASK) == 0) {
msg_cdbg2("Locking status at 0x%0*" PRIxPTR " not changed\n", PRIxPTR_WIDTH, offset);
return 0;
}
/* Normally lockdowns can not be cleared. Try nevertheless if requested. */
if ((old & REG2_LOCKDOWN) && !(new_bits & REG2_LOCKDOWN)) {
chip_writeb(flash, old & ~REG2_LOCKDOWN, wrprotect);
if (chip_readb(flash, wrprotect) != (old & ~REG2_LOCKDOWN)) {
msg_cerr("Lockdown can't be removed at 0x%0*" PRIxPTR "!\n", PRIxPTR_WIDTH, offset);
return -1;
}
}
/* Change read or write lock? */
if ((old ^ new_bits) & REG2_RWLOCK) {
/* Do not lockdown yet. */
msg_cdbg("Changing locking status at 0x%0*" PRIxPTR " to 0x%02x\n", PRIxPTR_WIDTH, offset, new_bits & REG2_RWLOCK);
chip_writeb(flash, new_bits & REG2_RWLOCK, wrprotect);
if (chip_readb(flash, wrprotect) != (new_bits & REG2_RWLOCK)) {
msg_cerr("Locking status change FAILED at 0x%0*" PRIxPTR "!\n", PRIxPTR_WIDTH, offset);
return -1;
}
}
/* Enable lockdown if requested. */
if (!(old & REG2_LOCKDOWN) && (new_bits & REG2_LOCKDOWN)) {
msg_cdbg("Enabling lockdown at 0x%0*" PRIxPTR "\n", PRIxPTR_WIDTH, offset);
chip_writeb(flash, new_bits, wrprotect);
if (chip_readb(flash, wrprotect) != new_bits) {
msg_cerr("Enabling lockdown FAILED at 0x%0*" PRIxPTR "!\n", PRIxPTR_WIDTH, offset);
return -1;
}
}
return 0;
}
int unlock_regspace2_block(const struct flashctx *flash, chipaddr off)
{
chipaddr wrprotect = flash->virtual_registers + off + 2;
uint8_t old = chip_readb(flash, wrprotect);
/* We don't care for the lockdown bit as long as the RW locks are 0 after we're done */
return changelock_regspace2_block(flash, off, old & ~REG2_RWLOCK);
}
static int unlock_regspace2_uniform(struct flashctx *flash, unsigned long block_size)
{
const unsigned int elems = flash->chip->total_size * 1024 / block_size;
struct unlockblock blocks[2] = {{.size = block_size, .count = elems}};
return regspace2_walk_unlockblocks(flash, blocks, &unlock_regspace2_block);
}
int unlock_regspace2_uniform_64k(struct flashctx *flash)
{
return unlock_regspace2_uniform(flash, 64 * 1024);
}
int unlock_regspace2_uniform_32k(struct flashctx *flash)
{
return unlock_regspace2_uniform(flash, 32 * 1024);
}
int unlock_regspace2_block_eraser_0(struct flashctx *flash)
{
// FIXME: this depends on the eraseblocks not to be filled up completely (i.e. to be null-terminated).
const struct unlockblock *unlockblocks =
(const struct unlockblock *)flash->chip->block_erasers[0].eraseblocks;
return regspace2_walk_unlockblocks(flash, unlockblocks, &unlock_regspace2_block);
}
int unlock_regspace2_block_eraser_1(struct flashctx *flash)
{
// FIXME: this depends on the eraseblocks not to be filled up completely (i.e. to be null-terminated).
const struct unlockblock *unlockblocks =
(const struct unlockblock *)flash->chip->block_erasers[1].eraseblocks;
return regspace2_walk_unlockblocks(flash, unlockblocks, &unlock_regspace2_block);
}
/*
* This file is part of the flashrom project.
*
* Copyright (C) 2004 Tyan Corporation
* Copyright (C) 2007 Nikolay Petukhov <nikolay.petukhov@gmail.com>
* Copyright (C) 2007 Reinder E.N. de Haan <lb_reha@mveas.com>
*
* 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
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "flash.h"
static void write_lockbits_49fl00x(const struct flashctx *flash,
unsigned int size, unsigned char bits,
unsigned int block_size)
{
unsigned int i, left = size;
chipaddr bios = flash->virtual_registers;
for (i = 0; left >= block_size; i++, left -= block_size) {
/* pm49fl002 */
if (block_size == 16384 && i % 2)
continue;
chip_writeb(flash, bits, bios + (i * block_size) + 2);
}
}
int unlock_49fl00x(struct flashctx *flash)
{
write_lockbits_49fl00x(flash, flash->chip->total_size * 1024, 0,
flash->chip->page_size);
return 0;
}
int lock_49fl00x(struct flashctx *flash)
{
write_lockbits_49fl00x(flash, flash->chip->total_size * 1024, 1,
flash->chip->page_size);
return 0;
}
......@@ -23,45 +23,6 @@
#include "flash.h"
#include "chipdrivers.h"
static int write_lockbits_block_49lfxxxc(struct flashctx *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(flash, lock));
chip_writeb(flash, bits, lock);
return 0;
}
static int write_lockbits_49lfxxxc(struct flashctx *flash, unsigned char bits)
{
chipaddr registers = flash->virtual_registers;
unsigned int i, left = flash->chip->total_size * 1024;
unsigned long address;
msg_cdbg("\nbios=0x%08" PRIxPTR "\n", registers);
for (i = 0; left > 65536; i++, left -= 65536) {
write_lockbits_block_49lfxxxc(flash, i * 65536, bits);
}
address = i * 65536;
write_lockbits_block_49lfxxxc(flash, address, bits);
address += 32768;
write_lockbits_block_49lfxxxc(flash, address, bits);
address += 8192;
write_lockbits_block_49lfxxxc(flash, address, bits);
address += 8192;
write_lockbits_block_49lfxxxc(flash, address, bits);
return 0;
}
int unlock_49lfxxxc(struct flashctx *flash)
{
return write_lockbits_49lfxxxc(flash, 0);
}
int erase_sector_49lfxxxc(struct flashctx *flash, unsigned int address,
unsigned int sector_size)
{
......
......@@ -27,63 +27,8 @@
*/
#include "flash.h"
#include "flashchips.h"
#include "chipdrivers.h"
static int stm50_unlock_address(struct flashctx *flash, int offset)
{
chipaddr wrprotect = flash->virtual_registers + 2;
static const uint8_t unlock_sector = 0x00;
msg_cdbg("unlocking at 0x%x\n", offset);
chip_writeb(flash, unlock_sector, wrprotect + offset);
if (chip_readb(flash, wrprotect + offset) != unlock_sector) {
msg_cerr("Cannot unlock address 0x%x\n", offset);
return -1;
}
return 0;
}
/* Chips known to use a non-uniform block and sector layout for locking (as well as for erasing):
* Name Size Address range of lock registers
* M50FLW080A 1MB FFB00002 - FFBFF002
* M50FLW080B 1MB FFB00002 - FFBFF002
* M50FW002 256k FFBC0002 - FFBFC002
* M50LPW116 2MB FFA00002 - FFBFC002
*/
int unlock_stm50_nonuniform(struct flashctx *flash)
{
int i;
struct eraseblock *eraseblocks = flash->chip->block_erasers[0].eraseblocks;
unsigned int done = 0;
for (i = 0; i < NUM_ERASEREGIONS && eraseblocks[i].count != 0; i++) {
unsigned int block_size = eraseblocks[i].size;
unsigned int block_count = eraseblocks[i].count;
int j;
for (j = 0; j < block_count; j++) {
if (stm50_unlock_address(flash, done)) {
msg_cerr("UNLOCK FAILED!\n");
return -1;
}
done += block_count * block_size;
}
}
return 0;
}
/* Unlocking for uniform 64 kB blocks starting at offset 2 of the feature registers. */
int unlock_stm50_uniform(struct flashctx *flash)
{
int i;
for (i = 0; i < flash->chip->total_size * 1024; i+= 64 * 1024) {
if (stm50_unlock_address(flash, i)) {
msg_cerr("UNLOCK FAILED!\n");
return -1;
}
}
return 0;
}
static int stm50_erase_sector(struct flashctx *flash, unsigned int addr)
{
chipaddr bios = flash->virtual_memory + addr;
......
......@@ -20,65 +20,7 @@
*/
#include "flash.h"
static int printlock_w39_fwh_block(struct flashctx *flash, unsigned int offset)
{
chipaddr wrprotect = flash->virtual_registers + offset + 2;
uint8_t locking;
locking = chip_readb(flash, wrprotect);
msg_cdbg("Lock status of block at 0x%08x is ", offset);
switch (locking & 0x7) {
case 0:
msg_cdbg("Full Access.\n");
break;
case 1:
msg_cdbg("Write Lock (Default State).\n");
break;
case 2:
msg_cdbg("Locked Open (Full Access, Lock Down).\n");
break;
case 3:
msg_cerr("Error: Write Lock, Locked Down.\n");
break;
case 4:
msg_cdbg("Read Lock.\n");
break;
case 5:
msg_cdbg("Read/Write Lock.\n");
break;
case 6:
msg_cerr("Error: Read Lock, Locked Down.\n");
break;
case 7:
msg_cerr("Error: Read/Write Lock, Locked Down.\n");
break;
}
/* Read or write lock present? */
return (locking & ((1 << 2) | (1 << 0))) ? -1 : 0;
}
static int unlock_w39_fwh_block(struct flashctx *flash, unsigned int offset)
{
chipaddr wrprotect = flash->virtual_registers + offset + 2;
uint8_t locking;
locking = chip_readb(flash, wrprotect);
/* Read or write lock present? */
if (locking & ((1 << 2) | (1 << 0))) {
/* Lockdown active? */
if (locking & (1 << 1)) {
msg_cerr("Can't unlock block at 0x%08x!\n", offset);
return -1;
} else {
msg_cdbg("Unlocking block at 0x%08x\n", offset);
chip_writeb(flash, 0, wrprotect);
}
}
return 0;
}
#include "chipdrivers.h"
static uint8_t w39_idmode_readb(struct flashctx *flash, unsigned int offset)
{
......@@ -145,30 +87,6 @@ static int printlock_w39_common(struct flashctx *flash, unsigned int offset)
return printlock_w39_tblwp(lock);
}
static int printlock_w39_fwh(struct flashctx *flash)
{
unsigned int i, total_size = flash->chip->total_size * 1024;
int ret = 0;
/* Print lock status of the complete chip */
for (i = 0; i < total_size; i += flash->chip->page_size)
ret |= printlock_w39_fwh_block(flash, i);
return ret;
}
static int unlock_w39_fwh(struct flashctx *flash)
{
unsigned int i, total_size = flash->chip->total_size * 1024;
/* Unlock the complete chip */
for (i = 0; i < total_size; i += flash->chip->page_size)
if (unlock_w39_fwh_block(flash, i))
return -1;
return 0;
}
int printlock_w39f010(struct flashctx *flash)
{
uint8_t lock;
......@@ -267,7 +185,7 @@ int printlock_w39v040fa(struct flashctx *flash)
int ret = 0;
ret = printlock_w39v040a(flash);
ret |= printlock_w39_fwh(flash);
ret |= printlock_regspace2_uniform_64k(flash);
return ret;
}
......@@ -277,7 +195,7 @@ int printlock_w39v040fb(struct flashctx *flash)
int ret = 0;
ret = printlock_w39v040b(flash);
ret |= printlock_w39_fwh(flash);
ret |= printlock_regspace2_uniform_64k(flash);
return ret;
}
......@@ -288,7 +206,7 @@ int printlock_w39v040fc(struct flashctx *flash)
/* W39V040C and W39V040FC use different WP/TBL offsets. */
ret = printlock_w39_common(flash, 0x7fff2);
ret |= printlock_w39_fwh(flash);
ret |= printlock_regspace2_uniform_64k(flash);
return ret;
}
......@@ -303,7 +221,7 @@ int printlock_w39v080fa(struct flashctx *flash)
int ret = 0;
ret = printlock_w39v080a(flash);
ret |= printlock_w39_fwh(flash);
ret |= printlock_regspace2_uniform_64k(flash);
return ret;
}
......@@ -316,26 +234,6 @@ int printlock_w39v080fa_dual(struct flashctx *flash)
return -1;
}
int unlock_w39v040fb(struct flashctx *flash)
{
if (unlock_w39_fwh(flash))
return -1;
if (printlock_w39_common(flash, 0x7fff2))
return -1;
return 0;
}
int unlock_w39v080fa(struct flashctx *flash)
{
if (unlock_w39_fwh(flash))
return -1;
if (printlock_w39_common(flash, 0xffff2))
return -1;
return 0;
}
int printlock_at49f(struct flashctx *flash)
{
uint8_t lock = w39_idmode_readb(flash, 0x00002);
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment