/**
******************************************************************************
* @file low_level_security.c
* @author MCD Application Team
* @brief security protection implementation for secure boot on STM32U5xx
*
******************************************************************************
* @attention
*
*
© Copyright (c) 2021 STMicroelectronics.
* Copyright (c) 2017-2020 Arm Limited
* All rights reserved.
*
* This software component is licensed by ST under BSD 3-Clause license,
* the "License"; You may not use this file except in compliance with the
* License. You may obtain a copy of the License at:
* opensource.org/licenses/BSD-3-Clause
*
******************************************************************************
*/
/* Includes ------------------------------------------------------------------*/
#include
#include "boot_hal_cfg.h"
#include "mpu_armv8m_drv.h"
#include "region_defs.h"
#include "mcuboot_config/mcuboot_config.h"
#include "low_level_security.h"
#if defined(FLOW_CONTROL)
#include "boot_hal_flowcontrol.h"
#else
/* dummy definitions */
extern volatile uint32_t uFlowStage;
#define FLOW_CONTROL_STEP(C,B,A) ((void)0)
#define FLOW_CONTROL_CHECK(B,A) ((void)0)
#define FLOW_STAGE_CFG (0x0)
#define FLOW_STAGE_CHK (0x1)
#endif
#ifdef TFM_DEV_MODE
#define BOOT_LOG_LEVEL BOOT_LOG_LEVEL_INFO
#else
#define BOOT_LOG_LEVEL BOOT_LOG_LEVEL_OFF
#endif /* TFM_DEV_MODE */
#include "bootutil/bootutil_log.h"
#if (TFM_TAMPER_ENABLE != NO_TAMPER)
#include "low_level_rng.h"
#endif /* (TFM_TAMPER_ENABLE != NO_TAMPER)*/
#include "target_cfg.h"
#define ARRAY_SIZE(arr) (sizeof(arr)/sizeof(arr[0]))
/** @defgroup TFM_SECURITY_Private_Defines Private Defines
* @{
*/
/* DUAL BANK page size */
#define PAGE_SIZE FLASH_AREA_IMAGE_SECTOR_SIZE
#define PAGE_MAX_NUMBER_IN_BANK 127
/* SBSFU_Boot Vector Address */
#define SBSFU_BOOT_VTOR_ADDR ((uint32_t)(BL2_CODE_START))
const struct mpu_armv8m_region_cfg_t region_cfg_init_s[] = {
/* background region is enabled , secure execution on unsecure flash is not possible*/
/* but non secure execution on unsecure flash is possible , non secure mpu is used to protect execution */
/* since SAU is enabled later to gain access to non secure flash */
/* Forbid execuction outside of flash write protected area */
/* descriptor 0 is set execute readonly before jumping in Secure application */
{
0,
FLASH_BASE_S + S_IMAGE_PRIMARY_PARTITION_OFFSET,
FLASH_BASE_S + S_IMAGE_PRIMARY_PARTITION_OFFSET + FLASH_S_PARTITION_SIZE,
MPU_ARMV8M_MAIR_ATTR_DATANOCACHE_IDX,
MPU_ARMV8M_XN_EXEC_NEVER,
MPU_ARMV8M_AP_RW_PRIV_ONLY,
MPU_ARMV8M_SH_NONE,
#ifdef FLOW_CONTROL
FLOW_STEP_MPU_S_I_EN_R0,
FLOW_CTRL_MPU_S_I_EN_R0,
FLOW_STEP_MPU_S_I_CH_R0,
FLOW_CTRL_MPU_S_I_CH_R0,
#endif /* FLOW_CONTROL */
},
{
1,
FLASH_BASE_S + S_IMAGE_PRIMARY_PARTITION_OFFSET + FLASH_S_PARTITION_SIZE,
#if !defined(MCUBOOT_PRIMARY_ONLY) && !defined(EXTERNAL_FLASH)
FLASH_BASE_S + NS_IMAGE_SECONDARY_PARTITION_OFFSET + FLASH_NS_PARTITION_SIZE,
#else
FLASH_BASE_S + S_IMAGE_PRIMARY_PARTITION_OFFSET + FLASH_S_PARTITION_SIZE + FLASH_NS_PARTITION_SIZE,
#endif /* MCUBOOT_PRIMARY_ONLY */
MPU_ARMV8M_MAIR_ATTR_DATANOCACHE_IDX,
MPU_ARMV8M_XN_EXEC_NEVER,
MPU_ARMV8M_AP_RW_PRIV_ONLY,
MPU_ARMV8M_SH_NONE,
#ifdef FLOW_CONTROL
FLOW_STEP_MPU_S_I_EN_R1,
FLOW_CTRL_MPU_S_I_EN_R1,
FLOW_STEP_MPU_S_I_CH_R1,
FLOW_CTRL_MPU_S_I_CH_R1,
#endif /* FLOW_CONTROL */
},
{
2,
FLASH_BASE_S,
FLASH_BASE_S + FLASH_AREA_BL2_OFFSET,
MPU_ARMV8M_MAIR_ATTR_DATANOCACHE_IDX,
MPU_ARMV8M_XN_EXEC_NEVER,
MPU_ARMV8M_AP_RW_PRIV_ONLY,
MPU_ARMV8M_SH_NONE,
#ifdef FLOW_CONTROL
FLOW_STEP_MPU_S_I_EN_R2,
FLOW_CTRL_MPU_S_I_EN_R2,
FLOW_STEP_MPU_S_I_CH_R2,
FLOW_CTRL_MPU_S_I_CH_R2,
#endif /* FLOW_CONTROL */
},
{
3,
FLASH_BASE_S + FLASH_AREA_BL2_NOHDP_OFFSET + FLASH_AREA_BL2_NOHDP_SIZE,
FLASH_BASE_S + FLASH_AREA_0_OFFSET,
MPU_ARMV8M_MAIR_ATTR_DATANOCACHE_IDX,
MPU_ARMV8M_XN_EXEC_NEVER,
MPU_ARMV8M_AP_RW_PRIV_ONLY,
MPU_ARMV8M_SH_NONE,
#ifdef FLOW_CONTROL
FLOW_STEP_MPU_S_I_EN_R3,
FLOW_CTRL_MPU_S_I_EN_R3,
FLOW_STEP_MPU_S_I_CH_R3,
FLOW_CTRL_MPU_S_I_CH_R3,
#endif /* FLOW_CONTROL */
},
/* Forbid execution on full SRAM area */
{
4,
BL2_SRAM_AREA_BASE,
BL2_SRAM_AREA_END,
MPU_ARMV8M_MAIR_ATTR_DATA_IDX,
MPU_ARMV8M_XN_EXEC_NEVER,
MPU_ARMV8M_AP_RW_PRIV_ONLY,
MPU_ARMV8M_SH_NONE,
#ifdef FLOW_CONTROL
FLOW_STEP_MPU_S_I_EN_R4,
FLOW_CTRL_MPU_S_I_EN_R4,
FLOW_STEP_MPU_S_I_CH_R4,
FLOW_CTRL_MPU_S_I_CH_R4,
#endif /* FLOW_CONTROL */
},
/* forbid secure peripheral execution */
{
5,
PERIPH_BASE_S,
PERIPH_BASE_S + 0x10000000,
MPU_ARMV8M_MAIR_ATTR_DEVICE_IDX,
MPU_ARMV8M_XN_EXEC_NEVER,
MPU_ARMV8M_AP_RW_PRIV_ONLY,
MPU_ARMV8M_SH_NONE,
#ifdef FLOW_CONTROL
FLOW_STEP_MPU_S_I_EN_R5,
FLOW_CTRL_MPU_S_I_EN_R5,
FLOW_STEP_MPU_S_I_CH_R5,
FLOW_CTRL_MPU_S_I_CH_R5,
#endif /* FLOW_CONTROL */
},
/* forbid execution of flash non secure alias */
{
6,
FLASH_BASE_NS,
FLASH_BASE_NS + FLASH_TOTAL_SIZE,
MPU_ARMV8M_MAIR_ATTR_DATANOCACHE_IDX,
MPU_ARMV8M_XN_EXEC_NEVER,
MPU_ARMV8M_AP_RW_PRIV_ONLY,
MPU_ARMV8M_SH_NONE,
#ifdef FLOW_CONTROL
FLOW_STEP_MPU_S_I_EN_R6,
FLOW_CTRL_MPU_S_I_EN_R6,
FLOW_STEP_MPU_S_I_CH_R6,
FLOW_CTRL_MPU_S_I_CH_R6,
#endif /* FLOW_CONTROL */
}
};
const struct mpu_armv8m_region_cfg_t region_cfg_init_ns[] = {
/* forbid execution on non secure FLASH /RAM in case of jump in non secure */
/* Non Secure MPU background all access in priviligied */
/* reduced execution to all flash during control */
{
0,
FLASH_BASE_NS + NS_IMAGE_PRIMARY_PARTITION_OFFSET,
FLASH_BASE_NS + NS_IMAGE_PRIMARY_PARTITION_OFFSET + FLASH_NS_PARTITION_SIZE,
MPU_ARMV8M_MAIR_ATTR_DATANOCACHE_IDX,
MPU_ARMV8M_XN_EXEC_NEVER,
MPU_ARMV8M_AP_RW_PRIV_ONLY,
MPU_ARMV8M_SH_NONE,
#ifdef FLOW_CONTROL
FLOW_STEP_MPU_NS_I_EN_R0,
FLOW_CTRL_MPU_NS_I_EN_R0,
FLOW_STEP_MPU_NS_I_CH_R0,
FLOW_CTRL_MPU_NS_I_CH_R0,
#endif /* FLOW_CONTROL */
},
#if !defined(MCUBOOT_PRIMARY_ONLY) && !defined(EXTERNAL_FLASH)
{
1,
FLASH_BASE_NS + S_IMAGE_SECONDARY_PARTITION_OFFSET,
FLASH_BASE_NS + NS_IMAGE_SECONDARY_PARTITION_OFFSET + FLASH_NS_PARTITION_SIZE,
MPU_ARMV8M_MAIR_ATTR_DATANOCACHE_IDX,
MPU_ARMV8M_XN_EXEC_NEVER,
MPU_ARMV8M_AP_RW_PRIV_ONLY,
MPU_ARMV8M_SH_NONE,
#ifdef FLOW_CONTROL
FLOW_STEP_MPU_NS_I_EN_R1,
FLOW_CTRL_MPU_NS_I_EN_R1,
FLOW_STEP_MPU_NS_I_CH_R1,
FLOW_CTRL_MPU_NS_I_CH_R1,
#endif /* FLOW_CONTROL */
},
#endif /* MCUBOOT_PRIMARY_ONLY */
/* Forbid execuction on full SRAM area */
{
2,
#ifdef TFM_ERROR_HANDLER_NON_SECURE
SRAM1_BASE_NS + (~MPU_RBAR_BASE_Msk) + 1,
#else
SRAM1_BASE_NS,
#endif /* TFM_ERROR_HANDLER_NON_SECURE */
SRAM1_BASE_NS + TOTAL_RAM_SIZE,
MPU_ARMV8M_MAIR_ATTR_DATA_IDX,
MPU_ARMV8M_XN_EXEC_NEVER,
MPU_ARMV8M_AP_RW_PRIV_ONLY,
MPU_ARMV8M_SH_NONE,
#ifdef FLOW_CONTROL
FLOW_STEP_MPU_NS_I_EN_R2,
FLOW_CTRL_MPU_NS_I_EN_R2,
FLOW_STEP_MPU_NS_I_CH_R2,
FLOW_CTRL_MPU_NS_I_CH_R2,
#endif /* FLOW_CONTROL */
},
/* forbid secure peripheral execution */
{
3,
PERIPH_BASE_NS,
PERIPH_BASE_NS + 0x10000000,
MPU_ARMV8M_MAIR_ATTR_DEVICE_IDX,
MPU_ARMV8M_XN_EXEC_NEVER,
MPU_ARMV8M_AP_RW_PRIV_ONLY,
MPU_ARMV8M_SH_NONE,
#ifdef FLOW_CONTROL
FLOW_STEP_MPU_NS_I_EN_R3,
FLOW_CTRL_MPU_NS_I_EN_R3,
FLOW_STEP_MPU_NS_I_CH_R3,
FLOW_CTRL_MPU_NS_I_CH_R3,
#endif /* FLOW_CONTROL */
}
};
#if defined(__ICCARM__)
#pragma location=".BL2_NoHdp_Data"
#endif
const struct mpu_armv8m_region_cfg_t region_cfg_appli_s[] __attribute__((section(".BL2_NoHdp_Data"))) = {
/* region 0 is now enable for execution */
{
0,
FLASH_BASE_S + S_IMAGE_PRIMARY_PARTITION_OFFSET,
/* Reduce area to allow write to validate the Secure Image */
FLASH_BASE_S + S_IMAGE_PRIMARY_PARTITION_OFFSET + FLASH_S_PARTITION_SIZE - (~MPU_RLAR_LIMIT_Msk +1),
MPU_ARMV8M_MAIR_ATTR_DATA_IDX,
MPU_ARMV8M_XN_EXEC_OK,
MPU_ARMV8M_AP_RO_PRIV_ONLY,
MPU_ARMV8M_SH_NONE,
#ifdef FLOW_CONTROL
FLOW_STEP_MPU_S_A_EN_R0,
FLOW_CTRL_MPU_S_A_EN_R0,
FLOW_STEP_MPU_S_A_CH_R0,
FLOW_CTRL_MPU_S_A_CH_R0,
#endif /* FLOW_CONTROL */
}
};
#if defined(__ICCARM__)
#pragma location=".BL2_NoHdp_Data"
#endif
const struct mpu_armv8m_region_cfg_t region_cfg_appli_ns[] __attribute__((section(".BL2_NoHdp_Data"))) = {
/* region 0 is now enable for execution */
{
0,
FLASH_BASE_NS + NS_IMAGE_PRIMARY_PARTITION_OFFSET,
/* Reduce area to allow write to validate the Non Secure Image */
FLASH_BASE_NS + NS_IMAGE_PRIMARY_PARTITION_OFFSET + FLASH_NS_PARTITION_SIZE - (~MPU_RLAR_LIMIT_Msk +1),
MPU_ARMV8M_MAIR_ATTR_DATA_IDX,
MPU_ARMV8M_XN_EXEC_OK,
MPU_ARMV8M_AP_RO_PRIV_ONLY,
MPU_ARMV8M_SH_NONE,
#ifdef FLOW_CONTROL
FLOW_STEP_MPU_NS_A_EN_R0,
FLOW_CTRL_MPU_NS_A_EN_R0,
FLOW_STEP_MPU_NS_A_CH_R0,
FLOW_CTRL_MPU_NS_A_CH_R0,
#endif /* FLOW_CONTROL */
}
};
const struct sau_cfg_t sau_init_cfg[] = {
#ifdef TFM_ERROR_HANDLER_NON_SECURE
/* Configures SAU regions non-secure to gain access to SRAM1 non secure */
{
0,
SRAM1_BASE_NS,
(SRAM1_BASE_NS + NS_NO_INIT_DATA_SIZE),
TFM_FALSE,
#ifdef FLOW_CONTROL
FLOW_STEP_SAU_I_EN_R0,
FLOW_CTRL_SAU_I_EN_R0,
FLOW_STEP_SAU_I_CH_R0,
FLOW_CTRL_SAU_I_CH_R0,
#endif /* FLOW_CONTROL */
},
#endif /* TFM_ERROR_HANDLER_NON_SECURE */
/* Allow non secure access to Flash non Secure peripheral for regression */
/* Secure HAL flash driver uses the non secure flash address to perform access on non secure flash area */
{
1,
(uint32_t)FLASH_NS,
((uint32_t)FLASH_NS + 0x10000),
TFM_FALSE,
#ifdef FLOW_CONTROL
FLOW_STEP_SAU_I_EN_R1,
FLOW_CTRL_SAU_I_EN_R1,
FLOW_STEP_SAU_I_CH_R1,
FLOW_CTRL_SAU_I_CH_R1,
#endif /* FLOW_CONTROL */
},
/* Allow non secure Flash base access for Area 1/2/3 */
{
2,
((uint32_t)FLASH_BASE_NS + NS_IMAGE_PRIMARY_PARTITION_OFFSET),
#if defined(MCUBOOT_PRIMARY_ONLY) || defined(EXTERNAL_FLASH)
((uint32_t)FLASH_BASE_NS + NS_IMAGE_PRIMARY_PARTITION_OFFSET + FLASH_NS_PARTITION_SIZE),
#else
((uint32_t)FLASH_BASE_NS + S_IMAGE_SECONDARY_PARTITION_OFFSET + FLASH_PARTITION_SIZE),
#endif /* MCUBOOT_PRIMARY_ONLY || EXTERNAL_FLASH */
TFM_FALSE,
#ifdef FLOW_CONTROL
FLOW_STEP_SAU_I_EN_R2,
FLOW_CTRL_SAU_I_EN_R2,
FLOW_STEP_SAU_I_CH_R2,
FLOW_CTRL_SAU_I_CH_R2,
#endif /* FLOW_CONTROL */
},
#if defined(MCUBOOT_EXT_LOADER)
/* create a region to access to loader code for hash check */
{
3,
LOADER_NS_ROM_ALIAS(FLASH_AREA_LOADER_OFFSET),
LOADER_NS_ROM_ALIAS(FLASH_TOTAL_SIZE),
TFM_FALSE,
#ifdef FLOW_CONTROL
FLOW_STEP_SAU_I_EN_R3,
FLOW_CTRL_SAU_I_EN_R3,
FLOW_STEP_SAU_I_CH_R3,
FLOW_CTRL_SAU_I_CH_R3,
#endif /* FLOW_CONTROL */
}
#endif
};
#ifdef MCUBOOT_EXT_LOADER
#if defined(__ICCARM__)
#pragma location=".BL2_NoHdp_Data"
#endif
const struct sau_cfg_t sau_load_cfg[] __attribute__((section(".BL2_NoHdp_Data"))) = {
/* allow access to non secure loader area ram*/
{
0,
(uint32_t)LOADER_NS_DATA_START,
(uint32_t)LOADER_NS_DATA_LIMIT + 1,
TFM_FALSE,
#ifdef FLOW_CONTROL
FLOW_STEP_SAU_L_EN_R0,
FLOW_CTRL_SAU_L_EN_R0,
FLOW_STEP_SAU_L_CH_R0,
FLOW_CTRL_SAU_L_CH_R0,
#endif /* FLOW_CONTROL */
},
/* loader non secure need access to periph */
{
1,
(uint32_t)PERIPH_BASE_NS,
((uint32_t)PERIPH_BASE_NS + 0x10000000),
TFM_FALSE,
#ifdef FLOW_CONTROL
FLOW_STEP_SAU_L_EN_R1,
FLOW_CTRL_SAU_L_EN_R1,
FLOW_STEP_SAU_L_CH_R1,
FLOW_CTRL_SAU_L_CH_R1,
#endif /* FLOW_CONTROL */
},
{
2,
((uint32_t)FLASH_BASE_NS + NS_IMAGE_PRIMARY_PARTITION_OFFSET),
#if !defined(MCUBOOT_PRIMARY_ONLY)
((uint32_t)FLASH_BASE_NS + S_IMAGE_SECONDARY_PARTITION_OFFSET + FLASH_PARTITION_SIZE),
#else
((uint32_t)FLASH_BASE_NS + NS_IMAGE_PRIMARY_PARTITION_OFFSET + FLASH_NS_PARTITION_SIZE),
#endif /* MCUBOOT_PRIMARY_ONLY */
TFM_FALSE,
#ifdef FLOW_CONTROL
FLOW_STEP_SAU_L_EN_R2,
FLOW_CTRL_SAU_L_EN_R2,
FLOW_STEP_SAU_L_CH_R2,
FLOW_CTRL_SAU_L_CH_R2,
#endif /* FLOW_CONTROL */
},
/* allow access to non secure loader area code */
{
3,
(uint32_t)LOADER_NS_CODE_START,
(uint32_t)LOADER_NS_CODE_LIMIT + 1,
TFM_FALSE,
#ifdef FLOW_CONTROL
FLOW_STEP_SAU_L_EN_R3,
FLOW_CTRL_SAU_L_EN_R3,
FLOW_STEP_SAU_L_CH_R3,
FLOW_CTRL_SAU_L_CH_R3,
#endif /* FLOW_CONTROL */
},
#if defined(MCUBOOT_PRIMARY_ONLY)
/* allow access to non secure calleable area */
{
4,
(uint32_t)LOADER_CMSE_VENEER_REGION_START,
(uint32_t)LOADER_CMSE_VENEER_REGION_LIMIT + 1,
TFM_TRUE,
#ifdef FLOW_CONTROL
FLOW_STEP_SAU_L_EN_R4,
FLOW_CTRL_SAU_L_EN_R4,
FLOW_STEP_SAU_L_CH_R4,
FLOW_CTRL_SAU_L_CH_R4,
#endif /* FLOW_CONTROL */
}
#endif
};
#endif /* MCUBOOT_EXT_LOADER */
/**
* @}
*/
/* Private function prototypes -----------------------------------------------*/
/** @defgroup TFM_SECURITY_Private_Functions Private Functions
* @{
*/
#ifdef TFM_OB_RDP_LEVEL_VALUE
static void rdp_level(uint32_t rdplevel, uint32_t current_rdplevel);
#endif /* TFM_OB_RDP_LEVEL_VALUE */
static void mpu_init_cfg(void);
static void mpu_appli_cfg(void);
static void flash_priv_cfg(void);
static void enable_hdp_protection(void);
static void lock_bl2_shared_area(void);
static void apply_wrp_sram2(uint32_t offset, uint32_t len);
#ifdef MCUBOOT_EXT_LOADER
static void mpu_loader_cfg(void);
static void sau_loader_cfg(void);
#if defined(MCUBOOT_EXT_LOADER) && defined(MCUBOOT_PRIMARY_ONLY)
static void secure_internal_flash(uint32_t offset_start, uint32_t offset_end);
#endif /* defined(MCUBOOT_EXT_LOADER) && defined(MCUBOOT_PRIMARY_ONLY) */
#endif /* MCUBOOT_EXT_LOADER */
static void active_tamper(void);
/**
* @}
*/
/** @defgroup TFM_SECURITY_Exported_Functions Exported Functions
* @{
*/
#if defined(MCUBOOT_EXT_LOADER) && defined(MCUBOOT_PRIMARY_ONLY)
void LL_SECU_SetLoaderCodeSecure(void)
{
secure_internal_flash(FLASH_AREA_LOADER_OFFSET, FLASH_AREA_LOADER_OFFSET+LOADER_IMAGE_S_CODE_SIZE - 1);
}
/* Place code in a specific section */
#endif /* defined(MCUBOOT_EXT_LOADER) && defined(MCUBOOT_PRIMARY_ONLY) */
#if defined(MCUBOOT_EXT_LOADER)
#if defined(__ICCARM__)
#pragma default_function_attributes = @ ".BL2_NoHdp_Code"
#else
__attribute__((section(".BL2_NoHdp_Code")))
#endif /* __ICCARM__ */
/**
* @brief Update the runtime security protections for application start
*
* @param None
* @retval None
*/
void LL_SECU_UpdateLoaderRunTimeProtections(void)
{
/* Enable HDP protection to hide sensible boot material */
enable_hdp_protection();
/* Set MPU to enable execution of secure /non secure loader */
mpu_loader_cfg();
/* reconfigure SAU to allow non secure execution */
sau_loader_cfg();
}
/* Stop placing data in specified section */
#if defined(__ICCARM__)
#pragma default_function_attributes =
#endif /* __ICCARM__ */
#endif /*MCUBOOT_EXT_LOADER*/
/**
* @brief Apply the runtime security protections to
*
* @param None
* @note By default, the best security protections are applied
* @retval None
*/
void LL_SECU_ApplyRunTimeProtections(void)
{
/* Unsecure bottom of SRAM1 for error_handler */
gtzc_init_cfg();
/* Set MPU to forbidd execution outside of not muteable code */
/* Initialize not secure MPU to forbidd execution on Flash /SRAM */
mpu_init_cfg();
/* Enable SAU to gain access to flash area non secure for write/read */
sau_and_idau_cfg();
/* With TFM_DEV_MODE , active tamper calls Error_Handler */
/* Error_Handler requires sau_and_idau_cfg */
active_tamper();
/* Lock top of SRAM2 in secure */
lock_bl2_shared_area();
/* Configure Flash Privilege access */
flash_priv_cfg();
}
/* Place code in a specific section */
#if defined(__ICCARM__)
#pragma default_function_attributes = @ ".BL2_NoHdp_Code"
#else
__attribute__((section(".BL2_NoHdp_Code")))
#endif /* __ICCARM__ */
/**
* @brief Update the runtime security protections for application start
*
* @param None
* @retval None
*/
void LL_SECU_UpdateRunTimeProtections(void)
{
/* Write Protect SRAM2 */
apply_wrp_sram2(BOOT_TFM_SHARED_DATA_BASE, BOOT_TFM_SHARED_DATA_SIZE);
/* Enable HDP protection to hide sensible boot material */
enable_hdp_protection();
/* Set MPU to enable execution of Secure and Non Secure active slots */
mpu_appli_cfg();
}
/* Stop placing data in specified section */
#if defined(__ICCARM__)
#pragma default_function_attributes =
#endif /* __ICCARM__ */
/**
* @brief Check if the Static security protections to
* all the Sections in Flash: WRP, SECURE FLASH, SECURE USER FLASH.
* those protections not impacted by a Reset. They are set using the Option Bytes
* When the device is locked (RDP Level2), these protections cannot be changed anymore
* @param None
* @note By default, the best security protections are applied to the different
* flash sections in order to maximize the security level for the specific MCU.
* @retval None
*/
void LL_SECU_CheckStaticProtections(void)
{
static FLASH_OBProgramInitTypeDef flash_option_bytes_bank1 = {0};
static FLASH_OBProgramInitTypeDef flash_option_bytes_bank2 = {0};
#ifdef TFM_NSBOOT_CHECK_ENABLE
static FLASH_OBProgramInitTypeDef flash_option_bytes_nsboot0 = {0};
static FLASH_OBProgramInitTypeDef flash_option_bytes_nsboot1 = {0};
#endif /* TFM_NSBOOT_CHECK_ENABLE */
#ifdef TFM_ENABLE_SET_OB
HAL_StatusTypeDef ret = HAL_ERROR;
#endif /* TFM_ENABLE_SET_OB */
uint32_t start;
uint32_t end;
#ifdef TFM_NSBOOT_CHECK_ENABLE
/* Get NSBOOTADD0 and NSBOOTADD1 value */
flash_option_bytes_nsboot0.BootAddrConfig = OB_BOOTADDR_NS0;
HAL_FLASHEx_OBGetConfig(&flash_option_bytes_nsboot0);
flash_option_bytes_nsboot1.BootAddrConfig = OB_BOOTADDR_NS1;
HAL_FLASHEx_OBGetConfig(&flash_option_bytes_nsboot1);
#endif /* TFM_NSBOOT_CHECK_ENABLE */
/* Get bank1 areaA OB */
flash_option_bytes_bank1.WRPArea = OB_WRPAREA_BANK1_AREAA;
flash_option_bytes_bank1.WMSecConfig = OB_WMSEC_AREA1;
flash_option_bytes_bank1.BootAddrConfig = OB_BOOTADDR_SEC0;
HAL_FLASHEx_OBGetConfig(&flash_option_bytes_bank1);
/* Get bank2 areaB OB */
flash_option_bytes_bank2.WRPArea = OB_WRPAREA_BANK2_AREAA;
flash_option_bytes_bank2.WMSecConfig = OB_WMSEC_AREA2;
HAL_FLASHEx_OBGetConfig(&flash_option_bytes_bank2);
#ifdef TFM_ENABLE_SET_OB
/* Clean the option configuration */
flash_option_bytes_bank1.OptionType = 0;
flash_option_bytes_bank2.OptionType = 0;
flash_option_bytes_bank2.WRPArea = 0;
flash_option_bytes_bank1.WRPArea = 0;
#endif /* TFM_ENABLE_SET_OB */
/* Check TZEN = 1 , we are in secure */
if ((flash_option_bytes_bank1.USERConfig & FLASH_OPTR_TZEN) != FLASH_OPTR_TZEN)
{
BOOT_LOG_ERR("Unexpected value for TZEN");
Error_Handler();
}
/* Check if dual bank is set */
if ((flash_option_bytes_bank1.USERConfig & FLASH_OPTR_DUALBANK) != FLASH_OPTR_DUALBANK)
{
BOOT_LOG_ERR("Unexpected value for dual bank configuration");
Error_Handler();
}
/* Check if swap bank is reset */
if ((flash_option_bytes_bank1.USERConfig & FLASH_OPTR_SWAP_BANK) != 0)
{
BOOT_LOG_ERR("Unexpected value for swap bank configuration");
Error_Handler();
}
/* Check secure boot address */
if (flash_option_bytes_bank1.BootAddr != BL2_BOOT_VTOR_ADDR)
{
BOOT_LOG_INF("BootAddr 0x%x", flash_option_bytes_bank1.BootAddr);
BOOT_LOG_ERR("Unexpected value for SEC BOOT Address");
Error_Handler();
}
#ifdef TFM_NSBOOT_CHECK_ENABLE
/* Check non-secure boot addresses */
if ((flash_option_bytes_nsboot0.BootAddr != BL2_BOOT_VTOR_ADDR)
|| (flash_option_bytes_nsboot1.BootAddr != BL2_BOOT_VTOR_ADDR))
{
BOOT_LOG_ERR("Unexpected value for NS BOOT Address");
Error_Handler();
}
#endif /* TFM_NSBOOT_CHECK_ENABLE */
/* Check bank1 secure flash protection */
start = FLASH_AREA_SCRATCH_OFFSET / PAGE_SIZE;
end = (S_IMAGE_PRIMARY_PARTITION_OFFSET + FLASH_S_PARTITION_SIZE - 1) / PAGE_SIZE;
if (end > PAGE_MAX_NUMBER_IN_BANK)
{
end = PAGE_MAX_NUMBER_IN_BANK;
}
if ((start != flash_option_bytes_bank1.WMSecStartPage)
|| (end != flash_option_bytes_bank1.WMSecEndPage))
{
BOOT_LOG_INF("BANK 1 secure flash [%d, %d] : OB [%d, %d]",
start, end, flash_option_bytes_bank1.WMSecStartPage, flash_option_bytes_bank1.WMSecEndPage);
#ifndef TFM_ENABLE_SET_OB
BOOT_LOG_ERR("Unexpected value for secure flash protection");
Error_Handler();
#else
BOOT_LOG_ERR("Unexpected value for secure flash protection: set wmsec1");
flash_option_bytes_bank1.WMSecStartPage = start;
flash_option_bytes_bank1.WMSecEndPage = end;
flash_option_bytes_bank1.OptionType |= OPTIONBYTE_WMSEC;
flash_option_bytes_bank1.WMSecConfig |= OB_WMSEC_AREA1 | OB_WMSEC_SECURE_AREA_CONFIG;
#endif /* TFM_ENABLE_SET_OB */
}
/* Check bank2 secure flash protection */
start = 0;
end = (S_IMAGE_PRIMARY_PARTITION_OFFSET + FLASH_S_PARTITION_SIZE - 1) / PAGE_SIZE;
if (end > PAGE_MAX_NUMBER_IN_BANK)
{
end = end - (PAGE_MAX_NUMBER_IN_BANK + 1);
if ((start != flash_option_bytes_bank2.WMSecStartPage)
|| (end != flash_option_bytes_bank2.WMSecEndPage))
{
BOOT_LOG_INF("BANK 2 secure flash [%d, %d] : OB [%d, %d]", start, end, flash_option_bytes_bank2.WMSecStartPage,
flash_option_bytes_bank2.WMSecEndPage);
#ifndef TFM_ENABLE_SET_OB
BOOT_LOG_ERR("Unexpected value for secure flash protection");
Error_Handler();
#else
BOOT_LOG_ERR("Unexpected value for secure flash protection : set wmsec2");
flash_option_bytes_bank2.WMSecStartPage = start;
flash_option_bytes_bank2.WMSecEndPage = end;
flash_option_bytes_bank2.OptionType = OPTIONBYTE_WMSEC;
flash_option_bytes_bank2.WMSecConfig |= OB_WMSEC_AREA2 | OB_WMSEC_SECURE_AREA_CONFIG ;
#endif /* TFM_ENABLE_SET_OB */
}
}
/* the bank 2 must be fully unsecure */
else if (flash_option_bytes_bank2.WMSecEndPage >= flash_option_bytes_bank2.WMSecStartPage)
{
BOOT_LOG_INF("BANK 2 secure flash [%d, %d] : OB [%d, %d]", 127, 0, flash_option_bytes_bank2.WMSecStartPage,
flash_option_bytes_bank2.WMSecEndPage);
#ifndef TFM_ENABLE_SET_OB
BOOT_LOG_ERR("Unexpected value for secure flash protection");
Error_Handler();
#else
/* bank is not unsecured , modify option bytes */
flash_option_bytes_bank2.WMSecStartPage = 127;
flash_option_bytes_bank2.WMSecEndPage = 0;
flash_option_bytes_bank2.OptionType = OPTIONBYTE_WMSEC;
flash_option_bytes_bank2.WMSecConfig |= OB_WMSEC_AREA2 | OB_WMSEC_SECURE_AREA_CONFIG ;
#endif /* TFM_ENABLE_SET_OB */
}
#ifdef TFM_WRP_PROTECT_ENABLE
/* Check flash write protection */
start = FLASH_AREA_PERSO_OFFSET / PAGE_SIZE;
end = (FLASH_AREA_PERSO_OFFSET + FLASH_AREA_PERSO_SIZE + FLASH_AREA_BL2_SIZE +
FLASH_AREA_BL2_NOHDP_SIZE - 1) / PAGE_SIZE;
if ((flash_option_bytes_bank1.WRPStartOffset > flash_option_bytes_bank1.WRPEndOffset)
|| (start != flash_option_bytes_bank1.WRPStartOffset)
|| (end != flash_option_bytes_bank1.WRPEndOffset))
{
BOOT_LOG_INF("BANK 1 flash write protection [%d, %d] : OB [%d, %d]", start, end,
flash_option_bytes_bank1.WRPStartOffset,
flash_option_bytes_bank1.WRPEndOffset);
#ifndef TFM_ENABLE_SET_OB
BOOT_LOG_ERR("Unexpected value for write protection ");
Error_Handler();
#else
flash_option_bytes_bank1.WRPStartOffset = start;
flash_option_bytes_bank1.WRPEndOffset = end;
flash_option_bytes_bank1.WRPArea |= OB_WRPAREA_BANK1_AREAA;
BOOT_LOG_ERR("Unexpected value for write protection : set wrp1");
flash_option_bytes_bank1.OptionType |= OPTIONBYTE_WRP;
#endif /* TFM_ENABLE_SET_OB */
}
#if defined(TFM_WRP_LOCK_ENABLE)
/* Check WRP lock protection */
if (flash_option_bytes_bank1.WRPLock != ENABLE)
{
BOOT_LOG_INF("BANK 1 WRP Lock 0x%x", flash_option_bytes_bank1.WRPLock);
BOOT_LOG_ERR("Unexpected value for WRP Lock");
Error_Handler();
}
#endif /* TFM_WRP_LOCK_ENABLE */
#ifdef MCUBOOT_EXT_LOADER
/* Check flash write protection for local loader */
start = FLASH_AREA_LOADER_BANK_OFFSET / PAGE_SIZE;
end = (FLASH_B_SIZE - 1) / PAGE_SIZE;
if ((flash_option_bytes_bank2.WRPStartOffset > flash_option_bytes_bank2.WRPEndOffset)
|| (start != flash_option_bytes_bank2.WRPStartOffset)
|| (end != flash_option_bytes_bank2.WRPEndOffset))
{
BOOT_LOG_INF("BANK 2 flash write protection [%d, %d] : OB [%d, %d]", start, end,
flash_option_bytes_bank2.WRPStartOffset,
flash_option_bytes_bank2.WRPEndOffset);
#ifndef TFM_ENABLE_SET_OB
BOOT_LOG_ERR("Unexpected value for write protection ");
Error_Handler();
#else
flash_option_bytes_bank2.WRPStartOffset = start;
flash_option_bytes_bank2.WRPEndOffset = end;
flash_option_bytes_bank2.WRPArea |= OB_WRPAREA_BANK2_AREAA;
BOOT_LOG_ERR("Unexpected value for write protection : set wrp2");
flash_option_bytes_bank2.OptionType |= OPTIONBYTE_WRP;
#endif /* TFM_ENABLE_SET_OB */
}
#if defined(TFM_WRP_LOCK_ENABLE)
/* Check WRP lock protection */
if (flash_option_bytes_bank2.WRPLock != ENABLE)
{
BOOT_LOG_INF("BANK 2 WRP Lock 0x%x", flash_option_bytes_bank2.WRPLock);
BOOT_LOG_ERR("Unexpected value for WRP Lock");
Error_Handler();
}
#endif /* TFM_WRP_LOCK_ENABLE */
#endif /* MCUBOOT_EXT_LOADER */
#endif /* TFM_WRP_PROTECT_ENABLE */
#ifdef TFM_HDP_PROTECT_ENABLE
/* Check secure user flash protection (HDP) */
start = FLASH_BL2_NVCNT_AREA_OFFSET / PAGE_SIZE;
end = (FLASH_BL2_HDP_END) / PAGE_SIZE;
if (
(flash_option_bytes_bank1.WMSecStartPage > flash_option_bytes_bank1.WMHDPEndPage)
|| (start < flash_option_bytes_bank1.WMSecStartPage)
|| (end > flash_option_bytes_bank1.WMHDPEndPage)
|| (flash_option_bytes_bank1.WMSecConfig & OB_WMSEC_HDP_AREA_DISABLE))
{
BOOT_LOG_INF("BANK 1 secure user flash [%d, %d] : OB [%d, %d]",
start,
end,
flash_option_bytes_bank1.WMSecStartPage,
flash_option_bytes_bank1.WMHDPEndPage);
#ifndef TFM_ENABLE_SET_OB
BOOT_LOG_ERR("Unexpected value for secure user flash protection");
Error_Handler();
#else
BOOT_LOG_ERR("Unexpected value for secure user flash protection : set hdp1");
flash_option_bytes_bank1.WMSecStartPage = start;
flash_option_bytes_bank1.WMHDPEndPage = end;
flash_option_bytes_bank1.OptionType |= OPTIONBYTE_WMSEC;
/* clean disable */
flash_option_bytes_bank1.WMSecConfig &= ~OB_WMSEC_HDP_AREA_DISABLE;
/* enable */
flash_option_bytes_bank1.WMSecConfig |= OB_WMSEC_HDP_AREA_CONFIG ;
flash_option_bytes_bank1.WMSecConfig |= OB_WMSEC_HDP_AREA_ENABLE;
flash_option_bytes_bank1.WMSecConfig |= OB_WMSEC_AREA1;
#endif /* TFM_ENABLE_SET_OB */
}
#else /* TFM_HDP_PROTECT_ENABLE */
flash_option_bytes_bank1.WMSecConfig &= ~(OB_WMSEC_HDP_AREA_CONFIG | OB_WMSEC_HDP_AREA_ENABLE);
flash_option_bytes_bank1.WMSecConfig |= OB_WMSEC_HDP_AREA_DISABLE;
#endif /* TFM_HDP_PROTECT_ENABLE */
#ifdef TFM_SECURE_USER_SRAM2_ERASE_AT_RESET
/* Check SRAM2 ERASE on reset */
if ((flash_option_bytes_bank1.USERConfig & FLASH_OPTR_SRAM2_RST) != 0)
{
BOOT_LOG_ERR("Unexpected value for SRAM2 ERASE at Reset");
Error_Handler();
}
#endif /*TFM_SECURE_USER_SRAM2_ERASE_AT_RESET */
#ifdef TFM_ENABLE_SET_OB
/* Configure Options Bytes */
if ((flash_option_bytes_bank1.OptionType != 0) || (flash_option_bytes_bank2.OptionType != 0))
{
/* Unlock the Flash to enable the flash control register access */
HAL_FLASH_Unlock();
/* Unlock the Options Bytes */
HAL_FLASH_OB_Unlock();
/* Verify Options Bytes to configure */
if ((flash_option_bytes_bank1.OptionType & OPTIONBYTE_RDP) != 0)
{
BOOT_LOG_ERR("Unexpected value for OB RDP to program");
Error_Handler();
}
if ((flash_option_bytes_bank2.OptionType & OPTIONBYTE_RDP) != 0)
{
BOOT_LOG_ERR("Unexpected value for OB RDP to program");
Error_Handler();
}
#ifdef MCUBOOT_EXT_LOADER
if ((flash_option_bytes_bank2.WRPArea & ~OB_WRPAREA_BANK2_AREAA) != 0)
#else
if ((flash_option_bytes_bank2.WRPArea & ~OB_WRPAREA_BANK2_AREAA) != 0)
#endif
{
BOOT_LOG_ERR("Unexpected value for bank 2 OB WRP AREA to program");
Error_Handler();
}
if ((flash_option_bytes_bank1.WRPArea & ~OB_WRPAREA_BANK1_AREAA) != 0)
{
BOOT_LOG_ERR("Unexpected value for bank 1 OB WRP AREA to program");
Error_Handler();
}
if ((flash_option_bytes_bank1.OptionType) != 0)
{
/* Program the Options Bytes */
ret = HAL_FLASHEx_OBProgram(&flash_option_bytes_bank1);
if (ret != HAL_OK)
{
BOOT_LOG_ERR("Error while setting OB Bank1 config");
Error_Handler();
}
}
if ((flash_option_bytes_bank2.OptionType) != 0)
{
/* Program the Options Bytes */
ret = HAL_FLASHEx_OBProgram(&flash_option_bytes_bank2);
if (ret != HAL_OK)
{
BOOT_LOG_ERR("Error while setting OB Bank1 config");
Error_Handler();
}
}
/* Launch the Options Bytes (reset the board, should not return) */
ret = HAL_FLASH_OB_Launch();
if (ret != HAL_OK)
{
BOOT_LOG_ERR("Error while execution OB_Launch");
Error_Handler();
}
/* Code should not be reached, reset the board */
HAL_NVIC_SystemReset();
}
#endif /* TFM_ENABLE_SET_OB */
#ifdef TFM_OB_BOOT_LOCK
/* Check Boot lock protection */
if (flash_option_bytes_bank1.BootLock != TFM_OB_BOOT_LOCK)
{
BOOT_LOG_INF("BootLock 0x%x", flash_option_bytes_bank1.BootLock);
BOOT_LOG_ERR("Unexpected value for SEC BOOT LOCK");
Error_Handler();
}
#endif /* TFM_OB_BOOT_LOCK */
#ifdef TFM_OB_RDP_LEVEL_VALUE
/* Check RDL level : boot if current RDP level is greater or equal to selected RDP level */
switch (TFM_OB_RDP_LEVEL_VALUE)
{
case OB_RDP_LEVEL_2:
if (flash_option_bytes_bank1.RDPLevel != OB_RDP_LEVEL_2)
{
rdp_level(TFM_OB_RDP_LEVEL_VALUE, flash_option_bytes_bank1.RDPLevel);
Error_Handler_rdp();
}
break;
case OB_RDP_LEVEL_1:
if ((flash_option_bytes_bank1.RDPLevel != OB_RDP_LEVEL_2) &&
(flash_option_bytes_bank1.RDPLevel != OB_RDP_LEVEL_1))
{
rdp_level(TFM_OB_RDP_LEVEL_VALUE, flash_option_bytes_bank1.RDPLevel);
Error_Handler_rdp();
}
break;
case OB_RDP_LEVEL_0_5:
if ((flash_option_bytes_bank1.RDPLevel != OB_RDP_LEVEL_2) &&
(flash_option_bytes_bank1.RDPLevel != OB_RDP_LEVEL_1) &&
(flash_option_bytes_bank1.RDPLevel != OB_RDP_LEVEL_0_5))
{
rdp_level(TFM_OB_RDP_LEVEL_VALUE, flash_option_bytes_bank1.RDPLevel);
Error_Handler_rdp();
}
break;
case OB_RDP_LEVEL_0:
break;
default:
Error_Handler();
break;
}
#endif /* TFM_OB_RDP_LEVEL_VALUE */
}
#ifdef TFM_OB_RDP_LEVEL_VALUE
static void rdp_level(uint32_t rdplevel, uint32_t current_rdplevel)
{
BOOT_LOG_INF("RDPLevel 0x%x (0x%x)", current_rdplevel, rdplevel);
BOOT_LOG_ERR("Unexpected value for RDP level");
#ifdef TFM_ENABLE_SET_OB
static FLASH_OBProgramInitTypeDef flash_option_bytes_bank = {0};
HAL_StatusTypeDef ret = HAL_ERROR;
/* Automatic programming to RDP 2 is not allowed */
if (rdplevel == OB_RDP_LEVEL_2)
{
Error_Handler();
}
flash_option_bytes_bank.OptionType = OPTIONBYTE_RDP;
flash_option_bytes_bank.RDPLevel = rdplevel;
BOOT_LOG_INF("Programming RDP to %x", rdplevel);
BOOT_LOG_INF("Unplug/Plug jumper JP3 (IDD)");
/* Unlock the Flash to enable the flash control register access */
HAL_FLASH_Unlock();
/* Unlock the Options Bytes */
HAL_FLASH_OB_Unlock();
/* Program the Options Bytes */
ret = HAL_FLASHEx_OBProgram(&flash_option_bytes_bank);
if (ret != HAL_OK)
{
BOOT_LOG_ERR("Error while setting RDP level");
Error_Handler();
}
/* Launch the Options Bytes (reset the board, should not return) */
ret = HAL_FLASH_OB_Launch();
if (ret != HAL_OK)
{
BOOT_LOG_ERR("Error while execution OB_Launch");
Error_Handler();
}
/* Code should not be reached, reset the board */
HAL_NVIC_SystemReset();
#endif /* TFM_ENABLE_SET_OB */
}
#endif /* TFM_OB_RDP_LEVEL_VALUE */
#if defined(MCUBOOT_EXT_LOADER) && defined(MCUBOOT_PRIMARY_ONLY)
static void secure_internal_flash(uint32_t offset_start, uint32_t offset_end)
{
volatile uint32_t *SecBB[8]= {&FLASH_S->SECBB1R1, &FLASH_S->SECBB1R2, &FLASH_S->SECBB1R3, &FLASH_S->SECBB1R4,
&FLASH_S->SECBB2R1, &FLASH_S->SECBB2R2, &FLASH_S->SECBB2R3, &FLASH_S->SECBB2R4};
volatile uint32_t *ptr;
uint32_t regwrite=0x0, index;
uint32_t block_start = offset_start;
uint32_t block_end = offset_end;
block_start = block_start / PAGE_SIZE;
block_end = (block_end / PAGE_SIZE) ;
/* Check alignment to avoid further problem */
if (offset_start & (PAGE_SIZE-1))
Error_Handler();
/* configuration stage */
if (uFlowStage == FLOW_STAGE_CFG)
{
/* 1f is for 32 bits */
for (index = block_start & ~0x1f; index < (8<<5) ; index++)
{ /* clean register on index aligned */
if (!(index & 0x1f)){
regwrite=0x0;
}
if ((index >= block_start) && (index <= block_end))
regwrite = regwrite | ( 1 << (index & 0x1f));
/* write register when 32 sub block are set or last block to set */
if ((index & 0x1f ) == 0x1f) {
ptr = (uint32_t *)SecBB[index>>5];
*ptr = regwrite;
}
}
FLOW_CONTROL_STEP(uFlowProtectValue, FLOW_STEP_FLASH_S_L_EN, FLOW_CTRL_FLASH_S_L_EN);
}
/* verification stage */
else
{
/* 1f is for 32 bits */
for (index = block_start & ~0x1f; index < (8<<5) ; index++)
{ /* clean register on index aligned */
if (!(index & 0x1f)){
regwrite=0x0;
}
if ((index >= block_start) && (index <= block_end))
regwrite = regwrite | ( 1 << (index & 0x1f));
/* write register when 32 sub block are set or last block to set */
if ((index & 0x1f ) == 0x1f) {
ptr = (uint32_t *)SecBB[index>>5];
if (*ptr != regwrite)
{
Error_Handler();
}
}
}
FLOW_CONTROL_STEP(uFlowProtectValue, FLOW_STEP_FLASH_S_L_CH, FLOW_CTRL_FLASH_S_L_CH);
}
}
#endif /* defined(MCUBOOT_EXT_LOADER) && defined(MCUBOOT_PRIMARY_ONLY) */
/**
* @brief Memory Config Init
* @param None
* @retval None
*/
void gtzc_init_cfg(void)
{
__HAL_RCC_GTZC1_CLK_ENABLE();
#ifdef TFM_ERROR_HANDLER_NON_SECURE
/* unsecure only one block in SRAM1 */
GTZC_MPCBB1_S->SECCFGR[0] = 0xfffffffe;
#endif /* TFM_ERROR_HANDLER_NON_SECURE */
}
/**
* @brief Sau idau init
* @param None
* @retval None
*/
void sau_and_idau_cfg(void)
{
uint32_t i;
uint32_t rnr;
uint32_t rbar;
uint32_t rlar;
uint32_t rnr_reg;
uint32_t rbar_reg;
uint32_t rlar_reg;
uint32_t ctrl_reg;
/* configuration stage */
if (uFlowStage == FLOW_STAGE_CFG)
{
/* Disable SAU */
TZ_SAU_Disable();
for (i = 0; i < ARRAY_SIZE(sau_init_cfg); i++)
{
SAU->RNR = sau_init_cfg[i].RNR;
SAU->RBAR = sau_init_cfg[i].RBAR & SAU_RBAR_BADDR_Msk;
SAU->RLAR = (sau_init_cfg[i].RLAR & SAU_RLAR_LADDR_Msk) |
(sau_init_cfg[i].nsc ? SAU_RLAR_NSC_Msk : 0U) |
SAU_RLAR_ENABLE_Msk;
/* Execution stopped if flow control failed */
FLOW_CONTROL_STEP(uFlowProtectValue, sau_init_cfg[i].flow_step_enable,
sau_init_cfg[i].flow_ctrl_enable);
}
/* Force memory writes before continuing */
__DSB();
/* Flush and refill pipeline with updated permissions */
__ISB();
/* Enable SAU */
TZ_SAU_Enable();
/* Execution stopped if flow control failed */
FLOW_CONTROL_STEP(uFlowProtectValue, FLOW_STEP_SAU_I_EN, FLOW_CTRL_SAU_I_EN);
}
/* verification stage */
else
{
for (i = 0; i < ARRAY_SIZE(sau_init_cfg); i++)
{
SAU->RNR = sau_init_cfg[i].RNR;
rnr = sau_init_cfg[i].RNR;
rbar = sau_init_cfg[i].RBAR & SAU_RBAR_BADDR_Msk;
rlar = (sau_init_cfg[i].RLAR & SAU_RLAR_LADDR_Msk) |
(sau_init_cfg[i].nsc ? SAU_RLAR_NSC_Msk : 0U) |
SAU_RLAR_ENABLE_Msk;
rnr_reg = SAU->RNR;
rbar_reg = SAU->RBAR;
rlar_reg = SAU->RLAR;
if ((rnr_reg != rnr) || (rbar_reg != rbar) || (rlar_reg != rlar))
{
Error_Handler();
}
/* Execution stopped if flow control failed */
FLOW_CONTROL_STEP(uFlowProtectValue, sau_init_cfg[i].flow_step_check,
sau_init_cfg[i].flow_ctrl_check);
}
ctrl_reg = SAU->CTRL;
if ((ctrl_reg && SAU_CTRL_ENABLE_Msk) != 1U)
{
Error_Handler();
}
else
{
/* Execution stopped if flow control failed */
FLOW_CONTROL_STEP(uFlowProtectValue, FLOW_STEP_SAU_I_CH, FLOW_CTRL_SAU_I_CH);
}
}
}
#ifdef MCUBOOT_EXT_LOADER
#if defined(__ICCARM__)
#pragma default_function_attributes = @ ".BL2_NoHdp_Code"
#else
__attribute__((section(".BL2_NoHdp_Code")))
#endif /* __ICCARM__ */
/**
* @brief Sau idau update for executing loader
* @param None
* @retval None
*/
static void sau_loader_cfg(void)
{
uint32_t i;
uint32_t rnr;
uint32_t rbar;
uint32_t rlar;
uint32_t rnr_reg;
uint32_t rbar_reg;
uint32_t rlar_reg;
uint32_t ctrl_reg;
/* configuration stage */
if (uFlowStage == FLOW_STAGE_CFG)
{
/* Disable SAU */
TZ_SAU_Disable();
for (i = 0; i < ARRAY_SIZE(sau_load_cfg); i++)
{
SAU->RNR = sau_load_cfg[i].RNR;
SAU->RBAR = sau_load_cfg[i].RBAR & SAU_RBAR_BADDR_Msk;
SAU->RLAR = (sau_load_cfg[i].RLAR & SAU_RLAR_LADDR_Msk) |
(sau_load_cfg[i].nsc ? SAU_RLAR_NSC_Msk : 0U) |
SAU_RLAR_ENABLE_Msk;
/* Execution stopped if flow control failed */
FLOW_CONTROL_STEP(uFlowProtectValue, sau_load_cfg[i].flow_step_enable,
sau_load_cfg[i].flow_ctrl_enable);
}
/* Force memory writes before continuing */
__DSB();
/* Flush and refill pipeline with updated permissions */
__ISB();
/* Enable SAU */
TZ_SAU_Enable();
/* Execution stopped if flow control failed */
FLOW_CONTROL_STEP(uFlowProtectValue, FLOW_STEP_SAU_L_EN, FLOW_CTRL_SAU_L_EN);
}
/* verification stage */
else
{
for (i = 0; i < ARRAY_SIZE(sau_load_cfg); i++)
{
SAU->RNR = sau_load_cfg[i].RNR;
rnr = sau_load_cfg[i].RNR;
rbar = sau_load_cfg[i].RBAR & SAU_RBAR_BADDR_Msk;
rlar = (sau_load_cfg[i].RLAR & SAU_RLAR_LADDR_Msk) |
(sau_load_cfg[i].nsc ? SAU_RLAR_NSC_Msk : 0U) |
SAU_RLAR_ENABLE_Msk;
rnr_reg = SAU->RNR;
rbar_reg = SAU->RBAR;
rlar_reg = SAU->RLAR;
if ((rnr_reg != rnr) || (rbar_reg != rbar) || (rlar_reg != rlar))
{
Error_Handler();
}
/* Execution stopped if flow control failed */
FLOW_CONTROL_STEP(uFlowProtectValue, sau_load_cfg[i].flow_step_check,
sau_load_cfg[i].flow_ctrl_check);
}
ctrl_reg = SAU->CTRL;
if ((ctrl_reg && SAU_CTRL_ENABLE_Msk) != 1U)
{
Error_Handler();
}
else
{
/* Execution stopped if flow control failed */
FLOW_CONTROL_STEP(uFlowProtectValue, FLOW_STEP_SAU_L_CH, FLOW_CTRL_SAU_L_CH);
}
/* FIX ME to INDENT better */
#if 1
/* set up floating point */
/*
// Setup behaviour of Floating Point Unit
*/
#define TZ_FPU_NS_USAGE 1
/*
// Floating Point Unit usage
// <0=> Secure state only
// <3=> Secure and Non-Secure state
// Value for SCB->NSACR register bits CP10, CP11
*/
#define SCB_NSACR_CP10_11_VAL 3
/*
// Treat floating-point registers as Secure
// <0=> Disabled
// <1=> Enabled
// Value for FPU->FPCCR register bit TS
*/
#define FPU_FPCCR_TS_VAL 0
/*
// Clear on return (CLRONRET) accessibility
// <0=> Secure and Non-Secure state
// <1=> Secure state only
// Value for FPU->FPCCR register bit CLRONRETS
*/
#define FPU_FPCCR_CLRONRETS_VAL 0
/*
// Clear floating-point caller saved registers on exception return
// <0=> Disabled
// <1=> Enabled
// Value for FPU->FPCCR register bit CLRONRET
*/
#define FPU_FPCCR_CLRONRET_VAL 1
SCB->NSACR = (SCB->NSACR & ~(SCB_NSACR_CP10_Msk | SCB_NSACR_CP11_Msk)) |
((SCB_NSACR_CP10_11_VAL << SCB_NSACR_CP10_Pos) & (SCB_NSACR_CP10_Msk | SCB_NSACR_CP11_Msk));
FPU->FPCCR = (FPU->FPCCR & ~(FPU_FPCCR_TS_Msk | FPU_FPCCR_CLRONRETS_Msk | FPU_FPCCR_CLRONRET_Msk)) |
((FPU_FPCCR_TS_VAL << FPU_FPCCR_TS_Pos ) & FPU_FPCCR_TS_Msk ) |
((FPU_FPCCR_CLRONRETS_VAL << FPU_FPCCR_CLRONRETS_Pos) & FPU_FPCCR_CLRONRETS_Msk) |
((FPU_FPCCR_CLRONRET_VAL << FPU_FPCCR_CLRONRET_Pos ) & FPU_FPCCR_CLRONRET_Msk );
/* Lock SAU config */
__HAL_RCC_SYSCFG_CLK_ENABLE();
SYSCFG->CSLCKR |= SYSCFG_CSLCKR_LOCKSAU;
#endif
}
}
/* Stop placing data in specified section */
#if defined(__ICCARM__)
#pragma default_function_attributes =
#endif /* __ICCARM__ */
#endif /* MCUBOOT_EXT_LOADER */
/**
* @brief mpu init
* @param None
* @retval None
*/
static void mpu_init_cfg(void)
{
#ifdef TFM_BOOT_MPU_PROTECTION
struct mpu_armv8m_dev_t dev_mpu_s = { MPU_BASE };
struct mpu_armv8m_dev_t dev_mpu_ns = { MPU_BASE_NS };
int32_t i;
/* configuration stage */
if (uFlowStage == FLOW_STAGE_CFG)
{
/* configure secure MPU regions */
for (i = 0; i < ARRAY_SIZE(region_cfg_init_s); i++)
{
if (mpu_armv8m_region_enable(&dev_mpu_s,
(struct mpu_armv8m_region_cfg_t *)®ion_cfg_init_s[i]) != MPU_ARMV8M_OK)
{
Error_Handler();
}
else
{
/* Execution stopped if flow control failed */
FLOW_CONTROL_STEP(uFlowProtectValue, region_cfg_init_s[i].flow_step_enable,
region_cfg_init_s[i].flow_ctrl_enable);
}
}
/* enable secure MPU */
mpu_armv8m_enable(&dev_mpu_s, PRIVILEGED_DEFAULT_ENABLE, HARDFAULT_NMI_ENABLE);
FLOW_CONTROL_STEP(uFlowProtectValue, FLOW_STEP_MPU_S_I_EN, FLOW_CTRL_MPU_S_I_EN);
/* configure non secure MPU regions */
for (i = 0; i < ARRAY_SIZE(region_cfg_init_ns); i++)
{
if (mpu_armv8m_region_enable(&dev_mpu_ns,
(struct mpu_armv8m_region_cfg_t *)®ion_cfg_init_ns[i]) != MPU_ARMV8M_OK)
{
Error_Handler();
}
else
{
/* Execution stopped if flow control failed */
FLOW_CONTROL_STEP(uFlowProtectValue, region_cfg_init_ns[i].flow_step_enable,
region_cfg_init_ns[i].flow_ctrl_enable);
}
}
/* enable non secure MPU */
mpu_armv8m_enable(&dev_mpu_ns, PRIVILEGED_DEFAULT_ENABLE, HARDFAULT_NMI_ENABLE);
FLOW_CONTROL_STEP(uFlowProtectValue, FLOW_STEP_MPU_NS_I_EN, FLOW_CTRL_MPU_NS_I_EN);
}
/* verification stage */
else
{
/* check secure MPU regions */
for (i = 0; i < ARRAY_SIZE(region_cfg_init_s); i++)
{
if (mpu_armv8m_region_enable_check(&dev_mpu_s,
(struct mpu_armv8m_region_cfg_t *)®ion_cfg_init_s[i]) != MPU_ARMV8M_OK)
{
Error_Handler();
}
else
{
/* Execution stopped if flow control failed */
FLOW_CONTROL_STEP(uFlowProtectValue, region_cfg_init_s[i].flow_step_check,
region_cfg_init_s[i].flow_ctrl_check);
}
}
/* check secure MPU */
if (mpu_armv8m_check(&dev_mpu_s, PRIVILEGED_DEFAULT_ENABLE,
HARDFAULT_NMI_ENABLE) != MPU_ARMV8M_OK)
{
Error_Handler();
}
else
{
/* Execution stopped if flow control failed */
FLOW_CONTROL_STEP(uFlowProtectValue, FLOW_STEP_MPU_S_I_CH, FLOW_CTRL_MPU_S_I_CH);
}
/* check non secure MPU regions */
for (i = 0; i < ARRAY_SIZE(region_cfg_init_ns); i++)
{
if (mpu_armv8m_region_enable_check(&dev_mpu_ns,
(struct mpu_armv8m_region_cfg_t *)®ion_cfg_init_ns[i]) != MPU_ARMV8M_OK)
{
Error_Handler();
}
else
{
/* Execution stopped if flow control failed */
FLOW_CONTROL_STEP(uFlowProtectValue, region_cfg_init_ns[i].flow_step_check,
region_cfg_init_ns[i].flow_ctrl_check);
}
}
/* check non secure MPU */
if (mpu_armv8m_check(&dev_mpu_ns, PRIVILEGED_DEFAULT_ENABLE,
HARDFAULT_NMI_ENABLE) != MPU_ARMV8M_OK)
{
Error_Handler();
}
else
{
/* Execution stopped if flow control failed */
FLOW_CONTROL_STEP(uFlowProtectValue, FLOW_STEP_MPU_NS_I_CH, FLOW_CTRL_MPU_NS_I_CH);
}
}
#endif /* TFM_BOOT_MPU_PROTECTION */
}
/* Place code in a specific section */
#if defined(__ICCARM__)
#pragma default_function_attributes = @ ".BL2_NoHdp_Code"
#else
__attribute__((section(".BL2_NoHdp_Code")))
#endif /* __ICCARM__ */
static void mpu_appli_cfg(void)
{
#ifdef TFM_BOOT_MPU_PROTECTION
static struct mpu_armv8m_dev_t dev_mpu_s = { MPU_BASE };
static struct mpu_armv8m_dev_t dev_mpu_ns = { MPU_BASE_NS };
int32_t i;
/* configuration stage */
if (uFlowStage == FLOW_STAGE_CFG)
{
/* configure secure MPU regions */
for (i = 0; i < ARRAY_SIZE(region_cfg_appli_s); i++)
{
if (mpu_armv8m_region_enable(&dev_mpu_s,
(struct mpu_armv8m_region_cfg_t *)®ion_cfg_appli_s[i]) != MPU_ARMV8M_OK)
{
Error_Handler();
}
else
{
/* Execution stopped if flow control failed */
FLOW_CONTROL_STEP(uFlowProtectValue, region_cfg_appli_s[i].flow_step_enable,
region_cfg_appli_s[i].flow_ctrl_enable);
}
}
/* configure non secure MPU regions */
for (i = 0; i < ARRAY_SIZE(region_cfg_appli_ns); i++)
{
if (mpu_armv8m_region_enable(&dev_mpu_ns,
(struct mpu_armv8m_region_cfg_t *)®ion_cfg_appli_ns[i]) != MPU_ARMV8M_OK)
{
Error_Handler();
}
else
{
/* Execution stopped if flow control failed */
FLOW_CONTROL_STEP(uFlowProtectValue, region_cfg_appli_ns[i].flow_step_enable,
region_cfg_appli_ns[i].flow_ctrl_enable);
}
}
}
else
{
/* check secure MPU regions */
for (i = 0; i < ARRAY_SIZE(region_cfg_appli_s); i++)
{
if (mpu_armv8m_region_enable_check(&dev_mpu_s,
(struct mpu_armv8m_region_cfg_t *)®ion_cfg_appli_s[i]) != MPU_ARMV8M_OK)
{
Error_Handler();
}
else
{
/* Execution stopped if flow control failed */
FLOW_CONTROL_STEP(uFlowProtectValue, region_cfg_appli_s[i].flow_step_check,
region_cfg_appli_s[i].flow_ctrl_check);
}
}
/* check non secure MPU regions */
for (i = 0; i < ARRAY_SIZE(region_cfg_appli_ns); i++)
{
if (mpu_armv8m_region_enable_check(&dev_mpu_ns,
(struct mpu_armv8m_region_cfg_t *)®ion_cfg_appli_ns[i]) != MPU_ARMV8M_OK)
{
Error_Handler();
}
else
{
/* Execution stopped if flow control failed */
FLOW_CONTROL_STEP(uFlowProtectValue, region_cfg_appli_ns[i].flow_step_check,
region_cfg_appli_ns[i].flow_ctrl_check);
}
}
}
#endif /* TFM_BOOT_MPU_PROTECTION */
}
/* Stop placing data in specified section */
#if defined(__ICCARM__)
#pragma default_function_attributes =
#endif /* __ICCARM__ */
#ifdef MCUBOOT_EXT_LOADER
/* Place code in a specific section */
#if defined(__ICCARM__)
#pragma default_function_attributes = @ ".BL2_NoHdp_Code"
#else
__attribute__((section(".BL2_NoHdp_Code")))
#endif /* __ICCARM__ */
static void mpu_loader_cfg(void)
{
#ifdef TFM_BOOT_MPU_PROTECTION
#if defined(MCUBOOT_PRIMARY_ONLY)
static struct mpu_armv8m_dev_t dev_mpu_s = { MPU_BASE };
/* configuration stage */
if (uFlowStage == FLOW_STAGE_CFG)
{
/* secure region 2 is configured to allow read /write to NS_RAM */
mpu_armv8m_region_disable(&dev_mpu_s, 2);
/* Execution stopped if flow control failed */
FLOW_CONTROL_STEP(uFlowProtectValue, FLOW_STEP_MPU_S_L_DI_R2, FLOW_CTRL_MPU_S_L_DI_R2);
}
else
{
/* check region 2 is disabled */
if (mpu_armv8m_region_disable_check(&dev_mpu_s, 2) != MPU_ARMV8M_OK)
{
Error_Handler();
}
else
{
/* Execution stopped if flow control failed */
FLOW_CONTROL_STEP(uFlowProtectValue, FLOW_STEP_MPU_S_L_CH_R2, FLOW_CTRL_MPU_S_L_CH_R2);
}
}
#endif /* MCUBOOT_PRIMARY_ONLY */
#endif /* TFM_BOOT_MPU_PROTECTION */
/* configuration stage */
if (uFlowStage != FLOW_STAGE_CFG)
{
/* Lock Secure MPU config */
__HAL_RCC_SYSCFG_CLK_ENABLE();
SYSCFG->CSLCKR |= SYSCFG_CSLCKR_LOCKSMPU;
/* Lock Non Secure MPU config */
__HAL_RCC_SYSCFG_CLK_ENABLE();
SYSCFG->CSLCKR |= SYSCFG_CNSLCKR_LOCKNSMPU;
}
}
/* Stop placing data in specified section */
#if defined(__ICCARM__)
#pragma default_function_attributes =
#endif /* __ICCARM__ */
#endif /* MCUBOOT_EXT_LOADER */
/**
* @brief lock bl2 shared sram in secure
* @param None
* @retval None
*/
static void lock_bl2_shared_area(void)
{
uint32_t lockAttributes = GTZC_MCPBB_SUPERBLOCK_LOCKED;
/* assumption shared area in SRAM2 in the last 8 Kbytes super block */
/* This area in SRAM 2 is updated BL2 and can be lock to avoid any changes */
if (
(BOOT_TFM_SHARED_DATA_BASE >= S_RAM_ALIAS(_SRAM2_TOP - GTZC_MPCBB_SUPERBLOCK_SIZE))
&& (BOOT_TFM_SHARED_DATA_SIZE <= GTZC_MPCBB_SUPERBLOCK_SIZE))
{
__HAL_RCC_GTZC1_CLK_ENABLE();
HAL_GTZC_MPCBB_LockConfig(S_RAM_ALIAS(_SRAM2_TOP - GTZC_MPCBB_SUPERBLOCK_SIZE),
1,
&lockAttributes);
}
else Error_Handler();
}
/**
* @brief configure flash privilege access
* @param None
* @retval None
*/
static void flash_priv_cfg(void)
{
#ifdef TFM_FLASH_PRIVONLY_ENABLE
/* configuration stage */
if (uFlowStage == FLOW_STAGE_CFG)
{
/* Configure Flash Privilege access */
HAL_FLASHEx_ConfigPrivMode(FLASH_SPRIV_DENIED);
/* Execution stopped if flow control failed */
FLOW_CONTROL_STEP(uFlowProtectValue, FLOW_STEP_FLASH_P_EN, FLOW_CTRL_FLASH_P_EN);
#endif /* TFM_FLASH_PRIVONLY_ENABLE */
}
/* verification stage */
else
{
if (HAL_FLASHEx_GetPrivMode() != FLASH_SPRIV_DENIED)
{
Error_Handler();
}
else
{
/* Execution stopped if flow control failed */
FLOW_CONTROL_STEP(uFlowProtectValue, FLOW_STEP_FLASH_P_CH, FLOW_CTRL_FLASH_P_CH);
}
}
}
/* Place code in a specific section */
#if defined(__ICCARM__)
#pragma default_function_attributes = @ ".BL2_NoHdp_Code"
#else
__attribute__((section(".BL2_NoHdp_Code")))
#endif /* __ICCARM__ */
/**
* @brief Enable HDP protection
* @param None
* @retval None
*/
static void enable_hdp_protection(void)
{
#ifdef TFM_HDP_PROTECT_ENABLE
do
{
/* Activate HDP protection */
SET_BIT(FLASH->SECHDPCR, FLASH_SECHDPCR_HDP1_ACCDIS);
} while ((FLASH->SECHDPCR & FLASH_SECHDPCR_HDP1_ACCDIS) != FLASH_SECHDPCR_HDP1_ACCDIS);
if ((FLASH->SECHDPCR & FLASH_SECHDPCR_HDP1_ACCDIS) != FLASH_SECHDPCR_HDP1_ACCDIS)
{
/* Security issue : execution stopped ! */
Error_Handler();
}
#endif /* TFM_HDP_PROTECT_ENABLE */
}
/* Stop placing data in specified section */
#if defined(__ICCARM__)
#pragma default_function_attributes =
#endif /* __ICCARM__ */
/* Place code in a specific section */
#if defined(__ICCARM__)
#pragma default_function_attributes = @ ".BL2_NoHdp_Code"
#else
__attribute__((section(".BL2_NoHdp_Code")))
#endif /* __ICCARM__ */
static void apply_wrp_sram2(uint32_t offset, uint32_t len)
{
uint32_t start_offset = ((offset - SRAM2_BASE_S)/ SRAM2_PAGE_SIZE);
uint32_t end_offset = start_offset + (len -1)/SRAM2_PAGE_SIZE;
uint32_t index;
uint32_t val0 = 0;
uint32_t val1 = 0;
RCC->AHB1ENR |= RCC_AHB1ENR_RAMCFGEN;
__HAL_RCC_SYSCFG_CLK_ENABLE();
#if 0
BOOT_LOG_INF("SRAM2 write protection [0x%x, 0x%x] : %d %d", offset, len, start_offset, end_offset);
#endif
for (index = start_offset; index <= end_offset; index ++)
{
if (index > 31U)
{
val1 |= (1 << (index - 32U));
}
else
{
val0 |= (1 << index);
}
}
#if 0
BOOT_LOG_INF("SRAM2 write protection [0x%x] : %x", (uint32_t)&RAMCFG_SRAM2_S->WPR1, val0);
BOOT_LOG_INF("SRAM2 write protection [0x%x] : %x", (uint32_t)&RAMCFG_SRAM2_S->WPR2, val1);
#endif
RAMCFG_SRAM2_S->WPR1 = val0;
RAMCFG_SRAM2_S->WPR2 = val1;
}
/* Stop placing data in specified section */
#if defined(__ICCARM__)
#pragma default_function_attributes =
#endif /* __ICCARM__ */
#if (TFM_TAMPER_ENABLE != NO_TAMPER)
const RTC_SecureStateTypeDef TamperSecureConf = {
.rtcSecureFull = RTC_SECURE_FULL_NO,
.rtcNonSecureFeatures = RTC_NONSECURE_FEATURE_ALL,
.tampSecureFull = TAMP_SECURE_FULL_YES,
.MonotonicCounterSecure = TAMP_MONOTONIC_CNT_SECURE_NO,
.backupRegisterStartZone2 = 0,
.backupRegisterStartZone3 = 0
};
const RTC_PrivilegeStateTypeDef TamperPrivConf = {
.rtcPrivilegeFull = RTC_PRIVILEGE_FULL_NO,
.rtcPrivilegeFeatures = RTC_PRIVILEGE_FEATURE_NONE,
.tampPrivilegeFull = TAMP_PRIVILEGE_FULL_YES,
.MonotonicCounterPrivilege = TAMP_MONOTONIC_CNT_PRIVILEGE_NO,
.backupRegisterStartZone2 = 0,
.backupRegisterStartZone3 = 0
};
const RTC_InternalTamperTypeDef InternalTamperConf = {
.IntTamper = RTC_INT_TAMPER_1 | RTC_INT_TAMPER_9,
.TimeStampOnTamperDetection = RTC_TIMESTAMPONTAMPERDETECTION_DISABLE,
.NoErase = RTC_TAMPER_ERASE_BACKUP_ENABLE
};
/* Place code in a specific section */
#if defined(__ICCARM__)
#pragma default_function_attributes = @ ".BL2_NoHdp_Code"
#else
__attribute__((section(".BL2_NoHdp_Code")))
#endif /* __ICCARM__ */
void TAMP_IRQHandler(void)
{
NVIC_SystemReset();
}
/* Stop placing data in specified section */
#if defined(__ICCARM__)
#pragma default_function_attributes =
#endif /* __ICCARM__ */
#ifdef TFM_DEV_MODE
extern volatile uint32_t TamperEventCleared;
#endif
#endif /* (TFM_TAMPER_ENABLE != NO_TAMPER) */
RTC_HandleTypeDef RTCHandle;
static void active_tamper(void)
{
#if 0
fih_int fih_rc = FIH_FAILURE;
#endif
#if (TFM_TAMPER_ENABLE == ALL_TAMPER)
RTC_ActiveTampersTypeDef sAllTamper;
/* use random generator to feed */
uint32_t Seed[4]={0,0,0,0};
uint32_t len=0;
uint32_t j;
#endif /* (TFM_TAMPER_ENABLE == ALL_TAMPER) */
#if (TFM_TAMPER_ENABLE != NO_TAMPER)
RTC_SecureStateTypeDef TamperSecureConfGet;
RTC_PrivilegeStateTypeDef TamperPrivConfGet;
#endif /* TFM_TAMPER_ENABLE != NO_TAMPER) */
/* configuration stage */
if (uFlowStage == FLOW_STAGE_CFG)
{
#if defined(TFM_DEV_MODE) && (TFM_TAMPER_ENABLE != NO_TAMPER)
if (TamperEventCleared) {
BOOT_LOG_INF("Boot with TAMPER Event Active");
#if (TFM_TAMPER_ENABLE == ALL_TAMPER)
/* avoid several re-boot in DEV_MODE with Tamper active */
BOOT_LOG_INF("Plug the tamper cable, and reboot");
BOOT_LOG_INF("Or");
#endif
BOOT_LOG_INF("Build and Flash with flag #define TFM_TAMPER_ENABLE NO_TAMPER\n");
Error_Handler();
}
#endif /* TFM_DEV_MODE && (TFM_TAMPER_ENABLE != NO_TAMPER) */
/* RTC Init */
RTCHandle.Instance = RTC;
RTCHandle.Init.HourFormat = RTC_HOURFORMAT_12;
RTCHandle.Init.AsynchPrediv = RTC_ASYNCH_PREDIV;
RTCHandle.Init.SynchPrediv = RTC_SYNCH_PREDIV;
RTCHandle.Init.OutPut = RTC_OUTPUT_DISABLE;
RTCHandle.Init.OutPutRemap = RTC_OUTPUT_REMAP_NONE;
RTCHandle.Init.OutPutPolarity = RTC_OUTPUT_POLARITY_HIGH;
RTCHandle.Init.OutPutType = RTC_OUTPUT_TYPE_PUSHPULL;
RTCHandle.Init.OutPutPullUp = RTC_OUTPUT_PULLUP_NONE;
if (HAL_RTC_Init(&RTCHandle) != HAL_OK)
{
Error_Handler();
}
#if (TFM_TAMPER_ENABLE == ALL_TAMPER)
/* generate random seed */
mbedtls_hardware_poll(NULL, (unsigned char *)Seed, sizeof(Seed),(size_t *)&len);
if (len == 0)
{
Error_Handler();
}
BOOT_LOG_INF("TAMPER SEED [0x%x,0x%x,0x%x,0x%x]", Seed[0], Seed[1], Seed[2], Seed[3]);
/* Configure active tamper common parameters */
sAllTamper.ActiveFilter = RTC_ATAMP_FILTER_ENABLE;
sAllTamper.ActiveAsyncPrescaler = RTC_ATAMP_ASYNCPRES_RTCCLK_32;
sAllTamper.TimeStampOnTamperDetection = RTC_TIMESTAMPONTAMPERDETECTION_ENABLE;
sAllTamper.ActiveOutputChangePeriod = 4;
sAllTamper.Seed[0] = Seed[0];
sAllTamper.Seed[1] = Seed[1];
sAllTamper.Seed[2] = Seed[2];
sAllTamper.Seed[3] = Seed[3];
/* Disable all Active Tampers */
/* No active tamper */
for (j = 0; j <= RTC_ATAMP_8; j++)
{
sAllTamper.TampInput[j].Enable = RTC_ATAMP_DISABLE;
}
sAllTamper.TampInput[7].Enable = RTC_ATAMP_ENABLE;
sAllTamper.TampInput[7].Output = 7;
sAllTamper.TampInput[7].NoErase = RTC_TAMPER_ERASE_BACKUP_ENABLE;
sAllTamper.TampInput[7].MaskFlag = RTC_TAMPERMASK_FLAG_DISABLE;
sAllTamper.TampInput[7].Interrupt = RTC_ATAMP_INTERRUPT_ENABLE;
/* Set active tampers */
if (HAL_RTCEx_SetActiveTampers(&RTCHandle, &sAllTamper) != HAL_OK)
{
Error_Handler();
}
FLOW_CONTROL_STEP(uFlowProtectValue, FLOW_STEP_TAMP_ACT_EN, FLOW_CTRL_TAMP_ACT_EN);
#else
HAL_RTCEx_DeactivateTamper(&RTCHandle, RTC_TAMPER_ALL);
#endif /* (TFM_TAMPER_ENABLE == ALL_TAMPER) */
#if (TFM_TAMPER_ENABLE != NO_TAMPER)
/* Internal Tamper activation */
/* Enable Cryptographic IPs fault (tamp_itamp9), Backup domain voltage threshold monitoring (tamp_itamp1)*/
if (HAL_RTCEx_SetInternalTamper(&RTCHandle,(RTC_InternalTamperTypeDef *)&InternalTamperConf)!=HAL_OK)
{
Error_Handler();
}
FLOW_CONTROL_STEP(uFlowProtectValue, FLOW_STEP_TAMP_INT_EN, FLOW_CTRL_TAMP_INT_EN);
/* Set tamper configuration secure only */
if (HAL_RTCEx_SecureModeSet(&RTCHandle, (RTC_SecureStateTypeDef *)&TamperSecureConf) != HAL_OK)
{
Error_Handler();
}
FLOW_CONTROL_STEP(uFlowProtectValue, FLOW_STEP_TAMP_SEC_EN, FLOW_CTRL_TAMP_SEC_EN);
/* Set tamper configuration privileged only */
if (HAL_RTCEx_PrivilegeModeSet(&RTCHandle,(RTC_PrivilegeStateTypeDef *)&TamperPrivConf) != HAL_OK)
{
Error_Handler();
}
FLOW_CONTROL_STEP(uFlowProtectValue, FLOW_STEP_TAMP_PRIV_EN, FLOW_CTRL_TAMP_PRIV_EN);
/* Activate Secret Erase */
HAL_RTCEx_Erase_SecretDev_Conf(&RTCHandle,(uint32_t)TAMP_SECRETDEVICE_ERASE_ENABLE);
FLOW_CONTROL_STEP(uFlowProtectValue, FLOW_STEP_TAMP_CFG_EN, FLOW_CTRL_TAMP_CFG_EN);
BOOT_LOG_INF("TAMPER Activated");
#else
HAL_RTCEx_DeactivateInternalTamper(&RTCHandle, RTC_INT_TAMPER_ALL);
#endif /* (TFM_TAMPER_ENABLE != NO_TAMPER) */
}
#if (TFM_TAMPER_ENABLE != NO_TAMPER)
/* verification stage */
else
{
#if (TFM_TAMPER_ENABLE == ALL_TAMPER)
/* Check active tampers */
if ((READ_BIT(TAMP->ATOR, TAMP_ATOR_INITS) == 0U) ||
(READ_REG(TAMP->IER) != 0x00000080U) ||
(READ_REG(TAMP->ATCR1) != 0x84050080U) ||
(READ_REG(TAMP->ATCR2) != 0xE0000000U) ||
(READ_REG(TAMP->CR1) != 0x01010080U) ||
(READ_REG(TAMP->CR2) != 0x00000000U))
{
Error_Handler();
}
FLOW_CONTROL_STEP(uFlowProtectValue, FLOW_STEP_TAMP_ACT_CH, FLOW_CTRL_TAMP_ACT_CH);
#endif /* (TFM_TAMPER_ENABLE == ALL_TAMPER) */
/* Check Internal Tamper activation */
if ((READ_BIT(RTC->CR, RTC_CR_TAMPTS) != InternalTamperConf.TimeStampOnTamperDetection) ||
#if (TFM_TAMPER_ENABLE == ALL_TAMPER)
(READ_REG(TAMP->CR1) != 0x01010080U) ||
#else
(READ_REG(TAMP->CR1) != 0x01010000U) ||
#endif /* (TFM_TAMPER_ENABLE == ALL_TAMPER) */
(READ_REG(TAMP->CR3) != 0x00000000U))
{
Error_Handler();
}
FLOW_CONTROL_STEP(uFlowProtectValue, FLOW_STEP_TAMP_INT_CH, FLOW_CTRL_TAMP_INT_CH);
#if 0
/* Check tamper configuration secure only */
if (HAL_RTCEx_SecureModeGet(&RTCHandle, (RTC_SecureStateTypeDef *)&TamperSecureConfGet) != HAL_OK)
{
Error_Handler();
}
FIH_CALL(boot_fih_memequal, fih_rc,(void *)&TamperSecureConf, (void *)&TamperSecureConfGet, sizeof(TamperSecureConf));
if (fih_not_eq(fih_rc, FIH_SUCCESS)) {
Error_Handler();
}
#endif
FLOW_CONTROL_STEP(uFlowProtectValue, FLOW_STEP_TAMP_SEC_CH, FLOW_CTRL_TAMP_SEC_CH);
#if 0
/* Check tamper configuration privileged only */
if (HAL_RTCEx_PrivilegeModeGet(&RTCHandle,(RTC_PrivilegeStateTypeDef *)&TamperPrivConfGet) != HAL_OK)
{
Error_Handler();
}
FIH_CALL(boot_fih_memequal, fih_rc,(void *)&TamperPrivConf, (void *)&TamperPrivConfGet, sizeof(TamperPrivConf));
if (fih_not_eq(fih_rc, FIH_SUCCESS)) {
Error_Handler();
}
#endif
FLOW_CONTROL_STEP(uFlowProtectValue, FLOW_STEP_TAMP_PRIV_CH, FLOW_CTRL_TAMP_PRIV_CH);
/* Check Secret Erase */
#if 0
/* On U5 Cut 2 only */
if (READ_BIT(TAMP->ERCFGR, TAMP_ERCFGR0) != TAMP_ERCFGR0)
{
Error_Handler();
}
#endif
FLOW_CONTROL_STEP(uFlowProtectValue, FLOW_STEP_TAMP_CFG_CH, FLOW_CTRL_TAMP_CFG_CH);
}
#endif /* TFM_TAMPER_ENABLE != NO_TAMPER */
}
/**
* @}
*/
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/