mirror of
https://review.coreboot.org/flashrom.git
synced 2025-04-27 23:22:37 +02:00
jedec.c: Move printlock stuff into printlock.c
Change-Id: Iacaa16c81e141aac30feb6871700c4fdc9eec8e9 Signed-off-by: Edward O'Callaghan <quasisec@google.com> Reviewed-on: https://review.coreboot.org/c/flashrom/+/72607 Reviewed-by: Stefan Reinauer <stefan.reinauer@coreboot.org> Reviewed-by: Thomas Heijligen <src@posteo.de> Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
This commit is contained in:
parent
ae07072e0a
commit
86babd0627
2
Makefile
2
Makefile
@ -379,7 +379,7 @@ endif
|
|||||||
###############################################################################
|
###############################################################################
|
||||||
# Flash chip drivers and bus support infrastructure.
|
# Flash chip drivers and bus support infrastructure.
|
||||||
|
|
||||||
CHIP_OBJS = jedec.o stm50.o w39.o w29ee011.o \
|
CHIP_OBJS = jedec.o printlock.o stm50.o w39.o w29ee011.o \
|
||||||
sst28sf040.o 82802ab.o \
|
sst28sf040.o 82802ab.o \
|
||||||
sst49lfxxxc.o sst_fwhub.o edi.o flashchips.o spi.o spi25.o spi25_statusreg.o \
|
sst49lfxxxc.o sst_fwhub.o edi.o flashchips.o spi.o spi25.o spi25_statusreg.o \
|
||||||
spi95.o opaque.o sfdp.o en29lv640b.o at45db.o s25f.o \
|
spi95.o opaque.o sfdp.o en29lv640b.o at45db.o s25f.o \
|
||||||
|
189
jedec.c
189
jedec.c
@ -478,192 +478,3 @@ int write_jedec(struct flashctx *flash, const uint8_t *buf, unsigned int start,
|
|||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
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 lockreg)
|
|
||||||
{
|
|
||||||
uint8_t state = chip_readb(flash, lockreg);
|
|
||||||
msg_cdbg("Lock status of block at 0x%0*" PRIxPTR " is ", PRIxPTR_WIDTH, lockreg);
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Try to change the lock register at address lockreg from cur to new.
|
|
||||||
*
|
|
||||||
* - Try to unlock the lock bit if requested and it is currently set (although this is probably futile).
|
|
||||||
* - Try to change the read/write bits if requested.
|
|
||||||
* - Try to set the lockdown bit if requested.
|
|
||||||
* Return an error immediately if any of this fails. */
|
|
||||||
static int changelock_regspace2_block(const struct flashctx *flash, chipaddr lockreg, uint8_t cur, uint8_t new)
|
|
||||||
{
|
|
||||||
/* Only allow changes to known read/write/lockdown bits */
|
|
||||||
if (((cur ^ new) & ~REG2_MASK) != 0) {
|
|
||||||
msg_cerr("Invalid lock change from 0x%02x to 0x%02x requested at 0x%0*" PRIxPTR "!\n"
|
|
||||||
"Please report a bug at flashrom@flashrom.org\n",
|
|
||||||
cur, new, PRIxPTR_WIDTH, lockreg);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Exit early if no change (of read/write/lockdown bits) was requested. */
|
|
||||||
if (((cur ^ new) & REG2_MASK) == 0) {
|
|
||||||
msg_cdbg2("Lock bits at 0x%0*" PRIxPTR " not changed.\n", PRIxPTR_WIDTH, lockreg);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Normally the lockdown bit can not be cleared. Try nevertheless if requested. */
|
|
||||||
if ((cur & REG2_LOCKDOWN) && !(new & REG2_LOCKDOWN)) {
|
|
||||||
chip_writeb(flash, cur & ~REG2_LOCKDOWN, lockreg);
|
|
||||||
cur = chip_readb(flash, lockreg);
|
|
||||||
if ((cur & REG2_LOCKDOWN) == REG2_LOCKDOWN) {
|
|
||||||
msg_cwarn("Lockdown can't be removed at 0x%0*" PRIxPTR "! New value: 0x%02x.\n",
|
|
||||||
PRIxPTR_WIDTH, lockreg, cur);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Change read and/or write bit */
|
|
||||||
if ((cur ^ new) & REG2_RWLOCK) {
|
|
||||||
/* Do not lockdown yet. */
|
|
||||||
uint8_t wanted = (cur & ~REG2_RWLOCK) | (new & REG2_RWLOCK);
|
|
||||||
chip_writeb(flash, wanted, lockreg);
|
|
||||||
cur = chip_readb(flash, lockreg);
|
|
||||||
if (cur != wanted) {
|
|
||||||
msg_cerr("Changing lock bits failed at 0x%0*" PRIxPTR "! New value: 0x%02x.\n",
|
|
||||||
PRIxPTR_WIDTH, lockreg, cur);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
msg_cdbg("Changed lock bits at 0x%0*" PRIxPTR " to 0x%02x.\n",
|
|
||||||
PRIxPTR_WIDTH, lockreg, cur);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Eventually, enable lockdown if requested. */
|
|
||||||
if (!(cur & REG2_LOCKDOWN) && (new & REG2_LOCKDOWN)) {
|
|
||||||
chip_writeb(flash, new, lockreg);
|
|
||||||
cur = chip_readb(flash, lockreg);
|
|
||||||
if (cur != new) {
|
|
||||||
msg_cerr("Enabling lockdown FAILED at 0x%0*" PRIxPTR "! New value: 0x%02x.\n",
|
|
||||||
PRIxPTR_WIDTH, lockreg, cur);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
msg_cdbg("Enabled lockdown at 0x%0*" PRIxPTR ".\n", PRIxPTR_WIDTH, lockreg);
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int unlock_regspace2_block_generic(const struct flashctx *flash, chipaddr lockreg)
|
|
||||||
{
|
|
||||||
uint8_t old = chip_readb(flash, lockreg);
|
|
||||||
/* 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, lockreg, old, 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_generic);
|
|
||||||
}
|
|
||||||
|
|
||||||
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_generic);
|
|
||||||
}
|
|
||||||
|
|
||||||
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_generic);
|
|
||||||
}
|
|
||||||
|
@ -61,6 +61,7 @@ srcs = files(
|
|||||||
'helpers_fileio.c',
|
'helpers_fileio.c',
|
||||||
'ich_descriptors.c',
|
'ich_descriptors.c',
|
||||||
'jedec.c',
|
'jedec.c',
|
||||||
|
'printlock.c',
|
||||||
'layout.c',
|
'layout.c',
|
||||||
'libflashrom.c',
|
'libflashrom.c',
|
||||||
'opaque.c',
|
'opaque.c',
|
||||||
|
213
printlock.c
Normal file
213
printlock.c
Normal file
@ -0,0 +1,213 @@
|
|||||||
|
/*
|
||||||
|
* This file is part of the flashrom project.
|
||||||
|
*
|
||||||
|
* 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-2012 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
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "flash.h"
|
||||||
|
#include "chipdrivers.h"
|
||||||
|
|
||||||
|
|
||||||
|
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 lockreg)
|
||||||
|
{
|
||||||
|
uint8_t state = chip_readb(flash, lockreg);
|
||||||
|
msg_cdbg("Lock status of block at 0x%0*" PRIxPTR " is ", PRIxPTR_WIDTH, lockreg);
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Try to change the lock register at address lockreg from cur to new.
|
||||||
|
*
|
||||||
|
* - Try to unlock the lock bit if requested and it is currently set (although this is probably futile).
|
||||||
|
* - Try to change the read/write bits if requested.
|
||||||
|
* - Try to set the lockdown bit if requested.
|
||||||
|
* Return an error immediately if any of this fails. */
|
||||||
|
static int changelock_regspace2_block(const struct flashctx *flash, chipaddr lockreg, uint8_t cur, uint8_t new)
|
||||||
|
{
|
||||||
|
/* Only allow changes to known read/write/lockdown bits */
|
||||||
|
if (((cur ^ new) & ~REG2_MASK) != 0) {
|
||||||
|
msg_cerr("Invalid lock change from 0x%02x to 0x%02x requested at 0x%0*" PRIxPTR "!\n"
|
||||||
|
"Please report a bug at flashrom@flashrom.org\n",
|
||||||
|
cur, new, PRIxPTR_WIDTH, lockreg);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Exit early if no change (of read/write/lockdown bits) was requested. */
|
||||||
|
if (((cur ^ new) & REG2_MASK) == 0) {
|
||||||
|
msg_cdbg2("Lock bits at 0x%0*" PRIxPTR " not changed.\n", PRIxPTR_WIDTH, lockreg);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Normally the lockdown bit can not be cleared. Try nevertheless if requested. */
|
||||||
|
if ((cur & REG2_LOCKDOWN) && !(new & REG2_LOCKDOWN)) {
|
||||||
|
chip_writeb(flash, cur & ~REG2_LOCKDOWN, lockreg);
|
||||||
|
cur = chip_readb(flash, lockreg);
|
||||||
|
if ((cur & REG2_LOCKDOWN) == REG2_LOCKDOWN) {
|
||||||
|
msg_cwarn("Lockdown can't be removed at 0x%0*" PRIxPTR "! New value: 0x%02x.\n",
|
||||||
|
PRIxPTR_WIDTH, lockreg, cur);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Change read and/or write bit */
|
||||||
|
if ((cur ^ new) & REG2_RWLOCK) {
|
||||||
|
/* Do not lockdown yet. */
|
||||||
|
uint8_t wanted = (cur & ~REG2_RWLOCK) | (new & REG2_RWLOCK);
|
||||||
|
chip_writeb(flash, wanted, lockreg);
|
||||||
|
cur = chip_readb(flash, lockreg);
|
||||||
|
if (cur != wanted) {
|
||||||
|
msg_cerr("Changing lock bits failed at 0x%0*" PRIxPTR "! New value: 0x%02x.\n",
|
||||||
|
PRIxPTR_WIDTH, lockreg, cur);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
msg_cdbg("Changed lock bits at 0x%0*" PRIxPTR " to 0x%02x.\n",
|
||||||
|
PRIxPTR_WIDTH, lockreg, cur);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Eventually, enable lockdown if requested. */
|
||||||
|
if (!(cur & REG2_LOCKDOWN) && (new & REG2_LOCKDOWN)) {
|
||||||
|
chip_writeb(flash, new, lockreg);
|
||||||
|
cur = chip_readb(flash, lockreg);
|
||||||
|
if (cur != new) {
|
||||||
|
msg_cerr("Enabling lockdown FAILED at 0x%0*" PRIxPTR "! New value: 0x%02x.\n",
|
||||||
|
PRIxPTR_WIDTH, lockreg, cur);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
msg_cdbg("Enabled lockdown at 0x%0*" PRIxPTR ".\n", PRIxPTR_WIDTH, lockreg);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int unlock_regspace2_block_generic(const struct flashctx *flash, chipaddr lockreg)
|
||||||
|
{
|
||||||
|
uint8_t old = chip_readb(flash, lockreg);
|
||||||
|
/* 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, lockreg, old, 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_generic);
|
||||||
|
}
|
||||||
|
|
||||||
|
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_generic);
|
||||||
|
}
|
||||||
|
|
||||||
|
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_generic);
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user