summaryrefslogtreecommitdiff
path: root/common/flash.c
diff options
context:
space:
mode:
authorNicolas Boichat <drinkcat@google.com>2017-02-13 17:17:01 +0800
committerchrome-bot <chrome-bot@chromium.org>2017-02-23 19:06:16 -0800
commit83cf8d0a7a3e952da34740b9a1e255eaa64395af (patch)
tree0e14cd038b2b1e49998d8b0ef9fc8fecaee54851 /common/flash.c
parented396c5efbadefaf7b6a7dee64258f063f4b9fd3 (diff)
downloadchrome-ec-83cf8d0a7a3e952da34740b9a1e255eaa64395af.tar.gz
flash: Add EC_FLASH_PROTECT_RW_[AT_BOOT|NOW] flagsstabilize-9313.B
The idea of this flag is to be able to protect/unprotect only the RW portion of the flash. In the (usual) case where ALL=RO+RW, with no other region, this makes no difference compared to the existing EC_FLASH_PROTECT_ALL_* flag, and this flag may not be supported. This is necessary for futher work, where a ROLLBACK region is added, so that RW/ROLLBACK can be protected/unprotected individually. Only support for stm32f0 is added, as this is the target for hammer. BRANCH=none BUG=chrome-os-partner:61671 TEST=build and flash hammer (stm32f072) flashinfo => RO+RW not protected flashwp true; reboot => only RO protected flashwp all; reboot => RO+RW protected flashwp noall; reboot => only RO protected flashwp rw/norw not available TEST=enable CONFIG_FLASH_PROTECT_RW build and flash hammer (stm32f072) flashinfo => RO+RW not protected flashwp true; reboot => only RO protected flashwp all; reboot => RO+RW protected flashwp noall; reboot => only RO protected flashwp rw; reboot => RO+RW protected flashwp norw; reboot => only RO protected TEST=build and flash reef (npcx) flashinfo => RO+RW not protected flashwp true => RO protected flashwp all; flashinfo => all_now displayed reboot => RO protected flashwp rw/norw not available Change-Id: Ica6f499cf2e8a9345b08ef52c915655a983ffe3c Reviewed-on: https://chromium-review.googlesource.com/442265 Commit-Ready: Nicolas Boichat <drinkcat@chromium.org> Tested-by: Nicolas Boichat <drinkcat@chromium.org> Reviewed-by: Randall Spangler <rspangler@chromium.org>
Diffstat (limited to 'common/flash.c')
-rw-r--r--common/flash.c77
1 files changed, 62 insertions, 15 deletions
diff --git a/common/flash.c b/common/flash.c
index 275e4692e8..673c962295 100644
--- a/common/flash.c
+++ b/common/flash.c
@@ -523,8 +523,12 @@ int flash_protect_at_boot(uint32_t new_flags)
uint32_t flash_get_protect(void)
{
uint32_t flags = 0;
- int not_protected[2] = {0};
int i;
+ /* Region protection status */
+ int not_protected[FLASH_REGION_COUNT] = {0};
+ /* Flags that must be set to set ALL_NOW flag. */
+ const uint32_t all_flags = EC_FLASH_PROTECT_RO_NOW |
+ EC_FLASH_PROTECT_RW_NOW;
/* Read write protect GPIO */
#ifdef CONFIG_WP_ALWAYS
@@ -544,26 +548,29 @@ uint32_t flash_get_protect(void)
/* Scan flash protection */
for (i = 0; i < PHYSICAL_BANKS; i++) {
- /* Is this bank part of RO */
int is_ro = (i >= WP_BANK_OFFSET &&
- i < WP_BANK_OFFSET + WP_BANK_COUNT) ? 1 : 0;
-
- int bank_flag = (is_ro ? EC_FLASH_PROTECT_RO_NOW :
- EC_FLASH_PROTECT_ALL_NOW);
+ i < WP_BANK_OFFSET + WP_BANK_COUNT);
+ enum flash_region region = is_ro ? FLASH_REGION_RO :
+ FLASH_REGION_RW;
+ int bank_flag = is_ro ? EC_FLASH_PROTECT_RO_NOW :
+ EC_FLASH_PROTECT_RW_NOW;
if (flash_physical_get_protect(i)) {
/* At least one bank in the region is protected */
flags |= bank_flag;
- if (not_protected[is_ro])
+ if (not_protected[region])
flags |= EC_FLASH_PROTECT_ERROR_INCONSISTENT;
} else {
/* At least one bank in the region is NOT protected */
- not_protected[is_ro] = 1;
+ not_protected[region] = 1;
if (flags & bank_flag)
flags |= EC_FLASH_PROTECT_ERROR_INCONSISTENT;
}
}
+ if ((flags & all_flags) == all_flags)
+ flags |= EC_FLASH_PROTECT_ALL_NOW;
+
/*
* If the RW banks are protected but the RO banks aren't, that's
* inconsistent.
@@ -572,10 +579,14 @@ uint32_t flash_get_protect(void)
* since some chips can also protect ALL_NOW for the current boot by
* locking up the flash program-erase registers.
*/
- if ((flags & EC_FLASH_PROTECT_ALL_NOW) &&
- !(flags & EC_FLASH_PROTECT_RO_NOW))
+ if ((flags & all_flags) && !(flags & EC_FLASH_PROTECT_RO_NOW))
flags |= EC_FLASH_PROTECT_ERROR_INCONSISTENT;
+#ifndef CONFIG_FLASH_PROTECT_RW
+ /* RW flag was used for intermediate computations, clear it now. */
+ flags &= ~EC_FLASH_PROTECT_RW_NOW;
+#endif
+
/* Add in flags from physical layer */
return flags | flash_physical_get_protect_flags();
}
@@ -585,7 +596,8 @@ int flash_set_protect(uint32_t mask, uint32_t flags)
int retval = EC_SUCCESS;
int rv;
int old_flags_at_boot = flash_get_protect() &
- (EC_FLASH_PROTECT_RO_AT_BOOT | EC_FLASH_PROTECT_ALL_AT_BOOT);
+ (EC_FLASH_PROTECT_RO_AT_BOOT | EC_FLASH_PROTECT_RW_AT_BOOT |
+ EC_FLASH_PROTECT_ALL_AT_BOOT);
int new_flags_at_boot = old_flags_at_boot;
/* Sanitize input flags */
@@ -618,9 +630,23 @@ int flash_set_protect(uint32_t mask, uint32_t flags)
new_flags_at_boot &= ~(mask & EC_FLASH_PROTECT_RO_AT_BOOT);
new_flags_at_boot |= flags & EC_FLASH_PROTECT_RO_AT_BOOT;
+ /* Removing ALL must also remove RW */
if ((mask & EC_FLASH_PROTECT_ALL_AT_BOOT) &&
- !(flags & EC_FLASH_PROTECT_ALL_AT_BOOT))
+ !(flags & EC_FLASH_PROTECT_ALL_AT_BOOT)) {
new_flags_at_boot &= ~EC_FLASH_PROTECT_ALL_AT_BOOT;
+#ifdef CONFIG_FLASH_PROTECT_RW
+ new_flags_at_boot &= ~EC_FLASH_PROTECT_RW_AT_BOOT;
+#endif
+ }
+
+#ifdef CONFIG_FLASH_PROTECT_RW
+ /* Removing RW must also remove ALL (otherwise nothing will happen). */
+ if ((mask & EC_FLASH_PROTECT_RW_AT_BOOT) &&
+ !(flags & EC_FLASH_PROTECT_RW_AT_BOOT)) {
+ new_flags_at_boot &= ~EC_FLASH_PROTECT_ALL_AT_BOOT;
+ new_flags_at_boot &= ~EC_FLASH_PROTECT_RW_AT_BOOT;
+ }
+#endif
if (new_flags_at_boot != old_flags_at_boot) {
rv = flash_protect_at_boot(new_flags_at_boot);
@@ -638,11 +664,15 @@ int flash_set_protect(uint32_t mask, uint32_t flags)
return retval;
/*
- * The case where ALL_AT_BOOT is unset is already covered above,
+ * The case where ALL/RW_AT_BOOT is unset is already covered above,
* so we do not need to mask it out.
*/
new_flags_at_boot |= flags & EC_FLASH_PROTECT_ALL_AT_BOOT;
+#ifdef CONFIG_FLASH_PROTECT_RW
+ new_flags_at_boot |= flags & EC_FLASH_PROTECT_RW_AT_BOOT;
+#endif
+
if (new_flags_at_boot != old_flags_at_boot) {
rv = flash_protect_at_boot(new_flags_at_boot);
if (rv)
@@ -689,6 +719,12 @@ static int command_flash_info(int argc, char **argv)
ccputs(" ro_now");
if (i & EC_FLASH_PROTECT_ALL_NOW)
ccputs(" all_now");
+#ifdef CONFIG_FLASH_PROTECT_RW
+ if (i & EC_FLASH_PROTECT_RW_AT_BOOT)
+ ccputs(" rw_at_boot");
+ if (i & EC_FLASH_PROTECT_RW_NOW)
+ ccputs(" rw_now");
+#endif
if (i & EC_FLASH_PROTECT_ERROR_STUCK)
ccputs(" STUCK");
if (i & EC_FLASH_PROTECT_ERROR_INCONSISTENT)
@@ -838,6 +874,14 @@ static int command_flash_wp(int argc, char **argv)
if (!strcasecmp(argv[1], "noall"))
return flash_set_protect(EC_FLASH_PROTECT_ALL_AT_BOOT, 0);
+#ifdef CONFIG_FLASH_PROTECT_RW
+ if (!strcasecmp(argv[1], "rw"))
+ return flash_set_protect(EC_FLASH_PROTECT_RW_AT_BOOT, -1);
+
+ if (!strcasecmp(argv[1], "norw"))
+ return flash_set_protect(EC_FLASH_PROTECT_RW_AT_BOOT, 0);
+#endif
+
/* Do this last, since anything starting with 'n' means "no" */
if (parse_bool(argv[1], &val))
return flash_set_protect(EC_FLASH_PROTECT_RO_AT_BOOT,
@@ -846,8 +890,11 @@ static int command_flash_wp(int argc, char **argv)
return EC_ERROR_PARAM1;
}
DECLARE_CONSOLE_COMMAND(flashwp, command_flash_wp,
- "<BOOLEAN> | now | all | noall",
- "Modify flash write protect");
+ "<BOOLEAN> | now | all | noall"
+#ifdef CONFIG_FLASH_PROTECT_RW
+ " | rw | norw"
+#endif
+ , "Modify flash write protect");
/*****************************************************************************/
/* Host commands */