Skip to content

Commit

Permalink
[flash_ctrl] Relax the hardening in flash_ctrl_data_region_protect
Browse files Browse the repository at this point in the history
The hardening in the function `flash_ctrl_data_region_protect` resulted
in 1304 bytes of RV32 machine code.  This relaxed version results in
250 bytes of RV32 machine code.

Signed-off-by: Chris Frantz <[email protected]>
  • Loading branch information
cfrantz committed Jan 28, 2025
1 parent 08857c8 commit 4d2709b
Show file tree
Hide file tree
Showing 4 changed files with 50 additions and 140 deletions.
182 changes: 42 additions & 140 deletions sw/device/silicon_creator/lib/drivers/flash_ctrl.c
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
2 changes: 2 additions & 0 deletions sw/device/silicon_creator/lib/drivers/flash_ctrl.h
Original file line number Diff line number Diff line change
Expand Up @@ -176,6 +176,8 @@ enum {
kFlashCtrlSecMmioInfoPermsSet = 1,
kFlashCtrlSecMmioBankErasePermsSet = 1,
kFlashCtrlSecMmioInit = 3,
kFlashCtrlSecMmioDataRegionProtect = 1,
kFlashCtrlSecMmioDataRegionProtectLock = 1,
};

/**
Expand Down
1 change: 1 addition & 0 deletions sw/device/silicon_creator/lib/ownership/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -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",
],
Expand Down
5 changes: 5 additions & 0 deletions sw/device/silicon_creator/lib/ownership/owner_block.c
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -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;
Expand Down

0 comments on commit 4d2709b

Please sign in to comment.