mirror of
https://github.com/Telecominfraproject/OpenCellular.git
synced 2025-12-30 02:20:48 +00:00
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>
This commit is contained in:
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
|
||||
|
||||
@@ -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 */
|
||||
|
||||
|
||||
@@ -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. */
|
||||
|
||||
@@ -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.
|
||||
|
||||
Reference in New Issue
Block a user