summaryrefslogtreecommitdiff
path: root/core/cortex-m
diff options
context:
space:
mode:
Diffstat (limited to 'core/cortex-m')
-rw-r--r--core/cortex-m/mpu.c32
1 files changed, 27 insertions, 5 deletions
diff --git a/core/cortex-m/mpu.c b/core/cortex-m/mpu.c
index e2a2a464e1..32ce6fe5ef 100644
--- a/core/cortex-m/mpu.c
+++ b/core/cortex-m/mpu.c
@@ -251,11 +251,33 @@ int mpu_lock_ro_flash(void)
int mpu_lock_rw_flash(void)
{
/* Prevent execution from internal mapped RW flash */
- return mpu_config_region(REGION_STORAGE,
- CONFIG_MAPPED_STORAGE_BASE + CONFIG_RW_MEM_OFF,
- CONFIG_RW_SIZE,
- MPU_ATTR_XN | MPU_ATTR_RW_RW |
- MPU_ATTR_FLASH_MEMORY, 1);
+ const uint16_t mpu_attr = MPU_ATTR_XN | MPU_ATTR_RW_RW |
+ MPU_ATTR_FLASH_MEMORY;
+ const uint32_t rw_start_address =
+ CONFIG_MAPPED_STORAGE_BASE + CONFIG_RW_MEM_OFF;
+
+ /*
+ * Least significant set bit of the address determines the max size of
+ * the region because on the Cortex-M3, Cortex-M4 and Cortex-M7, the
+ * address used for an MPU region must be aligned to the size.
+ */
+ const int aligned_size_bit =
+ __fls(rw_start_address & -rw_start_address);
+ const uint32_t first_region_size =
+ MIN(BIT(aligned_size_bit), CONFIG_RW_SIZE);
+ const uint32_t second_region_address =
+ rw_start_address + first_region_size;
+ const uint32_t second_region_size = CONFIG_RW_SIZE - first_region_size;
+ int rv;
+
+ rv = mpu_config_region(REGION_STORAGE, rw_start_address,
+ first_region_size, mpu_attr, 1);
+ if ((rv != EC_SUCCESS) || (second_region_size == 0))
+ return rv;
+
+ /* If this fails then it's impossible to represent with two regions. */
+ return mpu_config_region(REGION_STORAGE2, second_region_address,
+ second_region_size, mpu_attr, 1);
}
#endif /* !CONFIG_EXTERNAL_STORAGE */