blob: b08a0d4c25cf5e7c98f41867f8369c77fefbbcf0 [file] [log] [blame]
/*
* Copyright (c) 2017-2022, Arm Limited. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*
*/
#include "arch.h"
#include "fih.h"
#include "ffm/tfm_boot_data.h"
#include "region.h"
#include "spm_func.h"
#include "tfm_hal_defs.h"
#include "tfm_hal_platform.h"
#include "tfm_hal_isolation.h"
#include "tfm_irq_list.h"
#include "tfm_spm_hal.h"
#include "tfm_spm_log.h"
#include "tfm_version.h"
#include "tfm_plat_otp.h"
#include "tfm_plat_provisioning.h"
/*
* Avoids the semihosting issue
* FixMe: describe 'semihosting issue'
*/
#if defined(__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050)
__asm(" .global __ARM_use_no_argv\n");
#endif
#ifndef TFM_LVL
#error TFM_LVL is not defined!
#elif (TFM_LVL != 1)
#error Only TFM_LVL 1 is supported for library model!
#endif
REGION_DECLARE(Image$$, ARM_LIB_STACK, $$ZI$$Base);
REGION_DECLARE(Image$$, ARM_LIB_STACK, $$ZI$$Limit)[];
REGION_DECLARE(Image$$, ER_INITIAL_PSP, $$ZI$$Limit)[];
static void configure_ns_code(void)
{
/* SCB_NS.VTOR points to the Non-secure vector table base address */
SCB_NS->VTOR = tfm_spm_hal_get_ns_VTOR();
/* Setups Main stack pointer of the non-secure code */
uint32_t ns_msp = tfm_spm_hal_get_ns_MSP();
__TZ_set_MSP_NS(ns_msp);
/* Get the address of non-secure code entry point to jump there */
uint32_t entry_ptr = tfm_spm_hal_get_ns_entry_point();
/* Clears LSB of the function address to indicate the function-call
* will perform the switch from secure to non-secure
*/
ns_entry = (nsfptr_t)cmse_nsfptr_create(entry_ptr);
}
static fih_int tfm_core_init(void)
{
size_t i;
enum tfm_hal_status_t hal_status = TFM_HAL_ERROR_GENERIC;
enum tfm_plat_err_t plat_err = TFM_PLAT_ERR_SYSTEM_ERR;
enum irq_target_state_t irq_target_state = TFM_IRQ_TARGET_STATE_SECURE;
#ifdef TFM_FIH_PROFILE_ON
fih_int fih_rc = FIH_FAILURE;
#endif
/*
* Access to any peripheral should be performed after programming
* the necessary security components such as PPC/SAU.
*/
#ifdef TFM_FIH_PROFILE_ON
FIH_CALL(tfm_hal_set_up_static_boundaries, fih_rc);
if (fih_not_eq(fih_rc, fih_int_encode(TFM_HAL_SUCCESS))) {
FIH_RET(fih_int_encode(TFM_ERROR_GENERIC));
}
#else /* TFM_FIH_PROFILE_ON */
hal_status = tfm_hal_set_up_static_boundaries();
if (hal_status != TFM_HAL_SUCCESS) {
return TFM_ERROR_GENERIC;
}
#endif /* TFM_FIH_PROFILE_ON */
#ifdef TFM_FIH_PROFILE_ON
FIH_CALL(tfm_hal_platform_init, fih_rc);
if (fih_not_eq(fih_rc, fih_int_encode(TFM_HAL_SUCCESS))) {
FIH_RET(fih_int_encode(TFM_ERROR_GENERIC));
}
#else /* TFM_FIH_PROFILE_ON */
hal_status = tfm_hal_platform_init();
if (hal_status != TFM_HAL_SUCCESS) {
return TFM_ERROR_GENERIC;
}
#endif /* TFM_FIH_PROFILE_ON */
plat_err = tfm_plat_otp_init();
if (plat_err != TFM_PLAT_ERR_SUCCESS) {
FIH_RET(fih_int_encode(TFM_ERROR_GENERIC));
}
/* Perform provisioning. */
if (tfm_plat_provisioning_is_required()) {
plat_err = tfm_plat_provisioning_perform();
if (plat_err != TFM_PLAT_ERR_SUCCESS) {
FIH_RET(fih_int_encode(TFM_ERROR_GENERIC));
}
} else {
tfm_plat_provisioning_check_for_dummy_keys();
}
/* Configures architecture */
tfm_arch_config_extensions();
SPMLOG_INFMSG("\033[1;34m[Sec Thread] Secure image initializing!\033[0m\r\n");
SPMLOG_DBGMSGVAL("TF-M isolation level is: ", TFM_LVL);
tfm_core_validate_boot_data();
configure_ns_code();
for (i = 0; i < tfm_core_irq_signals_count; ++i) {
plat_err = tfm_spm_hal_set_secure_irq_priority(
tfm_core_irq_signals[i].irq_line);
if (plat_err != TFM_PLAT_ERR_SUCCESS) {
FIH_RET(fih_int_encode(TFM_ERROR_GENERIC));
}
irq_target_state = tfm_spm_hal_set_irq_target_state(
tfm_core_irq_signals[i].irq_line,
TFM_IRQ_TARGET_STATE_SECURE);
if (irq_target_state != TFM_IRQ_TARGET_STATE_SECURE) {
FIH_RET(fih_int_encode(TFM_ERROR_GENERIC));
}
}
FIH_RET(fih_int_encode(TFM_SUCCESS));
}
__attribute__((naked))
int main(void)
{
__ASM volatile(
#if !defined(__ICCARM__)
".syntax unified \n"
#endif
"msr msp, %0 \n"
"msr psp, %1 \n"
"mrs r0, control \n"
"movs r1, #2 \n"
"orrs r0, r0, r1 \n" /* Switch to PSP */
"msr control, r0 \n"
"bl c_main \n"
:
: "r" (REGION_NAME(Image$$, ARM_LIB_STACK, $$ZI$$Limit)),
"r" (REGION_NAME(Image$$, ER_INITIAL_PSP, $$ZI$$Limit))
: "r0", "memory"
);
}
int c_main(void)
{
enum spm_err_t spm_err = SPM_ERR_GENERIC_ERR;
fih_int fih_rc = FIH_FAILURE;
/* set Main Stack Pointer limit */
tfm_arch_init_secure_msp((uint32_t)&REGION_NAME(Image$$,
ARM_LIB_STACK,
$$ZI$$Base));
/* Seal the PSP stacks viz ARM_LIB_STACK and TFM_SECURE_STACK */
tfm_spm_seal_psp_stacks();
fih_delay_init();
FIH_CALL(tfm_core_init, fih_rc);
if (fih_not_eq(fih_rc, fih_int_encode(TFM_SUCCESS))) {
tfm_core_panic();
}
/* All isolation should have been set up at this point */
FIH_LABEL_CRITICAL_POINT();
/* Print the TF-M version */
SPMLOG_INFMSG("\033[1;34mBooting TFM v"VERSION_FULLSTR"\033[0m\r\n");
spm_err = tfm_spm_db_init();
if (spm_err != SPM_ERR_OK) {
tfm_core_panic();
}
tfm_spm_partition_set_state(TFM_SP_CORE_ID, SPM_PARTITION_STATE_RUNNING);
REGION_DECLARE(Image$$, ER_INITIAL_PSP, $$ZI$$Base)[];
uint32_t psp_stack_bottom =
(uint32_t)REGION_NAME(Image$$, ER_INITIAL_PSP, $$ZI$$Base);
tfm_arch_set_psplim(psp_stack_bottom);
FIH_CALL(tfm_spm_partition_init, fih_rc);
if (fih_not_eq(fih_rc, fih_int_encode(SPM_ERR_OK))) {
/* Certain systems might refuse to boot altogether if partitions fail
* to initialize. This is a placeholder for such an error handler
*/
}
/*
* Prioritise secure exceptions to avoid NS being able to pre-empt
* secure SVC or SecureFault. Do it before PSA API initialization.
*/
tfm_arch_set_secure_exception_priorities();
/* We close the TFM_SP_CORE_ID partition, because its only purpose is
* to be able to pass the state checks for the tests started from secure.
*/
tfm_spm_partition_set_state(TFM_SP_CORE_ID, SPM_PARTITION_STATE_CLOSED);
tfm_spm_partition_set_state(TFM_SP_NON_SECURE_ID,
SPM_PARTITION_STATE_RUNNING);
#ifdef TFM_FIH_PROFILE_ON
FIH_CALL(tfm_hal_verify_static_boundaries, fih_rc);
if (fih_not_eq(fih_rc, fih_int_encode(TFM_HAL_SUCCESS))) {
tfm_core_panic();
}
#endif
#ifdef TFM_CORE_DEBUG
/* Jumps to non-secure code */
SPMLOG_DBGMSG("\033[1;34mJumping to non-secure code...\033[0m\r\n");
#endif
jump_to_ns_code();
return 0;
}