summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRandall Spangler <rspangler@chromium.org>2012-12-10 15:23:57 -0800
committerRandall Spangler <rspangler@chromium.org>2012-12-10 15:42:21 -0800
commitab727c4941ddd0112be0e0de61c2900ae60913e7 (patch)
tree43cf3a0e39d3a771900423710c11f1d11a340b26
parent7a2e3372eef4d8eee8ee140f517a309dc7065887 (diff)
downloadchrome-ec-ab727c4941ddd0112be0e0de61c2900ae60913e7.tar.gz
Add more paranoia for flash write protect
If the entire flash is protected (as it normally is after software sync), fail all flash write/erase operations. Add a shadow copy of the all_now flag. BUG=chrome-os-partner:16727 BRANCH=link TEST=manual Verify that flash operations work properly before all_now. Then enable HW WP and flashwp enable flashwp now and try flasherase 0x38000 0x1000 flashwrite 0x38000 0x100 Those commands should fail with error 7 From the host side ectool flasherase 0x38000 0x1000 echo 'Khaaaaaaaaaaan' > /tmp/b16727 ectool flashwrite 0x38000 /tmp/b16727 should also fail. Change-Id: I99a4d2bb86080bd12c900582a8fbdfc79c99916c Signed-off-by: Randall Spangler <rspangler@chromium.org> Reviewed-on: https://gerrit.chromium.org/gerrit/39517 Reviewed-by: Bill Richardson <wfrichar@chromium.org>
-rw-r--r--chip/lm4/flash.c20
-rw-r--r--common/flash_common.c12
2 files changed, 32 insertions, 0 deletions
diff --git a/chip/lm4/flash.c b/chip/lm4/flash.c
index 51d9a46577..121936c26b 100644
--- a/chip/lm4/flash.c
+++ b/chip/lm4/flash.c
@@ -38,6 +38,7 @@
#define RO_BANK_COUNT (CONFIG_SECTION_RO_SIZE / CONFIG_FLASH_BANK_SIZE)
int stuck_locked; /* Is physical flash stuck protected? */
+int all_protected; /* Has all-flash protection been requested? */
/* Persistent protection state - emulates a SPI status register for flashrom */
struct persist_state {
@@ -162,6 +163,9 @@ static int write_buffer(void)
{
int t;
+ if (all_protected)
+ return EC_ERROR_ACCESS_DENIED;
+
if (!LM4_FLASH_FWBVAL)
return EC_SUCCESS; /* Nothing to do */
@@ -201,6 +205,9 @@ int flash_physical_write(int offset, int size, const char *data)
int rv;
int i;
+ if (all_protected)
+ return EC_ERROR_ACCESS_DENIED;
+
/* Get initial write buffer index and page */
LM4_FLASH_FMA = offset & ~(FLASH_FWB_BYTES - 1);
i = (offset >> 2) & (FLASH_FWB_WORDS - 1);
@@ -228,6 +235,9 @@ int flash_physical_write(int offset, int size, const char *data)
int flash_physical_erase(int offset, int size)
{
+ if (all_protected)
+ return EC_ERROR_ACCESS_DENIED;
+
LM4_FLASH_FCMISC = LM4_FLASH_FCRIS; /* Clear previous error status */
for ( ; size > 0; size -= CONFIG_FLASH_ERASE_SIZE,
@@ -280,6 +290,10 @@ uint32_t flash_get_protect(void)
uint32_t flags = 0;
int i;
+ /* Read all-protected state from our shadow copy */
+ if (all_protected)
+ flags |= EC_FLASH_PROTECT_ALL_NOW;
+
/* Read the current persist state from flash */
read_pstate(&pstate);
if (pstate.flags & PERSIST_FLAG_PROTECT_RO)
@@ -355,6 +369,7 @@ int flash_set_protect(uint32_t mask, uint32_t flags)
if ((mask & EC_FLASH_PROTECT_ALL_NOW) &&
(flags & EC_FLASH_PROTECT_ALL_NOW)) {
/* Protect the entire flash */
+ all_protected = 1;
protect_banks(0, CONFIG_FLASH_PHYSICAL_SIZE /
CONFIG_FLASH_BANK_SIZE);
}
@@ -391,6 +406,11 @@ int flash_pre_init(void)
/* Re-read flags */
prot_flags = flash_get_protect();
}
+
+ /* Update all-now flag if all flash is protected */
+ if (prot_flags & EC_FLASH_PROTECT_ALL_NOW)
+ all_protected = 1;
+
} else {
/* Don't want RO flash protected */
unwanted_prot_flags |= EC_FLASH_PROTECT_RO_NOW;
diff --git a/common/flash_common.c b/common/flash_common.c
index 11cb8150f3..9407f3336a 100644
--- a/common/flash_common.c
+++ b/common/flash_common.c
@@ -155,6 +155,9 @@ static int command_flash_erase(int argc, char **argv)
int size = CONFIG_FLASH_ERASE_SIZE;
int rv;
+ if (flash_get_protect() & EC_FLASH_PROTECT_ALL_NOW)
+ return EC_ERROR_ACCESS_DENIED;
+
rv = parse_offset_size(argc, argv, 1, &offset, &size);
if (rv)
return rv;
@@ -175,6 +178,9 @@ static int command_flash_write(int argc, char **argv)
char *data;
int i;
+ if (flash_get_protect() & EC_FLASH_PROTECT_ALL_NOW)
+ return EC_ERROR_ACCESS_DENIED;
+
rv = parse_offset_size(argc, argv, 1, &offset, &size);
if (rv)
return rv;
@@ -268,6 +274,9 @@ static int flash_command_write(struct host_cmd_handler_args *args)
{
const struct ec_params_flash_write *p = args->params;
+ if (flash_get_protect() & EC_FLASH_PROTECT_ALL_NOW)
+ return EC_RES_ACCESS_DENIED;
+
if (p->size > sizeof(p->data))
return EC_RES_INVALID_PARAM;
@@ -287,6 +296,9 @@ static int flash_command_erase(struct host_cmd_handler_args *args)
{
const struct ec_params_flash_erase *p = args->params;
+ if (flash_get_protect() & EC_FLASH_PROTECT_ALL_NOW)
+ return EC_RES_ACCESS_DENIED;
+
if (system_unsafe_to_overwrite(p->offset, p->size))
return EC_RES_ACCESS_DENIED;