diff options
-rw-r--r-- | chip/stm32/flash-f.c | 14 | ||||
-rw-r--r-- | chip/stm32/flash-stm32f0.c | 23 | ||||
-rw-r--r-- | common/flash.c | 59 | ||||
-rw-r--r-- | include/config.h | 9 | ||||
-rw-r--r-- | include/ec_commands.h | 4 | ||||
-rw-r--r-- | include/flash.h | 17 | ||||
-rw-r--r-- | util/ectool.c | 4 |
7 files changed, 121 insertions, 9 deletions
diff --git a/chip/stm32/flash-f.c b/chip/stm32/flash-f.c index 2ab05859fa..8421ca61b1 100644 --- a/chip/stm32/flash-f.c +++ b/chip/stm32/flash-f.c @@ -356,6 +356,11 @@ int flash_physical_protect_at_boot(uint32_t new_flags) if (block >= WP_BANK_OFFSET && block < WP_BANK_OFFSET + WP_BANK_COUNT) protect |= new_flags & EC_FLASH_PROTECT_RO_AT_BOOT; +#ifdef CONFIG_ROLLBACK + else if (block >= ROLLBACK_BANK_OFFSET && + block < ROLLBACK_BANK_OFFSET + ROLLBACK_BANK_COUNT) + protect |= new_flags & EC_FLASH_PROTECT_ROLLBACK_AT_BOOT; +#endif #ifdef CONFIG_FLASH_PROTECT_RW else protect |= new_flags & EC_FLASH_PROTECT_RW_AT_BOOT; @@ -489,6 +494,15 @@ int flash_pre_init(void) } #endif +#ifdef CONFIG_ROLLBACK + if ((flash_physical_get_valid_flags() & EC_FLASH_PROTECT_ROLLBACK_AT_BOOT) && + (!!(prot_flags & EC_FLASH_PROTECT_ROLLBACK_AT_BOOT) != + !!(prot_flags & EC_FLASH_PROTECT_ROLLBACK_NOW))) { + /* ROLLBACK_AT_BOOT and ROLLBACK_NOW do not match. */ + need_reset = 1; + } +#endif + if (need_reset) system_reset(SYSTEM_RESET_HARD | SYSTEM_RESET_PRESERVE_FLAGS); diff --git a/chip/stm32/flash-stm32f0.c b/chip/stm32/flash-stm32f0.c index e047854d0a..6472b3e23b 100644 --- a/chip/stm32/flash-stm32f0.c +++ b/chip/stm32/flash-stm32f0.c @@ -35,12 +35,16 @@ uint32_t flash_physical_get_protect_flags(void) * ROLLBACK independently (EC_FLASH_PROTECT_RO_AT_BOOT should be set * by pstate logic). */ -#if defined(CONFIG_FLASH_PROTECT_RW) +#if defined(CONFIG_FLASH_PROTECT_RW) || defined(CONFIG_ROLLBACK) /* Flags that must be set for each region. */ const int mask_flags[] = { [FLASH_REGION_RW] = EC_FLASH_PROTECT_RW_AT_BOOT, [FLASH_REGION_RO] = EC_FLASH_PROTECT_RO_AT_BOOT, +#ifdef CONFIG_ROLLBACK + [FLASH_REGION_ROLLBACK] = EC_FLASH_PROTECT_ROLLBACK_AT_BOOT, +#endif }; + /* * Sets up required mask for wrp01/23 registers: for protection to be * set, values set in the mask must be zeros, values in the mask << 8 @@ -64,6 +68,11 @@ uint32_t flash_physical_get_protect_flags(void) if (i >= WP_BANK_OFFSET && i < WP_BANK_OFFSET + WP_BANK_COUNT) region = FLASH_REGION_RO; +#ifdef CONFIG_ROLLBACK + if (i >= ROLLBACK_BANK_OFFSET && + i < ROLLBACK_BANK_OFFSET + ROLLBACK_BANK_COUNT) + region = FLASH_REGION_ROLLBACK; +#endif switch (i) { case 8: @@ -94,7 +103,7 @@ uint32_t flash_physical_get_protect_flags(void) #endif flags |= mask_flags[i]; } -#endif /* CONFIG_FLASH_PROTECT_RW */ +#endif /* CONFIG_FLASH_PROTECT_RW || CONFIG_ROLLBACK */ if (wrp01 == 0xff00ff00) #if CONFIG_FLASH_SIZE > 64 * 1024 @@ -124,6 +133,10 @@ uint32_t flash_physical_get_valid_flags(void) EC_FLASH_PROTECT_RW_AT_BOOT | EC_FLASH_PROTECT_RW_NOW | #endif +#ifdef CONFIG_ROLLBACK + EC_FLASH_PROTECT_ROLLBACK_AT_BOOT | + EC_FLASH_PROTECT_ROLLBACK_NOW | +#endif EC_FLASH_PROTECT_ALL_AT_BOOT | EC_FLASH_PROTECT_ALL_NOW; } @@ -150,5 +163,11 @@ uint32_t flash_physical_get_writable_flags(uint32_t cur_flags) ret |= EC_FLASH_PROTECT_RW_AT_BOOT; #endif +#ifdef CONFIG_ROLLBACK + if (cur_flags & (EC_FLASH_PROTECT_ROLLBACK_AT_BOOT | + EC_FLASH_PROTECT_GPIO_ASSERTED)) + ret |= EC_FLASH_PROTECT_ROLLBACK_AT_BOOT; +#endif + return ret; } diff --git a/common/flash.c b/common/flash.c index 673c962295..020dbd727e 100644 --- a/common/flash.c +++ b/common/flash.c @@ -526,9 +526,15 @@ uint32_t flash_get_protect(void) int i; /* Region protection status */ int not_protected[FLASH_REGION_COUNT] = {0}; +#ifdef CONFIG_ROLLBACK /* 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 | + EC_FLASH_PROTECT_ROLLBACK_NOW; +#else + const uint32_t all_flags = EC_FLASH_PROTECT_RO_NOW | EC_FLASH_PROTECT_RW_NOW; +#endif /* Read write protect GPIO */ #ifdef CONFIG_WP_ALWAYS @@ -555,6 +561,14 @@ uint32_t flash_get_protect(void) int bank_flag = is_ro ? EC_FLASH_PROTECT_RO_NOW : EC_FLASH_PROTECT_RW_NOW; +#ifdef CONFIG_ROLLBACK + if (i >= ROLLBACK_BANK_OFFSET && + i < ROLLBACK_BANK_OFFSET + ROLLBACK_BANK_COUNT) { + region = FLASH_REGION_ROLLBACK; + bank_flag = EC_FLASH_PROTECT_ROLLBACK_NOW; + } +#endif + if (flash_physical_get_protect(i)) { /* At least one bank in the region is protected */ flags |= bank_flag; @@ -572,8 +586,8 @@ uint32_t flash_get_protect(void) flags |= EC_FLASH_PROTECT_ALL_NOW; /* - * If the RW banks are protected but the RO banks aren't, that's - * inconsistent. + * If the RW or ROLLBACK banks are protected but the RO banks aren't, + * that's inconsistent. * * Note that we check this before adding in the physical flags below, * since some chips can also protect ALL_NOW for the current boot by @@ -597,6 +611,7 @@ int flash_set_protect(uint32_t mask, uint32_t flags) int rv; int old_flags_at_boot = flash_get_protect() & (EC_FLASH_PROTECT_RO_AT_BOOT | EC_FLASH_PROTECT_RW_AT_BOOT | + EC_FLASH_PROTECT_ROLLBACK_AT_BOOT | EC_FLASH_PROTECT_ALL_AT_BOOT); int new_flags_at_boot = old_flags_at_boot; @@ -630,21 +645,32 @@ 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 */ + /* Removing ALL must also remove RW/ROLLBACK */ if ((mask & 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_ROLLBACK + new_flags_at_boot &= ~EC_FLASH_PROTECT_ROLLBACK_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; + new_flags_at_boot &= ~EC_FLASH_PROTECT_ALL_AT_BOOT; + } +#endif + +#ifdef CONFIG_ROLLBACK + if ((mask & EC_FLASH_PROTECT_ROLLBACK_AT_BOOT) && + !(flags & EC_FLASH_PROTECT_ROLLBACK_AT_BOOT)) { + new_flags_at_boot &= ~EC_FLASH_PROTECT_ROLLBACK_AT_BOOT; + new_flags_at_boot &= ~EC_FLASH_PROTECT_ALL_AT_BOOT; } #endif @@ -664,8 +690,8 @@ int flash_set_protect(uint32_t mask, uint32_t flags) return retval; /* - * The case where ALL/RW_AT_BOOT is unset is already covered above, - * so we do not need to mask it out. + * The case where ALL/RW/ROLLBACK_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; @@ -673,6 +699,10 @@ int flash_set_protect(uint32_t mask, uint32_t flags) new_flags_at_boot |= flags & EC_FLASH_PROTECT_RW_AT_BOOT; #endif +#ifdef CONFIG_ROLLBACK + new_flags_at_boot |= flags & EC_FLASH_PROTECT_ROLLBACK_AT_BOOT; +#endif + if (new_flags_at_boot != old_flags_at_boot) { rv = flash_protect_at_boot(new_flags_at_boot); if (rv) @@ -729,6 +759,12 @@ static int command_flash_info(int argc, char **argv) ccputs(" STUCK"); if (i & EC_FLASH_PROTECT_ERROR_INCONSISTENT) ccputs(" INCONSISTENT"); +#ifdef CONFIG_ROLLBACK + if (i & EC_FLASH_PROTECT_ROLLBACK_AT_BOOT) + ccputs(" rollback_at_boot"); + if (i & EC_FLASH_PROTECT_ROLLBACK_NOW) + ccputs(" rollback_now"); +#endif ccputs("\n"); ccputs("Protected now:"); @@ -882,6 +918,14 @@ static int command_flash_wp(int argc, char **argv) return flash_set_protect(EC_FLASH_PROTECT_RW_AT_BOOT, 0); #endif +#ifdef CONFIG_ROLLBACK + if (!strcasecmp(argv[1], "rb")) + return flash_set_protect(EC_FLASH_PROTECT_ROLLBACK_AT_BOOT, -1); + + if (!strcasecmp(argv[1], "norb")) + return flash_set_protect(EC_FLASH_PROTECT_ROLLBACK_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, @@ -894,6 +938,9 @@ DECLARE_CONSOLE_COMMAND(flashwp, command_flash_wp, #ifdef CONFIG_FLASH_PROTECT_RW " | rw | norw" #endif +#ifdef CONFIG_ROLLBACK + " | rb | norb" +#endif , "Modify flash write protect"); /*****************************************************************************/ diff --git a/include/config.h b/include/config.h index 129b1bd648..29625d201d 100644 --- a/include/config.h +++ b/include/config.h @@ -1113,6 +1113,15 @@ #undef CONFIG_WP_STORAGE_SIZE /* + * Rollback protect region. If CONFIG_ROLLBACK is defined to enable the rollback + * protect region, CONFIG_ROLLBACK_OFF and CONFIG_ROLLBACK_SIZE must be defined + * too. + */ +#undef CONFIG_ROLLBACK +#undef CONFIG_ROLLBACK_OFF +#undef CONFIG_ROLLBACK_SIZE + +/* * Board Image ec.bin contains a RO firmware. If not defined, the image will * only contain the RW firmware. The RO firmware comes from another board. */ diff --git a/include/ec_commands.h b/include/ec_commands.h index 2a44a7dded..ed8c333cf4 100644 --- a/include/ec_commands.h +++ b/include/ec_commands.h @@ -1213,6 +1213,10 @@ struct __ec_align4 ec_params_flash_erase { #define EC_FLASH_PROTECT_RW_AT_BOOT (1 << 7) /* RW flash code protected now. */ #define EC_FLASH_PROTECT_RW_NOW (1 << 8) +/* Rollback information flash region protected when the EC boots */ +#define EC_FLASH_PROTECT_ROLLBACK_AT_BOOT (1 << 9) +/* Rollback information flash region protected now */ +#define EC_FLASH_PROTECT_ROLLBACK_NOW (1 << 10) struct __ec_align4 ec_params_flash_protect { uint32_t mask; /* Bits in flags to apply */ diff --git a/include/flash.h b/include/flash.h index 548f889e72..2d50708f8a 100644 --- a/include/flash.h +++ b/include/flash.h @@ -12,9 +12,13 @@ #include "ec_commands.h" /* For EC_FLASH_PROTECT_* flags */ /* Number of physical flash banks */ +/* + * TODO(crosbug.com/p/62372): This assumes flash protection blocks are all of + * identical sizes, which is incorrect, for example, on STM32F091VC. + */ #define PHYSICAL_BANKS (CONFIG_FLASH_SIZE / CONFIG_FLASH_BANK_SIZE) -/*WP region offset and size in units of flash banks */ +/* WP region offset and size in units of flash banks */ #define WP_BANK_OFFSET (CONFIG_WP_STORAGE_OFF / CONFIG_FLASH_BANK_SIZE) #define WP_BANK_COUNT (CONFIG_WP_STORAGE_SIZE / CONFIG_FLASH_BANK_SIZE) @@ -26,10 +30,21 @@ #define PSTATE_BANK_COUNT 0 #endif +#ifdef CONFIG_ROLLBACK +/* + * ROLLBACK region offset and size in units of flash banks. + */ +#define ROLLBACK_BANK_OFFSET (CONFIG_ROLLBACK_OFF / CONFIG_FLASH_BANK_SIZE) +#define ROLLBACK_BANK_COUNT (CONFIG_ROLLBACK_SIZE / CONFIG_FLASH_BANK_SIZE) +#endif + /* This enum is useful to identify different regions during verification. */ enum flash_region { FLASH_REGION_RW = 0, FLASH_REGION_RO, +#ifdef CONFIG_ROLLBACK + FLASH_REGION_ROLLBACK, +#endif FLASH_REGION_COUNT }; diff --git a/util/ectool.c b/util/ectool.c index f2bf6662ce..5180a1a85b 100644 --- a/util/ectool.c +++ b/util/ectool.c @@ -909,12 +909,16 @@ static void print_flash_protect_flags(const char *desc, uint32_t flags) printf(" ro_at_boot"); if (flags & EC_FLASH_PROTECT_RW_AT_BOOT) printf(" rw_at_boot"); + if (flags & EC_FLASH_PROTECT_ROLLBACK_AT_BOOT) + printf(" rollback_at_boot"); if (flags & EC_FLASH_PROTECT_ALL_AT_BOOT) printf(" all_at_boot"); if (flags & EC_FLASH_PROTECT_RO_NOW) printf(" ro_now"); if (flags & EC_FLASH_PROTECT_RW_NOW) printf(" rw_now"); + if (flags & EC_FLASH_PROTECT_ROLLBACK_NOW) + printf(" rollback_now"); if (flags & EC_FLASH_PROTECT_ALL_NOW) printf(" all_now"); if (flags & EC_FLASH_PROTECT_ERROR_STUCK) |