diff options
author | Nicolas Boichat <drinkcat@google.com> | 2017-02-13 17:17:01 +0800 |
---|---|---|
committer | chrome-bot <chrome-bot@chromium.org> | 2017-02-23 19:06:16 -0800 |
commit | 83cf8d0a7a3e952da34740b9a1e255eaa64395af (patch) | |
tree | 0e14cd038b2b1e49998d8b0ef9fc8fecaee54851 /common/flash.c | |
parent | ed396c5efbadefaf7b6a7dee64258f063f4b9fd3 (diff) | |
download | chrome-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.c | 77 |
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 */ |