diff options
author | Randall Spangler <rspangler@chromium.org> | 2013-05-20 15:14:01 -0700 |
---|---|---|
committer | ChromeBot <chrome-bot@google.com> | 2013-05-23 11:08:44 -0700 |
commit | bd8fec9bae8fc36cc1e46bf0417f2da00530b522 (patch) | |
tree | faec9b729b3ff9bd62c8fda2ce804bdae67fcddd | |
parent | aa419b29ac9d012333a416696c7449047e085d29 (diff) | |
download | chrome-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.c | 119 | ||||
-rw-r--r-- | chip/stm32/config-stm32l15x.h | 10 | ||||
-rw-r--r-- | chip/stm32/config.h | 3 | ||||
-rw-r--r-- | chip/stm32/flash-stm32f100.c | 144 | ||||
-rw-r--r-- | chip/stm32/flash-stm32l15x.c | 21 | ||||
-rw-r--r-- | common/flash_common.c | 112 | ||||
-rw-r--r-- | include/flash.h | 49 |
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(¤t_pstate); - if (!memcmp(¤t_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(¤t_pstate) && - !memcmp(¤t_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(¤t_pstate); + if (!memcmp(¤t_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. */ /** |