summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVincent Palatin <vpalatin@chromium.org>2015-01-02 15:03:42 -0800
committerChromeOS Commit Bot <chromeos-commit-bot@chromium.org>2015-01-05 19:10:27 +0000
commit9ce66a98b28df3e832b822bdec24e32e69d57e08 (patch)
tree8896694e47fedb83bd482a4c7da7df341e661bf2
parent05b0b9774a1c255e6332dc11f644b5e176f4f365 (diff)
downloadchrome-ec-9ce66a98b28df3e832b822bdec24e32e69d57e08.tar.gz
zinger: enable RO partition write-protection
Check the flash protection at startup, if the RDP is still at level 0 (no read protection) or if the RO partition is not write protected : - set the write protection on the first 16KB of flash (4 LSB of WRP0) - push the RDP to level 1, so SWD/serial monitor needs to fully erase the part before re-writing the code or the write-protection. Signed-off-by: Vincent Palatin <vpalatin@chromium.org> BRANCH=samus BUG=chrome-os-partner:34935 TEST=dump the content of the option bytes. Change-Id: I11af64365a6fbc34327b2e463eb8e2d369ffacd2 Reviewed-on: https://chromium-review.googlesource.com/238262 Reviewed-by: Alec Berg <alecaberg@chromium.org> Commit-Queue: Vincent Palatin <vpalatin@chromium.org> Trybot-Ready: Vincent Palatin <vpalatin@chromium.org> Tested-by: Vincent Palatin <vpalatin@chromium.org>
-rw-r--r--board/zinger/board.c4
-rw-r--r--board/zinger/board.h2
-rw-r--r--board/zinger/hardware.c79
-rw-r--r--chip/stm32/registers.h1
-rwxr-xr-xutil/flash_ec2
5 files changed, 87 insertions, 1 deletions
diff --git a/board/zinger/board.c b/board/zinger/board.c
index 3ea9850015..e06da587da 100644
--- a/board/zinger/board.c
+++ b/board/zinger/board.c
@@ -83,6 +83,10 @@ int main(void)
debug_printf("Power supply started ... %s\n",
is_ro_mode() ? "RO" : "RW");
+ /* the RO partition protection is not enabled : do it */
+ if (!flash_physical_is_permanently_protected())
+ flash_physical_permanent_protect();
+
/* Verify RW firmware and use it if valid */
if (is_ro_mode() && check_rw_valid())
jump_to_rw();
diff --git a/board/zinger/board.h b/board/zinger/board.h
index 79d60514eb..e307c6ff27 100644
--- a/board/zinger/board.h
+++ b/board/zinger/board.h
@@ -97,6 +97,8 @@ extern volatile uint32_t last_event;
/* RW section flashing */
int flash_erase_rw(void);
int flash_write_rw(int offset, int size, const char *data);
+void flash_physical_permanent_protect(void);
+int flash_physical_is_permanently_protected(void);
uint8_t *flash_hash_rw(void);
int is_ro_mode(void);
diff --git a/board/zinger/hardware.c b/board/zinger/hardware.c
index 1713ca342e..31f57da6a3 100644
--- a/board/zinger/hardware.c
+++ b/board/zinger/hardware.c
@@ -296,8 +296,11 @@ int adc_disable_watchdog(void)
/* Lock bits for FLASH_CR register */
#define PG (1<<0)
#define PER (1<<1)
+#define OPTPG (1<<4)
+#define OPTER (1<<5)
#define STRT (1<<6)
#define CR_LOCK (1<<7)
+#define OPTWRE (1<<9)
int flash_physical_write(int offset, int size, const char *data)
{
@@ -399,3 +402,79 @@ exit_er:
return res;
}
+
+static void unlock_erase_optb(void)
+{
+ int i;
+
+ /* Clear previous error status */
+ STM32_FLASH_SR = 0x34;
+
+ /* wait to be ready */
+ for (i = 0; (STM32_FLASH_SR & 1) && (i < FLASH_TIMEOUT_LOOP); i++)
+ ;
+
+ /* Unlock the option bytes access */
+ if (STM32_FLASH_CR & CR_LOCK) {
+ STM32_FLASH_KEYR = KEY1;
+ STM32_FLASH_KEYR = KEY2;
+ }
+ if (!(STM32_FLASH_CR & OPTWRE)) {
+ STM32_FLASH_OPTKEYR = KEY1;
+ STM32_FLASH_OPTKEYR = KEY2;
+ }
+ /* Must be set in 2 separate lines. */
+ STM32_FLASH_CR |= OPTER;
+ STM32_FLASH_CR |= STRT;
+
+ /* wait to be ready */
+ for (i = 0; (STM32_FLASH_SR & 1) && (i < FLASH_TIMEOUT_LOOP); i++)
+ ;
+ /* reset erasing bits */
+ STM32_FLASH_CR = OPTWRE;
+}
+
+
+static void write_optb(int byte, uint8_t value)
+{
+ volatile int16_t *hword = (uint16_t *)(STM32_OPTB_BASE + byte);
+ int i;
+
+ /* Clear previous error status */
+ STM32_FLASH_SR = 0x34;
+
+ /* set OPTPG bit */
+ STM32_FLASH_CR |= OPTPG;
+
+ *hword = ((~value) << STM32_OPTB_COMPL_SHIFT) | value;
+
+ /* reset OPTPG bit */
+ STM32_FLASH_CR = OPTWRE;
+
+ /* wait to be ready */
+ for (i = 0; (STM32_FLASH_SR & 1) && (i < FLASH_TIMEOUT_LOOP); i++)
+ ;
+}
+
+void flash_physical_permanent_protect(void)
+{
+ unlock_erase_optb();
+ /* protect the 16KB RO partition against write/erase in WRP0 */
+ write_optb(8, 0xF0);
+ /* Set RDP to level 1 to prevent disabling the protection */
+ write_optb(0, 0x11);
+ /* Reset by using OBL_LAUNCH to take changes into account */
+ asm volatile("cpsid i");
+ STM32_FLASH_CR |= STM32_FLASH_CR_OBL_LAUNCH;
+ /* Spin and wait for reboot; should never return */
+ while (1)
+ ;
+}
+
+int flash_physical_is_permanently_protected(void)
+{
+ /* if RDP is still at level 0, the flash protection is not in place */
+ return (STM32_FLASH_OBR & STM32_FLASH_OBR_RDP_MASK) &&
+ /* the low 16KB (RO partition) are write-protected */
+ !(STM32_FLASH_WRPR & 0xF);
+}
diff --git a/chip/stm32/registers.h b/chip/stm32/registers.h
index a99852b73d..59d7e16efb 100644
--- a/chip/stm32/registers.h
+++ b/chip/stm32/registers.h
@@ -871,6 +871,7 @@ typedef volatile struct stm32_spi_regs stm32_spi_regs_t;
#define STM32_FLASH_CR_OBL_LAUNCH (1 << 13)
#define STM32_FLASH_AR REG32(STM32_FLASH_REGS_BASE + 0x14)
#define STM32_FLASH_OBR REG32(STM32_FLASH_REGS_BASE + 0x1c)
+#define STM32_FLASH_OBR_RDP_MASK (3 << 1)
#define STM32_FLASH_WRPR REG32(STM32_FLASH_REGS_BASE + 0x20)
#define STM32_OPTB_BASE 0x1FFFF800
diff --git a/util/flash_ec b/util/flash_ec
index 934af83770..3278f1d8fd 100755
--- a/util/flash_ec
+++ b/util/flash_ec
@@ -333,7 +333,7 @@ function flash_stm32() {
# Reset the EC
ec_reset
# Unprotect flash, erase, and write
- ${STM32MON} -d ${EC_UART} -u -e -w "${IMG}"
+ ${STM32MON} -d ${EC_UART} -U -u -e -w "${IMG}"
}
function flash_stm32_dfu() {