diff options
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 */ |