diff options
author | Randall Spangler <rspangler@chromium.org> | 2012-07-16 14:19:59 -0700 |
---|---|---|
committer | Gerrit <chrome-bot@google.com> | 2012-07-16 17:49:10 -0700 |
commit | acf6f963a160f045d6b4c58f0ee3e249ded76b4e (patch) | |
tree | 1c724e7480104f9fa1284f6a3f013cbd44501c12 | |
parent | a42edb86c59cbc145eb99bd5b65bbd1f5567320e (diff) | |
download | chrome-ec-acf6f963a160f045d6b4c58f0ee3e249ded76b4e.tar.gz |
Flash pre-init reboots if it needs to clear protection registers
BUG=chrome-os-partner:11171
TEST=manual
1. Clear some of the writable-bits in the flash registers
> ww 0x400fe40c 0xffff1234
write 0x400fe40c = 0xffff1234
> rw 0x400fe40c
read 0x400fe40c = 0xffff1234
2. Reset using power+refresh
3. Register should be clear again
> rw 0x400fe40c
read 0x400fe40c = 0xffffffff
4. Sysinfo should indicate reset-pin reason AND hard-reset reason
> sysinfo
Reset flags: 0x0000000a (reset-pin power-on)
5. Reset using power+refresh
6. Sysinfo should indicate reset-pin reason only
> sysinfo
Reset flags: 0x00000002 (reset-pin)
7. Clear writable-bits again
> ww 0x400fe40c 0xffff1234
write 0x400fe40c = 0xffff1234
8. Jump to another image. This should NOT trigger a hard reset.
> sysjump A
> sysinfo
Reset flags: 0x00000402 (reset-pin sysjump)
Change-Id: Ie1d6af2acc68217bb82faae464798ee85d63d1ea
Signed-off-by: Randall Spangler <rspangler@chromium.org>
Reviewed-on: https://gerrit.chromium.org/gerrit/27540
Reviewed-by: Bill Richardson <wfrichar@chromium.org>
-rw-r--r-- | chip/lm4/flash.c | 41 | ||||
-rw-r--r-- | chip/stm32/flash-stm32f100.c | 5 | ||||
-rw-r--r-- | chip/stm32/flash-stm32l15x.c | 5 | ||||
-rw-r--r-- | common/flash_common.c | 20 | ||||
-rw-r--r-- | common/main.c | 22 | ||||
-rw-r--r-- | common/vboot.c | 6 | ||||
-rw-r--r-- | include/flash.h | 5 | ||||
-rw-r--r-- | include/vboot.h | 3 |
8 files changed, 81 insertions, 26 deletions
diff --git a/chip/lm4/flash.c b/chip/lm4/flash.c index 99289b4280..20c90793bd 100644 --- a/chip/lm4/flash.c +++ b/chip/lm4/flash.c @@ -7,6 +7,7 @@ #include "flash.h" #include "registers.h" +#include "system.h" #include "timer.h" #include "util.h" #include "watchdog.h" @@ -180,3 +181,43 @@ void flash_physical_set_protect(int block) { LM4_FLASH_FMPPE[F_BANK(block)] &= ~F_BIT(block); } + +int flash_physical_pre_init(void) +{ + int reset_flags = system_get_reset_flags(); + int any_wp = 0; + int i; + + /* + * If we have already jumped between images, an earlier image could + * have applied write protection. Nothing additional needs to be done. + */ + if (reset_flags & RESET_FLAG_SYSJUMP) + return EC_SUCCESS; + + /* Check if any blocks are currently physically write-protected */ + for (i = 0; i < (LM4_FLASH_FSIZE + 1) / 32; i++) { + if (LM4_FLASH_FMPPE[i] != 0xffffffff) { + any_wp = 1; + break; + } + } + + /* If nothing is write-protected, done. */ + if (!any_wp) + return EC_SUCCESS; + + /* + * If the last reboot was a power-on reset, it should have cleared + * write-protect. If it didn't, then the flash write protect registers + * have been permanently committed and we can't fix that. + */ + if (reset_flags & RESET_FLAG_POWER_ON) + return EC_ERROR_ACCESS_DENIED; + + /* Otherwise, do a hard boot to clear the flash protection registers */ + system_reset(SYSTEM_RESET_HARD | SYSTEM_RESET_PRESERVE_FLAGS); + + /* That doesn't return, so if we're still here that's an error */ + return EC_ERROR_UNKNOWN; +} diff --git a/chip/stm32/flash-stm32f100.c b/chip/stm32/flash-stm32f100.c index 670f715946..07a0ac2416 100644 --- a/chip/stm32/flash-stm32f100.c +++ b/chip/stm32/flash-stm32f100.c @@ -257,3 +257,8 @@ void flash_physical_set_protect(int block) write_optb(byte_off, val); } } + +int flash_physical_pre_init(void) +{ + return EC_SUCCESS; +} diff --git a/chip/stm32/flash-stm32l15x.c b/chip/stm32/flash-stm32l15x.c index e045694dab..d3e3db5033 100644 --- a/chip/stm32/flash-stm32l15x.c +++ b/chip/stm32/flash-stm32l15x.c @@ -317,3 +317,8 @@ void flash_physical_set_protect(int block) write_optb(byte_off, val); } } + +int flash_physical_pre_init(void) +{ + return EC_SUCCESS; +} diff --git a/common/flash_common.c b/common/flash_common.c index 20bbaa2561..184f5a79bb 100644 --- a/common/flash_common.c +++ b/common/flash_common.c @@ -272,9 +272,11 @@ int flash_lock_protect(int lock) const uint8_t *flash_get_protect_array(void) { - /* Return a copy of the current write protect state. This is an array + /* + * Return a copy of the current write protect state. This is an array * of per-protect-block flags. (This is NOT the actual array, so - * attempting to change it will have no effect.) */ + * attempting to change it will have no effect.) + */ int pbsize = flash_get_protect_block_size(); int banks = usable_flash_size / pbsize; int i; @@ -345,15 +347,25 @@ int flash_get_protect_lock(void) int flash_pre_init(void) { + /* Initialize the physical flash interface */ + /* + * TODO: track pre-init error so we can report it later. Do at the + * same time as new flash commands to get/set write protect status. + */ + flash_physical_pre_init(); + #ifdef CHIP_stm32 usable_flash_size = flash_physical_size(); #else - /* Calculate usable flash size. Reserve one protection block - * at the top to hold the "pretend SPI" write protect data. */ + /* + * Calculate usable flash size. Reserve one protection block + * at the top to hold the "pretend SPI" write protect data. + */ usable_flash_size = flash_physical_size() - flash_get_protect_block_size(); #endif + /* Apply write protect to blocks if needed */ return apply_pstate(); } diff --git a/common/main.c b/common/main.c index febebb2a0b..682ecf1e5c 100644 --- a/common/main.c +++ b/common/main.c @@ -6,8 +6,8 @@ */ #include "clock.h" +#include "common.h" #include "cpu.h" -#include "config.h" #include "eeprom.h" #include "eoption.h" #include "flash.h" @@ -44,18 +44,6 @@ int main(void) */ task_pre_init(); -#ifdef CONFIG_FLASH - flash_pre_init(); -#endif - -#ifdef CONFIG_VBOOT - /* - * Verified boot pre-init. This write-protects flash if necessary. - * Flash and GPIOs must be initialized first. - */ - vboot_pre_init(); -#endif - /* * Initialize the system module. This enables the hibernate clock * source we need to calibrate the internal oscillator. @@ -63,6 +51,14 @@ int main(void) system_pre_init(); system_common_pre_init(); +#ifdef CONFIG_FLASH + /* + * Initialize flash and apply write protecte if necessary. Requires + * the reset flags calculated by system initialization. + */ + flash_pre_init(); +#endif + /* Set the CPU clocks / PLLs. System is now running at full speed. */ clock_init(); diff --git a/common/vboot.c b/common/vboot.c index e4b9ee0aed..08fdef8930 100644 --- a/common/vboot.c +++ b/common/vboot.c @@ -15,12 +15,6 @@ #define CPUTS(outstr) cputs(CC_VBOOT, outstr) #define CPRINTF(format, args...) cprintf(CC_VBOOT, format, ## args) -int vboot_pre_init(void) -{ - /* FIXME(wfrichar): crosbug.com/p/7453: should protect flash */ - return EC_SUCCESS; -} - /****************************************************************************/ /* Host commands */ diff --git a/include/flash.h b/include/flash.h index 3dcce216c6..2ad8581440 100644 --- a/include/flash.h +++ b/include/flash.h @@ -14,6 +14,11 @@ /*****************************************************************************/ /* Low-level methods, for use by flash_common. */ +/** + * Initialize the physical flash interface. + */ +int flash_physical_pre_init(void); + /* Return the write / erase / protect block size, in bytes. Operations must be * aligned to and multiples of the granularity. For example, erase operations * must have offset and size which are multiples of the erase block size. */ diff --git a/include/vboot.h b/include/vboot.h index b6ec4b9e6b..a77243bc7e 100644 --- a/include/vboot.h +++ b/include/vboot.h @@ -10,9 +10,6 @@ #include "common.h" -/* Pre-initialize the module. This occurs before clocks or tasks are set up. */ -int vboot_pre_init(void); - /* * Check verified boot signatures, and jump to one of the RW images if * necessary. |