arm-trusted-firmware/plat/st/stm32mp1/bl2_plat_setup.c
Nicolas Le Bayon 072d7532d2 refactor(st-drivers): improve BSEC driver
Rename driver file to BSEC2.
Split header file in IP and feature parts.
Add functions to access BSEC scratch register.
Several corrections and improvements.
Probe the driver earlier, especially to check debug features.

Change-Id: I1981536398d598d67a19d2d7766dacc18de72ec1
Signed-off-by: Nicolas Le Bayon <nicolas.le.bayon@st.com>
Signed-off-by: Yann Gautier <yann.gautier@st.com>
2022-01-28 18:04:52 +01:00

500 lines
13 KiB
C

/*
* Copyright (c) 2015-2022, ARM Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include <assert.h>
#include <errno.h>
#include <string.h>
#include <arch_helpers.h>
#include <common/bl_common.h>
#include <common/debug.h>
#include <common/desc_image_load.h>
#include <drivers/generic_delay_timer.h>
#include <drivers/mmc.h>
#include <drivers/st/bsec.h>
#include <drivers/st/regulator_fixed.h>
#include <drivers/st/stm32_iwdg.h>
#include <drivers/st/stm32_uart.h>
#include <drivers/st/stm32mp1_clk.h>
#include <drivers/st/stm32mp1_pwr.h>
#include <drivers/st/stm32mp1_ram.h>
#include <drivers/st/stm32mp_pmic.h>
#include <lib/fconf/fconf.h>
#include <lib/fconf/fconf_dyn_cfg_getter.h>
#include <lib/mmio.h>
#include <lib/optee_utils.h>
#include <lib/xlat_tables/xlat_tables_v2.h>
#include <plat/common/platform.h>
#include <platform_def.h>
#include <stm32mp_common.h>
#include <stm32mp1_dbgmcu.h>
static struct stm32mp_auth_ops stm32mp1_auth_ops;
static void print_reset_reason(void)
{
uint32_t rstsr = mmio_read_32(stm32mp_rcc_base() + RCC_MP_RSTSCLRR);
if (rstsr == 0U) {
WARN("Reset reason unknown\n");
return;
}
INFO("Reset reason (0x%x):\n", rstsr);
if ((rstsr & RCC_MP_RSTSCLRR_PADRSTF) == 0U) {
if ((rstsr & RCC_MP_RSTSCLRR_STDBYRSTF) != 0U) {
INFO("System exits from STANDBY\n");
return;
}
if ((rstsr & RCC_MP_RSTSCLRR_CSTDBYRSTF) != 0U) {
INFO("MPU exits from CSTANDBY\n");
return;
}
}
if ((rstsr & RCC_MP_RSTSCLRR_PORRSTF) != 0U) {
INFO(" Power-on Reset (rst_por)\n");
return;
}
if ((rstsr & RCC_MP_RSTSCLRR_BORRSTF) != 0U) {
INFO(" Brownout Reset (rst_bor)\n");
return;
}
if ((rstsr & RCC_MP_RSTSCLRR_MCSYSRSTF) != 0U) {
if ((rstsr & RCC_MP_RSTSCLRR_PADRSTF) != 0U) {
INFO(" System reset generated by MCU (MCSYSRST)\n");
} else {
INFO(" Local reset generated by MCU (MCSYSRST)\n");
}
return;
}
if ((rstsr & RCC_MP_RSTSCLRR_MPSYSRSTF) != 0U) {
INFO(" System reset generated by MPU (MPSYSRST)\n");
return;
}
if ((rstsr & RCC_MP_RSTSCLRR_HCSSRSTF) != 0U) {
INFO(" Reset due to a clock failure on HSE\n");
return;
}
if ((rstsr & RCC_MP_RSTSCLRR_IWDG1RSTF) != 0U) {
INFO(" IWDG1 Reset (rst_iwdg1)\n");
return;
}
if ((rstsr & RCC_MP_RSTSCLRR_IWDG2RSTF) != 0U) {
INFO(" IWDG2 Reset (rst_iwdg2)\n");
return;
}
if ((rstsr & RCC_MP_RSTSCLRR_MPUP0RSTF) != 0U) {
INFO(" MPU Processor 0 Reset\n");
return;
}
if ((rstsr & RCC_MP_RSTSCLRR_MPUP1RSTF) != 0U) {
INFO(" MPU Processor 1 Reset\n");
return;
}
if ((rstsr & RCC_MP_RSTSCLRR_PADRSTF) != 0U) {
INFO(" Pad Reset from NRST\n");
return;
}
if ((rstsr & RCC_MP_RSTSCLRR_VCORERSTF) != 0U) {
INFO(" Reset due to a failure of VDD_CORE\n");
return;
}
ERROR(" Unidentified reset reason\n");
}
void bl2_el3_early_platform_setup(u_register_t arg0,
u_register_t arg1 __unused,
u_register_t arg2 __unused,
u_register_t arg3 __unused)
{
stm32mp_save_boot_ctx_address(arg0);
}
void bl2_platform_setup(void)
{
int ret;
ret = stm32mp1_ddr_probe();
if (ret < 0) {
ERROR("Invalid DDR init: error %d\n", ret);
panic();
}
/* Map DDR for binary load, now with cacheable attribute */
ret = mmap_add_dynamic_region(STM32MP_DDR_BASE, STM32MP_DDR_BASE,
STM32MP_DDR_MAX_SIZE, MT_MEMORY | MT_RW | MT_SECURE);
if (ret < 0) {
ERROR("DDR mapping: error %d\n", ret);
panic();
}
#if STM32MP_USE_STM32IMAGE
#ifdef AARCH32_SP_OPTEE
INFO("BL2 runs OP-TEE setup\n");
#else
INFO("BL2 runs SP_MIN setup\n");
#endif
#endif /* STM32MP_USE_STM32IMAGE */
}
void bl2_el3_plat_arch_setup(void)
{
const char *board_model;
boot_api_context_t *boot_context =
(boot_api_context_t *)stm32mp_get_boot_ctx_address();
uintptr_t pwr_base;
uintptr_t rcc_base;
if (bsec_probe() != 0U) {
panic();
}
mmap_add_region(BL_CODE_BASE, BL_CODE_BASE,
BL_CODE_END - BL_CODE_BASE,
MT_CODE | MT_SECURE);
#if STM32MP_USE_STM32IMAGE
#ifdef AARCH32_SP_OPTEE
mmap_add_region(STM32MP_OPTEE_BASE, STM32MP_OPTEE_BASE,
STM32MP_OPTEE_SIZE,
MT_MEMORY | MT_RW | MT_SECURE);
#else
/* Prevent corruption of preloaded BL32 */
mmap_add_region(BL32_BASE, BL32_BASE,
BL32_LIMIT - BL32_BASE,
MT_RO_DATA | MT_SECURE);
#endif
#endif /* STM32MP_USE_STM32IMAGE */
/* Prevent corruption of preloaded Device Tree */
mmap_add_region(DTB_BASE, DTB_BASE,
DTB_LIMIT - DTB_BASE,
MT_RO_DATA | MT_SECURE);
configure_mmu();
if (dt_open_and_check(STM32MP_DTB_BASE) < 0) {
panic();
}
pwr_base = stm32mp_pwr_base();
rcc_base = stm32mp_rcc_base();
/*
* Disable the backup domain write protection.
* The protection is enable at each reset by hardware
* and must be disabled by software.
*/
mmio_setbits_32(pwr_base + PWR_CR1, PWR_CR1_DBP);
while ((mmio_read_32(pwr_base + PWR_CR1) & PWR_CR1_DBP) == 0U) {
;
}
/* Reset backup domain on cold boot cases */
if ((mmio_read_32(rcc_base + RCC_BDCR) & RCC_BDCR_RTCSRC_MASK) == 0U) {
mmio_setbits_32(rcc_base + RCC_BDCR, RCC_BDCR_VSWRST);
while ((mmio_read_32(rcc_base + RCC_BDCR) & RCC_BDCR_VSWRST) ==
0U) {
;
}
mmio_clrbits_32(rcc_base + RCC_BDCR, RCC_BDCR_VSWRST);
}
/* Disable MCKPROT */
mmio_clrbits_32(rcc_base + RCC_TZCR, RCC_TZCR_MCKPROT);
/*
* Set minimum reset pulse duration to 31ms for discrete power
* supplied boards.
*/
if (dt_pmic_status() <= 0) {
mmio_clrsetbits_32(rcc_base + RCC_RDLSICR,
RCC_RDLSICR_MRD_MASK,
31U << RCC_RDLSICR_MRD_SHIFT);
}
generic_delay_timer_init();
#if STM32MP_UART_PROGRAMMER
/* Disable programmer UART before changing clock tree */
if (boot_context->boot_interface_selected ==
BOOT_API_CTX_BOOT_INTERFACE_SEL_SERIAL_UART) {
uintptr_t uart_prog_addr =
get_uart_address(boot_context->boot_interface_instance);
stm32_uart_stop(uart_prog_addr);
}
#endif
if (stm32mp1_clk_probe() < 0) {
panic();
}
if (stm32mp1_clk_init() < 0) {
panic();
}
stm32_save_boot_interface(boot_context->boot_interface_selected,
boot_context->boot_interface_instance);
#if STM32MP_USB_PROGRAMMER
/* Deconfigure all UART RX pins configured by ROM code */
stm32mp1_deconfigure_uart_pins();
#endif
if (stm32mp_uart_console_setup() != 0) {
goto skip_console_init;
}
stm32mp_print_cpuinfo();
board_model = dt_get_board_model();
if (board_model != NULL) {
NOTICE("Model: %s\n", board_model);
}
stm32mp_print_boardinfo();
if (boot_context->auth_status != BOOT_API_CTX_AUTH_NO) {
NOTICE("Bootrom authentication %s\n",
(boot_context->auth_status == BOOT_API_CTX_AUTH_FAILED) ?
"failed" : "succeeded");
}
skip_console_init:
if (fixed_regulator_register() != 0) {
panic();
}
if (dt_pmic_status() > 0) {
initialize_pmic();
print_pmic_info_and_debug();
}
stm32mp1_syscfg_init();
if (stm32_iwdg_init() < 0) {
panic();
}
stm32_iwdg_refresh();
stm32mp1_auth_ops.check_key = boot_context->bootrom_ecdsa_check_key;
stm32mp1_auth_ops.verify_signature =
boot_context->bootrom_ecdsa_verify_signature;
stm32mp_init_auth(&stm32mp1_auth_ops);
stm32mp1_arch_security_setup();
print_reset_reason();
stm32mp1_syscfg_enable_io_compensation_finish();
#if !STM32MP_USE_STM32IMAGE
fconf_populate("TB_FW", STM32MP_DTB_BASE);
#endif /* !STM32MP_USE_STM32IMAGE */
stm32mp_io_setup();
}
/*******************************************************************************
* This function can be used by the platforms to update/use image
* information for given `image_id`.
******************************************************************************/
int bl2_plat_handle_post_image_load(unsigned int image_id)
{
int err = 0;
bl_mem_params_node_t *bl_mem_params = get_bl_mem_params_node(image_id);
bl_mem_params_node_t *bl32_mem_params;
bl_mem_params_node_t *pager_mem_params __unused;
bl_mem_params_node_t *paged_mem_params __unused;
#if !STM32MP_USE_STM32IMAGE
const struct dyn_cfg_dtb_info_t *config_info;
bl_mem_params_node_t *tos_fw_mem_params;
unsigned int i;
unsigned int idx;
unsigned long long ddr_top __unused;
const unsigned int image_ids[] = {
BL32_IMAGE_ID,
BL33_IMAGE_ID,
HW_CONFIG_ID,
TOS_FW_CONFIG_ID,
};
#endif /* !STM32MP_USE_STM32IMAGE */
assert(bl_mem_params != NULL);
switch (image_id) {
#if !STM32MP_USE_STM32IMAGE
case FW_CONFIG_ID:
/* Set global DTB info for fixed fw_config information */
set_config_info(STM32MP_FW_CONFIG_BASE, STM32MP_FW_CONFIG_MAX_SIZE, FW_CONFIG_ID);
fconf_populate("FW_CONFIG", STM32MP_FW_CONFIG_BASE);
idx = dyn_cfg_dtb_info_get_index(TOS_FW_CONFIG_ID);
/* Iterate through all the fw config IDs */
for (i = 0U; i < ARRAY_SIZE(image_ids); i++) {
if ((image_ids[i] == TOS_FW_CONFIG_ID) && (idx == FCONF_INVALID_IDX)) {
continue;
}
bl_mem_params = get_bl_mem_params_node(image_ids[i]);
assert(bl_mem_params != NULL);
config_info = FCONF_GET_PROPERTY(dyn_cfg, dtb, image_ids[i]);
if (config_info == NULL) {
continue;
}
bl_mem_params->image_info.image_base = config_info->config_addr;
bl_mem_params->image_info.image_max_size = config_info->config_max_size;
bl_mem_params->image_info.h.attr &= ~IMAGE_ATTRIB_SKIP_LOADING;
switch (image_ids[i]) {
case BL32_IMAGE_ID:
bl_mem_params->ep_info.pc = config_info->config_addr;
/* In case of OPTEE, initialize address space with tos_fw addr */
pager_mem_params = get_bl_mem_params_node(BL32_EXTRA1_IMAGE_ID);
pager_mem_params->image_info.image_base = config_info->config_addr;
pager_mem_params->image_info.image_max_size =
config_info->config_max_size;
/* Init base and size for pager if exist */
paged_mem_params = get_bl_mem_params_node(BL32_EXTRA2_IMAGE_ID);
paged_mem_params->image_info.image_base = STM32MP_DDR_BASE +
(dt_get_ddr_size() - STM32MP_DDR_S_SIZE -
STM32MP_DDR_SHMEM_SIZE);
paged_mem_params->image_info.image_max_size = STM32MP_DDR_S_SIZE;
break;
case BL33_IMAGE_ID:
bl_mem_params->ep_info.pc = config_info->config_addr;
break;
case HW_CONFIG_ID:
case TOS_FW_CONFIG_ID:
break;
default:
return -EINVAL;
}
}
break;
#endif /* !STM32MP_USE_STM32IMAGE */
case BL32_IMAGE_ID:
if (optee_header_is_valid(bl_mem_params->image_info.image_base)) {
/* BL32 is OP-TEE header */
bl_mem_params->ep_info.pc = bl_mem_params->image_info.image_base;
pager_mem_params = get_bl_mem_params_node(BL32_EXTRA1_IMAGE_ID);
paged_mem_params = get_bl_mem_params_node(BL32_EXTRA2_IMAGE_ID);
assert((pager_mem_params != NULL) && (paged_mem_params != NULL));
#if STM32MP_USE_STM32IMAGE && defined(AARCH32_SP_OPTEE)
/* Set OP-TEE extra image load areas at run-time */
pager_mem_params->image_info.image_base = STM32MP_OPTEE_BASE;
pager_mem_params->image_info.image_max_size = STM32MP_OPTEE_SIZE;
paged_mem_params->image_info.image_base = STM32MP_DDR_BASE +
dt_get_ddr_size() -
STM32MP_DDR_S_SIZE -
STM32MP_DDR_SHMEM_SIZE;
paged_mem_params->image_info.image_max_size = STM32MP_DDR_S_SIZE;
#endif /* STM32MP_USE_STM32IMAGE && defined(AARCH32_SP_OPTEE) */
err = parse_optee_header(&bl_mem_params->ep_info,
&pager_mem_params->image_info,
&paged_mem_params->image_info);
if (err) {
ERROR("OPTEE header parse error.\n");
panic();
}
/* Set optee boot info from parsed header data */
bl_mem_params->ep_info.args.arg0 = paged_mem_params->image_info.image_base;
bl_mem_params->ep_info.args.arg1 = 0; /* Unused */
bl_mem_params->ep_info.args.arg2 = 0; /* No DT supported */
} else {
#if !STM32MP_USE_STM32IMAGE
bl_mem_params->ep_info.pc = bl_mem_params->image_info.image_base;
tos_fw_mem_params = get_bl_mem_params_node(TOS_FW_CONFIG_ID);
bl_mem_params->image_info.image_max_size +=
tos_fw_mem_params->image_info.image_max_size;
#endif /* !STM32MP_USE_STM32IMAGE */
bl_mem_params->ep_info.args.arg0 = 0;
}
break;
case BL33_IMAGE_ID:
bl32_mem_params = get_bl_mem_params_node(BL32_IMAGE_ID);
assert(bl32_mem_params != NULL);
bl32_mem_params->ep_info.lr_svc = bl_mem_params->ep_info.pc;
#if !STM32MP_USE_STM32IMAGE && PSA_FWU_SUPPORT
stm32mp1_fwu_set_boot_idx();
#endif /* !STM32MP_USE_STM32IMAGE && PSA_FWU_SUPPORT */
break;
default:
/* Do nothing in default case */
break;
}
#if STM32MP_SDMMC || STM32MP_EMMC
/*
* Invalidate remaining data read from MMC but not flushed by load_image_flush().
* We take the worst case which is 2 MMC blocks.
*/
if ((image_id != FW_CONFIG_ID) &&
((bl_mem_params->image_info.h.attr & IMAGE_ATTRIB_SKIP_LOADING) == 0U)) {
inv_dcache_range(bl_mem_params->image_info.image_base +
bl_mem_params->image_info.image_size,
2U * MMC_BLOCK_SIZE);
}
#endif /* STM32MP_SDMMC || STM32MP_EMMC */
return err;
}
void bl2_el3_plat_prepare_exit(void)
{
uint16_t boot_itf = stm32mp_get_boot_itf_selected();
switch (boot_itf) {
#if STM32MP_UART_PROGRAMMER || STM32MP_USB_PROGRAMMER
case BOOT_API_CTX_BOOT_INTERFACE_SEL_SERIAL_UART:
case BOOT_API_CTX_BOOT_INTERFACE_SEL_SERIAL_USB:
/* Invalidate the downloaded buffer used with io_memmap */
inv_dcache_range(DWL_BUFFER_BASE, DWL_BUFFER_SIZE);
break;
#endif /* STM32MP_UART_PROGRAMMER || STM32MP_USB_PROGRAMMER */
default:
/* Do nothing in default case */
break;
}
stm32mp1_security_setup();
}