summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--board/hatch_fp/board.h2
-rw-r--r--chip/stm32/flash-f.c121
-rw-r--r--chip/stm32/flash-f.h26
-rw-r--r--chip/stm32/flash-stm32f3.c7
-rw-r--r--chip/stm32/registers-stm32f4.h7
-rw-r--r--include/config.h6
6 files changed, 163 insertions, 6 deletions
diff --git a/board/hatch_fp/board.h b/board/hatch_fp/board.h
index 9829b6c4a1..c8b8bc726e 100644
--- a/board/hatch_fp/board.h
+++ b/board/hatch_fp/board.h
@@ -68,7 +68,7 @@
* We want to prevent flash readout, and use it as indicator of protection
* status.
*/
-/*TODO(b/125419658): enable CONFIG_FLASH_READOUT_PROTECTION_AS_PSTATE*/
+#define CONFIG_FLASH_READOUT_PROTECTION_AS_PSTATE
/* the UART console is on USART1 */
#undef CONFIG_UART_CONSOLE
diff --git a/chip/stm32/flash-f.c b/chip/stm32/flash-f.c
index 8518485caa..5bfec02a62 100644
--- a/chip/stm32/flash-f.c
+++ b/chip/stm32/flash-f.c
@@ -5,10 +5,12 @@
/* Common flash memory module for STM32F and STM32F0 */
+#include <stdbool.h>
#include "battery.h"
#include "console.h"
#include "clock.h"
#include "flash.h"
+#include "flash-f.h"
#include "hooks.h"
#include "registers.h"
#include "panic.h"
@@ -18,6 +20,9 @@
#include "util.h"
#include "watchdog.h"
+#define CPRINTF(format, args...) cprintf(CC_SYSTEM, format, ## args)
+#define CPRINTS(format, args...) cprints(CC_SYSTEM, format, ## args)
+
/*
* Approximate number of CPU cycles per iteration of the loop when polling
* the flash status
@@ -35,6 +40,19 @@
/* 20ms < tERASE < 40ms on F0/F3, for 1K / 2K sector size. */
#define FLASH_ERASE_TIMEOUT_US 40000
+#if defined(CONFIG_FLASH_READOUT_PROTECTION_AS_PSTATE)
+#if !defined(CHIP_FAMILY_STM32F4)
+#error "CONFIG_FLASH_READOUT_PROTECTION_AS_PSTATE should work with all STM32F "
+"series chips, but has not been tested"
+#endif /* !CHIP_FAMILY_STM32F4 */
+#endif /* CONFIG_FLASH_READOUT_PROTECTION_AS_PSTATE */
+
+/* Forward declarations */
+#if defined(CONFIG_FLASH_READOUT_PROTECTION_AS_PSTATE)
+static enum flash_rdp_level flash_physical_get_rdp_level(void);
+static int flash_physical_set_rdp_level(enum flash_rdp_level level);
+#endif /* CONFIG_FLASH_READOUT_PROTECTION_AS_PSTATE */
+
static inline int calculate_flash_timeout(void)
{
return (FLASH_WRITE_TIMEOUT_US *
@@ -248,6 +266,23 @@ static int write_optb(int byte, uint8_t value)
}
#endif
+#if defined(CONFIG_FLASH_READOUT_PROTECTION_AS_PSTATE)
+/**
+ * @return true if RDP (read protection) Level 1 or 2 enabled, false otherwise
+ */
+bool is_flash_rdp_enabled(void)
+{
+ enum flash_rdp_level level = flash_physical_get_rdp_level();
+
+ if (level == FLASH_RDP_LEVEL_INVALID) {
+ CPRINTS("ERROR: unable to read RDP level");
+ return false;
+ }
+
+ return level != FLASH_RDP_LEVEL_0;
+}
+#endif /* CONFIG_FLASH_READOUT_PROTECTION_AS_PSTATE */
+
/*****************************************************************************/
/* Physical layer APIs */
@@ -421,6 +456,28 @@ static int flash_physical_get_protect_at_boot(int block)
return !(STM32_OPTB_WP & STM32_OPTB_nWRP(block));
}
+static int flash_physical_protect_at_boot_update_rdp_pstate(uint32_t new_flags)
+{
+#if defined(CONFIG_FLASH_READOUT_PROTECTION_AS_PSTATE)
+ int rv = EC_SUCCESS;
+
+ bool rdp_enable = (new_flags & EC_FLASH_PROTECT_RO_AT_BOOT) != 0;
+
+ /*
+ * This is intentionally a one-way latch. Once we have enabled RDP
+ * Level 1, we will only allow going back to Level 0 using the
+ * bootloader (e.g., "stm32mon -U") since transitioning from Level 1 to
+ * Level 0 triggers a mass erase.
+ */
+ if (rdp_enable)
+ rv = flash_physical_set_rdp_level(FLASH_RDP_LEVEL_1);
+
+ return rv;
+#else
+ return EC_SUCCESS;
+#endif
+}
+
int flash_physical_protect_at_boot(uint32_t new_flags)
{
int block;
@@ -452,7 +509,7 @@ int flash_physical_protect_at_boot(uint32_t new_flags)
}
- return EC_SUCCESS;
+ return flash_physical_protect_at_boot_update_rdp_pstate(new_flags);
}
static void unprotect_all_blocks(void)
@@ -545,6 +602,68 @@ static int registers_need_reset(void)
return 0;
}
+#if defined(CONFIG_FLASH_READOUT_PROTECTION_AS_PSTATE)
+/**
+ * Set Flash RDP (read protection) level.
+ *
+ * @note Does not take effect until reset.
+ *
+ * @param level new RDP (read protection) level to set
+ * @return EC_SUCCESS on success, other on failure
+ */
+int flash_physical_set_rdp_level(enum flash_rdp_level level)
+{
+ uint32_t reg_level;
+
+ switch (level) {
+ case FLASH_RDP_LEVEL_0:
+ /*
+ * Asserting by default since we don't want to inadvertently
+ * go from Level 1 to Level 0, which triggers a mass erase.
+ * Remove assert if you want to use it.
+ */
+ ASSERT(false);
+ reg_level = FLASH_OPTCR_RDP_LEVEL_0;
+ break;
+ case FLASH_RDP_LEVEL_1:
+ reg_level = FLASH_OPTCR_RDP_LEVEL_1;
+ break;
+ case FLASH_RDP_LEVEL_2:
+ /*
+ * Asserting by default since it's permanent (there is no
+ * way to reverse). Remove assert if you want to use it.
+ */
+ ASSERT(false);
+ reg_level = FLASH_OPTCR_RDP_LEVEL_2;
+ break;
+ default:
+ return EC_ERROR_INVAL;
+ }
+
+ return write_optb(FLASH_OPTCR_RDP_MASK, reg_level);
+}
+
+/**
+ * @return On success, current flash read protection level.
+ * On failure, FLASH_RDP_LEVEL_INVALID
+ */
+enum flash_rdp_level flash_physical_get_rdp_level(void)
+{
+ uint32_t level = (STM32_FLASH_OPTCR & FLASH_OPTCR_RDP_MASK);
+
+ switch (level) {
+ case FLASH_OPTCR_RDP_LEVEL_0:
+ return FLASH_RDP_LEVEL_0;
+ case FLASH_OPTCR_RDP_LEVEL_1:
+ return FLASH_RDP_LEVEL_1;
+ case FLASH_OPTCR_RDP_LEVEL_2:
+ return FLASH_RDP_LEVEL_2;
+ default:
+ return FLASH_RDP_LEVEL_INVALID;
+ }
+}
+#endif /* CONFIG_FLASH_READOUT_PROTECTION_AS_PSTATE */
+
/*****************************************************************************/
/* High-level APIs */
diff --git a/chip/stm32/flash-f.h b/chip/stm32/flash-f.h
new file mode 100644
index 0000000000..cbbe6ec86f
--- /dev/null
+++ b/chip/stm32/flash-f.h
@@ -0,0 +1,26 @@
+/* Copyright 2019 The Chromium OS Authors. All rights reserved.
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef __CROS_EC_STM32_FLASH_F_H
+#define __CROS_EC_STM32_FLASH_F_H
+
+#include <stdbool.h>
+
+enum flash_rdp_level {
+ FLASH_RDP_LEVEL_INVALID = -1, /**< Error occurred. */
+ FLASH_RDP_LEVEL_0, /**< No read protection. */
+ FLASH_RDP_LEVEL_1, /**< Reading flash is disabled while in
+ * bootloader mode or JTAG attached.
+ * Changing to Level 0 from this level
+ * triggers mass erase.
+ */
+ FLASH_RDP_LEVEL_2, /**< Same as Level 1, but is permanent
+ * and can never be disabled.
+ */
+};
+
+bool is_flash_rdp_enabled(void);
+
+#endif /* __CROS_EC_STM32_FLASH_F_H */
diff --git a/chip/stm32/flash-stm32f3.c b/chip/stm32/flash-stm32f3.c
index f0c8028f61..efa74c90cd 100644
--- a/chip/stm32/flash-stm32f3.c
+++ b/chip/stm32/flash-stm32f3.c
@@ -5,8 +5,10 @@
/* Flash memory module for stm32f3 and stm32f4 */
+#include <stdbool.h>
#include "common.h"
#include "flash.h"
+#include "flash-f.h"
#include "hooks.h"
#include "registers.h"
#include "system.h"
@@ -103,6 +105,11 @@ uint32_t flash_physical_get_protect_flags(void)
if (entire_flash_locked)
flags |= EC_FLASH_PROTECT_ALL_NOW;
+#if defined(CONFIG_FLASH_READOUT_PROTECTION_AS_PSTATE)
+ if (is_flash_rdp_enabled())
+ flags |= EC_FLASH_PROTECT_RO_AT_BOOT;
+#endif
+
return flags;
}
diff --git a/chip/stm32/registers-stm32f4.h b/chip/stm32/registers-stm32f4.h
index 06ac8f61ad..aef2f87f6f 100644
--- a/chip/stm32/registers-stm32f4.h
+++ b/chip/stm32/registers-stm32f4.h
@@ -729,7 +729,12 @@ typedef volatile struct stm32_spi_regs stm32_spi_regs_t;
#define FLASH_OPTLOCK BIT(0)
#define FLASH_OPTSTRT BIT(1)
#define STM32_FLASH_BOR_LEV_OFFSET (2)
-#define STM32_FLASH_RDP_MASK (0xFF << 8)
+#define FLASH_OPTCR_RDP_SHIFT (8)
+#define FLASH_OPTCR_RDP_MASK (0xFF << FLASH_OPTCR_RDP_SHIFT)
+#define FLASH_OPTCR_RDP_LEVEL_0 (0xAA << FLASH_OPTCR_RDP_SHIFT)
+/* RDP Level 1: Anything but 0xAA/0xCC */
+#define FLASH_OPTCR_RDP_LEVEL_1 (0x00 << FLASH_OPTCR_RDP_SHIFT)
+#define FLASH_OPTCR_RDP_LEVEL_2 (0xCC << FLASH_OPTCR_RDP_SHIFT)
#define STM32_FLASH_nWRP_OFFSET (16)
#define STM32_FLASH_nWRP(_bank) BIT(_bank + STM32_FLASH_nWRP_OFFSET)
#define STM32_FLASH_nWRP_ALL (0xFF << STM32_FLASH_nWRP_OFFSET)
diff --git a/include/config.h b/include/config.h
index 14670e0be6..d1a4dfc8d0 100644
--- a/include/config.h
+++ b/include/config.h
@@ -1677,7 +1677,7 @@
* could allow protected regions readback.
*
* TODO(crbug.com/888109): Implementation is currently only available on
- * STM32H7, and requires more documentation.
+ * STM32H7 and STM32F4, and requires more documentation.
*/
#undef CONFIG_FLASH_READOUT_PROTECTION_AS_PSTATE
@@ -4748,8 +4748,8 @@
#error "Flash readout protection and PSTATE may not work as intended."
#endif
-#ifndef CHIP_FAMILY_STM32H7
-#error "Flash readout protection only implemented on STM32H7."
+#if !defined(CHIP_FAMILY_STM32H7) && !defined(CHIP_FAMILY_STM32F4)
+#error "Flash readout protection only implemented on STM32H7 and STM32F4."
#endif
#endif /* CONFIG_FLASH_READOUT_PROTECTION_AS_PSTATE */