diff --git a/sw/device/silicon_creator/lib/drivers/flash_ctrl.c b/sw/device/silicon_creator/lib/drivers/flash_ctrl.c index c10ac64cabb02..b67c87440acbb 100644 --- a/sw/device/silicon_creator/lib/drivers/flash_ctrl.c +++ b/sw/device/silicon_creator/lib/drivers/flash_ctrl.c @@ -523,157 +523,59 @@ flash_ctrl_cfg_t flash_ctrl_data_default_cfg_get(void) { }; } -// This X macro helps to generate code that operates on each of the flash_ctrl -// memory protection regions. -#define FLASH_CTRL_MP_REGIONS(X) \ - X(0) \ - X(1) \ - X(2) \ - X(3) \ - X(4) \ - X(5) \ - X(6) \ - X(7) - -// Defines the bounds of the given memory protection region by setting the -// MP_REGION_${region} register. -static void flash_ctrl_mp_region_write(flash_ctrl_region_index_t region, - uint32_t page_offset, - uint32_t num_pages) { -#define FLASH_CTRL_MP_REGION_WRITE_(region_macro_arg) \ - case ((region_macro_arg)): { \ - HARDENED_CHECK_EQ(region, (region_macro_arg)); \ - uint32_t mp_region = FLASH_CTRL_MP_REGION_##region_macro_arg##_REG_RESVAL; \ - /* Write the region's base address into the bitfield. */ \ - mp_region = bitfield_field32_write( \ - mp_region, \ - FLASH_CTRL_MP_REGION_##region_macro_arg##_BASE_##region_macro_arg##_FIELD, \ - page_offset); \ - /* Write the region's size in pages into the bitfield. */ \ - mp_region = bitfield_field32_write( \ - mp_region, \ - FLASH_CTRL_MP_REGION_##region_macro_arg##_SIZE_##region_macro_arg##_FIELD, \ - num_pages); \ - /* Write the bitfield to the MP_REGION_${region} register. */ \ - sec_mmio_write32( \ - kBase + FLASH_CTRL_MP_REGION_##region_macro_arg##_REG_OFFSET, \ - mp_region); \ - return; \ - } - - switch (launder32(region)) { - FLASH_CTRL_MP_REGIONS(FLASH_CTRL_MP_REGION_WRITE_) - default: - OT_UNREACHABLE(); - } - -#undef FLASH_CTRL_MP_REGION_WRITE_ -} - -// Resets the given region's memory protection config by resetting the -// MP_REGION_CFG_${region} register, which implicitly disables the region. -static void flash_ctrl_mp_region_cfg_reset(flash_ctrl_region_index_t region) { -#define FLASH_CTRL_MP_REGION_CFG_RESET_(region_macro_arg) \ - case ((region_macro_arg)): { \ - HARDENED_CHECK_EQ(region, (region_macro_arg)); \ - static_assert( \ - (FLASH_CTRL_MP_REGION_CFG_##region_macro_arg##_REG_RESVAL & \ - FLASH_CTRL_MP_REGION_CFG_##region_macro_arg##_EN_##region_macro_arg##_MASK) == \ - kMultiBitBool4False, \ - "FLASH_CTRL_MP_REGION_CFG_" #region_macro_arg \ - "'s reset value should disable the region"); \ - /* Reset the MP_REGION_CFG_${region} register. */ \ - sec_mmio_write32( \ - kBase + FLASH_CTRL_MP_REGION_CFG_##region_macro_arg##_REG_OFFSET, \ - FLASH_CTRL_MP_REGION_CFG_##region_macro_arg##_REG_RESVAL); \ - return; \ - } - - switch (launder32(region)) { - FLASH_CTRL_MP_REGIONS(FLASH_CTRL_MP_REGION_CFG_RESET_) - default: - OT_UNREACHABLE(); - } - -#undef FLASH_CTRL_MP_CFG_RESET_ -} - -// Configures permissions for the given MP region by setting the appropriate -// MP_REGION_CFG register. -static void flash_ctrl_mp_region_cfg_write(flash_ctrl_region_index_t region, - flash_ctrl_cfg_t cfg, - flash_ctrl_perms_t perms, - multi_bit_bool_t en, - hardened_bool_t lock) { -#define FLASH_CTRL_MP_REGION_CFG_WRITE_(region_macro_arg) \ - case ((region_macro_arg)): { \ - HARDENED_CHECK_EQ(region, (region_macro_arg)); \ - uint32_t mp_region_cfg = \ - FLASH_CTRL_MP_REGION_CFG_##region_macro_arg##_REG_RESVAL; \ - mp_region_cfg = bitfield_field32_write( \ - mp_region_cfg, \ - FLASH_CTRL_MP_REGION_CFG_##region_macro_arg##_HE_EN_##region_macro_arg##_FIELD, \ - cfg.he); \ - mp_region_cfg = bitfield_field32_write( \ - mp_region_cfg, \ - FLASH_CTRL_MP_REGION_CFG_##region_macro_arg##_ECC_EN_##region_macro_arg##_FIELD, \ - cfg.ecc); \ - mp_region_cfg = bitfield_field32_write( \ - mp_region_cfg, \ - FLASH_CTRL_MP_REGION_CFG_##region_macro_arg##_SCRAMBLE_EN_##region_macro_arg##_FIELD, \ - cfg.scrambling); \ - mp_region_cfg = bitfield_field32_write( \ - mp_region_cfg, \ - FLASH_CTRL_MP_REGION_CFG_##region_macro_arg##_ERASE_EN_##region_macro_arg##_FIELD, \ - perms.erase); \ - mp_region_cfg = bitfield_field32_write( \ - mp_region_cfg, \ - FLASH_CTRL_MP_REGION_CFG_##region_macro_arg##_PROG_EN_##region_macro_arg##_FIELD, \ - perms.write); \ - mp_region_cfg = bitfield_field32_write( \ - mp_region_cfg, \ - FLASH_CTRL_MP_REGION_CFG_##region_macro_arg##_RD_EN_##region_macro_arg##_FIELD, \ - perms.read); \ - mp_region_cfg = bitfield_field32_write( \ - mp_region_cfg, \ - FLASH_CTRL_MP_REGION_CFG_##region_macro_arg##_EN_##region_macro_arg##_FIELD, \ - en); \ - sec_mmio_write32( \ - kBase + FLASH_CTRL_MP_REGION_CFG_##region_macro_arg##_REG_OFFSET, \ - mp_region_cfg); \ - if (lock != kHardenedBoolFalse) { \ - sec_mmio_write32( \ - kBase + \ - FLASH_CTRL_REGION_CFG_REGWEN_##region_macro_arg##_REG_OFFSET, \ - 0); \ - } \ - return; \ - } - - switch (launder32(region)) { - FLASH_CTRL_MP_REGIONS(FLASH_CTRL_MP_REGION_CFG_WRITE_) - default: - OT_UNREACHABLE(); - } - -#undef FLASH_CTRL_MP_REGION_CFG_WRITE_ -} - void flash_ctrl_data_region_protect(flash_ctrl_region_index_t region, uint32_t page_offset, uint32_t num_pages, flash_ctrl_perms_t perms, flash_ctrl_cfg_t cfg, hardened_bool_t lock) { + HARDENED_CHECK_GE(region, 0); + HARDENED_CHECK_LT(region, 8); + region *= sizeof(uint32_t); + // Reset the region's configuration via the MP_REGION_CFG_${region} register. // This temporarily disables memory protection for the region. - flash_ctrl_mp_region_cfg_reset(region); + // + // We use abs_mmio here because we're going to re-write this value later and + // the intermediate REG_RESVAL should not be considered a valid data pattern + // in this register when we perfom a sec_mmio check. + abs_mmio_write32(kBase + FLASH_CTRL_MP_REGION_CFG_0_REG_OFFSET + region, + FLASH_CTRL_MP_REGION_CFG_0_REG_RESVAL); // Set the region's bounds in the MP_REGION_${region} register. - flash_ctrl_mp_region_write(region, page_offset, num_pages); + uint32_t mp_region = FLASH_CTRL_MP_REGION_0_REG_RESVAL; + mp_region = bitfield_field32_write( + mp_region, FLASH_CTRL_MP_REGION_0_BASE_0_FIELD, page_offset); + mp_region = bitfield_field32_write( + mp_region, FLASH_CTRL_MP_REGION_0_SIZE_0_FIELD, num_pages); + sec_mmio_write32(kBase + FLASH_CTRL_MP_REGION_0_REG_OFFSET + region, + mp_region); // Write the new value of MP_REGION_CFG_${region}. - flash_ctrl_mp_region_cfg_write(region, cfg, perms, - /*en=*/kMultiBitBool4True, lock); + uint32_t mp_region_cfg = FLASH_CTRL_MP_REGION_CFG_0_REG_RESVAL; + mp_region_cfg = bitfield_field32_write( + mp_region_cfg, FLASH_CTRL_MP_REGION_CFG_0_HE_EN_0_FIELD, cfg.he); + mp_region_cfg = bitfield_field32_write( + mp_region_cfg, FLASH_CTRL_MP_REGION_CFG_0_ECC_EN_0_FIELD, cfg.ecc); + mp_region_cfg = bitfield_field32_write( + mp_region_cfg, FLASH_CTRL_MP_REGION_CFG_0_SCRAMBLE_EN_0_FIELD, + cfg.scrambling); + mp_region_cfg = bitfield_field32_write( + mp_region_cfg, FLASH_CTRL_MP_REGION_CFG_0_ERASE_EN_0_FIELD, perms.erase); + mp_region_cfg = bitfield_field32_write( + mp_region_cfg, FLASH_CTRL_MP_REGION_CFG_0_PROG_EN_0_FIELD, perms.write); + mp_region_cfg = bitfield_field32_write( + mp_region_cfg, FLASH_CTRL_MP_REGION_CFG_0_RD_EN_0_FIELD, perms.read); + mp_region_cfg = bitfield_field32_write( + mp_region_cfg, FLASH_CTRL_MP_REGION_CFG_0_EN_0_FIELD, kMultiBitBool4True); + + SEC_MMIO_ASSERT_WRITE_INCREMENT(kFlashCtrlSecMmioDataRegionProtect, 1); + SEC_MMIO_ASSERT_WRITE_INCREMENT(kFlashCtrlSecMmioDataRegionProtectLock, 1); + sec_mmio_write32(kBase + FLASH_CTRL_MP_REGION_CFG_0_REG_OFFSET + region, + mp_region_cfg); + if (lock != kHardenedBoolFalse) { + sec_mmio_write32(kBase + FLASH_CTRL_REGION_CFG_REGWEN_0_REG_OFFSET + region, + 0); + } } void flash_ctrl_info_cfg_set(const flash_ctrl_info_page_t *info_page, diff --git a/sw/device/silicon_creator/lib/drivers/flash_ctrl.h b/sw/device/silicon_creator/lib/drivers/flash_ctrl.h index d55428f8688cf..0a06cd789f443 100644 --- a/sw/device/silicon_creator/lib/drivers/flash_ctrl.h +++ b/sw/device/silicon_creator/lib/drivers/flash_ctrl.h @@ -176,6 +176,8 @@ enum { kFlashCtrlSecMmioInfoPermsSet = 1, kFlashCtrlSecMmioBankErasePermsSet = 1, kFlashCtrlSecMmioInit = 3, + kFlashCtrlSecMmioDataRegionProtect = 1, + kFlashCtrlSecMmioDataRegionProtectLock = 1, }; /** diff --git a/sw/device/silicon_creator/lib/ownership/BUILD b/sw/device/silicon_creator/lib/ownership/BUILD index cba92e4445329..e074fe85da9ba 100644 --- a/sw/device/silicon_creator/lib/ownership/BUILD +++ b/sw/device/silicon_creator/lib/ownership/BUILD @@ -109,6 +109,7 @@ cc_library( "//sw/device/lib/base:hardened_memory", "//sw/device/silicon_creator/lib:boot_data", "//sw/device/silicon_creator/lib:dbg_print", + "//sw/device/silicon_creator/lib/base:sec_mmio", "//sw/device/silicon_creator/lib/drivers:flash_ctrl", "//sw/device/silicon_creator/lib/drivers:lifecycle", ], diff --git a/sw/device/silicon_creator/lib/ownership/owner_block.c b/sw/device/silicon_creator/lib/ownership/owner_block.c index c15117fe65b8e..ecdcbef100f0a 100644 --- a/sw/device/silicon_creator/lib/ownership/owner_block.c +++ b/sw/device/silicon_creator/lib/ownership/owner_block.c @@ -10,6 +10,7 @@ #include "sw/device/lib/base/macros.h" #include "sw/device/lib/base/memory.h" #include "sw/device/silicon_creator/lib/base/chip.h" +#include "sw/device/silicon_creator/lib/base/sec_mmio.h" #include "sw/device/silicon_creator/lib/boot_data.h" #include "sw/device/silicon_creator/lib/drivers/flash_ctrl.h" #include "sw/device/silicon_creator/lib/error.h" @@ -246,6 +247,10 @@ rom_error_t owner_block_flash_apply(const owner_flash_config_t *flash, } flash_ctrl_data_region_protect(i, config->start, config->size, perm, cfg, lock); + SEC_MMIO_WRITE_INCREMENT(kFlashCtrlSecMmioDataRegionProtect + lock == + kHardenedBoolTrue + ? kFlashCtrlSecMmioDataRegionProtectLock + : 0); } } return kErrorOk;