summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNicolas Boichat <drinkcat@google.com>2017-02-14 11:13:52 +0800
committerchrome-bot <chrome-bot@chromium.org>2017-02-25 08:36:41 -0800
commit2dcfd2446cbc0133d1351c018956c46717751e65 (patch)
treed69c6f9c5a0db457daf64f7835858fbd3fa9f157
parentf4174ddaa431ea8fccfda3e0efa66a34b46896d5 (diff)
downloadchrome-ec-2dcfd2446cbc0133d1351c018956c46717751e65.tar.gz
flash: Add ROLLBACK flash region, that can be protected separately
ROLLBACK region will be used to store rollback information, and can be protected independently of RW (it can only be protected when RO is protected, though). This is only supported on stm32f0 currently. BRANCH=none BUG=chrome-os-partner:61671 TEST=on hammer (stm32f072) flashinfo => RO+RW not protected flashwp true; reboot => only RO protected flashwp all; reboot => RO+RW+RB protected flashwp noall; reboot => only RO protected flashwp rw; reboot => only RO+RW protected flashwp rb; reboot => RO+RW+RB protected flashwp norb; reboot => RO+RW protected flashwp all; reboot => RO+RW+RB protected flashwp norw; reboot => RO+RB protected TEST=on reef, rb/norb commands not available Change-Id: I45ffc66d91cf3699ecff025e5114c59a73dc8274 Reviewed-on: https://chromium-review.googlesource.com/430519 Commit-Ready: Nicolas Boichat <drinkcat@chromium.org> Tested-by: Nicolas Boichat <drinkcat@chromium.org> Reviewed-by: Randall Spangler <rspangler@chromium.org>
-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)