summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--chip/stm32/flash-f.c14
-rw-r--r--chip/stm32/flash-stm32f0.c23
-rw-r--r--common/flash.c59
-rw-r--r--include/config.h9
-rw-r--r--include/ec_commands.h4
-rw-r--r--include/flash.h17
-rw-r--r--util/ectool.c4
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)