summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRandall Spangler <rspangler@chromium.org>2013-05-20 15:14:01 -0700
committerChromeBot <chrome-bot@google.com>2013-05-23 11:08:44 -0700
commitbd8fec9bae8fc36cc1e46bf0417f2da00530b522 (patch)
treefaec9b729b3ff9bd62c8fda2ce804bdae67fcddd
parentaa419b29ac9d012333a416696c7449047e085d29 (diff)
downloadchrome-ec-bd8fec9bae8fc36cc1e46bf0417f2da00530b522.tar.gz
Move flash persistent state to flash_common
Persistent state is needed by all platforms to hold the protect-ro-at-boot flag. STM32F100 and LM4 implementations were near-identical, and are now common code (with one #ifdef to handle the single place where they weren't). STM32L doesn't use pstate yet, but it'll need to. I can't simply store the protect-ro-at-boot flag inside the WRP registers themselves because they're still writable in EC-RW. The change to STM32L to use pstate is coming next. BUG=chrome-os-partner:15613 BRANCH=none TEST=build pit, link, spring; on link and spring, do - flashinfo -> (no flags) - enable WP (via screw or dut-control) - flashinfo -> wp_gpio_asserted - flashwp enable - flashinfo -> wp_gpio_asserted ro_at_boot - flashwp now - flashinfo -> wp_gpio_asserted ro_at_boot all_now (and possibly ro_now) - flashwp disable -> fails - flashinfo -> wp_gpio_asserted ro_at_boot all_now - reboot ap-off - flashinfo -> wp_gpio_asserted ro_at_boot ro_now - disable WP (via screw or dut-control) - reboot - flashinfo -> ro_at_boot - flashwp disable - flashinfo -> (no flags) (Note that on Spring you'll need to 'forceen on' before enabling WP, or the console will be disabled once you enable ro_at_boot and reboot.) Change-Id: I415388b98ec8bf1d149803aaaa7fe8c7f3076c36 Signed-off-by: Randall Spangler <rspangler@chromium.org> Reviewed-on: https://gerrit.chromium.org/gerrit/56064
-rw-r--r--chip/lm4/flash.c119
-rw-r--r--chip/stm32/config-stm32l15x.h10
-rw-r--r--chip/stm32/config.h3
-rw-r--r--chip/stm32/flash-stm32f100.c144
-rw-r--r--chip/stm32/flash-stm32l15x.c21
-rw-r--r--common/flash_common.c112
-rw-r--r--include/flash.h49
7 files changed, 194 insertions, 264 deletions
diff --git a/chip/lm4/flash.c b/chip/lm4/flash.c
index 0b451d53ad..f7a08d67dd 100644
--- a/chip/lm4/flash.c
+++ b/chip/lm4/flash.c
@@ -25,121 +25,9 @@
#define ERASE_TIMEOUT_MS 200
#define WRITE_TIMEOUT_US 300
-/* Number of physical banks of flash */
-#define PHYSICAL_BANKS (CONFIG_FLASH_PHYSICAL_SIZE / CONFIG_FLASH_BANK_SIZE)
-
-/* Persistent protection state flash offset / size / bank */
-#define PSTATE_OFFSET CONFIG_SECTION_FLASH_PSTATE_OFF
-#define PSTATE_SIZE CONFIG_SECTION_FLASH_PSTATE_SIZE
-#define PSTATE_BANK (PSTATE_OFFSET / CONFIG_FLASH_BANK_SIZE)
-
-/* Read-only firmware offset and size in units of flash banks */
-#define RO_BANK_OFFSET (CONFIG_SECTION_RO_OFF / CONFIG_FLASH_BANK_SIZE)
-#define RO_BANK_COUNT (CONFIG_SECTION_RO_SIZE / CONFIG_FLASH_BANK_SIZE)
-
int stuck_locked; /* Is physical flash stuck protected? */
int all_protected; /* Has all-flash protection been requested? */
-/* Persistent protection state - emulates a SPI status register for flashrom */
-struct persist_state {
- uint8_t version; /* Version of this struct */
- uint8_t flags; /* Lock flags (PERSIST_FLAG_*) */
- uint8_t reserved[2]; /* Reserved; set 0 */
-};
-
-#define PERSIST_STATE_VERSION 2 /* Expected persist_state.version */
-
-/* Flags for persist_state.flags */
-/* Protect persist state and RO firmware at boot */
-#define PERSIST_FLAG_PROTECT_RO 0x02
-
-/**
- * Read persistent state into pstate.
- *
- * @param pstate Destination for persistent state
- */
-static void read_pstate(struct persist_state *pstate)
-{
- memcpy(pstate, flash_physical_dataptr(PSTATE_OFFSET), sizeof(*pstate));
-
- /* Sanity-check data and initialize if necessary */
- if (pstate->version != PERSIST_STATE_VERSION) {
- memset(pstate, 0, sizeof(*pstate));
- pstate->version = PERSIST_STATE_VERSION;
- }
-}
-
-/**
- * Write persistent state from pstate, erasing if necessary.
- *
- * @param pstate Source persistent state
- * @return EC_SUCCESS, or nonzero if error.
- */
-static int write_pstate(const struct persist_state *pstate)
-{
- struct persist_state current_pstate;
- int rv;
-
- /* Check if pstate has actually changed */
- read_pstate(&current_pstate);
- if (!memcmp(&current_pstate, pstate, sizeof(*pstate)))
- return EC_SUCCESS;
-
- /* Erase pstate */
- rv = flash_physical_erase(PSTATE_OFFSET, PSTATE_SIZE);
- if (rv)
- return rv;
-
- /*
- * Note that if we lose power in here, we'll lose the pstate contents.
- * That's ok, because it's only possible to write the pstate before
- * it's protected.
- */
-
- /* Rewrite the data */
- return flash_physical_write(PSTATE_OFFSET, sizeof(*pstate),
- (const char *)pstate);
-}
-
-/**
- * Enable write protect for the read-only code.
- *
- * Once write protect is enabled, it will STAY enabled until the system is
- * hard-rebooted with the hardware write protect pin deasserted. If the write
- * protect pin is deasserted, the protect setting is ignored, and the entire
- * flash will be writable.
- *
- * @param enable Enable write protection
- * @return EC_SUCCESS, or nonzero if error.
- */
-static int protect_ro_at_boot(int enable)
-{
- struct persist_state pstate;
- int new_flags = enable ? PERSIST_FLAG_PROTECT_RO : 0;
- int rv;
-
- /* Read the current persist state from flash */
- read_pstate(&pstate);
-
- /* Update state if necessary */
- if (pstate.flags != new_flags) {
-
- /* Fail if write protect block is already locked */
- if (flash_physical_get_protect(PSTATE_BANK))
- return EC_ERROR_ACCESS_DENIED;
-
- /* Set the new flag */
- pstate.flags = new_flags;
-
- /* Write the state back to flash */
- rv = write_pstate(&pstate);
- if (rv)
- return rv;
- }
-
- return EC_SUCCESS;
-}
-
/**
* Protect flash banks until reboot.
*
@@ -293,7 +181,6 @@ int flash_physical_get_protect(int bank)
uint32_t flash_get_protect(void)
{
- struct persist_state pstate;
uint32_t flags = 0;
int not_protected[2] = {0};
int i;
@@ -303,8 +190,7 @@ uint32_t flash_get_protect(void)
flags |= EC_FLASH_PROTECT_ALL_NOW;
/* Read the current persist state from flash */
- read_pstate(&pstate);
- if (pstate.flags & PERSIST_FLAG_PROTECT_RO)
+ if (flash_get_protect_ro_at_boot())
flags |= EC_FLASH_PROTECT_RO_AT_BOOT;
#ifdef HAS_TASK_SWITCH
@@ -356,7 +242,8 @@ int flash_set_protect(uint32_t mask, uint32_t flags)
* all flags before returning.
*/
if (mask & EC_FLASH_PROTECT_RO_AT_BOOT) {
- rv = protect_ro_at_boot(flags & EC_FLASH_PROTECT_RO_AT_BOOT);
+ rv = flash_protect_ro_at_boot(
+ flags & EC_FLASH_PROTECT_RO_AT_BOOT);
if (rv)
retval = rv;
}
diff --git a/chip/stm32/config-stm32l15x.h b/chip/stm32/config-stm32l15x.h
index 9014ce5717..83af295f9d 100644
--- a/chip/stm32/config-stm32l15x.h
+++ b/chip/stm32/config-stm32l15x.h
@@ -27,7 +27,8 @@
#define CONFIG_FW_IMAGE_SIZE (64 * 1024)
#define CONFIG_FW_RO_OFF 0
-#define CONFIG_FW_RO_SIZE CONFIG_FW_IMAGE_SIZE
+#define CONFIG_FW_RO_SIZE (CONFIG_FW_IMAGE_SIZE \
+ - CONFIG_SECTION_FLASH_PSTATE_SIZE)
#define CONFIG_FW_RW_OFF CONFIG_FW_IMAGE_SIZE
#define CONFIG_FW_RW_SIZE CONFIG_FW_IMAGE_SIZE
@@ -39,12 +40,11 @@
#define CONFIG_SECTION_WP_RO_SIZE CONFIG_FW_RO_SIZE
/*
- * The EC uses the top bank of flash to emulate a SPI-like write protect
- * register with persistent state. Put that up at the top.
+ * Put this after RO to give RW more space. This also makes RO write protect
+ * region contiguous.
*/
#define CONFIG_SECTION_FLASH_PSTATE_SIZE (1 * CONFIG_FLASH_BANK_SIZE)
-#define CONFIG_SECTION_FLASH_PSTATE_OFF (CONFIG_FLASH_SIZE \
- - CONFIG_SECTION_FLASH_PSTATE_SIZE)
+#define CONFIG_SECTION_FLASH_PSTATE_OFF (CONFIG_FW_RO_OFF + CONFIG_FW_RO_SIZE)
/* Number of IRQ vectors on the NVIC */
#define CONFIG_IRQ_COUNT 45
diff --git a/chip/stm32/config.h b/chip/stm32/config.h
index ef97180ebd..d4107b1d36 100644
--- a/chip/stm32/config.h
+++ b/chip/stm32/config.h
@@ -46,6 +46,9 @@
/* Enable watchdog timer */
#define CONFIG_WATCHDOG
+/* Flash protection applies to the next boot, not the current one */
+#define CONFIG_FLASH_PROTECT_NEXT_BOOT
+
/* Compile for running from RAM instead of flash */
/* #define COMPILE_FOR_RAM */
diff --git a/chip/stm32/flash-stm32f100.c b/chip/stm32/flash-stm32f100.c
index 45ce7e4bfc..8343b82f37 100644
--- a/chip/stm32/flash-stm32f100.c
+++ b/chip/stm32/flash-stm32f100.c
@@ -42,35 +42,6 @@
#define PRG_LOCK 0
#define OPT_LOCK (1<<9)
-#define PHYSICAL_BANKS (CONFIG_FLASH_PHYSICAL_SIZE / CONFIG_FLASH_BANK_SIZE)
-
-/* Persistent protection state flash offset / size / bank */
-#define PSTATE_OFFSET CONFIG_SECTION_FLASH_PSTATE_OFF
-#define PSTATE_SIZE CONFIG_SECTION_FLASH_PSTATE_SIZE
-#define PSTATE_BANK (PSTATE_OFFSET / CONFIG_FLASH_BANK_SIZE)
-#define PSTATE_BANK_COUNT (PSTATE_SIZE / CONFIG_FLASH_BANK_SIZE)
-
-/* Read-only firmware offset and size in units of flash banks */
-#define RO_BANK_OFFSET (CONFIG_SECTION_RO_OFF / CONFIG_FLASH_BANK_SIZE)
-#define RO_BANK_COUNT (CONFIG_SECTION_RO_SIZE / CONFIG_FLASH_BANK_SIZE)
-
-/* Read-write firmware offset and size in units of flash banks */
-#define RW_BANK_OFFSET (CONFIG_SECTION_RW_OFF / CONFIG_FLASH_BANK_SIZE)
-#define RW_BANK_COUNT (CONFIG_SECTION_RW_SIZE / CONFIG_FLASH_BANK_SIZE)
-
-/* Persistent protection state - emulates a SPI status register for flashrom */
-struct persist_state {
- uint8_t version; /* Version of this struct */
- uint8_t flags; /* Lock flags (PERSIST_FLAG_*) */
- uint8_t reserved[2]; /* Reserved; set 0 */
-};
-
-#define PERSIST_STATE_VERSION 2 /* Expected persist_state.version */
-
-/* Flags for persist_state.flags */
-/* Protect persist state and RO firmware at boot */
-#define PERSIST_FLAG_PROTECT_RO 0x02
-
/* Flag indicating whether we have locked down entire flash */
static int entire_flash_locked;
@@ -239,56 +210,6 @@ static int write_optb(int byte, uint8_t value)
return EC_SUCCESS;
}
-/**
- * Read persistent state into pstate.
- *
- * @param pstate Destination for persistent state
- */
-static int read_pstate(struct persist_state *pstate)
-{
- memcpy(pstate, flash_physical_dataptr(PSTATE_OFFSET), sizeof(*pstate));
-
- /* Sanity-check data and initialize if necessary */
- if (pstate->version != PERSIST_STATE_VERSION) {
- memset(pstate, 0, sizeof(*pstate));
- pstate->version = PERSIST_STATE_VERSION;
- }
-
- return EC_SUCCESS;
-}
-
-/**
- * Write persistent state from pstate, erasing if necessary.
- *
- * @param pstate Source persistent state
- * @return EC_SUCCESS, or nonzero if error.
- */
-static int write_pstate(const struct persist_state *pstate)
-{
- struct persist_state current_pstate;
- int rv;
-
- /* Check if pstate has actually changed */
- if (!read_pstate(&current_pstate) &&
- !memcmp(&current_pstate, pstate, sizeof(*pstate)))
- return EC_SUCCESS;
-
- /* Erase pstate */
- rv = flash_physical_erase(PSTATE_OFFSET, PSTATE_SIZE);
- if (rv)
- return rv;
-
- /*
- * Note that if we lose power in here, we'll lose the pstate contents.
- * That's ok, because it's only possible to write the pstate before
- * it's protected.
- */
-
- /* Rewrite the data */
- return flash_physical_write(PSTATE_OFFSET, sizeof(*pstate),
- (const char *)pstate);
-}
-
/*****************************************************************************/
/* Physical layer APIs */
@@ -428,9 +349,8 @@ static int flash_physical_get_protect_at_boot(int block)
return (!(val & (1 << (block % 8)))) ? 1 : 0;
}
-static void flash_physical_set_protect_at_boot(int start_bank,
- int bank_count,
- int enable)
+int flash_physical_set_protect_at_boot(int start_bank, int bank_count,
+ int enable)
{
int block;
int i;
@@ -450,40 +370,6 @@ static void flash_physical_set_protect_at_boot(int start_bank,
for (i = 0; i < 4; ++i)
if (original_val[i] != val[i])
write_optb(i * 2 + 8, val[i]);
-}
-
-static int protect_ro_at_boot(int enable, int force)
-{
- struct persist_state pstate;
- int new_flags = enable ? PERSIST_FLAG_PROTECT_RO : 0;
- int rv;
-
- /* Read the current persist state from flash */
- rv = read_pstate(&pstate);
- if (rv)
- return rv;
-
- /* Update state if necessary */
- if (pstate.flags != new_flags || force) {
- /* Fail if write protect block is already locked */
- if (flash_physical_get_protect(PSTATE_BANK))
- return EC_ERROR_ACCESS_DENIED;
-
- /* Set the new flag */
- pstate.flags = new_flags;
-
- /* Write the state back to flash */
- rv = write_pstate(&pstate);
- if (rv)
- return rv;
-
- /*
- * Write to write protect register.
- * Since we already wrote to pstate, ignore error here.
- */
- flash_physical_set_protect_at_boot(RO_BANK_OFFSET,
- RO_BANK_COUNT + PSTATE_BANK_COUNT, new_flags);
- }
return EC_SUCCESS;
}
@@ -559,20 +445,25 @@ int flash_pre_init(void)
if ((prot_flags & EC_FLASH_PROTECT_RO_AT_BOOT) &&
!(prot_flags & EC_FLASH_PROTECT_RO_NOW)) {
/*
- * Pstate say "ro_at_boot". WP register says otherwise.
- * Listen to pstate.
+ * Pstate wants RO protected at boot, but the write
+ * protect register wasn't set to protect it. Force an
+ * update to the write protect register and reboot so
+ * it takes effect.
*/
- protect_ro_at_boot(1, 1);
+ flash_protect_ro_at_boot(1);
need_reset = 1;
}
if (registers_need_reset()) {
/*
- * Reset RO protect registers to make sure this doesn't
- * happen again due to RO protect state inconsistency.
+ * Write protect register was in an inconsistent state.
+ * Set it back to a good state and reboot.
+ *
+ * TODO: this seems really similar to the check above.
+ * One of them should be able to go away.
*/
- protect_ro_at_boot(
- prot_flags & EC_FLASH_PROTECT_RO_AT_BOOT, 1);
+ flash_protect_ro_at_boot(
+ prot_flags & EC_FLASH_PROTECT_RO_AT_BOOT);
need_reset = 1;
}
}
@@ -595,7 +486,6 @@ int flash_pre_init(void)
uint32_t flash_get_protect(void)
{
- struct persist_state pstate;
uint32_t flags = 0;
int i;
int not_protected[2] = {0};
@@ -604,8 +494,7 @@ uint32_t flash_get_protect(void)
flags |= EC_FLASH_PROTECT_GPIO_ASSERTED;
/* Read the current persist state from flash */
- read_pstate(&pstate);
- if (pstate.flags & PERSIST_FLAG_PROTECT_RO)
+ if (flash_get_protect_ro_at_boot())
flags |= EC_FLASH_PROTECT_RO_AT_BOOT;
if (entire_flash_locked) {
@@ -646,7 +535,8 @@ int flash_set_protect(uint32_t mask, uint32_t flags)
* all flags before returning.
*/
if (mask & EC_FLASH_PROTECT_RO_AT_BOOT) {
- rv = protect_ro_at_boot(flags & EC_FLASH_PROTECT_RO_AT_BOOT, 0);
+ rv = flash_protect_ro_at_boot(
+ flags & EC_FLASH_PROTECT_RO_AT_BOOT);
if (rv)
retval = rv;
}
diff --git a/chip/stm32/flash-stm32l15x.c b/chip/stm32/flash-stm32l15x.c
index 8fa1d711d4..d119dbb41c 100644
--- a/chip/stm32/flash-stm32l15x.c
+++ b/chip/stm32/flash-stm32l15x.c
@@ -26,12 +26,6 @@
#define FLASH_TIMEOUT_LOOP \
(FLASH_TIMEOUT_US * (CPU_CLOCK / SECOND) / CYCLE_PER_FLASH_LOOP)
-#define PHYSICAL_BANKS (CONFIG_FLASH_PHYSICAL_SIZE / CONFIG_FLASH_BANK_SIZE)
-
-/* Read-only firmware offset and size in units of flash banks */
-#define RO_BANK_OFFSET (CONFIG_SECTION_RO_OFF / CONFIG_FLASH_BANK_SIZE)
-#define RO_BANK_COUNT (CONFIG_SECTION_RO_SIZE / CONFIG_FLASH_BANK_SIZE)
-
#ifdef CONFIG_64B_WORKAROUND
/*
* Use the real write buffer size inside the driver. We only lie to the
@@ -336,8 +330,8 @@ int flash_physical_get_protect(int block)
return STM32_FLASH_WRPR & (1 << block);
}
-static int flash_physical_set_protect(int start_bank, int bank_count,
- int enable)
+int flash_physical_set_protect_at_boot(int start_bank, int bank_count,
+ int enable)
{
uint32_t prot;
uint32_t mask = ((1 << bank_count) - 1) << start_bank;
@@ -366,13 +360,6 @@ static int flash_physical_set_protect(int start_bank, int bank_count,
/* Relock */
lock(0);
- /*
- * Note that on STM32L, the flash protection bits are only read from
- * the option bytes at power-on or if OBL_LAUNCH is set in PECR (which
- * causes a reboot). Until then, the previous protection bits apply.
- * We take care of the reboot in flash_pre_init().
- */
-
return EC_SUCCESS;
}
@@ -456,7 +443,9 @@ int flash_set_protect(uint32_t mask, uint32_t flags)
* Start with the persistent state of at-boot protection.
*/
if (mask & EC_FLASH_PROTECT_RO_AT_BOOT) {
- rv = flash_physical_set_protect(RO_BANK_OFFSET, RO_BANK_COUNT,
+ rv = flash_physical_set_protect_at_boot(
+ RO_BANK_OFFSET,
+ RO_BANK_COUNT,
flags & EC_FLASH_PROTECT_RO_AT_BOOT);
if (rv)
retval = rv;
diff --git a/common/flash_common.c b/common/flash_common.c
index c7767c031f..b86c631fd8 100644
--- a/common/flash_common.c
+++ b/common/flash_common.c
@@ -15,6 +15,67 @@
#include "util.h"
#include "vboot_hash.h"
+/* Persistent protection state - emulates a SPI status register for flashrom */
+struct persist_state {
+ uint8_t version; /* Version of this struct */
+ uint8_t flags; /* Lock flags (PERSIST_FLAG_*) */
+ uint8_t reserved[2]; /* Reserved; set 0 */
+};
+
+#define PERSIST_STATE_VERSION 2 /* Expected persist_state.version */
+
+/* Flags for persist_state.flags */
+/* Protect persist state and RO firmware at boot */
+#define PERSIST_FLAG_PROTECT_RO 0x02
+
+/**
+ * Read persistent state into pstate.
+ *
+ * @param pstate Destination for persistent state
+ */
+static void flash_read_pstate(struct persist_state *pstate)
+{
+ memcpy(pstate, flash_physical_dataptr(PSTATE_OFFSET), sizeof(*pstate));
+
+ /* Sanity-check data and initialize if necessary */
+ if (pstate->version != PERSIST_STATE_VERSION) {
+ memset(pstate, 0, sizeof(*pstate));
+ pstate->version = PERSIST_STATE_VERSION;
+ }
+}
+
+/**
+ * Write persistent state from pstate, erasing if necessary.
+ *
+ * @param pstate Source persistent state
+ * @return EC_SUCCESS, or nonzero if error.
+ */
+static int flash_write_pstate(const struct persist_state *pstate)
+{
+ struct persist_state current_pstate;
+ int rv;
+
+ /* Check if pstate has actually changed */
+ flash_read_pstate(&current_pstate);
+ if (!memcmp(&current_pstate, pstate, sizeof(*pstate)))
+ return EC_SUCCESS;
+
+ /* Erase pstate */
+ rv = flash_physical_erase(PSTATE_OFFSET, PSTATE_SIZE);
+ if (rv)
+ return rv;
+
+ /*
+ * Note that if we lose power in here, we'll lose the pstate contents.
+ * That's ok, because it's only possible to write the pstate before
+ * it's protected.
+ */
+
+ /* Rewrite the data */
+ return flash_physical_write(PSTATE_OFFSET, sizeof(*pstate),
+ (const char *)pstate);
+}
+
int flash_dataptr(int offset, int size_req, int align, char **ptrp)
{
if (offset < 0 || size_req < 0 ||
@@ -68,6 +129,57 @@ test_mockable int flash_erase(int offset, int size)
return flash_physical_erase(offset, size);
}
+int flash_get_protect_ro_at_boot(void)
+{
+ struct persist_state pstate;
+
+ flash_read_pstate(&pstate);
+
+ return (pstate.flags & PERSIST_FLAG_PROTECT_RO) ? 1 : 0;
+}
+
+int flash_protect_ro_at_boot(int enable)
+{
+ struct persist_state pstate;
+ int new_flags = enable ? PERSIST_FLAG_PROTECT_RO : 0;
+
+ /* Read the current persist state from flash */
+ flash_read_pstate(&pstate);
+
+ if (pstate.flags != new_flags) {
+ /* Need to update pstate */
+ int rv;
+
+ /* Fail if write protect block is already locked */
+ if (flash_physical_get_protect(PSTATE_BANK))
+ return EC_ERROR_ACCESS_DENIED;
+
+ /* Set the new flag */
+ pstate.flags = new_flags;
+
+ /* Write the state back to flash */
+ rv = flash_write_pstate(&pstate);
+ if (rv)
+ return rv;
+ }
+
+#ifdef CONFIG_FLASH_PROTECT_NEXT_BOOT
+ /*
+ * Try updating at-boot protection state, if on a platform where write
+ * protection only changes after a reboot. Otherwise we wouldn't
+ * update it until after the next reboot, and we'd need to reboot
+ * again. Ignore errors, because the protection registers might
+ * already be locked this boot, and we'll still apply the correct state
+ * again on the next boot.
+ */
+ flash_physical_set_protect_at_boot(RO_BANK_OFFSET,
+ RO_BANK_COUNT + PSTATE_BANK_COUNT,
+ new_flags);
+#endif
+
+ return EC_SUCCESS;
+}
+
/*****************************************************************************/
/* Console commands */
diff --git a/include/flash.h b/include/flash.h
index fe592e3478..8969a56c8b 100644
--- a/include/flash.h
+++ b/include/flash.h
@@ -11,6 +11,23 @@
#include "common.h"
#include "ec_commands.h" /* For EC_FLASH_PROTECT_* flags */
+/* Number of physical flash banks */
+#define PHYSICAL_BANKS (CONFIG_FLASH_PHYSICAL_SIZE / CONFIG_FLASH_BANK_SIZE)
+
+/* Read-only firmware offset and size in units of flash banks */
+#define RO_BANK_OFFSET (CONFIG_SECTION_RO_OFF / CONFIG_FLASH_BANK_SIZE)
+#define RO_BANK_COUNT (CONFIG_SECTION_RO_SIZE / CONFIG_FLASH_BANK_SIZE)
+
+/* Read-write firmware offset and size in units of flash banks */
+#define RW_BANK_OFFSET (CONFIG_SECTION_RW_OFF / CONFIG_FLASH_BANK_SIZE)
+#define RW_BANK_COUNT (CONFIG_SECTION_RW_SIZE / CONFIG_FLASH_BANK_SIZE)
+
+/* Persistent protection state flash offset / size / bank */
+#define PSTATE_OFFSET CONFIG_SECTION_FLASH_PSTATE_OFF
+#define PSTATE_SIZE CONFIG_SECTION_FLASH_PSTATE_SIZE
+#define PSTATE_BANK (PSTATE_OFFSET / CONFIG_FLASH_BANK_SIZE)
+#define PSTATE_BANK_COUNT (PSTATE_SIZE / CONFIG_FLASH_BANK_SIZE)
+
/*****************************************************************************/
/* Low-level methods, for use by flash_common. */
@@ -71,6 +88,17 @@ int flash_physical_erase(int offset, int size);
int flash_physical_get_protect(int bank);
/**
+ * Set physical write protect status for the next boot.
+ *
+ * @param start_bank Start bank
+ * @param bank_count Number of banks to protect
+ * @param enable Enable (non-zero) or disable (zero) protection
+ * @return non-zero if error.
+ */
+int flash_physical_set_protect_at_boot(int start_bank, int bank_count,
+ int enable);
+
+/**
* Force reload of flash protection bits.
*
* Some EC architectures (STM32L) only load the bits from option bytes at
@@ -82,6 +110,27 @@ int flash_physical_get_protect(int bank);
int flash_physical_force_reload(void);
/*****************************************************************************/
+/* Low-level persistent state code for use by flash modules. */
+
+/**
+ * Return non-zero if RO flash should be protected at boot.
+ */
+int flash_get_protect_ro_at_boot(void);
+
+/**
+ * Enable write protect for the read-only code.
+ *
+ * Once write protect is enabled, it will STAY enabled until the system is
+ * hard-rebooted with the hardware write protect pin deasserted. If the write
+ * protect pin is deasserted, the protect setting is ignored, and the entire
+ * flash will be writable.
+ *
+ * @param enable Enable write protection
+ * @return EC_SUCCESS, or nonzero if error.
+ */
+int flash_protect_ro_at_boot(int enable);
+
+/*****************************************************************************/
/* High-level interface for use by other modules. */
/**