From b0fe59df00feda1d0863222bb5ce75802c0f55ad Mon Sep 17 00:00:00 2001 From: Devaraj Ranganna Date: Thu, 6 Jun 2019 14:47:00 +0100 Subject: [PATCH 1/9] [trusted-firmware-m]: Updated to e7efdc6 --- .../interface/src/tfm_ns_lock_rtx.c | 11 +- .../COMPONENT_SPE/bl2/include/boot_record.h | 81 ++ .../platform/include/tfm_spm_hal.h | 6 +- .../secure_fw/core/CMakeLists.inc | 72 ++ .../secure_fw/core/ipc/CMakeLists.inc | 73 ++ .../core/ipc/include/tfm_message_queue.h | 4 +- .../secure_fw/core/ipc/include/tfm_spm.h | 50 +- .../core/ipc/include/tfm_spm_signal_defs.h | 18 + .../secure_fw/core/ipc/include/tfm_thread.h | 27 +- .../secure_fw/core/ipc/psa_client.c | 10 +- .../secure_fw/core/ipc/psa_service.c | 20 +- .../secure_fw/core/ipc/tfm_arch_v8m.c | 13 +- .../secure_fw/core/ipc/tfm_spm.c | 110 +- .../secure_fw/core/ipc/tfm_svcalls.c | 53 +- .../secure_fw/core/ipc/tfm_thread.c | 87 +- .../secure_fw/core/secure_utilities.h | 2 - .../secure_fw/core/tfm_boot_data.c | 33 +- .../COMPONENT_SPE/secure_fw/core/tfm_core.c | 38 +- .../secure_fw/core/tfm_func_api.c | 1036 ++++++++++++++++ .../secure_fw/core/tfm_handler.c | 47 +- .../COMPONENT_SPE/secure_fw/core/tfm_nspm.c | 22 + .../COMPONENT_SPE/secure_fw/core/tfm_nspm.h | 13 +- .../secure_fw/core/tfm_secure_api.c | 1066 +---------------- .../secure_fw/core/tfm_secure_api.h | 52 +- .../secure_fw/core/tfm_spm_services.c | 11 +- .../COMPONENT_SPE/secure_fw/core/tfm_svc.h | 1 + .../tfm_psa_api_veneers.c} | 4 +- .../secure_fw/spm/CMakeLists.inc | 61 + .../COMPONENT_SPE/secure_fw/spm/spm_api.c | 88 +- .../COMPONENT_SPE/secure_fw/spm/spm_api.h | 104 +- .../COMPONENT_SPE/secure_fw/spm/spm_db.h | 11 +- .../secure_fw/spm/spm_db_setup.h | 9 +- .../secure_fw/spm/spm_partition_defs.h | 2 +- .../TARGET_TFM/interface/include/tfm_api.h | 4 +- tools/importer/tfm_importer.json | 9 +- 35 files changed, 1915 insertions(+), 1333 deletions(-) create mode 100644 components/TARGET_PSA/TARGET_TFM/COMPONENT_SPE/bl2/include/boot_record.h create mode 100644 components/TARGET_PSA/TARGET_TFM/COMPONENT_SPE/secure_fw/core/CMakeLists.inc create mode 100644 components/TARGET_PSA/TARGET_TFM/COMPONENT_SPE/secure_fw/core/ipc/CMakeLists.inc create mode 100644 components/TARGET_PSA/TARGET_TFM/COMPONENT_SPE/secure_fw/core/ipc/include/tfm_spm_signal_defs.h create mode 100644 components/TARGET_PSA/TARGET_TFM/COMPONENT_SPE/secure_fw/core/tfm_func_api.c rename components/TARGET_PSA/TARGET_TFM/COMPONENT_SPE/secure_fw/{core/tfm_psa_api_client.c => ns_callable/tfm_psa_api_veneers.c} (97%) create mode 100644 components/TARGET_PSA/TARGET_TFM/COMPONENT_SPE/secure_fw/spm/CMakeLists.inc diff --git a/components/TARGET_PSA/TARGET_TFM/COMPONENT_NSPE/interface/src/tfm_ns_lock_rtx.c b/components/TARGET_PSA/TARGET_TFM/COMPONENT_NSPE/interface/src/tfm_ns_lock_rtx.c index 0c677623aa..14fd76a0d6 100644 --- a/components/TARGET_PSA/TARGET_TFM/COMPONENT_NSPE/interface/src/tfm_ns_lock_rtx.c +++ b/components/TARGET_PSA/TARGET_TFM/COMPONENT_NSPE/interface/src/tfm_ns_lock_rtx.c @@ -6,9 +6,9 @@ */ #include #include -#include "cmsis.h" -#include "rtx_os.h" + #include "cmsis_os2.h" + #include "tfm_api.h" #include "tfm_ns_lock.h" @@ -29,14 +29,11 @@ static struct ns_lock_state ns_lock = {.init=false, .id=NULL}; /** * \brief Mutex properties, NS lock */ - -static osRtxMutex_t ns_lock_cb = { 0 }; - static const osMutexAttr_t ns_lock_attrib = { .name = "ns_lock", .attr_bits = osMutexPrioInherit, - .cb_mem = &ns_lock_cb, - .cb_size = sizeof(ns_lock_cb) + .cb_mem = NULL, + .cb_size = 0U }; /** diff --git a/components/TARGET_PSA/TARGET_TFM/COMPONENT_SPE/bl2/include/boot_record.h b/components/TARGET_PSA/TARGET_TFM/COMPONENT_SPE/bl2/include/boot_record.h new file mode 100644 index 0000000000..217a20684c --- /dev/null +++ b/components/TARGET_PSA/TARGET_TFM/COMPONENT_SPE/bl2/include/boot_record.h @@ -0,0 +1,81 @@ +/* + * Copyright (c) 2018-2019, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#ifndef __BOOT_RECORD_H__ +#define __BOOT_RECORD_H__ + +#include +#include +#include +#include "../ext/mcuboot/bootutil/include/bootutil/image.h" +#include "../ext/mcuboot/include/flash_map/flash_map.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/*! + * \enum shared_data_err_t + * + * \brief Return values for adding data entry to shared memory area + */ +enum shared_memory_err_t { + SHARED_MEMORY_OK = 0, + SHARED_MEMORY_OVERFLOW = 1, + SHARED_MEMORY_OVERWRITE = 2, + + /* This is used to force the maximum size */ + TLV_TYPE_MAX = INT_MAX +}; + +/*! + * \enum boot_status_err_t + * + * \brief Return values for saving boot status information to shared memory are + */ +enum boot_status_err_t { + BOOT_STATUS_OK, + BOOT_STATUS_ERROR, +}; + +/*! + * \brief Add a data item to the shared data area between bootloader and + * runtime SW + * + * \param[in] major_type TLV major type, identify consumer + * \param[in] minor_type TLV minor type, identify TLV type + * \param[in] size length of added data + * \param[in] data pointer to data + * + * \return Returns error code as specified in \ref shared_memory_err_t + */ +enum shared_memory_err_t +boot_add_data_to_shared_area(uint8_t major_type, + uint16_t minor_type, + size_t size, + const uint8_t *data); + +/*! + * \brief Add an image's all boot status information to the shared data area + * between bootloader and runtime SW + * + * \param[in] sw_module Identifier of the SW component + * \param[in] hdr Pointer to the image header stored in RAM + * \param[in] fap Pointer to the flash area where image is stored + * + * \return Returns error code as specified in \ref boot_status_err_t + */ +enum boot_status_err_t +boot_save_boot_status(uint8_t sw_module, + const struct image_header *hdr, + const struct flash_area *fap); + +#ifdef __cplusplus +} +#endif + +#endif /* __BOOT_RECORD_H__ */ diff --git a/components/TARGET_PSA/TARGET_TFM/COMPONENT_SPE/platform/include/tfm_spm_hal.h b/components/TARGET_PSA/TARGET_TFM/COMPONENT_SPE/platform/include/tfm_spm_hal.h index 509f153d65..3ce0b29b19 100644 --- a/components/TARGET_PSA/TARGET_TFM/COMPONENT_SPE/platform/include/tfm_spm_hal.h +++ b/components/TARGET_PSA/TARGET_TFM/COMPONENT_SPE/platform/include/tfm_spm_hal.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, Arm Limited. All rights reserved. + * Copyright (c) 2018-2019, Arm Limited. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause * @@ -28,7 +28,7 @@ */ struct tfm_spm_partition_platform_data_t; -#if TFM_LVL != 1 +#if defined (TFM_PSA_API) || (TFM_LVL != 1) /** * \brief Holds SPM db fields that define the memory regions used by a * partition. @@ -147,7 +147,7 @@ uint32_t tfm_spm_hal_get_ns_MSP(void); uint32_t tfm_spm_hal_get_ns_entry_point(void); -#if TFM_LVL != 1 +#if (TFM_LVL != 1) && !defined(TFM_PSA_API) /** * \brief Configure the sandbox for a partition. * diff --git a/components/TARGET_PSA/TARGET_TFM/COMPONENT_SPE/secure_fw/core/CMakeLists.inc b/components/TARGET_PSA/TARGET_TFM/COMPONENT_SPE/secure_fw/core/CMakeLists.inc new file mode 100644 index 0000000000..c9bfbb73cf --- /dev/null +++ b/components/TARGET_PSA/TARGET_TFM/COMPONENT_SPE/secure_fw/core/CMakeLists.inc @@ -0,0 +1,72 @@ +#------------------------------------------------------------------------------- +# Copyright (c) 2017-2018, Arm Limited. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# +#------------------------------------------------------------------------------- + +#Definitions to compile the "core" module. +#This file assumes it will be included from a project specific cmakefile, and +#will not create a library or executable. +#Inputs: +# TFM_ROOT_DIR - directory where secure FW sourec is located. +# +#Outputs: +# Will modify include directories to make the source compile. +# ALL_SRC_C: C source files to be compiled will be added to this list. +# This shall be added to your add_executable or add_library command. +# ALL_SRC_CXX: C++ source files to be compiled will be added to this list. +# This shall be added to your add_executable or add_library command. +# ALL_SRC_ASM: assembly source files to be compiled will be added to this +# list. This shall be added to your add_executable or add_library +# command. +# Include directories will be modified by using the include_directories() +# commands as needed. + +#Get the current directory where this file is located. +set(SS_CORE_DIR ${CMAKE_CURRENT_LIST_DIR}) +if(NOT DEFINED TFM_ROOT_DIR) + message(FATAL_ERROR + "Please set TFM_ROOT_DIR before including this file.") +endif() + +set (SS_CORE_C_SRC + "${SS_CORE_DIR}/tfm_core.c" + "${SS_CORE_DIR}/tfm_handler.c" + "${SS_CORE_DIR}/tfm_secure_api.c" + "${SS_CORE_DIR}/tfm_func_api.c" + "${SS_CORE_DIR}/tfm_spm_services.c" + "${SS_CORE_DIR}/tfm_nspm.c" + "${SS_CORE_DIR}/tfm_boot_data.c" + ) + +#Append all our source files to global lists. +list(APPEND ALL_SRC_C ${SS_CORE_C_SRC}) +unset(SS_CORE_C_SRC) + +#Setting include directories +embedded_include_directories(PATH ${TFM_ROOT_DIR} ABSOLUTE) +embedded_include_directories(PATH ${TFM_ROOT_DIR}/interface/include ABSOLUTE) +embedded_include_directories(PATH ${TFM_ROOT_DIR}/secure_fw/spm ABSOLUTE) +embedded_include_directories(PATH ${TFM_ROOT_DIR}/secure_fw/core ABSOLUTE) + +set(BUILD_CMSIS_CORE Off) +set(BUILD_RETARGET Off) +set(BUILD_NATIVE_DRIVERS Off) +set(BUILD_STARTUP Off) +set(BUILD_TARGET_CFG Off) +set(BUILD_TARGET_HARDWARE_KEYS Off) +set(BUILD_TARGET_NV_COUNTERS Off) +set(BUILD_CMSIS_DRIVERS Off) +set(BUILD_TIME Off) +set(BUILD_UART_STDOUT Off) +set(BUILD_FLASH Off) +set(BUILD_BOOT_SEED Off) +set(BUILD_DEVICE_ID Off) +if(NOT DEFINED PLATFORM_CMAKE_FILE) + message (FATAL_ERROR "Platform specific CMake is not defined. Please set PLATFORM_CMAKE_FILE.") +elseif(NOT EXISTS ${PLATFORM_CMAKE_FILE}) + message (FATAL_ERROR "Platform specific CMake \"${PLATFORM_CMAKE_FILE}\" file does not exist. Please fix value of PLATFORM_CMAKE_FILE.") +else() + include(${PLATFORM_CMAKE_FILE}) +endif() diff --git a/components/TARGET_PSA/TARGET_TFM/COMPONENT_SPE/secure_fw/core/ipc/CMakeLists.inc b/components/TARGET_PSA/TARGET_TFM/COMPONENT_SPE/secure_fw/core/ipc/CMakeLists.inc new file mode 100644 index 0000000000..1f9a81dca3 --- /dev/null +++ b/components/TARGET_PSA/TARGET_TFM/COMPONENT_SPE/secure_fw/core/ipc/CMakeLists.inc @@ -0,0 +1,73 @@ +#------------------------------------------------------------------------------- +# Copyright (c) 2018-2019, Arm Limited. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# +#------------------------------------------------------------------------------- + +#Definitions to compile the "ipc" module. +#This file assumes it will be included from a project specific cmakefile, and +#will not create a library or executable. +#Inputs: +# TFM_ROOT_DIR - directory where secure FW sourec is located. +# +#Outputs: +# Will modify include directories to make the source compile. +# ALL_SRC_C: C source files to be compiled will be added to this list. +# This shall be added to your add_executable or add_library command. +# ALL_SRC_CXX: C++ source files to be compiled will be added to this list. +# This shall be added to your add_executable or add_library command. +# ALL_SRC_ASM: assembly source files to be compiled will be added to this +# list. This shall be added to your add_executable or add_library +# command. +# Include directories will be modified by using the include_directories() +# commands as needed. + +#Get the current directory where this file is located. +set(SS_IPC_DIR ${CMAKE_CURRENT_LIST_DIR}) +if(NOT DEFINED TFM_ROOT_DIR) + message(FATAL_ERROR + "Please set TFM_ROOT_DIR before including this file.") +endif() + +if (NOT DEFINED TFM_PSA_API) + message(FATAL_ERROR "Incomplete build configuration: TFM_PSA_API is undefined. ") +elseif (TFM_PSA_API) + set (SS_IPC_C_SRC "${SS_IPC_DIR}/tfm_svcalls.c" + "${SS_IPC_DIR}/psa_service.c" + "${SS_IPC_DIR}/psa_client.c" + "${SS_IPC_DIR}/tfm_arch_v8m.c" + "${SS_IPC_DIR}/tfm_thread.c" + "${SS_IPC_DIR}/tfm_wait.c" + "${SS_IPC_DIR}/tfm_utils.c" + "${SS_IPC_DIR}/tfm_message_queue.c" + "${SS_IPC_DIR}/tfm_pools.c" + "${SS_IPC_DIR}/tfm_spm.c" + "${SS_IPC_DIR}/../tfm_core.c" + "${SS_IPC_DIR}/../tfm_secure_api.c" + "${SS_IPC_DIR}/../tfm_spm_services.c" + "${SS_IPC_DIR}/../tfm_handler.c" + "${SS_IPC_DIR}/../tfm_nspm.c" + "${SS_IPC_DIR}/../tfm_boot_data.c" + ) +endif() + +#Append all our source files to global lists. +list(APPEND ALL_SRC_C ${SS_IPC_C_SRC}) +unset(SS_IPC_C_SRC) + +#Setting include directories +embedded_include_directories(PATH ${TFM_ROOT_DIR} ABSOLUTE) +embedded_include_directories(PATH ${TFM_ROOT_DIR}/interface/include ABSOLUTE) +embedded_include_directories(PATH ${TFM_ROOT_DIR}/secure_fw/spm ABSOLUTE) +embedded_include_directories(PATH ${TFM_ROOT_DIR}/secure_fw/core ABSOLUTE) +embedded_include_directories(PATH ${TFM_ROOT_DIR}/secure_fw/core/ipc ABSOLUTE) +embedded_include_directories(PATH ${TFM_ROOT_DIR}/secure_fw/core/ipc/include ABSOLUTE) + +if(NOT DEFINED PLATFORM_CMAKE_FILE) + message (FATAL_ERROR "Platform specific CMake is not defined. Please set PLATFORM_CMAKE_FILE.") +elseif(NOT EXISTS ${PLATFORM_CMAKE_FILE}) + message (FATAL_ERROR "Platform specific CMake \"${PLATFORM_CMAKE_FILE}\" file does not exist. Please fix value of PLATFORM_CMAKE_FILE.") +else() + include(${PLATFORM_CMAKE_FILE}) +endif() diff --git a/components/TARGET_PSA/TARGET_TFM/COMPONENT_SPE/secure_fw/core/ipc/include/tfm_message_queue.h b/components/TARGET_PSA/TARGET_TFM/COMPONENT_SPE/secure_fw/core/ipc/include/tfm_message_queue.h index 44f5af44bf..3edf3fbb8b 100644 --- a/components/TARGET_PSA/TARGET_TFM/COMPONENT_SPE/secure_fw/core/ipc/include/tfm_message_queue.h +++ b/components/TARGET_PSA/TARGET_TFM/COMPONENT_SPE/secure_fw/core/ipc/include/tfm_message_queue.h @@ -7,9 +7,7 @@ #ifndef __TFM_MESSAGE_QUEUE_H__ #define __TFM_MESSAGE_QUEUE_H__ -#ifndef TFM_MSG_QUEUE_MAX_MSG_NUM -#define TFM_MSG_QUEUE_MAX_MSG_NUM 128 -#endif +#define TFM_MSG_QUEUE_MAX_MSG_NUM 16 #define TFM_MSG_MAGIC 0x15154343 /* Message struct to collect parameter from client */ struct tfm_msg_body_t { diff --git a/components/TARGET_PSA/TARGET_TFM/COMPONENT_SPE/secure_fw/core/ipc/include/tfm_spm.h b/components/TARGET_PSA/TARGET_TFM/COMPONENT_SPE/secure_fw/core/ipc/include/tfm_spm.h index e4df835df8..fcd3bc27b8 100644 --- a/components/TARGET_PSA/TARGET_TFM/COMPONENT_SPE/secure_fw/core/ipc/include/tfm_spm.h +++ b/components/TARGET_PSA/TARGET_TFM/COMPONENT_SPE/secure_fw/core/ipc/include/tfm_spm.h @@ -11,15 +11,11 @@ #include "tfm_list.h" #include "tfm_secure_api.h" -#ifndef TFM_SPM_MAX_ROT_SERV_NUM #define TFM_SPM_MAX_ROT_SERV_NUM 28 -#endif #define TFM_VERSION_POLICY_RELAXED 0 #define TFM_VERSION_POLICY_STRICT 1 -#ifndef TFM_CONN_HANDLE_MAX_NUM #define TFM_CONN_HANDLE_MAX_NUM 32 -#endif /* RoT connection handle list */ struct tfm_conn_handle_t { @@ -75,6 +71,16 @@ struct tfm_spm_ipc_partition_t { */ uint32_t tfm_spm_partition_get_running_partition_id_ext(void); +/** + * \brief Get the current partition mode. + * + * \param[in] partition_idx Index of current partition + * + * \retval TFM_PARTITION_PRIVILEGED_MODE Privileged mode + * \retval TFM_PARTITION_UNPRIVILEGED_MODE Unprivileged mode + */ +uint32_t tfm_spm_partition_get_privileged_mode(uint32_t partition_idx); + /******************** Service handle management functions ********************/ /** @@ -279,22 +285,38 @@ int32_t tfm_spm_check_client_version(struct tfm_spm_service_t *service, uint32_t minor_version); /** - * \brief Check the memory reference is valid. + * \brief Check the memory reference is valid. * - * \param[in] buffer Pointer of memory reference - * \param[in] len Length of memory reference in bytes - * \param[in] ns_caller From non-secure caller - * \param[in] access Type of access specified by the - * \ref tfm_memory_access_e + * \param[in] buffer Pointer of memory reference + * \param[in] len Length of memory reference in bytes + * \param[in] ns_caller From non-secure caller + * \param[in] access Type of access specified by the + * \ref tfm_memory_access_e + * \param[in] privileged Privileged mode or unprivileged mode: + * \ref TFM_PARTITION_UNPRIVILEGED_MODE + * \ref TFM_PARTITION_PRIVILEGED_MODE * - * \retval IPC_SUCCESS Success - * \retval IPC_ERROR_BAD_PARAMETERS Bad parameters input - * \retval IPC_ERROR_MEMORY_CHECK Check failed + * \retval IPC_SUCCESS Success + * \retval IPC_ERROR_BAD_PARAMETERS Bad parameters input + * \retval IPC_ERROR_MEMORY_CHECK Check failed */ int32_t tfm_memory_check(void *buffer, size_t len, int32_t ns_caller, - enum tfm_memory_access_e access); + enum tfm_memory_access_e access, + uint32_t privileged); /* This function should be called before schedule function */ void tfm_spm_init(void); +/* + * PendSV specified function. + * + * Parameters : + * ctxb - State context storage pointer + * + * Notes: + * This is a staging API. Scheduler should be called in SPM finally and + * this function will be obsoleted later. + */ +void tfm_pendsv_do_schedule(struct tfm_state_context_ext *ctxb); + #endif diff --git a/components/TARGET_PSA/TARGET_TFM/COMPONENT_SPE/secure_fw/core/ipc/include/tfm_spm_signal_defs.h b/components/TARGET_PSA/TARGET_TFM/COMPONENT_SPE/secure_fw/core/ipc/include/tfm_spm_signal_defs.h new file mode 100644 index 0000000000..67bb1957db --- /dev/null +++ b/components/TARGET_PSA/TARGET_TFM/COMPONENT_SPE/secure_fw/core/ipc/include/tfm_spm_signal_defs.h @@ -0,0 +1,18 @@ +/* + * Copyright (c) 2018-2019, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ +#ifndef __TFM_SPM_SIGNAL_DEFS_H__ +#define __TFM_SPM_SIGNAL_DEFS_H__ + +#include "test/test_services/tfm_ipc_service/tfm_ipc_service_partition.h" +#include "test/test_services/tfm_core_test/tfm_ss_core_test_signal.h" +#include "test/test_services/tfm_core_test_2/tfm_ss_core_test_2_signal.h" +#include "secure_fw/services/crypto/tfm_crypto_signal.h" +#include "test/test_services/tfm_secure_client_service/tfm_sec_client_ser_sig.h" +#include "secure_fw/services/secure_storage/tfm_sst_signal.h" +#include "secure_fw/services/initial_attestation/tfm_attest_signal.h" + +#endif /* __TFM_SPM_SIGNAL_DEFS_H__ */ diff --git a/components/TARGET_PSA/TARGET_TFM/COMPONENT_SPE/secure_fw/core/ipc/include/tfm_thread.h b/components/TARGET_PSA/TARGET_TFM/COMPONENT_SPE/secure_fw/core/ipc/include/tfm_thread.h index 8a6d86364d..68aa5a20b0 100644 --- a/components/TARGET_PSA/TARGET_TFM/COMPONENT_SPE/secure_fw/core/ipc/include/tfm_thread.h +++ b/components/TARGET_PSA/TARGET_TFM/COMPONENT_SPE/secure_fw/core/ipc/include/tfm_thread.h @@ -177,6 +177,19 @@ struct tfm_thrd_ctx *tfm_thrd_curr_thread(void); */ struct tfm_thrd_ctx *tfm_thrd_next_thread(void); +/* + * Start scheduler for existing threads + * + * Parameters: + * pth - pointer of the caller context collecting thread + * + * Notes : + * This function should be called only ONCE to start the scheduler. + * Caller needs to provide a thread object to collect current context. + * The usage of the collected context is caller defined. + */ +void tfm_thrd_start_scheduler(struct tfm_thrd_ctx *pth); + /* * Activate a scheduling action after exception. * @@ -201,23 +214,19 @@ void tfm_thrd_context_switch(struct tfm_state_context_ext *ctxb, struct tfm_thrd_ctx *next); /* - * Exit current running thread. + * Svcall to exit current running thread. * * Notes : * Remove current thread out of schedulable list. */ -void tfm_thrd_do_exit(void); +void tfm_svcall_thrd_exit(void); /* - * PendSV specified function. - * - * Parameters : - * ctxb - State context storage pointer + * Exit current running thread for client. * * Notes: - * This is a staging API. Scheduler should be called in SPM finally and - * this function will be obsoleted later. + * Must be called in thread mode. */ -void tfm_pendsv_do_schedule(struct tfm_state_context_ext *ctxb); +void tfm_thrd_exit(void); #endif diff --git a/components/TARGET_PSA/TARGET_TFM/COMPONENT_SPE/secure_fw/core/ipc/psa_client.c b/components/TARGET_PSA/TARGET_TFM/COMPONENT_SPE/secure_fw/core/ipc/psa_client.c index 8d71af7a8f..6abc9665a1 100644 --- a/components/TARGET_PSA/TARGET_TFM/COMPONENT_SPE/secure_fw/core/ipc/psa_client.c +++ b/components/TARGET_PSA/TARGET_TFM/COMPONENT_SPE/secure_fw/core/ipc/psa_client.c @@ -10,7 +10,7 @@ #include "tfm_svc.h" #include "psa_client.h" -__attribute__((naked)) +__attribute__((naked, section("SFN"))) uint32_t psa_framework_version(void) { __ASM volatile("SVC %0 \n" @@ -18,7 +18,7 @@ uint32_t psa_framework_version(void) : : "I" (TFM_SVC_PSA_FRAMEWORK_VERSION)); } -__attribute__((naked)) +__attribute__((naked, section("SFN"))) uint32_t psa_version(uint32_t sid) { __ASM volatile("SVC %0 \n" @@ -26,7 +26,7 @@ uint32_t psa_version(uint32_t sid) : : "I" (TFM_SVC_PSA_VERSION)); } -__attribute__((naked)) +__attribute__((naked, section("SFN"))) psa_handle_t psa_connect(uint32_t sid, uint32_t minor_version) { __ASM volatile("SVC %0 \n" @@ -34,7 +34,7 @@ psa_handle_t psa_connect(uint32_t sid, uint32_t minor_version) : : "I" (TFM_SVC_PSA_CONNECT)); } -__attribute__((naked)) +__attribute__((naked, section("SFN"))) psa_status_t psa_call(psa_handle_t handle, const psa_invec *in_vec, size_t in_len, @@ -46,7 +46,7 @@ psa_status_t psa_call(psa_handle_t handle, : : "I" (TFM_SVC_PSA_CALL)); } -__attribute__((naked)) +__attribute__((naked, section("SFN"))) void psa_close(psa_handle_t handle) { __ASM volatile("SVC %0 \n" diff --git a/components/TARGET_PSA/TARGET_TFM/COMPONENT_SPE/secure_fw/core/ipc/psa_service.c b/components/TARGET_PSA/TARGET_TFM/COMPONENT_SPE/secure_fw/core/ipc/psa_service.c index cd2e1cd09f..0c86954d21 100644 --- a/components/TARGET_PSA/TARGET_TFM/COMPONENT_SPE/secure_fw/core/ipc/psa_service.c +++ b/components/TARGET_PSA/TARGET_TFM/COMPONENT_SPE/secure_fw/core/ipc/psa_service.c @@ -11,7 +11,7 @@ #include "psa_client.h" #include "psa_service.h" -__attribute__((naked)) +__attribute__((naked, section("SFN"))) psa_signal_t psa_wait(psa_signal_t signal_mask, uint32_t timeout) { @@ -20,7 +20,7 @@ psa_signal_t psa_wait(psa_signal_t signal_mask, uint32_t timeout) : : "I" (TFM_SVC_PSA_WAIT)); } -__attribute__((naked)) +__attribute__((naked, section("SFN"))) psa_status_t psa_get(psa_signal_t signal, psa_msg_t *msg) { __ASM volatile("SVC %0 \n" @@ -28,7 +28,7 @@ psa_status_t psa_get(psa_signal_t signal, psa_msg_t *msg) : : "I" (TFM_SVC_PSA_GET)); } -__attribute__((naked)) +__attribute__((naked, section("SFN"))) void psa_set_rhandle(psa_handle_t msg_handle, void *rhandle) { __ASM volatile("SVC %0 \n" @@ -36,7 +36,7 @@ void psa_set_rhandle(psa_handle_t msg_handle, void *rhandle) : : "I" (TFM_SVC_PSA_SET_RHANDLE)); } -__attribute__((naked)) +__attribute__((naked, section("SFN"))) size_t psa_read(psa_handle_t msg_handle, uint32_t invec_idx, void *buffer, size_t num_bytes) @@ -46,7 +46,7 @@ size_t psa_read(psa_handle_t msg_handle, uint32_t invec_idx, : : "I" (TFM_SVC_PSA_READ)); } -__attribute__((naked)) +__attribute__((naked, section("SFN"))) size_t psa_skip(psa_handle_t msg_handle, uint32_t invec_idx, size_t num_bytes) { __ASM volatile("SVC %0 \n" @@ -54,7 +54,7 @@ size_t psa_skip(psa_handle_t msg_handle, uint32_t invec_idx, size_t num_bytes) : : "I" (TFM_SVC_PSA_SKIP)); } -__attribute__((naked)) +__attribute__((naked, section("SFN"))) void psa_write(psa_handle_t msg_handle, uint32_t outvec_idx, const void *buffer, size_t num_bytes) { @@ -63,7 +63,7 @@ void psa_write(psa_handle_t msg_handle, uint32_t outvec_idx, : : "I" (TFM_SVC_PSA_WRITE)); } -__attribute__((naked)) +__attribute__((naked, section("SFN"))) void psa_reply(psa_handle_t msg_handle, psa_status_t retval) { __ASM volatile("SVC %0 \n" @@ -71,7 +71,7 @@ void psa_reply(psa_handle_t msg_handle, psa_status_t retval) : : "I" (TFM_SVC_PSA_REPLY)); } -__attribute__((naked)) +__attribute__((naked, section("SFN"))) void psa_notify(int32_t partition_id) { __ASM volatile("SVC %0 \n" @@ -79,7 +79,7 @@ void psa_notify(int32_t partition_id) : : "I" (TFM_SVC_PSA_NOTIFY)); } -__attribute__((naked)) +__attribute__((naked, section("SFN"))) void psa_clear(void) { __ASM volatile("SVC %0 \n" @@ -87,7 +87,7 @@ void psa_clear(void) : : "I" (TFM_SVC_PSA_CLEAR)); } -__attribute__((naked)) +__attribute__((naked, section("SFN"))) void psa_eoi(psa_signal_t irq_signal) { __ASM volatile("SVC %0 \n" diff --git a/components/TARGET_PSA/TARGET_TFM/COMPONENT_SPE/secure_fw/core/ipc/tfm_arch_v8m.c b/components/TARGET_PSA/TARGET_TFM/COMPONENT_SPE/secure_fw/core/ipc/tfm_arch_v8m.c index 137c3e75b6..ebe1c45a6d 100644 --- a/components/TARGET_PSA/TARGET_TFM/COMPONENT_SPE/secure_fw/core/ipc/tfm_arch_v8m.c +++ b/components/TARGET_PSA/TARGET_TFM/COMPONENT_SPE/secure_fw/core/ipc/tfm_arch_v8m.c @@ -17,19 +17,10 @@ /* This file contains the ARCH code for ARM V8M */ -/* - * Thread exit zone. - * This function is set as the return address of thread entry and only - * privileged thread could return here. Un-privileged thread triggers - * fault if it tries to jump here and it gets exit by fault handler. - * - * The reason of putting this function here is for fault handler checking. - * Function address could be checked in fault handler to know it is a REAL - * thread exit or just an exception. - */ +__attribute__((section("SFN"))) static void exit_zone(void) { - tfm_thrd_do_exit(); + tfm_thrd_exit(); } void tfm_initialize_context(struct tfm_state_context *ctx, diff --git a/components/TARGET_PSA/TARGET_TFM/COMPONENT_SPE/secure_fw/core/ipc/tfm_spm.c b/components/TARGET_PSA/TARGET_TFM/COMPONENT_SPE/secure_fw/core/ipc/tfm_spm.c index fe82120a04..d16b13a530 100644 --- a/components/TARGET_PSA/TARGET_TFM/COMPONENT_SPE/secure_fw/core/ipc/tfm_spm.c +++ b/components/TARGET_PSA/TARGET_TFM/COMPONENT_SPE/secure_fw/core/ipc/tfm_spm.c @@ -38,6 +38,8 @@ static struct tfm_spm_ipc_partition_t /* Extern SPM variable */ extern struct spm_partition_db_t g_spm_partition_db; +/* Extern secure lock variable */ +extern int32_t tfm_secure_lock; /* Pools */ TFM_POOL_DECLARE(conn_handle_pool, sizeof(struct tfm_conn_handle_t), TFM_CONN_HANDLE_MAX_NUM); @@ -47,7 +49,7 @@ TFM_POOL_DECLARE(msg_db_pool, sizeof(struct tfm_msg_body_t), TFM_MSG_QUEUE_MAX_MSG_NUM); static struct tfm_spm_service_db_t g_spm_service_db[] = { - #include "tfm_service_list.inc" + #include "secure_fw/services/tfm_service_list.inc" }; /********************** SPM functions for handler mode ***********************/ @@ -110,8 +112,6 @@ int32_t tfm_spm_free_conn_handle(struct tfm_spm_service_t *service, /* Remove node from handle list */ tfm_list_del_node(&node->list); - node->rhandle = NULL; - /* Back handle buffer to pool */ tfm_pool_free(node); return IPC_SUCCESS; @@ -433,21 +433,6 @@ tfm_spm_partition_get_thread_info_ext(uint32_t partition_idx) return &g_spm_partition_db.partitions[partition_idx].sp_thrd; } -static uint32_t tfm_spm_partition_get_stack_size_ext(uint32_t partition_idx) -{ - return g_spm_partition_db.partitions[partition_idx].stack_size; -} - -static uint32_t tfm_spm_partition_get_stack_limit_ext(uint32_t partition_idx) -{ - return g_spm_partition_db.partitions[partition_idx].stack_limit; -} - -static uint32_t tfm_spm_partition_get_stack_base_ext(uint32_t partition_idx) -{ - return tfm_spm_partition_get_stack_limit_ext(partition_idx) + tfm_spm_partition_get_stack_size_ext(partition_idx); -} - static tfm_thrd_func_t tfm_spm_partition_get_init_func_ext(uint32_t partition_idx) { @@ -461,9 +446,9 @@ static uint32_t tfm_spm_partition_get_priority_ext(uint32_t partition_idx) partition_priority; } -/* FixMe: This is only valid for TFM LVL 1 now */ int32_t tfm_memory_check(void *buffer, size_t len, int32_t ns_caller, - enum tfm_memory_access_e access) + enum tfm_memory_access_e access, + uint32_t privileged) { int32_t err; @@ -481,17 +466,28 @@ int32_t tfm_memory_check(void *buffer, size_t len, int32_t ns_caller, } if (access == TFM_MEMORY_ACCESS_RW) { - err = tfm_core_has_write_access_to_region(buffer, len, ns_caller); + err = tfm_core_has_write_access_to_region(buffer, len, ns_caller, + privileged); } else { - err = tfm_core_has_read_access_to_region(buffer, len, ns_caller); + err = tfm_core_has_read_access_to_region(buffer, len, ns_caller, + privileged); } - if (err == 1) { + if (err == TFM_SUCCESS) { return IPC_SUCCESS; } return IPC_ERROR_MEMORY_CHECK; } +uint32_t tfm_spm_partition_get_privileged_mode(uint32_t partition_idx) +{ + if (tfm_spm_partition_get_flags(partition_idx) & SPM_PART_FLAG_PSA_ROT) { + return TFM_PARTITION_PRIVILEGED_MODE; + } else { + return TFM_PARTITION_UNPRIVILEGED_MODE; + } +} + /********************** SPM functions for thread mode ************************/ void tfm_spm_init(void) @@ -499,7 +495,8 @@ void tfm_spm_init(void) uint32_t i, num; struct tfm_spm_ipc_partition_t *partition; struct tfm_spm_service_t *service; - struct tfm_thrd_ctx *pth; + struct tfm_thrd_ctx *pth, this_thrd; + struct spm_partition_desc_t *part; tfm_pool_init(conn_handle_pool, POOL_BUFFER_SIZE(conn_handle_pool), @@ -514,10 +511,12 @@ void tfm_spm_init(void) /* Init partition first for it will be used when init service */ for (i = 0; i < SPM_MAX_PARTITIONS; i++) { + part = &g_spm_partition_db.partitions[i]; + tfm_spm_hal_configure_default_isolation(part->platform_data); + g_spm_ipc_partition[i].index = i; if ((tfm_spm_partition_get_flags(i) & SPM_PART_FLAG_IPC) == 0) { continue; } - g_spm_ipc_partition[i].index = i; g_spm_ipc_partition[i].id = tfm_spm_partition_get_partition_id(i); tfm_event_init(&g_spm_ipc_partition[i].signal_evnt); @@ -531,8 +530,9 @@ void tfm_spm_init(void) tfm_thrd_init(pth, tfm_spm_partition_get_init_func_ext(i), NULL, - (uint8_t *)tfm_spm_partition_get_stack_base_ext(i), - (uint8_t *)tfm_spm_partition_get_stack_limit_ext(i)); + (uint8_t *)tfm_spm_partition_get_stack_top(i), + (uint8_t *)tfm_spm_partition_get_stack_bottom(i)); + pth->prior = tfm_spm_partition_get_priority_ext(i); /* Kick off */ @@ -559,6 +559,58 @@ void tfm_spm_init(void) tfm_list_add_tail(&partition->service_list, &service->list); } - /* All thread inited.... trigger scheduler */ - tfm_thrd_activate_schedule(); + /* + * All threads initialized, start the scheduler. + * + * NOTE: + * Here is the booting privileged thread mode, and will never + * return to this place after scheduler is started. The start + * function has to save current runtime context to act as a + * 'current thread' to avoid repeating NULL 'current thread' + * checking while context switching. This saved context is worthy + * of being saved somewhere if there are potential usage purpose. + * Let's save this context in a local variable 'this_thrd' at + * current since there is no usage for it. + * Also set tfm_nspm_thread_entry as pfn for this thread to + * use in detecting NS/S thread scheduling changes. + */ + this_thrd.pfn = (tfm_thrd_func_t)tfm_nspm_thread_entry; + tfm_thrd_start_scheduler(&this_thrd); +} + +void tfm_pendsv_do_schedule(struct tfm_state_context_ext *ctxb) +{ +#if TFM_LVL == 2 + struct spm_partition_desc_t *p_next_partition; + uint32_t is_privileged; +#endif + struct tfm_thrd_ctx *pth_next = tfm_thrd_next_thread(); + struct tfm_thrd_ctx *pth_curr = tfm_thrd_curr_thread(); + + if (pth_curr != pth_next) { +#if TFM_LVL == 2 + p_next_partition = TFM_GET_CONTAINER_PTR(pth_next, + struct spm_partition_desc_t, + sp_thrd); + + if (p_next_partition->static_data.partition_flags & + SPM_PART_FLAG_PSA_ROT) { + is_privileged = TFM_PARTITION_PRIVILEGED_MODE; + } else { + is_privileged = TFM_PARTITION_UNPRIVILEGED_MODE; + } + + tfm_spm_partition_change_privilege(is_privileged); +#endif + /* Increase the secure lock, if we enter secure from non-secure */ + if ((void *)pth_curr->pfn == (void *)tfm_nspm_thread_entry) { + ++tfm_secure_lock; + } + /* Decrease the secure lock, if we return from secure to non-secure */ + if ((void *)pth_next->pfn == (void *)tfm_nspm_thread_entry) { + --tfm_secure_lock; + } + + tfm_thrd_context_switch(ctxb, pth_curr, pth_next); + } } diff --git a/components/TARGET_PSA/TARGET_TFM/COMPONENT_SPE/secure_fw/core/ipc/tfm_svcalls.c b/components/TARGET_PSA/TARGET_TFM/COMPONENT_SPE/secure_fw/core/ipc/tfm_svcalls.c index 29f9130499..eefc031d04 100644 --- a/components/TARGET_PSA/TARGET_TFM/COMPONENT_SPE/secure_fw/core/ipc/tfm_svcalls.c +++ b/components/TARGET_PSA/TARGET_TFM/COMPONENT_SPE/secure_fw/core/ipc/tfm_svcalls.c @@ -21,6 +21,7 @@ #include "tfm_api.h" #include "tfm_secure_api.h" #include "tfm_memory_utils.h" +#include "spm_api.h" #define PSA_TIMEOUT_MASK PSA_BLOCK @@ -116,9 +117,18 @@ psa_status_t tfm_svcall_psa_call(uint32_t *args, int32_t ns_caller, uint32_t lr) struct tfm_spm_service_t *service; struct tfm_msg_body_t *msg; int i; + struct tfm_spm_ipc_partition_t *partition = NULL; + uint32_t privileged; TFM_ASSERT(args != NULL); handle = (psa_handle_t)args[0]; + + partition = tfm_spm_get_running_partition(); + if (!partition) { + tfm_panic(); + } + privileged = tfm_spm_partition_get_privileged_mode(partition->index); + if (!ns_caller) { inptr = (psa_invec *)args[1]; in_num = (size_t)args[2]; @@ -153,11 +163,11 @@ psa_status_t tfm_svcall_psa_call(uint32_t *args, int32_t ns_caller, uint32_t lr) * memory reference for buffer is invalid or not readable. */ if (tfm_memory_check((void *)args[1], sizeof(uint32_t), - ns_caller, TFM_MEMORY_ACCESS_RO) != IPC_SUCCESS) { + ns_caller, TFM_MEMORY_ACCESS_RO, privileged) != IPC_SUCCESS) { tfm_panic(); } if (tfm_memory_check((void *)args[2], sizeof(uint32_t), - ns_caller, TFM_MEMORY_ACCESS_RO) != IPC_SUCCESS) { + ns_caller, TFM_MEMORY_ACCESS_RO, privileged) != IPC_SUCCESS) { tfm_panic(); } @@ -185,7 +195,7 @@ psa_status_t tfm_svcall_psa_call(uint32_t *args, int32_t ns_caller, uint32_t lr) * readable. */ if (tfm_memory_check((void *)inptr, in_num * sizeof(psa_invec), - ns_caller, TFM_MEMORY_ACCESS_RO) != IPC_SUCCESS) { + ns_caller, TFM_MEMORY_ACCESS_RO, privileged) != IPC_SUCCESS) { tfm_panic(); } /* @@ -194,7 +204,7 @@ psa_status_t tfm_svcall_psa_call(uint32_t *args, int32_t ns_caller, uint32_t lr) * the wrap output vector is invalid or not read-write. */ if (tfm_memory_check((void *)outptr, out_num * sizeof(psa_outvec), - ns_caller, TFM_MEMORY_ACCESS_RW) != IPC_SUCCESS) { + ns_caller, TFM_MEMORY_ACCESS_RW, privileged) != IPC_SUCCESS) { tfm_panic(); } @@ -211,7 +221,7 @@ psa_status_t tfm_svcall_psa_call(uint32_t *args, int32_t ns_caller, uint32_t lr) */ for (i = 0; i < in_num; i++) { if (tfm_memory_check((void *)invecs[i].base, invecs[i].len, - ns_caller, TFM_MEMORY_ACCESS_RO) != IPC_SUCCESS) { + ns_caller, TFM_MEMORY_ACCESS_RO, privileged) != IPC_SUCCESS) { tfm_panic(); } } @@ -221,7 +231,7 @@ psa_status_t tfm_svcall_psa_call(uint32_t *args, int32_t ns_caller, uint32_t lr) */ for (i = 0; i < out_num; i++) { if (tfm_memory_check(outvecs[i].base, outvecs[i].len, - ns_caller, TFM_MEMORY_ACCESS_RW) != IPC_SUCCESS) { + ns_caller, TFM_MEMORY_ACCESS_RW, privileged) != IPC_SUCCESS) { tfm_panic(); } } @@ -363,6 +373,7 @@ static psa_status_t tfm_svcall_psa_get(uint32_t *args) struct tfm_spm_service_t *service = NULL; struct tfm_msg_body_t *tmp_msg = NULL; struct tfm_spm_ipc_partition_t *partition = NULL; + uint32_t privileged; TFM_ASSERT(args != NULL); signal = (psa_signal_t)args[0]; @@ -376,17 +387,18 @@ static psa_status_t tfm_svcall_psa_get(uint32_t *args) tfm_panic(); } + partition = tfm_spm_get_running_partition(); + if (!partition) { + tfm_panic(); + } + privileged = tfm_spm_partition_get_privileged_mode(partition->index); + /* * Write the message to the service buffer. It is a fatal error if the * input msg pointer is not a valid memory reference or not read-write. */ if (tfm_memory_check((void *)msg, sizeof(psa_msg_t), - false, TFM_MEMORY_ACCESS_RW) != IPC_SUCCESS) { - tfm_panic(); - } - - partition = tfm_spm_get_running_partition(); - if (!partition) { + false, TFM_MEMORY_ACCESS_RW, privileged) != IPC_SUCCESS) { tfm_panic(); } @@ -499,6 +511,8 @@ static size_t tfm_svcall_psa_read(uint32_t *args) size_t num_bytes; size_t bytes; struct tfm_msg_body_t *msg = NULL; + uint32_t privileged; + struct tfm_spm_ipc_partition_t *partition = NULL; TFM_ASSERT(args != NULL); msg_handle = (psa_handle_t)args[0]; @@ -512,6 +526,9 @@ static size_t tfm_svcall_psa_read(uint32_t *args) tfm_panic(); } + partition = msg->service->partition; + privileged = tfm_spm_partition_get_privileged_mode(partition->index); + /* * It is a fatal error if message handle does not refer to a PSA_IPC_CALL * message @@ -538,7 +555,7 @@ static size_t tfm_svcall_psa_read(uint32_t *args) * if the memory reference for buffer is invalid or not read-write. */ if (tfm_memory_check(buffer, num_bytes, false, - TFM_MEMORY_ACCESS_RW) != IPC_SUCCESS) { + TFM_MEMORY_ACCESS_RW, privileged) != IPC_SUCCESS) { tfm_panic(); } @@ -650,6 +667,8 @@ static void tfm_svcall_psa_write(uint32_t *args) void *buffer = NULL; size_t num_bytes; struct tfm_msg_body_t *msg = NULL; + uint32_t privileged; + struct tfm_spm_ipc_partition_t *partition = NULL; TFM_ASSERT(args != NULL); msg_handle = (psa_handle_t)args[0]; @@ -663,6 +682,9 @@ static void tfm_svcall_psa_write(uint32_t *args) tfm_panic(); } + partition = msg->service->partition; + privileged = tfm_spm_partition_get_privileged_mode(partition->index); + /* * It is a fatal error if message handle does not refer to a PSA_IPC_CALL * message @@ -693,7 +715,7 @@ static void tfm_svcall_psa_write(uint32_t *args) * if the memory reference for buffer is invalid or not readable. */ if (tfm_memory_check(buffer, num_bytes, false, - TFM_MEMORY_ACCESS_RO) != IPC_SUCCESS) { + TFM_MEMORY_ACCESS_RO, privileged) != IPC_SUCCESS) { tfm_panic(); } @@ -957,6 +979,9 @@ int32_t SVC_Handler_IPC(tfm_svc_number_t svc_num, uint32_t *ctx, uint32_t lr) case TFM_SVC_SCHEDULE: tfm_thrd_activate_schedule(); break; + case TFM_SVC_EXIT_THRD: + tfm_svcall_thrd_exit(); + break; case TFM_SVC_PSA_FRAMEWORK_VERSION: return tfm_svcall_psa_framework_version(); case TFM_SVC_PSA_VERSION: diff --git a/components/TARGET_PSA/TARGET_TFM/COMPONENT_SPE/secure_fw/core/ipc/tfm_thread.c b/components/TARGET_PSA/TARGET_TFM/COMPONENT_SPE/secure_fw/core/ipc/tfm_thread.c index cd01259e6e..21f22091a7 100644 --- a/components/TARGET_PSA/TARGET_TFM/COMPONENT_SPE/secure_fw/core/ipc/tfm_thread.c +++ b/components/TARGET_PSA/TARGET_TFM/COMPONENT_SPE/secure_fw/core/ipc/tfm_thread.c @@ -10,6 +10,8 @@ #include "tfm_thread.h" #include "tfm_utils.h" #include "tfm_memory_utils.h" +#include "tfm_svc.h" +#include "spm_api.h" /* Force ZERO in case ZI(bss) clear is missing */ static struct tfm_thrd_ctx *p_thrd_head = NULL; @@ -124,75 +126,56 @@ void tfm_thrd_set_status(struct tfm_thrd_ctx *pth, uint32_t new_status) update_running_head(&RUNN_HEAD, pth); } -/* - * TEMP WORKAROUND: The caller function who called thread module init needs to - * be returned. The caller is not a thread. Create a dummy IDLE thread to - * collect caller context; and schedule back to the caller with this context - * after all other real threads blocked. - * - * This WORKAROUND needs to be removed after IPC NSPM takes place. - */ -#define DUMMY_IDLE_TAG 0xDEEDDEED -static uint8_t idle_stack[32] __attribute__((aligned(8))); -static struct tfm_thrd_ctx idle_thread; -static struct tfm_thrd_ctx *init_idle_thread(struct tfm_thrd_ctx *pth) -{ - /* - * IDLE thread is a thread with the lowest priority. - * It gets scheduled after all other higher priority threads get blocked. - * The entry of IDLE thread is a dummy and has no mean. - */ - tfm_thrd_init(pth, (tfm_thrd_func_t)DUMMY_IDLE_TAG, NULL, - (uint8_t *)&idle_stack[32], (uint8_t *)idle_stack); - tfm_thrd_priority(pth, THRD_PRIOR_LOWEST); - tfm_thrd_start(pth); - return pth; -} - /* Scheduling won't happen immediately but after the exception returns */ void tfm_thrd_activate_schedule(void) { - /* - * The current thread can be NULL only when initializing. Create the IDLE - * thread and set it as the current thread to collect caller context. - */ - if (CURR_THRD == NULL) { - CURR_THRD = init_idle_thread(&idle_thread); - } - tfm_trigger_pendsv(); } +void tfm_thrd_start_scheduler(struct tfm_thrd_ctx *pth) +{ + /* + * There is no selected thread before scheduler start, assign + * a caller provided thread as current thread. This function + * should get called only ONCE; further calling triggers assert. + */ + TFM_ASSERT(CURR_THRD == NULL); + TFM_ASSERT(pth != NULL); + + CURR_THRD = pth; + tfm_thrd_activate_schedule(); +} + /* Remove current thread out of the schedulable list */ -void tfm_thrd_do_exit(void) +void tfm_svcall_thrd_exit(void) { CURR_THRD->status = THRD_STAT_DETACH; tfm_trigger_pendsv(); } +__attribute__((section("SFN"))) +void tfm_thrd_exit(void) +{ + SVC(TFM_SVC_EXIT_THRD); + while (1) { + ; + } +} + void tfm_thrd_context_switch(struct tfm_state_context_ext *ctxb, struct tfm_thrd_ctx *prev, struct tfm_thrd_ctx *next) { - /* Update latest context into the current thread context */ + TFM_ASSERT(prev != NULL); + TFM_ASSERT(next != NULL); + + /* + * First, update latest context into the current thread context. + * Then, update background context with next thread's context. + */ tfm_memcpy(&prev->state_ctx.ctxb, ctxb, sizeof(*ctxb)); - /* Update background context with next thread's context */ tfm_memcpy(ctxb, &next->state_ctx.ctxb, sizeof(next->state_ctx.ctxb)); - /* Set current thread indicator with next thread */ + + /* Update current thread indicator */ CURR_THRD = next; } - -/* - * This function is a reference implementation for PendSV handler in - * isolation level 1. More jobs (sandboxing e.g.) need to be done while - * scheduling in other isolation levels. - */ -void tfm_pendsv_do_schedule(struct tfm_state_context_ext *ctxb) -{ - struct tfm_thrd_ctx *pth = tfm_thrd_next_thread(); - - /* Swith context if another thread ready to run */ - if (pth && pth != CURR_THRD) { - tfm_thrd_context_switch(ctxb, CURR_THRD, pth); - } -} diff --git a/components/TARGET_PSA/TARGET_TFM/COMPONENT_SPE/secure_fw/core/secure_utilities.h b/components/TARGET_PSA/TARGET_TFM/COMPONENT_SPE/secure_fw/core/secure_utilities.h index 82a4f5a8a0..d367fe8400 100644 --- a/components/TARGET_PSA/TARGET_TFM/COMPONENT_SPE/secure_fw/core/secure_utilities.h +++ b/components/TARGET_PSA/TARGET_TFM/COMPONENT_SPE/secure_fw/core/secure_utilities.h @@ -25,8 +25,6 @@ #define EXC_NUM_PENDSV (14) #define EXC_NUM_SYSTICK (15) -#define printf(...) - /* Disable NS exceptions by setting NS PRIMASK to 1 */ #define TFM_NS_EXC_DISABLE() __TZ_set_PRIMASK_NS(1) /* Enable NS exceptions by setting NS PRIMASK to 0 */ diff --git a/components/TARGET_PSA/TARGET_TFM/COMPONENT_SPE/secure_fw/core/tfm_boot_data.c b/components/TARGET_PSA/TARGET_TFM/COMPONENT_SPE/secure_fw/core/tfm_boot_data.c index 3ec8b8e7fd..44c38a35ca 100644 --- a/components/TARGET_PSA/TARGET_TFM/COMPONENT_SPE/secure_fw/core/tfm_boot_data.c +++ b/components/TARGET_PSA/TARGET_TFM/COMPONENT_SPE/secure_fw/core/tfm_boot_data.c @@ -12,6 +12,15 @@ #include "tfm_api.h" #include "flash_layout.h" #include "secure_fw/spm/spm_api.h" +#ifdef TFM_PSA_API +#include "tfm_internal_defines.h" +#include "tfm_utils.h" +#include "psa_service.h" +#include "tfm_thread.h" +#include "tfm_wait.h" +#include "tfm_message_queue.h" +#include "tfm_spm.h" +#endif /*! * \def BOOT_DATA_VALID @@ -60,13 +69,19 @@ void tfm_core_get_boot_data_handler(uint32_t args[]) uint8_t *buf_start = (uint8_t *)args[1]; uint16_t buf_size = (uint16_t)args[2]; uint8_t *ptr; - uint32_t running_partition_idx = - tfm_spm_partition_get_running_partition_idx(); struct tfm_boot_data *boot_data; struct shared_data_tlv_entry tlv_entry; uintptr_t tlv_end, offset; +#ifndef TFM_PSA_API + uint32_t running_partition_idx = + tfm_spm_partition_get_running_partition_idx(); uint32_t res; +#else + struct tfm_spm_ipc_partition_t *partition = NULL; + uint32_t privileged; +#endif +#ifndef TFM_PSA_API /* Make sure that the output pointer points to a memory area that is owned * by the partition */ @@ -79,6 +94,20 @@ void tfm_core_get_boot_data_handler(uint32_t args[]) args[0] = TFM_ERROR_INVALID_PARAMETER; return; } +#else + partition = tfm_spm_get_running_partition(); + if (!partition) { + tfm_panic(); + } + privileged = tfm_spm_partition_get_privileged_mode(partition->index); + + if (tfm_memory_check(buf_start, buf_size, false, TFM_MEMORY_ACCESS_RW, + privileged) != IPC_SUCCESS) { + /* Not in accessible range, return error */ + args[0] = TFM_ERROR_INVALID_PARAMETER; + return; + } +#endif /* FixMe: Check whether caller has access right to given tlv_major_type */ diff --git a/components/TARGET_PSA/TARGET_TFM/COMPONENT_SPE/secure_fw/core/tfm_core.c b/components/TARGET_PSA/TARGET_TFM/COMPONENT_SPE/secure_fw/core/tfm_core.c index 7d831b5451..fc060f3b11 100644 --- a/components/TARGET_PSA/TARGET_TFM/COMPONENT_SPE/secure_fw/core/tfm_core.c +++ b/components/TARGET_PSA/TARGET_TFM/COMPONENT_SPE/secure_fw/core/tfm_core.c @@ -11,6 +11,7 @@ #include "tfm_internal.h" #include "tfm_api.h" #include "platform/include/tfm_spm_hal.h" +#include "uart_stdout.h" #include "secure_utilities.h" #include "secure_fw/spm/spm_api.h" #include "secure_fw/include/tfm_spm_services_api.h" @@ -47,6 +48,7 @@ __asm(" .global __ARM_use_no_argv\n"); #error Only TFM_LVL 1, 2 and 3 are supported! #endif +#ifndef TFM_PSA_API /* Macros to pick linker symbols and allow to form the partition data base */ #define REGION(a, b, c) a##b##c #define REGION_NAME(a, b, c) REGION(a, b, c) @@ -54,6 +56,7 @@ __asm(" .global __ARM_use_no_argv\n"); REGION_DECLARE(Image$$, TFM_UNPRIV_SCRATCH, $$ZI$$Base); REGION_DECLARE(Image$$, TFM_UNPRIV_SCRATCH, $$ZI$$Limit); +#endif void configure_ns_code(void) { @@ -87,6 +90,7 @@ int32_t tfm_core_init(void) __enable_irq(); + stdio_init(); LOG_MSG("Secure image initializing!"); #ifdef TFM_CORE_DEBUG @@ -106,11 +110,20 @@ int32_t tfm_core_init(void) /* Enable secure peripherals interrupts */ nvic_interrupt_enable(); +#ifdef TFM_PSA_API + /* FixMe: In case of IPC messaging, scratch area must not be referenced + * These variables should be removed when all obsolete references are + * removed from the codebase + */ + tfm_scratch_area = NULL; + tfm_scratch_area_size = 0; +#else tfm_scratch_area = (uint8_t *)®ION_NAME(Image$$, TFM_UNPRIV_SCRATCH, $$ZI$$Base); tfm_scratch_area_size = (uint32_t)®ION_NAME(Image$$, TFM_UNPRIV_SCRATCH, $$ZI$$Limit) - (uint32_t)®ION_NAME(Image$$, TFM_UNPRIV_SCRATCH, $$ZI$$Base); +#endif return 0; } @@ -179,6 +192,7 @@ int main(void) tfm_spm_hal_setup_isolation_hw(); +#ifndef TFM_PSA_API tfm_spm_partition_set_state(TFM_SP_CORE_ID, SPM_PARTITION_STATE_RUNNING); extern uint32_t Image$$ARM_LIB_STACK$$ZI$$Base[]; @@ -198,21 +212,25 @@ int main(void) */ tfm_core_set_secure_exception_priorities(); -#ifdef TFM_PSA_API - tfm_spm_init(); -#endif + /* 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_CORE_DEBUG /* Jumps to non-secure code */ LOG_MSG("Jumping to non-secure code..."); #endif - /* 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); - jump_to_ns_code(); +#else + /* + * Prioritise secure exceptions to avoid NS being able to pre-empt + * secure SVC or SecureFault. Do it before PSA API initialization. + */ + tfm_core_set_secure_exception_priorities(); + tfm_spm_init(); +#endif } diff --git a/components/TARGET_PSA/TARGET_TFM/COMPONENT_SPE/secure_fw/core/tfm_func_api.c b/components/TARGET_PSA/TARGET_TFM/COMPONENT_SPE/secure_fw/core/tfm_func_api.c new file mode 100644 index 0000000000..aeaf5f2e3d --- /dev/null +++ b/components/TARGET_PSA/TARGET_TFM/COMPONENT_SPE/secure_fw/core/tfm_func_api.c @@ -0,0 +1,1036 @@ +/* + * Copyright (c) 2017-2019, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#include +#include +#include +#include +#include "tfm_secure_api.h" +#include "tfm_nspm.h" +#include "secure_utilities.h" +#include "uart_stdout.h" +#include "secure_fw/spm/spm_api.h" +#include "region_defs.h" +#include "tfm_api.h" + +#define EXC_RETURN_SECURE_FUNCTION 0xFFFFFFFD + +#ifndef TFM_LVL +#error TFM_LVL is not defined! +#endif + +/* Macros to pick linker symbols and allow references to sections */ +#define REGION(a, b, c) a##b##c +#define REGION_NAME(a, b, c) REGION(a, b, c) +#define REGION_DECLARE(a, b, c) extern uint32_t REGION_NAME(a, b, c) + +REGION_DECLARE(Image$$, TFM_UNPRIV_SCRATCH, $$ZI$$Base); +REGION_DECLARE(Image$$, TFM_UNPRIV_SCRATCH, $$ZI$$Limit); + +#if TFM_LVL == 1 +REGION_DECLARE(Image$$, TFM_SECURE_STACK, $$ZI$$Base); +REGION_DECLARE(Image$$, TFM_SECURE_STACK, $$ZI$$Limit); +#endif + +/* This is the "Big Lock" on the secure side, to guarantee single entry + * to SPE + */ +extern int32_t tfm_secure_lock; +static int32_t tfm_secure_api_initializing = 1; + +static int32_t is_iovec_api_call(void) +{ + uint32_t current_partition_idx = + tfm_spm_partition_get_running_partition_idx(); + const struct spm_partition_runtime_data_t *curr_part_data = + tfm_spm_partition_get_runtime_data(current_partition_idx); + return curr_part_data->iovec_api; +} + +static uint32_t *prepare_partition_ctx( + const struct tfm_exc_stack_t *svc_ctx, + const struct tfm_sfn_req_s *desc_ptr, + uint32_t *dst) +{ + /* XPSR = as was when called, but make sure it's thread mode */ + *(--dst) = svc_ctx->XPSR & 0xFFFFFE00U; + /* ReturnAddress = resume veneer in new context */ + *(--dst) = svc_ctx->RetAddr; + /* LR = sfn address */ + *(--dst) = (uint32_t)desc_ptr->sfn; + /* R12 = don't care */ + *(--dst) = 0; + + /* R0-R3 = sfn arguments */ + int32_t i = 4; + + while (i > 0) { + i--; + *(--dst) = (uint32_t)desc_ptr->args[i]; + } + return dst; +} + +static uint32_t *prepare_partition_iovec_ctx( + const struct tfm_exc_stack_t *svc_ctx, + const struct tfm_sfn_req_s *desc_ptr, + const struct iovec_args_t *iovec_args, + uint32_t *dst) +{ + /* XPSR = as was when called, but make sure it's thread mode */ + *(--dst) = svc_ctx->XPSR & 0xFFFFFE00U; + /* ReturnAddress = resume veneer in new context */ + *(--dst) = svc_ctx->RetAddr; + /* LR = sfn address */ + *(--dst) = (uint32_t)desc_ptr->sfn; + /* R12 = don't care */ + *(--dst) = 0U; + + /* R0-R3 = sfn arguments */ + *(--dst) = iovec_args->out_len; + *(--dst) = (uint32_t)iovec_args->out_vec; + *(--dst) = iovec_args->in_len; + *(--dst) = (uint32_t)iovec_args->in_vec; + + return dst; +} + +static void restore_caller_ctx( + const struct tfm_exc_stack_t *svc_ctx, + struct tfm_exc_stack_t *target_ctx) +{ + /* ReturnAddress = resume veneer after second SVC */ + target_ctx->RetAddr = svc_ctx->RetAddr; + + /* R0 = function return value */ + target_ctx->R0 = svc_ctx->R0; + + return; +} + +/** \brief Check whether the iovec parameters are valid, and the memory ranges + * are in the posession of the calling partition + * + * \param[in] desc_ptr The secure function request descriptor + * + * \return Return /ref TFM_SUCCESS if the iovec parameters are valid, error code + * otherwise as in /ref tfm_status_e + */ +static int32_t tfm_core_check_sfn_parameters( + const struct tfm_sfn_req_s *desc_ptr) +{ + struct psa_invec *in_vec = (psa_invec *)desc_ptr->args[0]; + size_t in_len; + struct psa_outvec *out_vec = (psa_outvec *)desc_ptr->args[2]; + size_t out_len; + + uint32_t i; + + if ((desc_ptr->args[1] < 0) || (desc_ptr->args[3] < 0)) { + return TFM_ERROR_INVALID_PARAMETER; + } + + in_len = (size_t)(desc_ptr->args[1]); + out_len = (size_t)(desc_ptr->args[3]); + + /* The number of vectors are within range. Extra checks to avoid overflow */ + if ((in_len > PSA_MAX_IOVEC) || (out_len > PSA_MAX_IOVEC) || + (in_len + out_len > PSA_MAX_IOVEC)) { + return TFM_ERROR_INVALID_PARAMETER; + } + + /* Check whether the caller partition has at write access to the iovec + * structures themselves. Use the TT instruction for this. + */ + if (in_len > 0) { + if ((in_vec == NULL) || + (tfm_core_has_write_access_to_region(in_vec, + sizeof(psa_invec)*in_len, desc_ptr->ns_caller, + TFM_PARTITION_UNPRIVILEGED_MODE) != TFM_SUCCESS)) { + return TFM_ERROR_INVALID_PARAMETER; + } + } else { + if (in_vec != NULL) { + return TFM_ERROR_INVALID_PARAMETER; + } + } + if (out_len > 0) { + if ((out_vec == NULL) || + (tfm_core_has_write_access_to_region(out_vec, + sizeof(psa_outvec)*out_len, desc_ptr->ns_caller, + TFM_PARTITION_UNPRIVILEGED_MODE) != TFM_SUCCESS)) { + return TFM_ERROR_INVALID_PARAMETER; + } + } else { + if (out_vec != NULL) { + return TFM_ERROR_INVALID_PARAMETER; + } + } + + /* Check whether the caller partition has access to the data inside the + * iovecs + */ + for (i = 0; i < in_len; ++i) { + if (in_vec[i].len > 0) { + if ((in_vec[i].base == NULL) || + (tfm_core_has_read_access_to_region(in_vec[i].base, + in_vec[i].len, desc_ptr->ns_caller, + TFM_PARTITION_UNPRIVILEGED_MODE) != TFM_SUCCESS)) { + return TFM_ERROR_INVALID_PARAMETER; + } + } + } + for (i = 0; i < out_len; ++i) { + if (out_vec[i].len > 0) { + if ((out_vec[i].base == NULL) || + (tfm_core_has_write_access_to_region(out_vec[i].base, + out_vec[i].len, desc_ptr->ns_caller, + TFM_PARTITION_UNPRIVILEGED_MODE) != TFM_SUCCESS)) { + return TFM_ERROR_INVALID_PARAMETER; + } + } + } + + return TFM_SUCCESS; +} + +static void tfm_copy_iovec_parameters(struct iovec_args_t *target, + const struct iovec_args_t *source) +{ + size_t i; + + target->in_len = source->in_len; + for (i = 0; i < source->in_len; ++i) { + target->in_vec[i].base = source->in_vec[i].base; + target->in_vec[i].len = source->in_vec[i].len; + } + target->out_len = source->out_len; + for (i = 0; i < source->out_len; ++i) { + target->out_vec[i].base = source->out_vec[i].base; + target->out_vec[i].len = source->out_vec[i].len; + } +} + +static void tfm_clear_iovec_parameters(struct iovec_args_t *args) +{ + int i; + + args->in_len = 0; + for (i = 0; i < PSA_MAX_IOVEC; ++i) { + args->in_vec[i].base = NULL; + args->in_vec[i].len = 0; + } + args->out_len = 0; + for (i = 0; i < PSA_MAX_IOVEC; ++i) { + args->out_vec[i].base = NULL; + args->out_vec[i].len = 0; + } +} + +static int32_t tfm_start_partition(const struct tfm_sfn_req_s *desc_ptr, + uint32_t excReturn) +{ + uint32_t caller_partition_idx = desc_ptr->caller_part_idx; + const struct spm_partition_runtime_data_t *curr_part_data; + uint32_t caller_flags; + register uint32_t partition_idx; + uint32_t psp; + uint32_t partition_psp, partition_psplim; + uint32_t partition_state; + uint32_t partition_flags; + struct tfm_exc_stack_t *svc_ctx; + uint32_t caller_partition_id; + int32_t client_id; + struct iovec_args_t *iovec_args; + + psp = __get_PSP(); + svc_ctx = (struct tfm_exc_stack_t *)psp; + caller_flags = tfm_spm_partition_get_flags(caller_partition_idx); + + /* Check partition state consistency */ + if (((caller_flags & SPM_PART_FLAG_APP_ROT) != 0) + != (!desc_ptr->ns_caller)) { + /* Partition state inconsistency detected */ + return TFM_SECURE_LOCK_FAILED; + } + + if ((caller_flags & SPM_PART_FLAG_APP_ROT) == 0) { + /* Disable NS exception handling while secure service is running. + * FixMe: + * This restriction is applied to limit the number of possible attack + * vectors. + * To be removed when pre-emption and context management issues have + * been analysed and resolved. + */ + TFM_NS_EXC_DISABLE(); + } + + partition_idx = get_partition_idx(desc_ptr->sp_id); + + curr_part_data = tfm_spm_partition_get_runtime_data(partition_idx); + partition_state = curr_part_data->partition_state; + partition_flags = tfm_spm_partition_get_flags(partition_idx); + caller_partition_id = tfm_spm_partition_get_partition_id( + caller_partition_idx); + + if (tfm_secure_api_initializing) { +#if TFM_LVL != 1 + /* Make thread mode unprivileged while untrusted partition init is + * executed + */ + if ((partition_flags & SPM_PART_FLAG_PSA_ROT) == 0) { + tfm_spm_partition_change_privilege( + TFM_PARTITION_UNPRIVILEGED_MODE); + } +#endif + } else if (partition_state == SPM_PARTITION_STATE_RUNNING || + partition_state == SPM_PARTITION_STATE_SUSPENDED || + partition_state == SPM_PARTITION_STATE_BLOCKED) { + /* Recursion is not permitted! */ + return TFM_ERROR_PARTITION_NON_REENTRANT; + } else if (partition_state != SPM_PARTITION_STATE_IDLE) { + /* The partition to be called is not in a proper state */ + return TFM_SECURE_LOCK_FAILED; + } + +#if TFM_LVL == 1 + /* Prepare switch to shared secure partition stack */ + /* In case the call is coming from the non-secure world, we save the iovecs + * on the stop of the stack. So the memory area, that can actually be used + * as stack by the partitions starts at a lower address + */ + partition_psp = + (uint32_t)®ION_NAME(Image$$, TFM_SECURE_STACK, $$ZI$$Limit)- + sizeof(struct iovec_args_t); + partition_psplim = + (uint32_t)®ION_NAME(Image$$, TFM_SECURE_STACK, $$ZI$$Base); +#else + partition_psp = curr_part_data->stack_ptr; + partition_psplim = tfm_spm_partition_get_stack_bottom(partition_idx); +#endif + /* Store the context for the partition call */ + tfm_spm_partition_set_caller_partition_idx(partition_idx, + caller_partition_idx); + tfm_spm_partition_store_context(caller_partition_idx, psp, excReturn); + + if ((caller_flags & SPM_PART_FLAG_APP_ROT)) { + tfm_spm_partition_set_caller_client_id(partition_idx, + caller_partition_id); + } else { + client_id = tfm_nspm_get_current_client_id(); + if (client_id >= 0) { + return TFM_SECURE_LOCK_FAILED; + } + tfm_spm_partition_set_caller_client_id(partition_idx, client_id); + } + +#if (TFM_LVL != 1) && (TFM_LVL != 2) + /* Dynamic partitioning is only done is TFM level 3 */ + tfm_spm_partition_sandbox_deconfig(caller_partition_idx); + + /* Configure partition execution environment */ + if (tfm_spm_partition_sandbox_config(partition_idx) != SPM_ERR_OK) { + ERROR_MSG("Failed to configure sandbox for partition!"); + tfm_secure_api_error_handler(); + } +#endif + + /* Default share to scratch area in case of partition to partition calls + * this way partitions always get default access to input buffers + */ + /* FixMe: return value/error handling TBD */ + tfm_spm_partition_set_share(partition_idx, desc_ptr->ns_caller ? + TFM_BUFFER_SHARE_NS_CODE : TFM_BUFFER_SHARE_SCRATCH); + +#if TFM_LVL == 1 + /* In level one, only switch context and return from exception if in + * handler mode + */ + if ((desc_ptr->ns_caller) || (tfm_secure_api_initializing)) { + if (desc_ptr->iovec_api == TFM_SFN_API_IOVEC) { + /* Save the iovecs on the common stack. The vectors had been sanity + * checked already, and since then the interrupts have been kept + * disabled. So we can be sure that the vectors haven't been + * tampered with since the check. + */ + iovec_args = (struct iovec_args_t *) + ((uint32_t)®ION_NAME(Image$$, TFM_SECURE_STACK, $$ZI$$Limit)- + sizeof(struct iovec_args_t)); + if (tfm_spm_partition_set_iovec(partition_idx, desc_ptr->args) != + SPM_ERR_OK) { + return TFM_ERROR_GENERIC; + } + tfm_copy_iovec_parameters(iovec_args, + &(curr_part_data->iovec_args)); + + /* Prepare the partition context, update stack ptr */ + psp = (uint32_t)prepare_partition_iovec_ctx(svc_ctx, desc_ptr, + iovec_args, + (uint32_t *)partition_psp); + } else { + /* Prepare the partition context, update stack ptr */ + psp = (uint32_t)prepare_partition_ctx(svc_ctx, desc_ptr, + (uint32_t *)partition_psp); + } + __set_PSP(psp); + __set_PSPLIM(partition_psplim); + } +#else + if (desc_ptr->iovec_api == TFM_SFN_API_IOVEC) { + /* Save the iovecs on the stack of the partition. The vectors had been + * sanity checked already, and since then the interrupts have been kept + * disabled. So we can be sure that the vectors haven't been tampered + * with since the check. + */ + iovec_args = + (struct iovec_args_t *)(tfm_spm_partition_get_stack_top(partition_idx) - + sizeof(struct iovec_args_t)); + if (tfm_spm_partition_set_iovec(partition_idx, desc_ptr->args) != + SPM_ERR_OK) { + return TFM_ERROR_GENERIC; + } + tfm_copy_iovec_parameters(iovec_args, &(curr_part_data->iovec_args)); + + /* Prepare the partition context, update stack ptr */ + psp = (uint32_t)prepare_partition_iovec_ctx(svc_ctx, desc_ptr, + iovec_args, + (uint32_t *)partition_psp); + } else { + /* Prepare the partition context, update stack ptr */ + psp = (uint32_t)prepare_partition_ctx(svc_ctx, desc_ptr, + (uint32_t *)partition_psp); + } + __set_PSP(psp); + __set_PSPLIM(partition_psplim); +#endif + + tfm_spm_partition_set_state(caller_partition_idx, + SPM_PARTITION_STATE_BLOCKED); + tfm_spm_partition_set_state(partition_idx, SPM_PARTITION_STATE_RUNNING); + tfm_secure_lock++; + + return TFM_SUCCESS; +} + +static int32_t tfm_return_from_partition(uint32_t *excReturn) +{ + uint32_t current_partition_idx = + tfm_spm_partition_get_running_partition_idx(); + const struct spm_partition_runtime_data_t *curr_part_data, *ret_part_data; + uint32_t current_partition_flags; + uint32_t return_partition_idx; + uint32_t return_partition_flags; + uint32_t psp = __get_PSP(); + size_t i; + struct tfm_exc_stack_t *svc_ctx = (struct tfm_exc_stack_t *)psp; + struct iovec_args_t *iovec_args; + + if (current_partition_idx == SPM_INVALID_PARTITION_IDX) { + return TFM_SECURE_UNLOCK_FAILED; + } + + curr_part_data = tfm_spm_partition_get_runtime_data(current_partition_idx); + return_partition_idx = curr_part_data->caller_partition_idx; + + if (return_partition_idx == SPM_INVALID_PARTITION_IDX) { + return TFM_SECURE_UNLOCK_FAILED; + } + + ret_part_data = tfm_spm_partition_get_runtime_data(return_partition_idx); + + return_partition_flags = tfm_spm_partition_get_flags(return_partition_idx); + current_partition_flags = tfm_spm_partition_get_flags( + current_partition_idx); + + tfm_secure_lock--; + + if ((return_partition_flags & SPM_PART_FLAG_APP_ROT) == 0) { + /* Re-enable NS exceptions when secure service returns to NS client. + * FixMe: + * To be removed when pre-emption and context management issues have + * been analysed and resolved. + */ + TFM_NS_EXC_ENABLE(); + } + +#if (TFM_LVL != 1) && (TFM_LVL != 2) + /* Deconfigure completed partition environment */ + tfm_spm_partition_sandbox_deconfig(current_partition_idx); + if (tfm_secure_api_initializing) { + /* Restore privilege for thread mode during TF-M init. This is only + * have to be done if the partition is not trusted. + */ + if ((current_partition_flags & SPM_PART_FLAG_PSA_ROT) == 0) { + tfm_spm_partition_change_privilege(TFM_PARTITION_PRIVILEGED_MODE); + } + } else { + /* Configure the caller partition environment in case this was a + * partition to partition call and returning to untrusted partition + */ + if (tfm_spm_partition_sandbox_config(return_partition_idx) + != SPM_ERR_OK) { + ERROR_MSG("Failed to configure sandbox for partition!"); + tfm_secure_api_error_handler(); + } + if (return_partition_flags & SPM_PART_FLAG_APP_ROT) { + /* Restore share status */ + tfm_spm_partition_set_share( + return_partition_idx, + tfm_spm_partition_get_runtime_data( + return_partition_idx)->share); + } + } +#endif + +#if TFM_LVL == 1 + if (!(return_partition_flags & SPM_PART_FLAG_APP_ROT) || + (tfm_secure_api_initializing)) { + /* In TFM level 1 context restore is only done when + * returning to NS or after initialization + */ + /* Restore caller context */ + restore_caller_ctx(svc_ctx, + (struct tfm_exc_stack_t *)ret_part_data->stack_ptr); + *excReturn = ret_part_data->lr; + __set_PSP(ret_part_data->stack_ptr); + extern uint32_t Image$$ARM_LIB_STACK$$ZI$$Base[]; + uint32_t psp_stack_bottom = (uint32_t)Image$$ARM_LIB_STACK$$ZI$$Base; + __set_PSPLIM(psp_stack_bottom); + + /* FIXME: The condition should be removed once all the secure service + * calls are done via the iovec veneers + */ + if (curr_part_data->iovec_api) { + iovec_args = (struct iovec_args_t *) + ((uint32_t)®ION_NAME(Image$$, TFM_SECURE_STACK, $$ZI$$Limit) - + sizeof(struct iovec_args_t)); + + for (i = 0; i < curr_part_data->iovec_args.out_len; ++i) { + curr_part_data->orig_outvec[i].len = iovec_args->out_vec[i].len; + } + tfm_clear_iovec_parameters(iovec_args); + } + } +#else + /* Restore caller context */ + restore_caller_ctx(svc_ctx, + (struct tfm_exc_stack_t *)ret_part_data->stack_ptr); + *excReturn = ret_part_data->lr; + __set_PSP(ret_part_data->stack_ptr); + __set_PSPLIM(tfm_spm_partition_get_stack_bottom(return_partition_idx)); + /* Clear the context entry before returning */ + tfm_spm_partition_set_stack( + current_partition_idx, psp + sizeof(struct tfm_exc_stack_t)); + + /* FIXME: The condition should be removed once all the secure service + * calls are done via the iovec veneers */ + if (curr_part_data->iovec_api) { + iovec_args = (struct iovec_args_t *) + (tfm_spm_partition_get_stack_top(current_partition_idx) - + sizeof(struct iovec_args_t)); + + for (i = 0; i < curr_part_data->iovec_args.out_len; ++i) { + curr_part_data->orig_outvec[i].len = iovec_args->out_vec[i].len; + } + tfm_clear_iovec_parameters(iovec_args); + } +#endif + + tfm_spm_partition_cleanup_context(current_partition_idx); + + tfm_spm_partition_set_state(current_partition_idx, + SPM_PARTITION_STATE_IDLE); + tfm_spm_partition_set_state(return_partition_idx, + SPM_PARTITION_STATE_RUNNING); + + return TFM_SUCCESS; +} + +static int32_t tfm_check_sfn_req_integrity(const struct tfm_sfn_req_s *desc_ptr) +{ + if ((desc_ptr == NULL) || + (desc_ptr->sp_id == 0) || + (desc_ptr->sfn == NULL)) { + /* invalid parameter */ + return TFM_ERROR_INVALID_PARAMETER; + } + return TFM_SUCCESS; +} + +static int32_t tfm_core_check_sfn_req_rules( + const struct tfm_sfn_req_s *desc_ptr) +{ + /* Check partition idx validity */ + if (desc_ptr->caller_part_idx == SPM_INVALID_PARTITION_IDX) { + return TFM_ERROR_NO_ACTIVE_PARTITION; + } + + if ((desc_ptr->ns_caller) && (tfm_secure_lock != 0)) { + /* Secure domain is already locked! + * This should only happen if caller is secure partition! + * FixMe: This scenario is a potential security breach + * Take appropriate action! + */ + return TFM_ERROR_SECURE_DOMAIN_LOCKED; + } + + if (tfm_secure_api_initializing) { + int32_t id = + tfm_spm_partition_get_partition_id(desc_ptr->caller_part_idx); + + if ((id != TFM_SP_CORE_ID) || (tfm_secure_lock != 0)) { + /* Invalid request during system initialization */ + ERROR_MSG("Invalid service request during initialization!"); + return TFM_ERROR_NOT_INITIALIZED; + } + } + + return TFM_SUCCESS; +} + +void tfm_secure_api_init_done(void) +{ + tfm_secure_api_initializing = 0; +#if TFM_LVL != 1 + if (tfm_spm_partition_sandbox_config(TFM_SP_NON_SECURE_ID) != SPM_ERR_OK) { + ERROR_MSG("Failed to configure sandbox for partition!"); + tfm_secure_api_error_handler(); + } +#endif +} + +int32_t tfm_core_sfn_request_handler( + struct tfm_sfn_req_s *desc_ptr, uint32_t excReturn) +{ + int32_t res; + + res = tfm_check_sfn_req_integrity(desc_ptr); + if (res != TFM_SUCCESS) { + ERROR_MSG("Invalid service request!"); + tfm_secure_api_error_handler(); + } + + __disable_irq(); + + desc_ptr->caller_part_idx = tfm_spm_partition_get_running_partition_idx(); + + if (desc_ptr->iovec_api == TFM_SFN_API_IOVEC) { + res = tfm_core_check_sfn_parameters(desc_ptr); + if (res != TFM_SUCCESS) { + /* The sanity check of iovecs failed. */ + __enable_irq(); + tfm_secure_api_error_handler(); + } + } + + res = tfm_core_check_sfn_req_rules(desc_ptr); + if (res != TFM_SUCCESS) { + /* FixMe: error compartmentalization TBD */ + tfm_spm_partition_set_state( + desc_ptr->caller_part_idx, SPM_PARTITION_STATE_CLOSED); + __enable_irq(); + ERROR_MSG("Unauthorized service request!"); + tfm_secure_api_error_handler(); + } + + res = tfm_start_partition(desc_ptr, excReturn); + if (res != TFM_SUCCESS) { + /* FixMe: consider possible fault scenarios */ + __enable_irq(); + ERROR_MSG("Failed to process service request!"); + tfm_secure_api_error_handler(); + } + + __enable_irq(); + + return res; +} + +#if TFM_LVL == 1 +int32_t tfm_core_sfn_request_thread_mode(struct tfm_sfn_req_s *desc_ptr) +{ + int32_t res; + int32_t *args; + int32_t retVal; + + if (desc_ptr->iovec_api == TFM_SFN_API_IOVEC) { + res = tfm_core_check_sfn_parameters(desc_ptr); + if (res != TFM_SUCCESS) { + /* The sanity check of iovecs failed. */ + return res; + } + } + + /* No excReturn value is needed as no exception handling is used */ + res = tfm_core_sfn_request_handler(desc_ptr, 0); + + if (res != TFM_SUCCESS) { + tfm_secure_api_error_handler(); + } + + /* Secure partition to secure partition call in TFM level 1 */ + args = desc_ptr->args; + retVal = desc_ptr->sfn(args[0], args[1], args[2], args[3]); + + /* return handler should restore original exc_return value... */ + res = tfm_return_from_partition(NULL); + if (res == TFM_SUCCESS) { + /* If unlock successful, pass SS return value to caller */ + res = retVal; + } else { + /* Unlock errors indicate ctx database corruption or unknown + * anomalies. Halt execution + */ + ERROR_MSG("Secure API error during unlock!"); + tfm_secure_api_error_handler(); + } + return res; +} +#endif + +void tfm_core_validate_secure_caller_handler(uint32_t *svc_args) +{ + + int32_t res = TFM_ERROR_GENERIC; + uint32_t running_partition_idx = + tfm_spm_partition_get_running_partition_idx(); + const struct spm_partition_runtime_data_t *curr_part_data = + tfm_spm_partition_get_runtime_data(running_partition_idx); + uint32_t running_partition_flags = + tfm_spm_partition_get_flags(running_partition_idx); + uint32_t caller_partition_flags = + tfm_spm_partition_get_flags(curr_part_data->caller_partition_idx); + + if (!(running_partition_flags & SPM_PART_FLAG_APP_ROT)) { + /* This handler shouldn't be called from outside partition context. + * Partitions are only allowed to run while S domain is locked. + */ + svc_args[0] = TFM_ERROR_INVALID_PARAMETER; + return; + } + + /* Store return value in r0 */ + if (caller_partition_flags & SPM_PART_FLAG_APP_ROT) { + res = TFM_SUCCESS; + } + svc_args[0] = res; +} + +int32_t tfm_core_check_buffer_access(uint32_t partition_idx, + void *start_addr, + size_t len, + uint32_t alignment) +{ + uintptr_t start_addr_value = (uintptr_t)start_addr; + uintptr_t end_addr_value = (uintptr_t)start_addr + len; + uintptr_t alignment_mask; + + alignment_mask = (((uintptr_t)1) << alignment) - 1; + + /* Check that the pointer is aligned properly */ + if (start_addr_value & alignment_mask) { + /* not aligned, return error */ + return 0; + } + + /* Protect against overflow (and zero len) */ + if (end_addr_value <= start_addr_value) { + return 0; + } + +#if TFM_LVL == 1 + /* For privileged partition execution, all secure data memory and stack + * is accessible + */ + if (start_addr_value >= S_DATA_START && + end_addr_value <= (S_DATA_START + S_DATA_SIZE)) { + return 1; + } +#else + /* For non-privileged execution the partition's data and stack is + * accessible + */ + if (start_addr_value >= + tfm_spm_partition_get_stack_bottom(partition_idx) && + end_addr_value <= + tfm_spm_partition_get_stack_top(partition_idx)) { + return 1; + } + if (start_addr_value >= + tfm_spm_partition_get_rw_start(partition_idx) && + end_addr_value <= + tfm_spm_partition_get_rw_limit(partition_idx)) { + return 1; + } + if (start_addr_value >= + tfm_spm_partition_get_zi_start(partition_idx) && + end_addr_value <= + tfm_spm_partition_get_zi_limit(partition_idx)) { + return 1; + } +#endif + return 0; +} + +void tfm_core_get_caller_client_id_handler(uint32_t *svc_args) +{ + uintptr_t result_ptr_value = svc_args[0]; + uint32_t running_partition_idx = + tfm_spm_partition_get_running_partition_idx(); + const uint32_t running_partition_flags = + tfm_spm_partition_get_flags(running_partition_idx); + const struct spm_partition_runtime_data_t *curr_part_data = + tfm_spm_partition_get_runtime_data(running_partition_idx); + int res = 0; + + if (!(running_partition_flags & SPM_PART_FLAG_APP_ROT)) { + /* This handler shouldn't be called from outside partition context. + * Partitions are only allowed to run while S domain is locked. + */ + svc_args[0] = TFM_ERROR_INVALID_PARAMETER; + return; + } + + /* Make sure that the output pointer points to a memory area that is owned + * by the partition + */ + res = tfm_core_check_buffer_access(running_partition_idx, + (void *)result_ptr_value, + sizeof(curr_part_data->caller_client_id), + 2); + if (!res) { + /* Not in accessible range, return error */ + svc_args[0] = TFM_ERROR_INVALID_PARAMETER; + return; + } + + *((int32_t *)result_ptr_value) = curr_part_data->caller_client_id; + + /* Store return value in r0 */ + svc_args[0] = TFM_SUCCESS; +} + +void tfm_core_memory_permission_check_handler(uint32_t *svc_args) +{ + uint32_t ptr = svc_args[0]; + uint32_t size = svc_args[1]; + int32_t access = svc_args[2]; + + uint32_t max_buf_size, ptr_start, range_limit, range_check = false; + int32_t res; + uint32_t running_partition_idx = + tfm_spm_partition_get_running_partition_idx(); + const struct spm_partition_runtime_data_t *curr_part_data = + tfm_spm_partition_get_runtime_data(running_partition_idx); + uint32_t running_partition_flags = + tfm_spm_partition_get_flags(running_partition_idx); + int32_t flags = 0; + void *rangeptr; + + if (!(running_partition_flags & SPM_PART_FLAG_APP_ROT) || (size == 0)) { + /* This handler should only be called from a secure partition. */ + svc_args[0] = TFM_ERROR_INVALID_PARAMETER; + return; + } + + if (curr_part_data->share != TFM_BUFFER_SHARE_PRIV) { + flags |= CMSE_MPU_UNPRIV; + } + + if (access == TFM_MEMORY_ACCESS_RW) { + flags |= CMSE_MPU_READWRITE; + } else { + flags |= CMSE_MPU_READ; + } + + /* Check if partition access to address would fail */ + rangeptr = cmse_check_address_range((void *)ptr, size, flags); + + /* Get regions associated with address */ + cmse_address_info_t addr_info = cmse_TT((void *)ptr); + + if (rangeptr == NULL) { + svc_args[0] = TFM_ERROR_INVALID_PARAMETER; + return; + } + + if (addr_info.flags.secure) { +#if TFM_LVL == 1 + /* For privileged partition execution, all secure data memory is + * accessible + */ + max_buf_size = S_DATA_SIZE; + ptr_start = S_DATA_START; + range_limit = S_DATA_LIMIT; +#else + /* Only scratch is permitted in secure memory */ + max_buf_size = (uint32_t)tfm_scratch_area_size; + ptr_start = (uint32_t)tfm_scratch_area; + range_limit = (uint32_t)tfm_scratch_area + tfm_scratch_area_size - 1; +#endif + range_check = true; + } else { + if (!addr_info.flags.sau_region_valid) { + /* If address is NS, TF-M expects SAU to be configured + */ + svc_args[0] = TFM_ERROR_INVALID_PARAMETER; + return; + } + switch (addr_info.flags.sau_region) { + case TFM_NS_REGION_CODE: + if (access == TFM_MEMORY_ACCESS_RW) { + res = TFM_ERROR_INVALID_PARAMETER; + } else { + /* Currently TF-M does not support checks for NS Memory + * accesses by partitions + */ + res = TFM_SUCCESS; + } + break; + case TFM_NS_REGION_DATA: + /* Currently TF-M does not support checks for NS Memory + * accesses by partitions + */ + res = TFM_SUCCESS; + break; + default: + /* Only NS data and code regions can be accessed as buffers */ + res = TFM_ERROR_INVALID_PARAMETER; + break; + } + } + + if (range_check == true) { + if ((size <= max_buf_size) && (ptr >= ptr_start) + && (ptr <= range_limit + 1 - size)) { + res = TFM_SUCCESS; + } else { + res = TFM_ERROR_INVALID_PARAMETER; + } + } + + /* Store return value in r0 */ + svc_args[0] = res; +} + +/* This SVC handler is called if veneer is running in thread mode */ +uint32_t tfm_core_partition_request_svc_handler( + const struct tfm_exc_stack_t *svc_ctx, uint32_t excReturn) +{ + struct tfm_sfn_req_s *desc_ptr; + + if (!(excReturn & EXC_RETURN_STACK_PROCESS)) { + /* Service request SVC called with MSP active. + * Either invalid configuration for Thread mode or SVC called + * from Handler mode, which is not supported. + * FixMe: error severity TBD + */ + ERROR_MSG("Service request SVC called with MSP active!"); + tfm_secure_api_error_handler(); + } + + desc_ptr = (struct tfm_sfn_req_s *)svc_ctx->R0; + + if (tfm_core_sfn_request_handler(desc_ptr, excReturn) != TFM_SUCCESS) { + tfm_secure_api_error_handler(); + } + + return EXC_RETURN_SECURE_FUNCTION; +} + +/* This SVC handler is called when sfn returns */ +uint32_t tfm_core_partition_return_handler(uint32_t lr) +{ + int32_t res; + + if (!(lr & EXC_RETURN_STACK_PROCESS)) { + /* Partition return SVC called with MSP active. + * This should not happen! + */ + ERROR_MSG("Partition return SVC called with MSP active!"); + tfm_secure_api_error_handler(); + } + + /* Store return value from secure partition */ + int32_t retVal = *(int32_t *)__get_PSP(); + + if (!is_iovec_api_call()) { + if ((retVal > TFM_SUCCESS) && + (retVal < TFM_PARTITION_SPECIFIC_ERROR_MIN)) { + /* Secure function returned a reserved value */ +#ifdef TFM_CORE_DEBUG + LOG_MSG("Invalid return value from secure partition!"); +#endif + /* FixMe: error can be traced to specific secure partition + * and Core is not compromised. Error handling flow can be + * refined + */ + tfm_secure_api_error_handler(); + } + } + + res = tfm_return_from_partition(&lr); + if (res != TFM_SUCCESS) { + /* Unlock errors indicate ctx database corruption or unknown anomalies + * Halt execution + */ + ERROR_MSG("Secure API error during unlock!"); + tfm_secure_api_error_handler(); + } + + return lr; +} + +void tfm_core_set_buffer_area_handler(uint32_t *args) +{ + /* r0 is stored in args[0] in exception stack frame + * Store input parameter before writing return value to that address + */ + enum tfm_buffer_share_region_e share; + uint32_t running_partition_idx = + tfm_spm_partition_get_running_partition_idx(); + const struct spm_partition_runtime_data_t *curr_part_data = + tfm_spm_partition_get_runtime_data(running_partition_idx); + uint32_t caller_partition_idx = curr_part_data->caller_partition_idx; + uint32_t running_partition_flags = + tfm_spm_partition_get_flags(running_partition_idx); + uint32_t caller_partition_flags = + tfm_spm_partition_get_flags(caller_partition_idx); + + /* tfm_core_set_buffer_area() returns int32_t */ + int32_t *res_ptr = (int32_t *)&args[0]; + + if (!(running_partition_flags & SPM_PART_FLAG_APP_ROT)) { + /* This handler should only be called from a secure partition. */ + *res_ptr = TFM_ERROR_INVALID_PARAMETER; + return; + } + + switch (args[0]) { + case TFM_BUFFER_SHARE_DEFAULT: + share = (!(caller_partition_flags & SPM_PART_FLAG_APP_ROT)) ? + (TFM_BUFFER_SHARE_NS_CODE) : (TFM_BUFFER_SHARE_SCRATCH); + break; + case TFM_BUFFER_SHARE_SCRATCH: + case TFM_BUFFER_SHARE_NS_CODE: + share = args[0]; + break; + default: + *res_ptr = TFM_ERROR_INVALID_PARAMETER; + return; + } + + if (tfm_spm_partition_set_share(running_partition_idx, share) == + SPM_ERR_OK) { + *res_ptr = TFM_SUCCESS; + } else { + *res_ptr = TFM_ERROR_INVALID_PARAMETER; + } + + return; +} + diff --git a/components/TARGET_PSA/TARGET_TFM/COMPONENT_SPE/secure_fw/core/tfm_handler.c b/components/TARGET_PSA/TARGET_TFM/COMPONENT_SPE/secure_fw/core/tfm_handler.c index ef07a13ac7..10a91a56dd 100644 --- a/components/TARGET_PSA/TARGET_TFM/COMPONENT_SPE/secure_fw/core/tfm_handler.c +++ b/components/TARGET_PSA/TARGET_TFM/COMPONENT_SPE/secure_fw/core/tfm_handler.c @@ -156,6 +156,30 @@ uint32_t SVCHandler_main(uint32_t *svc_args, uint32_t lr) return lr; } switch (svc_number) { +#ifdef TFM_PSA_API + case TFM_SVC_IPC_REQUEST: + tfm_psa_ipc_request_handler(svc_args); + break; + case TFM_SVC_SCHEDULE: + case TFM_SVC_EXIT_THRD: + case TFM_SVC_PSA_FRAMEWORK_VERSION: + case TFM_SVC_PSA_VERSION: + case TFM_SVC_PSA_CONNECT: + case TFM_SVC_PSA_CALL: + case TFM_SVC_PSA_CLOSE: + case TFM_SVC_PSA_WAIT: + case TFM_SVC_PSA_GET: + case TFM_SVC_PSA_SET_RHANDLE: + case TFM_SVC_PSA_READ: + case TFM_SVC_PSA_SKIP: + case TFM_SVC_PSA_WRITE: + case TFM_SVC_PSA_REPLY: + case TFM_SVC_PSA_NOTIFY: + case TFM_SVC_PSA_CLEAR: + case TFM_SVC_PSA_EOI: + svc_args[0] = SVC_Handler_IPC(svc_number, svc_args, lr); + break; +#else case TFM_SVC_SFN_REQUEST: lr = tfm_core_partition_request_svc_handler(svc_args, lr); break; @@ -177,10 +201,6 @@ uint32_t SVCHandler_main(uint32_t *svc_args, uint32_t lr) case TFM_SVC_SET_SHARE_AREA: tfm_core_set_buffer_area_handler(svc_args); break; -#ifdef TFM_PSA_API - case TFM_SVC_IPC_REQUEST: - tfm_psa_ipc_request_handler(svc_args); - break; #endif case TFM_SVC_PRINT: printf("\e[1;34m[Sec Thread] %s\e[0m\r\n", (char *)svc_args[0]); @@ -188,25 +208,6 @@ uint32_t SVCHandler_main(uint32_t *svc_args, uint32_t lr) case TFM_SVC_GET_BOOT_DATA: tfm_core_get_boot_data_handler(svc_args); break; -#ifdef TFM_PSA_API - case TFM_SVC_PSA_FRAMEWORK_VERSION: - case TFM_SVC_PSA_VERSION: - case TFM_SVC_PSA_CONNECT: - case TFM_SVC_PSA_CALL: - case TFM_SVC_PSA_CLOSE: - case TFM_SVC_PSA_WAIT: - case TFM_SVC_PSA_GET: - case TFM_SVC_PSA_SET_RHANDLE: - case TFM_SVC_PSA_READ: - case TFM_SVC_PSA_SKIP: - case TFM_SVC_PSA_WRITE: - case TFM_SVC_PSA_REPLY: - case TFM_SVC_PSA_NOTIFY: - case TFM_SVC_PSA_CLEAR: - case TFM_SVC_PSA_EOI: - svc_args[0] = SVC_Handler_IPC(svc_number, svc_args, lr); - break; -#endif default: LOG_MSG("Unknown SVC number requested!"); break; diff --git a/components/TARGET_PSA/TARGET_TFM/COMPONENT_SPE/secure_fw/core/tfm_nspm.c b/components/TARGET_PSA/TARGET_TFM/COMPONENT_SPE/secure_fw/core/tfm_nspm.c index 3188e2831d..3db30c2bc0 100644 --- a/components/TARGET_PSA/TARGET_TFM/COMPONENT_SPE/secure_fw/core/tfm_nspm.c +++ b/components/TARGET_PSA/TARGET_TFM/COMPONENT_SPE/secure_fw/core/tfm_nspm.c @@ -6,8 +6,13 @@ */ #include +#include #include "secure_utilities.h" #include "tfm_api.h" +#if TFM_PSA_API +#include "tfm_utils.h" +#include "tfm_internal.h" +#endif #ifndef TFM_MAX_NS_THREAD_COUNT #define TFM_MAX_NS_THREAD_COUNT 8 @@ -300,3 +305,20 @@ enum tfm_status_e tfm_register_client_id (int32_t ns_client_id) return TFM_SUCCESS; } #endif + +#ifdef TFM_PSA_API +__attribute__((section("SFN"))) +psa_status_t tfm_nspm_thread_entry(void) +{ +#ifdef TFM_CORE_DEBUG + /* Jumps to non-secure code */ + LOG_MSG("Jumping to non-secure code..."); +#endif + + jump_to_ns_code(); + + /* Should not run here */ + TFM_ASSERT(false); + return PSA_SUCCESS; +} +#endif diff --git a/components/TARGET_PSA/TARGET_TFM/COMPONENT_SPE/secure_fw/core/tfm_nspm.h b/components/TARGET_PSA/TARGET_TFM/COMPONENT_SPE/secure_fw/core/tfm_nspm.h index b485462519..572c734c0f 100644 --- a/components/TARGET_PSA/TARGET_TFM/COMPONENT_SPE/secure_fw/core/tfm_nspm.h +++ b/components/TARGET_PSA/TARGET_TFM/COMPONENT_SPE/secure_fw/core/tfm_nspm.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, Arm Limited. All rights reserved. + * Copyright (c) 2018-2019, Arm Limited. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause * @@ -23,4 +23,15 @@ void tfm_nspm_configure_clients(void); */ int32_t tfm_nspm_get_current_client_id(void); +#ifdef TFM_PSA_API +/** + * \brief NSPM thread main entry function + * + * \return PSA_SUCCESS indicates failed. + * + * Note: This function should not return back. + */ +psa_status_t tfm_nspm_thread_entry(void); +#endif + #endif /* __TFM_NSPM_H__ */ diff --git a/components/TARGET_PSA/TARGET_TFM/COMPONENT_SPE/secure_fw/core/tfm_secure_api.c b/components/TARGET_PSA/TARGET_TFM/COMPONENT_SPE/secure_fw/core/tfm_secure_api.c index affabbdd13..ca0e51c485 100644 --- a/components/TARGET_PSA/TARGET_TFM/COMPONENT_SPE/secure_fw/core/tfm_secure_api.c +++ b/components/TARGET_PSA/TARGET_TFM/COMPONENT_SPE/secure_fw/core/tfm_secure_api.c @@ -12,6 +12,7 @@ #include "tfm_secure_api.h" #include "tfm_nspm.h" #include "secure_utilities.h" +#include "uart_stdout.h" #include "secure_fw/spm/spm_api.h" #include "region_defs.h" #include "tfm_api.h" @@ -27,89 +28,15 @@ #define REGION_NAME(a, b, c) REGION(a, b, c) #define REGION_DECLARE(a, b, c) extern uint32_t REGION_NAME(a, b, c) +#ifndef TFM_PSA_API /* Only use scratch if using veneer functions, not IPC */ REGION_DECLARE(Image$$, TFM_UNPRIV_SCRATCH, $$ZI$$Base); REGION_DECLARE(Image$$, TFM_UNPRIV_SCRATCH, $$ZI$$Limit); - -#if TFM_LVL == 1 -REGION_DECLARE(Image$$, TFM_SECURE_STACK, $$ZI$$Base); -REGION_DECLARE(Image$$, TFM_SECURE_STACK, $$ZI$$Limit); -#endif +#endif /* !defined(TFM_PSA_API) */ /* This is the "Big Lock" on the secure side, to guarantee single entry * to SPE */ int32_t tfm_secure_lock; -static int32_t tfm_secure_api_initializing = 1; - -static int32_t is_iovec_api_call(void) -{ - uint32_t current_partition_idx = - tfm_spm_partition_get_running_partition_idx(); - const struct spm_partition_runtime_data_t *curr_part_data = - tfm_spm_partition_get_runtime_data(current_partition_idx); - return curr_part_data->iovec_api; -} - -static uint32_t *prepare_partition_ctx( - const struct tfm_exc_stack_t *svc_ctx, - const struct tfm_sfn_req_s *desc_ptr, - uint32_t *dst) -{ - /* XPSR = as was when called, but make sure it's thread mode */ - *(--dst) = svc_ctx->XPSR & 0xFFFFFE00U; - /* ReturnAddress = resume veneer in new context */ - *(--dst) = svc_ctx->RetAddr; - /* LR = sfn address */ - *(--dst) = (uint32_t)desc_ptr->sfn; - /* R12 = don't care */ - *(--dst) = 0; - - /* R0-R3 = sfn arguments */ - int32_t i = 4; - - while (i > 0) { - i--; - *(--dst) = (uint32_t)desc_ptr->args[i]; - } - return dst; -} - -static uint32_t *prepare_partition_iovec_ctx( - const struct tfm_exc_stack_t *svc_ctx, - const struct tfm_sfn_req_s *desc_ptr, - const struct iovec_args_t *iovec_args, - uint32_t *dst) -{ - /* XPSR = as was when called, but make sure it's thread mode */ - *(--dst) = svc_ctx->XPSR & 0xFFFFFE00U; - /* ReturnAddress = resume veneer in new context */ - *(--dst) = svc_ctx->RetAddr; - /* LR = sfn address */ - *(--dst) = (uint32_t)desc_ptr->sfn; - /* R12 = don't care */ - *(--dst) = 0U; - - /* R0-R3 = sfn arguments */ - *(--dst) = iovec_args->out_len; - *(--dst) = (uint32_t)iovec_args->out_vec; - *(--dst) = iovec_args->in_len; - *(--dst) = (uint32_t)iovec_args->in_vec; - - return dst; -} - -static void restore_caller_ctx( - const struct tfm_exc_stack_t *svc_ctx, - struct tfm_exc_stack_t *target_ctx) -{ - /* ReturnAddress = resume veneer after second SVC */ - target_ctx->RetAddr = svc_ctx->RetAddr; - - /* R0 = function return value */ - target_ctx->R0 = svc_ctx->R0; - - return; -} /** * \brief Check whether a memory range is inside a memory region. @@ -121,16 +48,17 @@ static void restore_caller_ctx( * \param[in] region_len The size of the region, which should contain the * range * - * \return 1 if the region contains the range, 0 otherwise. + * \return TFM_SUCCESS if the region contains the range, + * TFM_ERROR_GENERIC otherwise. */ static int32_t check_address_range(const void *p, size_t s, uintptr_t region_start, uint32_t region_len) { - int32_t range_in_region = 0; + int32_t range_in_region; /* Check for overflow in the range parameters */ if ((uintptr_t)p > UINTPTR_MAX-s) { - return 0; + return TFM_ERROR_GENERIC; } /* We trust the region parameters, and don't check for overflow */ @@ -138,8 +66,11 @@ static int32_t check_address_range(const void *p, size_t s, /* Calculate the result */ range_in_region = ((uintptr_t)p >= region_start) && ((uintptr_t)p+s <= region_start+region_len); - - return range_in_region; + if (range_in_region) { + return TFM_SUCCESS; + } else { + return TFM_ERROR_GENERIC; + } } /** @@ -155,47 +86,62 @@ static int32_t check_address_range(const void *p, size_t s, * \param[in] s The size of the range to check * \param[in] flags The flags to pass to the cmse_check_address_range func * - * \return 1 if the partition has access to the memory range, 0 otherwise. + * \return TFM_SUCCESS if the partition has access to the memory range, + * TFM_ERROR_GENERIC otherwise. */ static int32_t has_access_to_region(const void *p, size_t s, int flags) { int32_t range_access_allowed_by_mpu; +#ifndef TFM_PSA_API /* Only use scratch if using veneer functions, not IPC */ uint32_t scratch_base = (uint32_t)®ION_NAME(Image$$, TFM_UNPRIV_SCRATCH, $$ZI$$Base); uint32_t scratch_limit = (uint32_t)®ION_NAME(Image$$, TFM_UNPRIV_SCRATCH, $$ZI$$Limit); +#endif /* !defined(TFM_PSA_API) */ /* Use the TT instruction to check access to the partition's regions*/ range_access_allowed_by_mpu = cmse_check_address_range((void *)p, s, flags) != NULL; if (range_access_allowed_by_mpu) { - return 1; + return TFM_SUCCESS; } +#ifndef TFM_PSA_API /* Only use scratch if using veneer functions, not IPC */ /* If the check for the current MPU settings fails, check for the share * region, only if the partition is secure */ if ((flags & CMSE_NONSECURE) == 0) { if (check_address_range(p, s, scratch_base, - scratch_limit+1-scratch_base)) { - return 1; + scratch_limit+1-scratch_base) == TFM_SUCCESS) { + return TFM_SUCCESS; } } +#endif /* !defined(TFM_PSA_API) */ /* If all else fails, check whether the region is in the non-secure * memory */ - return - check_address_range(p, s, NS_CODE_START, NS_CODE_LIMIT+1-NS_CODE_START) || - check_address_range(p, s, NS_DATA_START, NS_DATA_LIMIT+1-NS_DATA_START); + if (check_address_range(p, s, NS_CODE_START, + NS_CODE_LIMIT+1-NS_CODE_START) == TFM_SUCCESS || + check_address_range(p, s, NS_DATA_START, + NS_DATA_LIMIT+1-NS_DATA_START) == TFM_SUCCESS) { + return TFM_SUCCESS; + } else { + return TFM_ERROR_GENERIC; + } } int32_t tfm_core_has_read_access_to_region(const void *p, size_t s, - uint32_t ns_caller) + uint32_t ns_caller, + uint32_t privileged) { - int flags = CMSE_MPU_UNPRIV|CMSE_MPU_READ; + int flags = CMSE_MPU_READ; + + if (privileged == TFM_PARTITION_UNPRIVILEGED_MODE) { + flags |= CMSE_MPU_UNPRIV; + } if (ns_caller) { flags |= CMSE_NONSECURE; @@ -205,9 +151,14 @@ int32_t tfm_core_has_read_access_to_region(const void *p, size_t s, } int32_t tfm_core_has_write_access_to_region(void *p, size_t s, - uint32_t ns_caller) + uint32_t ns_caller, + uint32_t privileged) { - int flags = CMSE_MPU_UNPRIV|CMSE_MPU_READWRITE; + int flags = CMSE_MPU_READWRITE; + + if (privileged == TFM_PARTITION_UNPRIVILEGED_MODE) { + flags |= CMSE_MPU_UNPRIV; + } if (ns_caller) { flags |= CMSE_NONSECURE; @@ -216,453 +167,6 @@ int32_t tfm_core_has_write_access_to_region(void *p, size_t s, return has_access_to_region(p, s, flags); } -/** \brief Check whether the iovec parameters are valid, and the memory ranges - * are in the posession of the calling partition - * - * \param[in] desc_ptr The secure function request descriptor - * - * \return Return /ref TFM_SUCCESS if the iovec parameters are valid, error code - * otherwise as in /ref tfm_status_e - */ -static int32_t tfm_core_check_sfn_parameters( - const struct tfm_sfn_req_s *desc_ptr) -{ - struct psa_invec *in_vec = (psa_invec *)desc_ptr->args[0]; - size_t in_len; - struct psa_outvec *out_vec = (psa_outvec *)desc_ptr->args[2]; - size_t out_len; - - uint32_t i; - - if ((desc_ptr->args[1] < 0) || (desc_ptr->args[3] < 0)) { - return TFM_ERROR_INVALID_PARAMETER; - } - - in_len = (size_t)(desc_ptr->args[1]); - out_len = (size_t)(desc_ptr->args[3]); - - /* The number of vectors are within range. Extra checks to avoid overflow */ - if ((in_len > PSA_MAX_IOVEC) || (out_len > PSA_MAX_IOVEC) || - (in_len + out_len > PSA_MAX_IOVEC)) { - return TFM_ERROR_INVALID_PARAMETER; - } - - /* Check whether the caller partition has at write access to the iovec - * structures themselves. Use the TT instruction for this. - */ - if (in_len > 0) { - if ((in_vec == NULL) || - (tfm_core_has_write_access_to_region(in_vec, - sizeof(psa_invec)*in_len, - desc_ptr->ns_caller) != 1)) { - return TFM_ERROR_INVALID_PARAMETER; - } - } else { - if (in_vec != NULL) { - return TFM_ERROR_INVALID_PARAMETER; - } - } - if (out_len > 0) { - if ((out_vec == NULL) || - (tfm_core_has_write_access_to_region(out_vec, - sizeof(psa_outvec)*out_len, - desc_ptr->ns_caller) != 1)) { - return TFM_ERROR_INVALID_PARAMETER; - } - } else { - if (out_vec != NULL) { - return TFM_ERROR_INVALID_PARAMETER; - } - } - - /* Check whether the caller partition has access to the data inside the - * iovecs - */ - for (i = 0; i < in_len; ++i) { - if (in_vec[i].len > 0) { - if ((in_vec[i].base == NULL) || - (tfm_core_has_read_access_to_region(in_vec[i].base, - in_vec[i].len, - desc_ptr->ns_caller) != 1)) { - return TFM_ERROR_INVALID_PARAMETER; - } - } - } - for (i = 0; i < out_len; ++i) { - if (out_vec[i].len > 0) { - if ((out_vec[i].base == NULL) || - (tfm_core_has_write_access_to_region(out_vec[i].base, - out_vec[i].len, - desc_ptr->ns_caller) != 1)) { - return TFM_ERROR_INVALID_PARAMETER; - } - } - } - - return TFM_SUCCESS; -} - -static void tfm_copy_iovec_parameters(struct iovec_args_t *target, - const struct iovec_args_t *source) -{ - size_t i; - - target->in_len = source->in_len; - for (i = 0; i < source->in_len; ++i) { - target->in_vec[i].base = source->in_vec[i].base; - target->in_vec[i].len = source->in_vec[i].len; - } - target->out_len = source->out_len; - for (i = 0; i < source->out_len; ++i) { - target->out_vec[i].base = source->out_vec[i].base; - target->out_vec[i].len = source->out_vec[i].len; - } -} - -static void tfm_clear_iovec_parameters(struct iovec_args_t *args) -{ - int i; - - args->in_len = 0; - for (i = 0; i < PSA_MAX_IOVEC; ++i) { - args->in_vec[i].base = NULL; - args->in_vec[i].len = 0; - } - args->out_len = 0; - for (i = 0; i < PSA_MAX_IOVEC; ++i) { - args->out_vec[i].base = NULL; - args->out_vec[i].len = 0; - } -} - -static int32_t tfm_start_partition(const struct tfm_sfn_req_s *desc_ptr, - uint32_t excReturn) -{ - uint32_t caller_partition_idx = desc_ptr->caller_part_idx; - const struct spm_partition_runtime_data_t *curr_part_data; - uint32_t caller_flags; - register uint32_t partition_idx; - uint32_t psp = __get_PSP(); - uint32_t partition_psp, partition_psplim; - uint32_t partition_state; - uint32_t partition_flags; - struct tfm_exc_stack_t *svc_ctx = (struct tfm_exc_stack_t *)psp; - uint32_t caller_partition_id; - int32_t client_id; - struct iovec_args_t *iovec_args; - - caller_flags = tfm_spm_partition_get_flags(caller_partition_idx); - - /* Check partition state consistency */ - if (((caller_flags & SPM_PART_FLAG_APP_ROT) != 0) - != (!desc_ptr->ns_caller)) { - /* Partition state inconsistency detected */ - return TFM_SECURE_LOCK_FAILED; - } - - if((caller_flags & SPM_PART_FLAG_APP_ROT) == 0) { - /* Disable NS exception handling while secure service is running. - * FixMe: - * This restriction is applied to limit the number of possible attack - * vectors. - * To be removed when pre-emption and context management issues have - * been analysed and resolved. - */ - TFM_NS_EXC_DISABLE(); - } - - partition_idx = get_partition_idx(desc_ptr->sp_id); - - curr_part_data = tfm_spm_partition_get_runtime_data(partition_idx); - partition_state = curr_part_data->partition_state; - partition_flags = tfm_spm_partition_get_flags(partition_idx); - caller_partition_id = tfm_spm_partition_get_partition_id( - caller_partition_idx); - - if (tfm_secure_api_initializing) { -#if TFM_LVL != 1 - /* Make thread mode unprivileged while untrusted partition init is - * executed - */ - if ((partition_flags & SPM_PART_FLAG_PSA_ROT) == 0) { - CONTROL_Type ctrl; - - ctrl.w = __get_CONTROL(); - ctrl.b.nPRIV = 1; - __set_CONTROL(ctrl.w); - __DSB(); - __ISB(); - } -#endif - } else if (partition_state == SPM_PARTITION_STATE_RUNNING || - partition_state == SPM_PARTITION_STATE_SUSPENDED || - partition_state == SPM_PARTITION_STATE_BLOCKED) { - /* Recursion is not permitted! */ - return TFM_ERROR_PARTITION_NON_REENTRANT; - } else if (partition_state != SPM_PARTITION_STATE_IDLE) { - /* The partition to be called is not in a proper state */ - return TFM_SECURE_LOCK_FAILED; - } - -#if TFM_LVL == 1 - /* Prepare switch to shared secure partition stack */ - /* In case the call is coming from the non-secure world, we save the iovecs - * on the stop of the stack. So the memory area, that can actually be used - * as stack by the partitions starts at a lower address - */ - partition_psp = - (uint32_t)®ION_NAME(Image$$, TFM_SECURE_STACK, $$ZI$$Limit)- - sizeof(struct iovec_args_t); - partition_psplim = - (uint32_t)®ION_NAME(Image$$, TFM_SECURE_STACK, $$ZI$$Base); -#else - partition_psp = curr_part_data->stack_ptr; - partition_psplim = tfm_spm_partition_get_stack_bottom(partition_idx); -#endif - /* Store the context for the partition call */ - tfm_spm_partition_set_caller_partition_idx(partition_idx, - caller_partition_idx); - tfm_spm_partition_store_context(caller_partition_idx, psp, excReturn); - - if ((caller_flags & SPM_PART_FLAG_APP_ROT)) { - tfm_spm_partition_set_caller_client_id(partition_idx, - caller_partition_id); - } else { - client_id = tfm_nspm_get_current_client_id(); - if (client_id >= 0) - { - return TFM_SECURE_LOCK_FAILED; - } - tfm_spm_partition_set_caller_client_id(partition_idx, client_id); - } - -#if (TFM_LVL != 1) && (TFM_LVL != 2) - /* Dynamic partitioning is only done is TFM level 3 */ - tfm_spm_partition_sandbox_deconfig(caller_partition_idx); - - /* Configure partition execution environment */ - if (tfm_spm_partition_sandbox_config(partition_idx) != SPM_ERR_OK) { - ERROR_MSG("Failed to configure sandbox for partition!"); - tfm_secure_api_error_handler(); - } -#endif - - /* Default share to scratch area in case of partition to partition calls - * this way partitions always get default access to input buffers - */ - /* FixMe: return value/error handling TBD */ - tfm_spm_partition_set_share(partition_idx, desc_ptr->ns_caller ? - TFM_BUFFER_SHARE_NS_CODE : TFM_BUFFER_SHARE_SCRATCH); - -#if TFM_LVL == 1 - /* In level one, only switch context and return from exception if in - * handler mode - */ - if ((desc_ptr->ns_caller) || (tfm_secure_api_initializing)) { - if (desc_ptr->iovec_api == TFM_SFN_API_IOVEC) { - /* Save the iovecs on the common stack. The vectors had been sanity - * checked already, and since then the interrupts have been kept - * disabled. So we can be sure that the vectors haven't been - * tampered with since the check. - */ - iovec_args = (struct iovec_args_t *) - ((uint32_t)®ION_NAME(Image$$, TFM_SECURE_STACK, $$ZI$$Limit)- - sizeof(struct iovec_args_t)); - if (tfm_spm_partition_set_iovec(partition_idx, desc_ptr->args) != - SPM_ERR_OK) { - return TFM_ERROR_GENERIC; - } - tfm_copy_iovec_parameters(iovec_args, - &(curr_part_data->iovec_args)); - - /* Prepare the partition context, update stack ptr */ - psp = (uint32_t)prepare_partition_iovec_ctx(svc_ctx, desc_ptr, - iovec_args, - (uint32_t *)partition_psp); - } else { - /* Prepare the partition context, update stack ptr */ - psp = (uint32_t)prepare_partition_ctx(svc_ctx, desc_ptr, - (uint32_t *)partition_psp); - } - __set_PSP(psp); - __set_PSPLIM(partition_psplim); - } -#else - if (desc_ptr->iovec_api == TFM_SFN_API_IOVEC) { - /* Save the iovecs on the stack of the partition. The vectors had been - * sanity checked already, and since then the interrupts have been kept - * disabled. So we can be sure that the vectors haven't been tampered - * with since the check. - */ - iovec_args = - (struct iovec_args_t *)(tfm_spm_partition_get_stack_top(partition_idx) - - sizeof(struct iovec_args_t)); - if (tfm_spm_partition_set_iovec(partition_idx, desc_ptr->args) != - SPM_ERR_OK) { - return TFM_ERROR_GENERIC; - } - tfm_copy_iovec_parameters(iovec_args, &(curr_part_data->iovec_args)); - - /* Prepare the partition context, update stack ptr */ - psp = (uint32_t)prepare_partition_iovec_ctx(svc_ctx, desc_ptr, - iovec_args, - (uint32_t *)partition_psp); - } else { - /* Prepare the partition context, update stack ptr */ - psp = (uint32_t)prepare_partition_ctx(svc_ctx, desc_ptr, - (uint32_t *)partition_psp); - } - __set_PSP(psp); - __set_PSPLIM(partition_psplim); -#endif - - tfm_spm_partition_set_state(caller_partition_idx, - SPM_PARTITION_STATE_BLOCKED); - tfm_spm_partition_set_state(partition_idx, SPM_PARTITION_STATE_RUNNING); - tfm_secure_lock++; - - return TFM_SUCCESS; -} - -static int32_t tfm_return_from_partition(uint32_t *excReturn) -{ - uint32_t current_partition_idx = - tfm_spm_partition_get_running_partition_idx(); - const struct spm_partition_runtime_data_t *curr_part_data, *ret_part_data; - uint32_t current_partition_flags; - uint32_t return_partition_idx; - uint32_t return_partition_flags; - uint32_t psp = __get_PSP(); - size_t i; - struct tfm_exc_stack_t *svc_ctx = (struct tfm_exc_stack_t *)psp; - struct iovec_args_t *iovec_args; - - if (current_partition_idx == SPM_INVALID_PARTITION_IDX) { - return TFM_SECURE_UNLOCK_FAILED; - } - - curr_part_data = tfm_spm_partition_get_runtime_data(current_partition_idx); - return_partition_idx = curr_part_data->caller_partition_idx; - - if (return_partition_idx == SPM_INVALID_PARTITION_IDX) { - return TFM_SECURE_UNLOCK_FAILED; - } - - ret_part_data = tfm_spm_partition_get_runtime_data(return_partition_idx); - - return_partition_flags = tfm_spm_partition_get_flags(return_partition_idx); - current_partition_flags = tfm_spm_partition_get_flags( - current_partition_idx); - - tfm_secure_lock--; - - if((return_partition_flags & SPM_PART_FLAG_APP_ROT) == 0) { - /* Re-enable NS exceptions when secure service returns to NS client. - * FixMe: - * To be removed when pre-emption and context management issues have - * been analysed and resolved. - */ - TFM_NS_EXC_ENABLE(); - } - -#if (TFM_LVL != 1) && (TFM_LVL != 2) - /* Deconfigure completed partition environment */ - tfm_spm_partition_sandbox_deconfig(current_partition_idx); - if (tfm_secure_api_initializing) { - /* Restore privilege for thread mode during TF-M init. This is only - * have to be done if the partition is not trusted. - */ - if ((current_partition_flags & SPM_PART_FLAG_PSA_ROT) == 0) { - CONTROL_Type ctrl; - - ctrl.w = __get_CONTROL(); - ctrl.b.nPRIV = 0; - __set_CONTROL(ctrl.w); - __DSB(); - __ISB(); - } - } else { - /* Configure the caller partition environment in case this was a - * partition to partition call and returning to untrusted partition - */ - if (tfm_spm_partition_sandbox_config(return_partition_idx) - != SPM_ERR_OK) { - ERROR_MSG("Failed to configure sandbox for partition!"); - tfm_secure_api_error_handler(); - } - if (return_partition_flags & SPM_PART_FLAG_APP_ROT) { - /* Restore share status */ - tfm_spm_partition_set_share( - return_partition_idx, - tfm_spm_partition_get_runtime_data( - return_partition_idx)->share); - } - } -#endif - -#if TFM_LVL == 1 - if (!(return_partition_flags & SPM_PART_FLAG_APP_ROT) || - (tfm_secure_api_initializing)) { - /* In TFM level 1 context restore is only done when - * returning to NS or after initialization - */ - /* Restore caller context */ - restore_caller_ctx(svc_ctx, - (struct tfm_exc_stack_t *)ret_part_data->stack_ptr); - *excReturn = ret_part_data->lr; - __set_PSP(ret_part_data->stack_ptr); - extern uint32_t Image$$ARM_LIB_STACK$$ZI$$Base[]; - uint32_t psp_stack_bottom = (uint32_t)Image$$ARM_LIB_STACK$$ZI$$Base; - __set_PSPLIM(psp_stack_bottom); - - /* FIXME: The condition should be removed once all the secure service - * calls are done via the iovec veneers */ - if (curr_part_data->iovec_api) { - iovec_args = (struct iovec_args_t *) - ((uint32_t)®ION_NAME(Image$$, TFM_SECURE_STACK, $$ZI$$Limit)- - sizeof(struct iovec_args_t)); - - for (i = 0; i < curr_part_data->iovec_args.out_len; ++i) { - curr_part_data->orig_outvec[i].len = iovec_args->out_vec[i].len; - } - tfm_clear_iovec_parameters(iovec_args); - } - } -#else - /* Restore caller context */ - restore_caller_ctx(svc_ctx, - (struct tfm_exc_stack_t *)ret_part_data->stack_ptr); - *excReturn = ret_part_data->lr; - __set_PSP(ret_part_data->stack_ptr); - __set_PSPLIM(tfm_spm_partition_get_stack_bottom(return_partition_idx)); - /* Clear the context entry before returning */ - tfm_spm_partition_set_stack( - current_partition_idx, psp + sizeof(struct tfm_exc_stack_t)); - - /* FIXME: The condition should be removed once all the secure service - * calls are done via the iovec veneers */ - if (curr_part_data->iovec_api) { - iovec_args = (struct iovec_args_t *) - (tfm_spm_partition_get_stack_top(current_partition_idx) - - sizeof(struct iovec_args_t)); - - for (i = 0; i < curr_part_data->iovec_args.out_len; ++i) { - curr_part_data->orig_outvec[i].len = iovec_args->out_vec[i].len; - } - tfm_clear_iovec_parameters(iovec_args); - } -#endif - - tfm_spm_partition_cleanup_context(current_partition_idx); - - tfm_spm_partition_set_state(current_partition_idx, - SPM_PARTITION_STATE_IDLE); - tfm_spm_partition_set_state(return_partition_idx, - SPM_PARTITION_STATE_RUNNING); - - return TFM_SUCCESS; -} - void tfm_secure_api_error_handler(void) { ERROR_MSG("Security violation when calling secure API"); @@ -671,487 +175,3 @@ void tfm_secure_api_error_handler(void) } } -static int32_t tfm_check_sfn_req_integrity(const struct tfm_sfn_req_s *desc_ptr) -{ - if ((desc_ptr == NULL) || - (desc_ptr->sp_id == 0) || - (desc_ptr->sfn == NULL)) { - /* invalid parameter */ - return TFM_ERROR_INVALID_PARAMETER; - } - return TFM_SUCCESS; -} - -static int32_t tfm_core_check_sfn_req_rules( - const struct tfm_sfn_req_s *desc_ptr) -{ - /* Check partition idx validity */ - if (desc_ptr->caller_part_idx == SPM_INVALID_PARTITION_IDX) { - return TFM_ERROR_NO_ACTIVE_PARTITION; - } - - if ((desc_ptr->ns_caller) && (tfm_secure_lock != 0)) { - /* Secure domain is already locked! - * This should only happen if caller is secure partition! - * FixMe: This scenario is a potential security breach - * Take appropriate action! - */ - return TFM_ERROR_SECURE_DOMAIN_LOCKED; - } - - if (tfm_secure_api_initializing) { - int32_t id = - tfm_spm_partition_get_partition_id(desc_ptr->caller_part_idx); - - if ((id != TFM_SP_CORE_ID) || (tfm_secure_lock != 0)) { - /* Invalid request during system initialization */ - ERROR_MSG("Invalid service request during initialization!"); - return TFM_ERROR_NOT_INITIALIZED; - } - } - - return TFM_SUCCESS; -} - -void tfm_secure_api_init_done(void) -{ - tfm_secure_api_initializing = 0; -#if TFM_LVL != 1 - if (tfm_spm_partition_sandbox_config(TFM_SP_NON_SECURE_ID) != SPM_ERR_OK) { - ERROR_MSG("Failed to configure sandbox for partition!"); - tfm_secure_api_error_handler(); - } -#endif -} - -int32_t tfm_core_sfn_request_handler( - struct tfm_sfn_req_s *desc_ptr, uint32_t excReturn) -{ - int32_t res; - - res = tfm_check_sfn_req_integrity(desc_ptr); - if (res != TFM_SUCCESS) { - ERROR_MSG("Invalid service request!"); - tfm_secure_api_error_handler(); - } - - __disable_irq(); - - desc_ptr->caller_part_idx = tfm_spm_partition_get_running_partition_idx(); - - if (desc_ptr->iovec_api == TFM_SFN_API_IOVEC) { - res = tfm_core_check_sfn_parameters(desc_ptr); - if (res != TFM_SUCCESS) { - /* The sanity check of iovecs failed. */ - __enable_irq(); - tfm_secure_api_error_handler(); - } - } - - res = tfm_core_check_sfn_req_rules(desc_ptr); - if (res != TFM_SUCCESS) { - /* FixMe: error compartmentalization TBD */ - tfm_spm_partition_set_state( - desc_ptr->caller_part_idx, SPM_PARTITION_STATE_CLOSED); - __enable_irq(); - ERROR_MSG("Unauthorized service request!"); - tfm_secure_api_error_handler(); - } - - res = tfm_start_partition(desc_ptr, excReturn); - if (res != TFM_SUCCESS) { - /* FixMe: consider possible fault scenarios */ - __enable_irq(); - ERROR_MSG("Failed to process service request!"); - tfm_secure_api_error_handler(); - } - - __enable_irq(); - - return res; -} - -#if TFM_LVL == 1 -int32_t tfm_core_sfn_request_thread_mode(struct tfm_sfn_req_s *desc_ptr) -{ - int32_t res; - int32_t *args; - int32_t retVal; - - if (desc_ptr->iovec_api == TFM_SFN_API_IOVEC) { - res = tfm_core_check_sfn_parameters(desc_ptr); - if (res != TFM_SUCCESS) { - /* The sanity check of iovecs failed. */ - return res; - } - } - - /* No excReturn value is needed as no exception handling is used */ - res = tfm_core_sfn_request_handler(desc_ptr, 0); - - if (res != TFM_SUCCESS) { - tfm_secure_api_error_handler(); - } - - /* Secure partition to secure partition call in TFM level 1 */ - args = desc_ptr->args; - retVal = desc_ptr->sfn(args[0], args[1], args[2], args[3]); - - /* return handler should restore original exc_return value... */ - res = tfm_return_from_partition(NULL); - if (res == TFM_SUCCESS) { - /* If unlock successful, pass SS return value to caller */ - res = retVal; - } else { - /* Unlock errors indicate ctx database corruption or unknown - * anomalies. Halt execution - */ - ERROR_MSG("Secure API error during unlock!"); - tfm_secure_api_error_handler(); - } - return res; -} -#endif - -void tfm_core_validate_secure_caller_handler(uint32_t *svc_args) -{ - - int32_t res = TFM_ERROR_GENERIC; - uint32_t running_partition_idx = - tfm_spm_partition_get_running_partition_idx(); - const struct spm_partition_runtime_data_t *curr_part_data = - tfm_spm_partition_get_runtime_data(running_partition_idx); - uint32_t running_partition_flags = - tfm_spm_partition_get_flags(running_partition_idx); - uint32_t caller_partition_flags = - tfm_spm_partition_get_flags(curr_part_data->caller_partition_idx); - - if (!(running_partition_flags & SPM_PART_FLAG_APP_ROT)) { - /* This handler shouldn't be called from outside partition context. - * Partitions are only allowed to run while S domain is locked. - */ - svc_args[0] = TFM_ERROR_INVALID_PARAMETER; - return; - } - - /* Store return value in r0 */ - if (caller_partition_flags & SPM_PART_FLAG_APP_ROT) { - res = TFM_SUCCESS; - } - svc_args[0] = res; -} - -int32_t tfm_core_check_buffer_access(uint32_t partition_idx, - void *start_addr, - size_t len, - uint32_t alignment) -{ - uintptr_t start_addr_value = (uintptr_t)start_addr; - uintptr_t end_addr_value = (uintptr_t)start_addr + len; - uintptr_t alignment_mask; - - alignment_mask = (((uintptr_t)1) << alignment) - 1; - - /* Check that the pointer is aligned properly */ - if (start_addr_value & alignment_mask) { - /* not aligned, return error */ - return 0; - } - - /* Protect against overflow (and zero len) */ - if (end_addr_value <= start_addr_value) - { - return 0; - } - -#if TFM_LVL == 1 - /* For privileged partition execution, all secure data memory and stack - * is accessible - */ - if (start_addr_value >= S_DATA_START && - end_addr_value <= (S_DATA_START + S_DATA_SIZE)) { - return 1; - } -#else - /* For non-privileged execution the partition's data and stack is - * accessible - */ - if (start_addr_value >= - tfm_spm_partition_get_stack_bottom(partition_idx) && - end_addr_value <= - tfm_spm_partition_get_stack_top(partition_idx)) { - return 1; - } - if (start_addr_value >= - tfm_spm_partition_get_rw_start(partition_idx) && - end_addr_value <= - tfm_spm_partition_get_rw_limit(partition_idx)) { - return 1; - } - if (start_addr_value >= - tfm_spm_partition_get_zi_start(partition_idx) && - end_addr_value <= - tfm_spm_partition_get_zi_limit(partition_idx)) { - return 1; - } -#endif - return 0; -} - -void tfm_core_get_caller_client_id_handler(uint32_t *svc_args) -{ - uintptr_t result_ptr_value = svc_args[0]; - uint32_t running_partition_idx = - tfm_spm_partition_get_running_partition_idx(); - const uint32_t running_partition_flags = - tfm_spm_partition_get_flags(running_partition_idx); - const struct spm_partition_runtime_data_t *curr_part_data = - tfm_spm_partition_get_runtime_data(running_partition_idx); - int res = 0; - - if (!(running_partition_flags & SPM_PART_FLAG_APP_ROT)) { - /* This handler shouldn't be called from outside partition context. - * Partitions are only allowed to run while S domain is locked. - */ - svc_args[0] = TFM_ERROR_INVALID_PARAMETER; - return; - } - - /* Make sure that the output pointer points to a memory area that is owned - * by the partition - */ - res = tfm_core_check_buffer_access(running_partition_idx, - (void *)result_ptr_value, - sizeof(curr_part_data->caller_client_id), - 2); - if (!res) { - /* Not in accessible range, return error */ - svc_args[0] = TFM_ERROR_INVALID_PARAMETER; - return; - } - - *((int32_t *)result_ptr_value) = curr_part_data->caller_client_id; - - /* Store return value in r0 */ - svc_args[0] = TFM_SUCCESS; -} - -void tfm_core_memory_permission_check_handler(uint32_t *svc_args) -{ - uint32_t ptr = svc_args[0]; - uint32_t size = svc_args[1]; - int32_t access = svc_args[2]; - - uint32_t max_buf_size, ptr_start, range_limit, range_check = false; - int32_t res; - uint32_t running_partition_idx = - tfm_spm_partition_get_running_partition_idx(); - const struct spm_partition_runtime_data_t *curr_part_data = - tfm_spm_partition_get_runtime_data(running_partition_idx); - uint32_t running_partition_flags = - tfm_spm_partition_get_flags(running_partition_idx); - int32_t flags = 0; - void *rangeptr; - - if (!(running_partition_flags & SPM_PART_FLAG_APP_ROT) || (size == 0)) { - /* This handler should only be called from a secure partition. */ - svc_args[0] = TFM_ERROR_INVALID_PARAMETER; - return; - } - - if (curr_part_data->share != TFM_BUFFER_SHARE_PRIV) { - flags |= CMSE_MPU_UNPRIV; - } - - if (access == TFM_MEMORY_ACCESS_RW) { - flags |= CMSE_MPU_READWRITE; - } else { - flags |= CMSE_MPU_READ; - } - - /* Check if partition access to address would fail */ - rangeptr = cmse_check_address_range((void *)ptr, size, flags); - - /* Get regions associated with address */ - cmse_address_info_t addr_info = cmse_TT((void *)ptr); - - if (rangeptr == NULL) { - svc_args[0] = TFM_ERROR_INVALID_PARAMETER; - return; - } - - if (addr_info.flags.secure) { -#if TFM_LVL == 1 - /* For privileged partition execution, all secure data memory is - * accessible - */ - max_buf_size = S_DATA_SIZE; - ptr_start = S_DATA_START; - range_limit = S_DATA_LIMIT; -#else - /* Only scratch is permitted in secure memory */ - max_buf_size = (uint32_t)tfm_scratch_area_size; - ptr_start = (uint32_t)tfm_scratch_area; - range_limit = (uint32_t)tfm_scratch_area + tfm_scratch_area_size - 1; -#endif - range_check = true; - } else { - if (!addr_info.flags.sau_region_valid) { - /* If address is NS, TF-M expects SAU to be configured - */ - svc_args[0] = TFM_ERROR_INVALID_PARAMETER; - return; - } - switch (addr_info.flags.sau_region) { - case TFM_NS_REGION_CODE: - if (access == TFM_MEMORY_ACCESS_RW) { - res = TFM_ERROR_INVALID_PARAMETER; - } else { - /* Currently TF-M does not support checks for NS Memory - * accesses by partitions - */ - res = TFM_SUCCESS; - } - break; - case TFM_NS_REGION_DATA: - /* Currently TF-M does not support checks for NS Memory - * accesses by partitions - */ - res = TFM_SUCCESS; - break; - default: - /* Only NS data and code regions can be accessed as buffers */ - res = TFM_ERROR_INVALID_PARAMETER; - break; - } - } - - if (range_check == true) { - if ((size <= max_buf_size) && (ptr >= ptr_start) - && (ptr <= range_limit + 1 - size)) { - res = TFM_SUCCESS; - } else { - res = TFM_ERROR_INVALID_PARAMETER; - } - } - - /* Store return value in r0 */ - svc_args[0] = res; -} - -/* This SVC handler is called if veneer is running in thread mode */ -uint32_t tfm_core_partition_request_svc_handler( - const struct tfm_exc_stack_t *svc_ctx, uint32_t excReturn) -{ - struct tfm_sfn_req_s *desc_ptr; - - if (!(excReturn & EXC_RETURN_STACK_PROCESS)) { - /* Service request SVC called with MSP active. - * Either invalid configuration for Thread mode or SVC called - * from Handler mode, which is not supported. - * FixMe: error severity TBD - */ - ERROR_MSG("Service request SVC called with MSP active!"); - tfm_secure_api_error_handler(); - } - - desc_ptr = (struct tfm_sfn_req_s *)svc_ctx->R0; - - if (tfm_core_sfn_request_handler(desc_ptr, excReturn) != TFM_SUCCESS) { - tfm_secure_api_error_handler(); - } - - return EXC_RETURN_SECURE_FUNCTION; -} - -/* This SVC handler is called when sfn returns */ -uint32_t tfm_core_partition_return_handler(uint32_t lr) -{ - int32_t res; - - if (!(lr & EXC_RETURN_STACK_PROCESS)) { - /* Partition return SVC called with MSP active. - * This should not happen! - */ - ERROR_MSG("Partition return SVC called with MSP active!"); - tfm_secure_api_error_handler(); - } - - /* Store return value from secure partition */ - int32_t retVal = *(int32_t *)__get_PSP(); - - if (!is_iovec_api_call()) { - if ((retVal > TFM_SUCCESS) && - (retVal < TFM_PARTITION_SPECIFIC_ERROR_MIN)) { - /* Secure function returned a reserved value */ -#ifdef TFM_CORE_DEBUG - LOG_MSG("Invalid return value from secure partition!"); -#endif - /* FixMe: error can be traced to specific secure partition - * and Core is not compromised. Error handling flow can be - * refined - */ - tfm_secure_api_error_handler(); - } - } - - res = tfm_return_from_partition(&lr); - if (res != TFM_SUCCESS) { - /* Unlock errors indicate ctx database corruption or unknown anomalies - * Halt execution - */ - ERROR_MSG("Secure API error during unlock!"); - tfm_secure_api_error_handler(); - } - - return lr; -} - -void tfm_core_set_buffer_area_handler(uint32_t *args) -{ - /* r0 is stored in args[0] in exception stack frame - * Store input parameter before writing return value to that address - */ - enum tfm_buffer_share_region_e share; - uint32_t running_partition_idx = - tfm_spm_partition_get_running_partition_idx(); - const struct spm_partition_runtime_data_t *curr_part_data = - tfm_spm_partition_get_runtime_data(running_partition_idx); - uint32_t caller_partition_idx = curr_part_data->caller_partition_idx; - uint32_t running_partition_flags = - tfm_spm_partition_get_flags(running_partition_idx); - uint32_t caller_partition_flags = - tfm_spm_partition_get_flags(caller_partition_idx); - - /* tfm_core_set_buffer_area() returns int32_t */ - int32_t *res_ptr = (int32_t *)&args[0]; - - if (!(running_partition_flags & SPM_PART_FLAG_APP_ROT)) { - /* This handler should only be called from a secure partition. */ - *res_ptr = TFM_ERROR_INVALID_PARAMETER; - return; - } - - switch (args[0]) { - case TFM_BUFFER_SHARE_DEFAULT: - share = (!(caller_partition_flags & SPM_PART_FLAG_APP_ROT)) ? - (TFM_BUFFER_SHARE_NS_CODE) : (TFM_BUFFER_SHARE_SCRATCH); - break; - case TFM_BUFFER_SHARE_SCRATCH: - case TFM_BUFFER_SHARE_NS_CODE: - share = args[0]; - break; - default: - *res_ptr = TFM_ERROR_INVALID_PARAMETER; - return; - } - - if (tfm_spm_partition_set_share(running_partition_idx, share) == - SPM_ERR_OK) { - *res_ptr = TFM_SUCCESS; - } else { - *res_ptr = TFM_ERROR_INVALID_PARAMETER; - } - - return; -} diff --git a/components/TARGET_PSA/TARGET_TFM/COMPONENT_SPE/secure_fw/core/tfm_secure_api.h b/components/TARGET_PSA/TARGET_TFM/COMPONENT_SPE/secure_fw/core/tfm_secure_api.h index 50f635708e..02f766a8e6 100644 --- a/components/TARGET_PSA/TARGET_TFM/COMPONENT_SPE/secure_fw/core/tfm_secure_api.h +++ b/components/TARGET_PSA/TARGET_TFM/COMPONENT_SPE/secure_fw/core/tfm_secure_api.h @@ -96,14 +96,19 @@ int32_t tfm_core_sfn_request_thread_mode(struct tfm_sfn_req_s *desc_ptr); * This function assumes, that the current MPU configuration is set for the * partition to be checked. * - * \param[in] p The start address of the range to check - * \param[in] s The size of the range to check - * \param[in] ns_caller Whether the current partition is a non-secure one + * \param[in] p The start address of the range to check + * \param[in] s The size of the range to check + * \param[in] ns_caller Whether the current partition is a non-secure one + * \param[in] privileged Privileged mode or unprivileged mode: + * \ref TFM_PARTITION_UNPRIVILEGED_MODE + * \ref TFM_PARTITION_PRIVILEGED_MODE * - * \return 1 if the partition has access to the memory range, 0 otherwise. + * \return TFM_SUCCESS if the partition has access to the memory range, + * TFM_ERROR_GENERIC otherwise. */ int32_t tfm_core_has_read_access_to_region(const void *p, size_t s, - uint32_t ns_caller); + uint32_t ns_caller, + uint32_t privileged); /** * \brief Check whether the current partition has write access to a memory range @@ -111,15 +116,39 @@ int32_t tfm_core_has_read_access_to_region(const void *p, size_t s, * This function assumes, that the current MPU configuration is set for the * partition to be checked. * - * \param[in] p The start address of the range to check - * \param[in] s The size of the range to check - * \param[in] ns_caller Whether the current partition is a non-secure one + * \param[in] p The start address of the range to check + * \param[in] s The size of the range to check + * \param[in] ns_caller Whether the current partition is a non-secure one + * \param[in] privileged Privileged mode or unprivileged mode: + * \ref TFM_PARTITION_UNPRIVILEGED_MODE + * \ref TFM_PARTITION_PRIVILEGED_MODE * - * \return 1 if the partition has access to the memory range, 0 otherwise. + * \return TFM_SUCCESS if the partition has access to the memory range, + * TFM_ERROR_GENERIC otherwise. */ int32_t tfm_core_has_write_access_to_region(void *p, size_t s, - uint32_t ns_caller); + uint32_t ns_caller, + uint32_t privileged); +#ifdef TFM_PSA_API +/* The following macros are only valid if secure services can be called + * using veneer functions. This is not the case if IPC messaging is enabled + */ +#define TFM_CORE_IOVEC_SFN_REQUEST(id, fn, a, b, c, d) \ + do { \ + ERROR_MSG("Invalid TF-M configuration detected"); \ + tfm_secure_api_error_handler(); \ + /* This point never reached */ \ + return (int32_t)TFM_ERROR_GENERIC; \ + } while (0) +#define TFM_CORE_SFN_REQUEST(id, fn, a, b, c, d) \ + do { \ + ERROR_MSG("Invalid TF-M configuration detected"); \ + tfm_secure_api_error_handler(); \ + /* This point never reached */ \ + return (int32_t)TFM_ERROR_GENERIC; \ + } while (0) +#else #define TFM_CORE_IOVEC_SFN_REQUEST(id, fn, a, b, c, d) \ return tfm_core_partition_request(id, fn, TFM_SFN_API_IOVEC, \ (int32_t)a, (int32_t)b, (int32_t)c, (int32_t)d) @@ -136,7 +165,7 @@ int32_t tfm_core_partition_request(uint32_t id, void *fn, int32_t iovec_api, struct tfm_sfn_req_s desc, *desc_ptr = &desc; desc.sp_id = id; - desc.sfn = fn; + desc.sfn = (sfn_t) fn; desc.args = args; /* * This preprocessor condition checks if a version of GCC smaller than @@ -180,5 +209,6 @@ int32_t tfm_core_partition_request(uint32_t id, void *fn, int32_t iovec_api, } } +#endif #endif /* __TFM_SECURE_API_H__ */ diff --git a/components/TARGET_PSA/TARGET_TFM/COMPONENT_SPE/secure_fw/core/tfm_spm_services.c b/components/TARGET_PSA/TARGET_TFM/COMPONENT_SPE/secure_fw/core/tfm_spm_services.c index dadf66f02c..83ff41b674 100644 --- a/components/TARGET_PSA/TARGET_TFM/COMPONENT_SPE/secure_fw/core/tfm_spm_services.c +++ b/components/TARGET_PSA/TARGET_TFM/COMPONENT_SPE/secure_fw/core/tfm_spm_services.c @@ -11,6 +11,7 @@ #include "tfm_secure_api.h" #include "tfm_internal.h" #include "secure_fw/include/tfm_spm_services_api.h" +#include "spm_api.h" uint8_t *tfm_scratch_area; uint32_t tfm_scratch_area_size; @@ -18,13 +19,9 @@ nsfptr_t ns_entry; void jump_to_ns_code(void) { -#if TFM_LVL != 1 +#if TFM_LVL == 3 || ((!defined(TFM_PSA_API)) && (TFM_LVL != 1)) /* Initialization is done, set thread mode to unprivileged. */ - CONTROL_Type ctrl; - - ctrl.w = __get_CONTROL(); - ctrl.b.nPRIV = 1; - __set_CONTROL(ctrl.w); + tfm_spm_partition_change_privilege(TFM_PARTITION_UNPRIVILEGED_MODE); #endif /* All changes made to memory will be effective after this point */ __DSB(); @@ -34,6 +31,7 @@ void jump_to_ns_code(void) ns_entry(); } +#ifndef TFM_PSA_API #if defined(__ARM_ARCH_8M_MAIN__) __attribute__((naked)) int32_t tfm_core_sfn_request( const struct tfm_sfn_req_s *desc_ptr) @@ -154,6 +152,7 @@ int32_t tfm_core_set_buffer_area(enum tfm_buffer_share_region_e share) "BX lr\n" : : "I" (TFM_SVC_SET_SHARE_AREA)); } +#endif __attribute__((naked)) int32_t tfm_core_get_boot_data(uint8_t major_type, diff --git a/components/TARGET_PSA/TARGET_TFM/COMPONENT_SPE/secure_fw/core/tfm_svc.h b/components/TARGET_PSA/TARGET_TFM/COMPONENT_SPE/secure_fw/core/tfm_svc.h index e4ed34b1b6..e0c11021d3 100644 --- a/components/TARGET_PSA/TARGET_TFM/COMPONENT_SPE/secure_fw/core/tfm_svc.h +++ b/components/TARGET_PSA/TARGET_TFM/COMPONENT_SPE/secure_fw/core/tfm_svc.h @@ -23,6 +23,7 @@ typedef enum { #ifdef TFM_PSA_API TFM_SVC_IPC_REQUEST, TFM_SVC_SCHEDULE, + TFM_SVC_EXIT_THRD, /* PSA Client SVC */ TFM_SVC_PSA_FRAMEWORK_VERSION, TFM_SVC_PSA_VERSION, diff --git a/components/TARGET_PSA/TARGET_TFM/COMPONENT_SPE/secure_fw/core/tfm_psa_api_client.c b/components/TARGET_PSA/TARGET_TFM/COMPONENT_SPE/secure_fw/ns_callable/tfm_psa_api_veneers.c similarity index 97% rename from components/TARGET_PSA/TARGET_TFM/COMPONENT_SPE/secure_fw/core/tfm_psa_api_client.c rename to components/TARGET_PSA/TARGET_TFM/COMPONENT_SPE/secure_fw/ns_callable/tfm_psa_api_veneers.c index 3c341bd902..33e1fdadd5 100644 --- a/components/TARGET_PSA/TARGET_TFM/COMPONENT_SPE/secure_fw/core/tfm_psa_api_client.c +++ b/components/TARGET_PSA/TARGET_TFM/COMPONENT_SPE/secure_fw/ns_callable/tfm_psa_api_veneers.c @@ -43,7 +43,7 @@ int32_t tfm_psa_veneer_sanity_check(struct tfm_sfn_req_s *desc_ptr) return tfm_core_ns_ipc_request(fn, (int32_t)a, (int32_t)b, \ (int32_t)c, (int32_t)d) -__attribute__ ((naked)) +__attribute__ ((naked, section("SFN"))) static int32_t tfm_core_ipc_request(const struct tfm_sfn_req_s *desc_ptr) { __ASM volatile("SVC %0 \n" @@ -99,7 +99,7 @@ psa_handle_t tfm_psa_connect_veneer(uint32_t sid, uint32_t minor_version) __tfm_secure_gateway_attributes__ psa_status_t tfm_psa_call_veneer(psa_handle_t handle, const psa_invec *in_vecs, - psa_outvec *out_vecs) + const psa_invec *out_vecs) { TFM_CORE_NS_IPC_REQUEST_VENEER(tfm_svcall_psa_call, handle, in_vecs, out_vecs, 0); diff --git a/components/TARGET_PSA/TARGET_TFM/COMPONENT_SPE/secure_fw/spm/CMakeLists.inc b/components/TARGET_PSA/TARGET_TFM/COMPONENT_SPE/secure_fw/spm/CMakeLists.inc new file mode 100644 index 0000000000..d1e57d888f --- /dev/null +++ b/components/TARGET_PSA/TARGET_TFM/COMPONENT_SPE/secure_fw/spm/CMakeLists.inc @@ -0,0 +1,61 @@ +#------------------------------------------------------------------------------- +# Copyright (c) 2017-2018, Arm Limited. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# +#------------------------------------------------------------------------------- + +#Definitions to compile the "spm" module. +#This file assumes it will be included from a project specific cmakefile, and +#will not create a library or executable. +#Inputs: +# TFM_ROOT_DIR - root directory of the TF-M repository. +# +#Outputs: +# Will modify include directories to make the source compile. +# ALL_SRC_C: C source files to be compiled will be added to this list. This shall be added to your add_executable or add_library command. +# ALL_SRC_CXX: C++ source files to be compiled will be added to this list. This shall be added to your add_executable or add_library command. +# ALL_SRC_ASM: assembly source files to be compiled will be added to this list. This shall be added to your add_executable or add_library command. +# Include directories will be modified by using the include_directories() commands as needed. + +#Get the current directory where this file is located. +set(SS_SPM_DIR ${CMAKE_CURRENT_LIST_DIR}) +if(NOT DEFINED TFM_ROOT_DIR) + message(FATAL_ERROR "Please set TFM_ROOT_DIR before including this file.") +endif() + +set (SS_SPM_C_SRC "${SS_SPM_DIR}/spm_api.c") + + +#Append all our source files to global lists. +list(APPEND ALL_SRC_C ${SS_SPM_C_SRC}) +unset(SS_SPM_C_SRC) + +#Setting include directories +embedded_include_directories(PATH ${TFM_ROOT_DIR} ABSOLUTE) +embedded_include_directories(PATH ${TFM_ROOT_DIR}/interface/include ABSOLUTE) +embedded_include_directories(PATH ${TFM_ROOT_DIR}/secure_fw/spm ABSOLUTE) +embedded_include_directories(PATH ${TFM_ROOT_DIR}/secure_fw/core ABSOLUTE) +embedded_include_directories(PATH ${TFM_ROOT_DIR} ABSOLUTE) + +set(BUILD_CMSIS_CORE Off) +set(BUILD_RETARGET Off) +set(BUILD_NATIVE_DRIVERS Off) +set(BUILD_STARTUP Off) +set(BUILD_TARGET_CFG Off) +set(BUILD_TARGET_HARDWARE_KEYS Off) +set(BUILD_TARGET_NV_COUNTERS Off) +set(BUILD_CMSIS_DRIVERS Off) +set(BUILD_TIME Off) +set(BUILD_UART_STDOUT Off) +set(BUILD_FLASH Off) +set(BUILD_BOOT_SEED Off) +set(BUILD_DEVICE_ID Off) +if(NOT DEFINED PLATFORM_CMAKE_FILE) + message (FATAL_ERROR "Platform specific CMake is not defined. Please set PLATFORM_CMAKE_FILE.") +elseif(NOT EXISTS ${PLATFORM_CMAKE_FILE}) + message (FATAL_ERROR "Platform specific CMake \"${PLATFORM_CMAKE_FILE}\" file does not exist. Please fix value of PLATFORM_CMAKE_FILE.") +else() + include(${PLATFORM_CMAKE_FILE}) +endif() + diff --git a/components/TARGET_PSA/TARGET_TFM/COMPONENT_SPE/secure_fw/spm/spm_api.c b/components/TARGET_PSA/TARGET_TFM/COMPONENT_SPE/secure_fw/spm/spm_api.c index 2559ac83b3..78999a8589 100644 --- a/components/TARGET_PSA/TARGET_TFM/COMPONENT_SPE/secure_fw/spm/spm_api.c +++ b/components/TARGET_PSA/TARGET_TFM/COMPONENT_SPE/secure_fw/spm/spm_api.c @@ -32,6 +32,7 @@ typedef enum { * In case of an error in the error handling, a non-zero value have to be * returned. */ +#ifndef TFM_PSA_API static void tfm_spm_partition_err_handler( const struct spm_partition_desc_t *partition, sp_error_type_t err_type, @@ -53,6 +54,7 @@ static void tfm_spm_partition_err_handler( tfm_spm_partition_set_state(partition->static_data.partition_id, SPM_PARTITION_STATE_CLOSED); } +#endif /* !defined(TFM_PSA_API) */ /* * This function prevents name clashes between the variable names accessibles in @@ -60,7 +62,7 @@ static void tfm_spm_partition_err_handler( * defined inside tfm_partition_list.inc file. */ static inline enum spm_err_t add_user_defined_partitions(void) { - #include "tfm_partition_list.inc" + #include "secure_fw/services/tfm_partition_list.inc" return SPM_ERR_OK; } @@ -98,29 +100,34 @@ enum spm_err_t tfm_spm_db_init(void) */ /* For the non secure Execution environment */ +#if (TFM_LVL != 1) || defined(TFM_PSA_API) extern uint32_t Image$$ARM_LIB_STACK$$ZI$$Base[]; extern uint32_t Image$$ARM_LIB_STACK$$ZI$$Limit[]; uint32_t psp_stack_bottom = (uint32_t)Image$$ARM_LIB_STACK$$ZI$$Base; uint32_t psp_stack_top = (uint32_t)Image$$ARM_LIB_STACK$$ZI$$Limit; - +#endif if (g_spm_partition_db.partition_count >= SPM_MAX_PARTITIONS) { return SPM_ERR_INVALID_CONFIG; } part_ptr = &(g_spm_partition_db.partitions[ g_spm_partition_db.partition_count]); part_ptr->static_data.partition_id = TFM_SP_NON_SECURE_ID; +#if TFM_PSA_API + part_ptr->static_data.partition_flags = SPM_PART_FLAG_APP_ROT | + SPM_PART_FLAG_IPC; + part_ptr->static_data.partition_priority = TFM_PRIORITY_LOW; + part_ptr->static_data.partition_init = tfm_nspm_thread_entry; +#else part_ptr->static_data.partition_flags = 0; +#endif -#if TFM_LVL != 1 +#if (TFM_LVL != 1) || defined(TFM_PSA_API) part_ptr->memory_data.stack_bottom = psp_stack_bottom; part_ptr->memory_data.stack_top = psp_stack_top; /* Since RW, ZI and stack are configured as one MPU region, configure * RW start address to psp_stack_bottom to get RW access to stack */ part_ptr->memory_data.rw_start = psp_stack_bottom; -#else - part_ptr->stack_limit = psp_stack_bottom; - part_ptr->stack_size = psp_stack_top - psp_stack_bottom; #endif part_ptr->runtime_data.partition_state = SPM_PARTITION_STATE_UNINIT; @@ -149,6 +156,7 @@ enum spm_err_t tfm_spm_db_init(void) return SPM_ERR_OK; } +#ifndef TFM_PSA_API enum spm_err_t tfm_spm_partition_init(void) { struct spm_partition_desc_t *part; @@ -161,11 +169,6 @@ enum spm_err_t tfm_spm_partition_init(void) for (idx = 0; idx < g_spm_partition_db.partition_count; ++idx) { part = &g_spm_partition_db.partitions[idx]; tfm_spm_hal_configure_default_isolation(part->platform_data); -#ifdef TFM_PSA_API - if (part->static_data.partition_flags & SPM_PART_FLAG_IPC) { - continue; - } -#endif if (part->static_data.partition_init == NULL) { tfm_spm_partition_set_state(idx, SPM_PARTITION_STATE_IDLE); tfm_spm_partition_set_caller_partition_idx(idx, @@ -196,8 +199,22 @@ enum spm_err_t tfm_spm_partition_init(void) return SPM_ERR_PARTITION_NOT_AVAILABLE; } } +#endif /* !defined(TFM_PSA_API) */ -#if TFM_LVL != 1 +#if (TFM_LVL != 1) || defined(TFM_PSA_API) +uint32_t tfm_spm_partition_get_stack_bottom(uint32_t partition_idx) +{ + return g_spm_partition_db.partitions[partition_idx]. + memory_data.stack_bottom; +} + +uint32_t tfm_spm_partition_get_stack_top(uint32_t partition_idx) +{ + return g_spm_partition_db.partitions[partition_idx].memory_data.stack_top; +} +#endif + +#if (TFM_LVL != 1) && !defined(TFM_PSA_API) enum spm_err_t tfm_spm_partition_sandbox_config(uint32_t partition_idx) { struct spm_partition_desc_t *part; @@ -226,17 +243,6 @@ enum spm_err_t tfm_spm_partition_sandbox_deconfig(uint32_t partition_idx) part->platform_data); } -uint32_t tfm_spm_partition_get_stack_bottom(uint32_t partition_idx) -{ - return g_spm_partition_db.partitions[partition_idx]. - memory_data.stack_bottom; -} - -uint32_t tfm_spm_partition_get_stack_top(uint32_t partition_idx) -{ - return g_spm_partition_db.partitions[partition_idx].memory_data.stack_top; -} - uint32_t tfm_spm_partition_get_zi_start(uint32_t partition_idx) { return g_spm_partition_db.partitions[partition_idx]. @@ -268,15 +274,6 @@ void tfm_spm_partition_set_stack(uint32_t partition_idx, uint32_t stack_ptr) } #endif -void tfm_spm_partition_store_context(uint32_t partition_idx, - uint32_t stack_ptr, uint32_t lr) -{ - g_spm_partition_db.partitions[partition_idx]. - runtime_data.stack_ptr = stack_ptr; - g_spm_partition_db.partitions[partition_idx]. - runtime_data.lr = lr; -} - uint32_t tfm_spm_partition_get_partition_id(uint32_t partition_idx) { return g_spm_partition_db.partitions[partition_idx].static_data. @@ -289,6 +286,16 @@ uint32_t tfm_spm_partition_get_flags(uint32_t partition_idx) partition_flags; } +#ifndef TFM_PSA_API +void tfm_spm_partition_store_context(uint32_t partition_idx, + uint32_t stack_ptr, uint32_t lr) +{ + g_spm_partition_db.partitions[partition_idx]. + runtime_data.stack_ptr = stack_ptr; + g_spm_partition_db.partitions[partition_idx]. + runtime_data.lr = lr; +} + const struct spm_partition_runtime_data_t * tfm_spm_partition_get_runtime_data(uint32_t partition_idx) { @@ -390,3 +397,20 @@ void tfm_spm_partition_cleanup_context(uint32_t partition_idx) partition->runtime_data.orig_outvec = 0; partition->runtime_data.iovec_api = 0; } +#endif /* !defined(TFM_PSA_API) */ + +__attribute__((section("SFN"))) +void tfm_spm_partition_change_privilege(uint32_t privileged) +{ + CONTROL_Type ctrl; + + ctrl.w = __get_CONTROL(); + + if (privileged == TFM_PARTITION_PRIVILEGED_MODE) { + ctrl.b.nPRIV = 0; + } else { + ctrl.b.nPRIV = 1; + } + + __set_CONTROL(ctrl.w); +} diff --git a/components/TARGET_PSA/TARGET_TFM/COMPONENT_SPE/secure_fw/spm/spm_api.h b/components/TARGET_PSA/TARGET_TFM/COMPONENT_SPE/secure_fw/spm/spm_api.h index 67accd5e8a..a15434d43a 100644 --- a/components/TARGET_PSA/TARGET_TFM/COMPONENT_SPE/secure_fw/spm/spm_api.h +++ b/components/TARGET_PSA/TARGET_TFM/COMPONENT_SPE/secure_fw/spm/spm_api.h @@ -15,6 +15,10 @@ #define SPM_INVALID_PARTITION_IDX (~0U) +/* Privileged definitions for partition thread mode */ +#define TFM_PARTITION_PRIVILEGED_MODE 1 +#define TFM_PARTITION_UNPRIVILEGED_MODE 0 + enum spm_err_t { SPM_ERR_OK = 0, SPM_ERR_PARTITION_DB_NOT_INIT, @@ -83,29 +87,7 @@ struct spm_partition_runtime_data_t { */ uint32_t get_partition_idx(uint32_t partition_id); -#if TFM_LVL != 1 -/** - * \brief Configure isolated sandbox for a partition - * - * \param[in] partition_idx Partition index - * - * \return Error code \ref spm_err_t - * - * \note This function doesn't check if partition_idx is valid. - */ -enum spm_err_t tfm_spm_partition_sandbox_config(uint32_t partition_idx); - -/** - * \brief Deconfigure sandbox for a partition - * - * \param[in] partition_idx Partition index - * - * \return Error code \ref spm_err_t - * - * \note This function doesn't check if partition_idx is valid. - */ -enum spm_err_t tfm_spm_partition_sandbox_deconfig(uint32_t partition_idx); - +#if (TFM_LVL != 1) || defined(TFM_PSA_API) /** * \brief Get bottom of stack region for a partition * @@ -127,6 +109,30 @@ uint32_t tfm_spm_partition_get_stack_bottom(uint32_t partition_idx); * \note This function doesn't check if partition_idx is valid. */ uint32_t tfm_spm_partition_get_stack_top(uint32_t partition_idx); +#endif + +#if (TFM_LVL != 1) && !defined(TFM_PSA_API) +/** + * \brief Configure isolated sandbox for a partition + * + * \param[in] partition_idx Partition index + * + * \return Error code \ref spm_err_t + * + * \note This function doesn't check if partition_idx is valid. + */ +enum spm_err_t tfm_spm_partition_sandbox_config(uint32_t partition_idx); + +/** + * \brief Deconfigure sandbox for a partition + * + * \param[in] partition_idx Partition index + * + * \return Error code \ref spm_err_t + * + * \note This function doesn't check if partition_idx is valid. + */ +enum spm_err_t tfm_spm_partition_sandbox_deconfig(uint32_t partition_idx); /** * \brief Get the start of the zero-initialised region for a partition @@ -185,6 +191,17 @@ uint32_t tfm_spm_partition_get_rw_limit(uint32_t partition_idx); void tfm_spm_partition_set_stack(uint32_t partition_idx, uint32_t stack_ptr); #endif +/** + * \brief Get the id of the partition for its index from the db + * + * \param[in] partition_idx Partition index + * + * \return Partition ID for that partition + * + * \note This function doesn't check if partition_idx is valid. + */ +uint32_t tfm_spm_partition_get_partition_id(uint32_t partition_idx); + /** * \brief Get the flags associated with a partition * @@ -196,6 +213,7 @@ void tfm_spm_partition_set_stack(uint32_t partition_idx, uint32_t stack_ptr); */ uint32_t tfm_spm_partition_get_flags(uint32_t partition_idx); +#ifndef TFM_PSA_API /** * \brief Get the current runtime data of a partition * @@ -228,17 +246,6 @@ uint32_t tfm_spm_partition_get_running_partition_idx(void); void tfm_spm_partition_store_context(uint32_t partition_idx, uint32_t stack_ptr, uint32_t lr); -/** - * \brief Get the id of the partition for its index from the db - * - * \param[in] partition_idx Partition index - * - * \return Partition ID for that partition - * - * \note This function doesn't check if partition_idx is valid. - */ -uint32_t tfm_spm_partition_get_partition_id(uint32_t partition_idx); - /** * \brief Set the current state of a partition * @@ -307,13 +314,6 @@ enum spm_err_t tfm_spm_partition_set_share(uint32_t partition_idx, enum spm_err_t tfm_spm_partition_set_iovec(uint32_t partition_idx, const int32_t *args); -/** - * \brief Initialize partition database - * - * \return Error code \ref spm_err_t - */ -enum spm_err_t tfm_spm_db_init(void); - /** * \brief Execute partition init function * @@ -329,5 +329,27 @@ enum spm_err_t tfm_spm_partition_init(void); * \note This function doesn't check if partition_idx is valid. */ void tfm_spm_partition_cleanup_context(uint32_t partition_idx); +#endif /* !defined(TFM_PSA_API) */ + +/** + * \brief Initialize partition database + * + * \return Error code \ref spm_err_t + */ +enum spm_err_t tfm_spm_db_init(void); + +/** + * \brief Change the privilege mode for partition thread mode. + * + * \param[in] privileged Privileged mode, + * \ref TFM_PARTITION_PRIVILEGED_MODE + * and \ref TFM_PARTITION_UNPRIVILEGED_MODE + * + * \note Barrier instructions are not called by this function, and if + * it is called in thread mode, it might be necessary to call + * them after this function returns (just like it is done in + * jump_to_ns_code()). + */ +void tfm_spm_partition_change_privilege(uint32_t privileged); #endif /*__SPM_API_H__ */ diff --git a/components/TARGET_PSA/TARGET_TFM/COMPONENT_SPE/secure_fw/spm/spm_db.h b/components/TARGET_PSA/TARGET_TFM/COMPONENT_SPE/secure_fw/spm/spm_db.h index 22d34ee8ff..6e6e25c801 100644 --- a/components/TARGET_PSA/TARGET_TFM/COMPONENT_SPE/secure_fw/spm/spm_db.h +++ b/components/TARGET_PSA/TARGET_TFM/COMPONENT_SPE/secure_fw/spm/spm_db.h @@ -21,8 +21,6 @@ typedef psa_status_t(*sp_init_function)(void); #define TFM_PARTITION_TYPE_APP "APPLICATION-ROT" #define TFM_PARTITION_TYPE_PSA "PSA-ROT" -#define TFM_STACK_SIZE (1024 * 5) - #ifdef TFM_PSA_API enum tfm_partition_priority { TFM_PRIORITY_LOW = THRD_PRIOR_LOWEST, @@ -59,23 +57,18 @@ struct spm_partition_desc_t { struct spm_partition_static_data_t static_data; struct spm_partition_runtime_data_t runtime_data; struct tfm_spm_partition_platform_data_t *platform_data; -#if TFM_LVL != 1 +#if (TFM_LVL != 1) || defined(TFM_PSA_API) struct tfm_spm_partition_memory_data_t memory_data; #endif #ifdef TFM_PSA_API struct tfm_thrd_ctx sp_thrd; - /* - * stack_limit points to starting address of the partitions' stack plus the partitions' stack size. - */ - uint32_t stack_limit; - uint32_t stack_size; #endif }; /* Macros to pick linker symbols and allow to form the partition data base */ #define REGION(a, b, c) a##b##c #define REGION_NAME(a, b, c) REGION(a, b, c) -#if TFM_LVL == 1 +#if (TFM_LVL == 1) && !defined(TFM_PSA_API) #define REGION_DECLARE(a, b, c) #else #define REGION_DECLARE(a, b, c) extern uint32_t REGION_NAME(a, b, c) diff --git a/components/TARGET_PSA/TARGET_TFM/COMPONENT_SPE/secure_fw/spm/spm_db_setup.h b/components/TARGET_PSA/TARGET_TFM/COMPONENT_SPE/secure_fw/spm/spm_db_setup.h index 099a800673..db061544e7 100644 --- a/components/TARGET_PSA/TARGET_TFM/COMPONENT_SPE/secure_fw/spm/spm_db_setup.h +++ b/components/TARGET_PSA/TARGET_TFM/COMPONENT_SPE/secure_fw/spm/spm_db_setup.h @@ -38,7 +38,7 @@ struct spm_partition_db_t { data.partition_priority = TFM_PRIORITY(priority); \ } while (0) -#if TFM_LVL == 1 +#if (TFM_LVL == 1) && !defined(TFM_PSA_API) #define PARTITION_INIT_MEMORY_DATA(data, partition) #else #define PARTITION_INIT_MEMORY_DATA(data, partition) \ @@ -56,7 +56,6 @@ struct spm_partition_db_t { } while (0) #endif - #if TFM_LVL == 1 #define PARTITION_INIT_RUNTIME_DATA(data, partition) \ do { \ @@ -76,7 +75,7 @@ struct spm_partition_db_t { } while (0) #endif -#define PARTITION_DECLARE(partition, flag, type, id, priority, part_stack_size) \ +#define PARTITION_DECLARE(partition, flag, type, id, priority) \ do { \ REGION_DECLARE(Image$$, partition, $$Base); \ REGION_DECLARE(Image$$, partition, $$Limit); \ @@ -102,12 +101,8 @@ struct spm_partition_db_t { if (g_spm_partition_db.partition_count >= SPM_MAX_PARTITIONS) { \ return SPM_ERR_INVALID_CONFIG; \ } \ - __attribute__((section(".data.partitions_stacks"))) \ - static uint8_t partition##_stack[part_stack_size] __attribute__((aligned(8))); \ part_ptr = &(g_spm_partition_db.partitions[ \ g_spm_partition_db.partition_count]); \ - part_ptr->stack_limit = (uint32_t)partition##_stack; \ - part_ptr->stack_size = part_stack_size; \ PARTITION_INIT_STATIC_DATA(part_ptr->static_data, partition, flags, \ id, priority); \ PARTITION_INIT_RUNTIME_DATA(part_ptr->runtime_data, partition); \ diff --git a/components/TARGET_PSA/TARGET_TFM/COMPONENT_SPE/secure_fw/spm/spm_partition_defs.h b/components/TARGET_PSA/TARGET_TFM/COMPONENT_SPE/secure_fw/spm/spm_partition_defs.h index 0533881f87..85ab1eca6e 100644 --- a/components/TARGET_PSA/TARGET_TFM/COMPONENT_SPE/secure_fw/spm/spm_partition_defs.h +++ b/components/TARGET_PSA/TARGET_TFM/COMPONENT_SPE/secure_fw/spm/spm_partition_defs.h @@ -29,7 +29,7 @@ */ #define TFM_SP_CORE_ID (1) -#include "tfm_partition_defs.inc" +#include "secure_fw/services/tfm_partition_defs.inc" /* This limit is only used to define the size of the database reserved for * partitions. There's no requirement that it match the number of partitions diff --git a/components/TARGET_PSA/TARGET_TFM/interface/include/tfm_api.h b/components/TARGET_PSA/TARGET_TFM/interface/include/tfm_api.h index d6ce6893a0..2ba93c0916 100644 --- a/components/TARGET_PSA/TARGET_TFM/interface/include/tfm_api.h +++ b/components/TARGET_PSA/TARGET_TFM/interface/include/tfm_api.h @@ -110,13 +110,13 @@ psa_handle_t tfm_psa_connect_veneer(uint32_t sid, uint32_t minor_version); * * \param[in] handle Handle to connection * \param[in] in_vecs invec containing pointer/count of input vectors - * \param[in] out_vecs outvec containing pointer/count of output vectors + * \param[in] out_vecs invec containing pointer/count of output vectors * * \return Returns \ref psa_status_t status code */ psa_status_t tfm_psa_call_veneer(psa_handle_t handle, const psa_invec *in_vecs, - psa_outvec *out_vecs); + const psa_invec *out_vecs); /** * \brief Close connection to secure function referenced by a connection handle diff --git a/tools/importer/tfm_importer.json b/tools/importer/tfm_importer.json index 3d0ac1a22d..99da7dcd72 100644 --- a/tools/importer/tfm_importer.json +++ b/tools/importer/tfm_importer.json @@ -35,6 +35,10 @@ { "src_file": "platform/include/tfm_spm_hal.h", "dest_file": "components/TARGET_PSA/TARGET_TFM/COMPONENT_SPE/platform/include/tfm_spm_hal.h" + }, + { + "src_file": "secure_fw/ns_callable/tfm_psa_api_veneers.c", + "dest_file": "components/TARGET_PSA/TARGET_TFM/COMPONENT_SPE/secure_fw/ns_callable/tfm_psa_api_veneers.c" } ], "folders": [ @@ -67,9 +71,6 @@ "fb068d2cb4e89cacf0e9f413075bb4b211f1484f", "5d41a2aeae71b13f2763bea4e55899646291e0eb", "9c1e080e39adc7211c8c2c12cd652da3dc124299", - "78ed87028718b1b926d847ff6fc2f91d44e53d6d", - "280715f9b74ab29459d81edaf02b39e7a6acb13c", - "ea81bf91c90ae23dd9de012bfd7498613be00601", - "5342015bb12a486a1c563175a8a7129f0737c925" + "280715f9b74ab29459d81edaf02b39e7a6acb13c" ] } From 11bff3f3cbfbd3e2c284e884d0066531e6b47d7e Mon Sep 17 00:00:00 2001 From: Michael Schwarcz Date: Thu, 7 Feb 2019 11:51:12 +0200 Subject: [PATCH 2/9] TF-M patch: General modifications - Remove un-needed files - Disable printf and uart - Modify include paths - Guard macros from mbed_lib with ifndef (cherry picked from commit 1f30b52488e88704cdb51c8c26e7225e580e5cc2) (cherry picked from commit 71cd34df3265d98da5c9b34e4e18ef039d7bef5c) (cherry picked from commit 185d2865da45cc2c6ac3acb755b90c196934d7d5) (cherry picked from commit fb068d2cb4e89cacf0e9f413075bb4b211f1484f) --- .../COMPONENT_SPE/bl2/include/boot_record.h | 81 ------------------- .../secure_fw/core/CMakeLists.inc | 72 ----------------- .../secure_fw/core/ipc/CMakeLists.inc | 73 ----------------- .../core/ipc/include/tfm_message_queue.h | 4 +- .../secure_fw/core/ipc/include/tfm_spm.h | 4 + .../core/ipc/include/tfm_spm_signal_defs.h | 18 ----- .../secure_fw/core/ipc/tfm_spm.c | 2 +- .../secure_fw/core/secure_utilities.h | 2 + .../COMPONENT_SPE/secure_fw/core/tfm_core.c | 2 - .../secure_fw/core/tfm_secure_api.c | 1 - .../secure_fw/spm/CMakeLists.inc | 61 -------------- .../COMPONENT_SPE/secure_fw/spm/spm_api.c | 2 +- .../secure_fw/spm/spm_partition_defs.h | 2 +- 13 files changed, 12 insertions(+), 312 deletions(-) delete mode 100644 components/TARGET_PSA/TARGET_TFM/COMPONENT_SPE/bl2/include/boot_record.h delete mode 100644 components/TARGET_PSA/TARGET_TFM/COMPONENT_SPE/secure_fw/core/CMakeLists.inc delete mode 100644 components/TARGET_PSA/TARGET_TFM/COMPONENT_SPE/secure_fw/core/ipc/CMakeLists.inc delete mode 100644 components/TARGET_PSA/TARGET_TFM/COMPONENT_SPE/secure_fw/core/ipc/include/tfm_spm_signal_defs.h delete mode 100644 components/TARGET_PSA/TARGET_TFM/COMPONENT_SPE/secure_fw/spm/CMakeLists.inc diff --git a/components/TARGET_PSA/TARGET_TFM/COMPONENT_SPE/bl2/include/boot_record.h b/components/TARGET_PSA/TARGET_TFM/COMPONENT_SPE/bl2/include/boot_record.h deleted file mode 100644 index 217a20684c..0000000000 --- a/components/TARGET_PSA/TARGET_TFM/COMPONENT_SPE/bl2/include/boot_record.h +++ /dev/null @@ -1,81 +0,0 @@ -/* - * Copyright (c) 2018-2019, Arm Limited. All rights reserved. - * - * SPDX-License-Identifier: BSD-3-Clause - * - */ - -#ifndef __BOOT_RECORD_H__ -#define __BOOT_RECORD_H__ - -#include -#include -#include -#include "../ext/mcuboot/bootutil/include/bootutil/image.h" -#include "../ext/mcuboot/include/flash_map/flash_map.h" - -#ifdef __cplusplus -extern "C" { -#endif - -/*! - * \enum shared_data_err_t - * - * \brief Return values for adding data entry to shared memory area - */ -enum shared_memory_err_t { - SHARED_MEMORY_OK = 0, - SHARED_MEMORY_OVERFLOW = 1, - SHARED_MEMORY_OVERWRITE = 2, - - /* This is used to force the maximum size */ - TLV_TYPE_MAX = INT_MAX -}; - -/*! - * \enum boot_status_err_t - * - * \brief Return values for saving boot status information to shared memory are - */ -enum boot_status_err_t { - BOOT_STATUS_OK, - BOOT_STATUS_ERROR, -}; - -/*! - * \brief Add a data item to the shared data area between bootloader and - * runtime SW - * - * \param[in] major_type TLV major type, identify consumer - * \param[in] minor_type TLV minor type, identify TLV type - * \param[in] size length of added data - * \param[in] data pointer to data - * - * \return Returns error code as specified in \ref shared_memory_err_t - */ -enum shared_memory_err_t -boot_add_data_to_shared_area(uint8_t major_type, - uint16_t minor_type, - size_t size, - const uint8_t *data); - -/*! - * \brief Add an image's all boot status information to the shared data area - * between bootloader and runtime SW - * - * \param[in] sw_module Identifier of the SW component - * \param[in] hdr Pointer to the image header stored in RAM - * \param[in] fap Pointer to the flash area where image is stored - * - * \return Returns error code as specified in \ref boot_status_err_t - */ -enum boot_status_err_t -boot_save_boot_status(uint8_t sw_module, - const struct image_header *hdr, - const struct flash_area *fap); - -#ifdef __cplusplus -} -#endif - -#endif /* __BOOT_RECORD_H__ */ diff --git a/components/TARGET_PSA/TARGET_TFM/COMPONENT_SPE/secure_fw/core/CMakeLists.inc b/components/TARGET_PSA/TARGET_TFM/COMPONENT_SPE/secure_fw/core/CMakeLists.inc deleted file mode 100644 index c9bfbb73cf..0000000000 --- a/components/TARGET_PSA/TARGET_TFM/COMPONENT_SPE/secure_fw/core/CMakeLists.inc +++ /dev/null @@ -1,72 +0,0 @@ -#------------------------------------------------------------------------------- -# Copyright (c) 2017-2018, Arm Limited. All rights reserved. -# -# SPDX-License-Identifier: BSD-3-Clause -# -#------------------------------------------------------------------------------- - -#Definitions to compile the "core" module. -#This file assumes it will be included from a project specific cmakefile, and -#will not create a library or executable. -#Inputs: -# TFM_ROOT_DIR - directory where secure FW sourec is located. -# -#Outputs: -# Will modify include directories to make the source compile. -# ALL_SRC_C: C source files to be compiled will be added to this list. -# This shall be added to your add_executable or add_library command. -# ALL_SRC_CXX: C++ source files to be compiled will be added to this list. -# This shall be added to your add_executable or add_library command. -# ALL_SRC_ASM: assembly source files to be compiled will be added to this -# list. This shall be added to your add_executable or add_library -# command. -# Include directories will be modified by using the include_directories() -# commands as needed. - -#Get the current directory where this file is located. -set(SS_CORE_DIR ${CMAKE_CURRENT_LIST_DIR}) -if(NOT DEFINED TFM_ROOT_DIR) - message(FATAL_ERROR - "Please set TFM_ROOT_DIR before including this file.") -endif() - -set (SS_CORE_C_SRC - "${SS_CORE_DIR}/tfm_core.c" - "${SS_CORE_DIR}/tfm_handler.c" - "${SS_CORE_DIR}/tfm_secure_api.c" - "${SS_CORE_DIR}/tfm_func_api.c" - "${SS_CORE_DIR}/tfm_spm_services.c" - "${SS_CORE_DIR}/tfm_nspm.c" - "${SS_CORE_DIR}/tfm_boot_data.c" - ) - -#Append all our source files to global lists. -list(APPEND ALL_SRC_C ${SS_CORE_C_SRC}) -unset(SS_CORE_C_SRC) - -#Setting include directories -embedded_include_directories(PATH ${TFM_ROOT_DIR} ABSOLUTE) -embedded_include_directories(PATH ${TFM_ROOT_DIR}/interface/include ABSOLUTE) -embedded_include_directories(PATH ${TFM_ROOT_DIR}/secure_fw/spm ABSOLUTE) -embedded_include_directories(PATH ${TFM_ROOT_DIR}/secure_fw/core ABSOLUTE) - -set(BUILD_CMSIS_CORE Off) -set(BUILD_RETARGET Off) -set(BUILD_NATIVE_DRIVERS Off) -set(BUILD_STARTUP Off) -set(BUILD_TARGET_CFG Off) -set(BUILD_TARGET_HARDWARE_KEYS Off) -set(BUILD_TARGET_NV_COUNTERS Off) -set(BUILD_CMSIS_DRIVERS Off) -set(BUILD_TIME Off) -set(BUILD_UART_STDOUT Off) -set(BUILD_FLASH Off) -set(BUILD_BOOT_SEED Off) -set(BUILD_DEVICE_ID Off) -if(NOT DEFINED PLATFORM_CMAKE_FILE) - message (FATAL_ERROR "Platform specific CMake is not defined. Please set PLATFORM_CMAKE_FILE.") -elseif(NOT EXISTS ${PLATFORM_CMAKE_FILE}) - message (FATAL_ERROR "Platform specific CMake \"${PLATFORM_CMAKE_FILE}\" file does not exist. Please fix value of PLATFORM_CMAKE_FILE.") -else() - include(${PLATFORM_CMAKE_FILE}) -endif() diff --git a/components/TARGET_PSA/TARGET_TFM/COMPONENT_SPE/secure_fw/core/ipc/CMakeLists.inc b/components/TARGET_PSA/TARGET_TFM/COMPONENT_SPE/secure_fw/core/ipc/CMakeLists.inc deleted file mode 100644 index 1f9a81dca3..0000000000 --- a/components/TARGET_PSA/TARGET_TFM/COMPONENT_SPE/secure_fw/core/ipc/CMakeLists.inc +++ /dev/null @@ -1,73 +0,0 @@ -#------------------------------------------------------------------------------- -# Copyright (c) 2018-2019, Arm Limited. All rights reserved. -# -# SPDX-License-Identifier: BSD-3-Clause -# -#------------------------------------------------------------------------------- - -#Definitions to compile the "ipc" module. -#This file assumes it will be included from a project specific cmakefile, and -#will not create a library or executable. -#Inputs: -# TFM_ROOT_DIR - directory where secure FW sourec is located. -# -#Outputs: -# Will modify include directories to make the source compile. -# ALL_SRC_C: C source files to be compiled will be added to this list. -# This shall be added to your add_executable or add_library command. -# ALL_SRC_CXX: C++ source files to be compiled will be added to this list. -# This shall be added to your add_executable or add_library command. -# ALL_SRC_ASM: assembly source files to be compiled will be added to this -# list. This shall be added to your add_executable or add_library -# command. -# Include directories will be modified by using the include_directories() -# commands as needed. - -#Get the current directory where this file is located. -set(SS_IPC_DIR ${CMAKE_CURRENT_LIST_DIR}) -if(NOT DEFINED TFM_ROOT_DIR) - message(FATAL_ERROR - "Please set TFM_ROOT_DIR before including this file.") -endif() - -if (NOT DEFINED TFM_PSA_API) - message(FATAL_ERROR "Incomplete build configuration: TFM_PSA_API is undefined. ") -elseif (TFM_PSA_API) - set (SS_IPC_C_SRC "${SS_IPC_DIR}/tfm_svcalls.c" - "${SS_IPC_DIR}/psa_service.c" - "${SS_IPC_DIR}/psa_client.c" - "${SS_IPC_DIR}/tfm_arch_v8m.c" - "${SS_IPC_DIR}/tfm_thread.c" - "${SS_IPC_DIR}/tfm_wait.c" - "${SS_IPC_DIR}/tfm_utils.c" - "${SS_IPC_DIR}/tfm_message_queue.c" - "${SS_IPC_DIR}/tfm_pools.c" - "${SS_IPC_DIR}/tfm_spm.c" - "${SS_IPC_DIR}/../tfm_core.c" - "${SS_IPC_DIR}/../tfm_secure_api.c" - "${SS_IPC_DIR}/../tfm_spm_services.c" - "${SS_IPC_DIR}/../tfm_handler.c" - "${SS_IPC_DIR}/../tfm_nspm.c" - "${SS_IPC_DIR}/../tfm_boot_data.c" - ) -endif() - -#Append all our source files to global lists. -list(APPEND ALL_SRC_C ${SS_IPC_C_SRC}) -unset(SS_IPC_C_SRC) - -#Setting include directories -embedded_include_directories(PATH ${TFM_ROOT_DIR} ABSOLUTE) -embedded_include_directories(PATH ${TFM_ROOT_DIR}/interface/include ABSOLUTE) -embedded_include_directories(PATH ${TFM_ROOT_DIR}/secure_fw/spm ABSOLUTE) -embedded_include_directories(PATH ${TFM_ROOT_DIR}/secure_fw/core ABSOLUTE) -embedded_include_directories(PATH ${TFM_ROOT_DIR}/secure_fw/core/ipc ABSOLUTE) -embedded_include_directories(PATH ${TFM_ROOT_DIR}/secure_fw/core/ipc/include ABSOLUTE) - -if(NOT DEFINED PLATFORM_CMAKE_FILE) - message (FATAL_ERROR "Platform specific CMake is not defined. Please set PLATFORM_CMAKE_FILE.") -elseif(NOT EXISTS ${PLATFORM_CMAKE_FILE}) - message (FATAL_ERROR "Platform specific CMake \"${PLATFORM_CMAKE_FILE}\" file does not exist. Please fix value of PLATFORM_CMAKE_FILE.") -else() - include(${PLATFORM_CMAKE_FILE}) -endif() diff --git a/components/TARGET_PSA/TARGET_TFM/COMPONENT_SPE/secure_fw/core/ipc/include/tfm_message_queue.h b/components/TARGET_PSA/TARGET_TFM/COMPONENT_SPE/secure_fw/core/ipc/include/tfm_message_queue.h index 3edf3fbb8b..44f5af44bf 100644 --- a/components/TARGET_PSA/TARGET_TFM/COMPONENT_SPE/secure_fw/core/ipc/include/tfm_message_queue.h +++ b/components/TARGET_PSA/TARGET_TFM/COMPONENT_SPE/secure_fw/core/ipc/include/tfm_message_queue.h @@ -7,7 +7,9 @@ #ifndef __TFM_MESSAGE_QUEUE_H__ #define __TFM_MESSAGE_QUEUE_H__ -#define TFM_MSG_QUEUE_MAX_MSG_NUM 16 +#ifndef TFM_MSG_QUEUE_MAX_MSG_NUM +#define TFM_MSG_QUEUE_MAX_MSG_NUM 128 +#endif #define TFM_MSG_MAGIC 0x15154343 /* Message struct to collect parameter from client */ struct tfm_msg_body_t { diff --git a/components/TARGET_PSA/TARGET_TFM/COMPONENT_SPE/secure_fw/core/ipc/include/tfm_spm.h b/components/TARGET_PSA/TARGET_TFM/COMPONENT_SPE/secure_fw/core/ipc/include/tfm_spm.h index fcd3bc27b8..82c25ebdd1 100644 --- a/components/TARGET_PSA/TARGET_TFM/COMPONENT_SPE/secure_fw/core/ipc/include/tfm_spm.h +++ b/components/TARGET_PSA/TARGET_TFM/COMPONENT_SPE/secure_fw/core/ipc/include/tfm_spm.h @@ -11,11 +11,15 @@ #include "tfm_list.h" #include "tfm_secure_api.h" +#ifndef TFM_SPM_MAX_ROT_SERV_NUM #define TFM_SPM_MAX_ROT_SERV_NUM 28 +#endif #define TFM_VERSION_POLICY_RELAXED 0 #define TFM_VERSION_POLICY_STRICT 1 +#ifndef TFM_CONN_HANDLE_MAX_NUM #define TFM_CONN_HANDLE_MAX_NUM 32 +#endif /* RoT connection handle list */ struct tfm_conn_handle_t { diff --git a/components/TARGET_PSA/TARGET_TFM/COMPONENT_SPE/secure_fw/core/ipc/include/tfm_spm_signal_defs.h b/components/TARGET_PSA/TARGET_TFM/COMPONENT_SPE/secure_fw/core/ipc/include/tfm_spm_signal_defs.h deleted file mode 100644 index 67bb1957db..0000000000 --- a/components/TARGET_PSA/TARGET_TFM/COMPONENT_SPE/secure_fw/core/ipc/include/tfm_spm_signal_defs.h +++ /dev/null @@ -1,18 +0,0 @@ -/* - * Copyright (c) 2018-2019, Arm Limited. All rights reserved. - * - * SPDX-License-Identifier: BSD-3-Clause - * - */ -#ifndef __TFM_SPM_SIGNAL_DEFS_H__ -#define __TFM_SPM_SIGNAL_DEFS_H__ - -#include "test/test_services/tfm_ipc_service/tfm_ipc_service_partition.h" -#include "test/test_services/tfm_core_test/tfm_ss_core_test_signal.h" -#include "test/test_services/tfm_core_test_2/tfm_ss_core_test_2_signal.h" -#include "secure_fw/services/crypto/tfm_crypto_signal.h" -#include "test/test_services/tfm_secure_client_service/tfm_sec_client_ser_sig.h" -#include "secure_fw/services/secure_storage/tfm_sst_signal.h" -#include "secure_fw/services/initial_attestation/tfm_attest_signal.h" - -#endif /* __TFM_SPM_SIGNAL_DEFS_H__ */ diff --git a/components/TARGET_PSA/TARGET_TFM/COMPONENT_SPE/secure_fw/core/ipc/tfm_spm.c b/components/TARGET_PSA/TARGET_TFM/COMPONENT_SPE/secure_fw/core/ipc/tfm_spm.c index d16b13a530..e2dbfd13f8 100644 --- a/components/TARGET_PSA/TARGET_TFM/COMPONENT_SPE/secure_fw/core/ipc/tfm_spm.c +++ b/components/TARGET_PSA/TARGET_TFM/COMPONENT_SPE/secure_fw/core/ipc/tfm_spm.c @@ -49,7 +49,7 @@ TFM_POOL_DECLARE(msg_db_pool, sizeof(struct tfm_msg_body_t), TFM_MSG_QUEUE_MAX_MSG_NUM); static struct tfm_spm_service_db_t g_spm_service_db[] = { - #include "secure_fw/services/tfm_service_list.inc" + #include "tfm_service_list.inc" }; /********************** SPM functions for handler mode ***********************/ diff --git a/components/TARGET_PSA/TARGET_TFM/COMPONENT_SPE/secure_fw/core/secure_utilities.h b/components/TARGET_PSA/TARGET_TFM/COMPONENT_SPE/secure_fw/core/secure_utilities.h index d367fe8400..82a4f5a8a0 100644 --- a/components/TARGET_PSA/TARGET_TFM/COMPONENT_SPE/secure_fw/core/secure_utilities.h +++ b/components/TARGET_PSA/TARGET_TFM/COMPONENT_SPE/secure_fw/core/secure_utilities.h @@ -25,6 +25,8 @@ #define EXC_NUM_PENDSV (14) #define EXC_NUM_SYSTICK (15) +#define printf(...) + /* Disable NS exceptions by setting NS PRIMASK to 1 */ #define TFM_NS_EXC_DISABLE() __TZ_set_PRIMASK_NS(1) /* Enable NS exceptions by setting NS PRIMASK to 0 */ diff --git a/components/TARGET_PSA/TARGET_TFM/COMPONENT_SPE/secure_fw/core/tfm_core.c b/components/TARGET_PSA/TARGET_TFM/COMPONENT_SPE/secure_fw/core/tfm_core.c index fc060f3b11..0be05ca8f1 100644 --- a/components/TARGET_PSA/TARGET_TFM/COMPONENT_SPE/secure_fw/core/tfm_core.c +++ b/components/TARGET_PSA/TARGET_TFM/COMPONENT_SPE/secure_fw/core/tfm_core.c @@ -11,7 +11,6 @@ #include "tfm_internal.h" #include "tfm_api.h" #include "platform/include/tfm_spm_hal.h" -#include "uart_stdout.h" #include "secure_utilities.h" #include "secure_fw/spm/spm_api.h" #include "secure_fw/include/tfm_spm_services_api.h" @@ -90,7 +89,6 @@ int32_t tfm_core_init(void) __enable_irq(); - stdio_init(); LOG_MSG("Secure image initializing!"); #ifdef TFM_CORE_DEBUG diff --git a/components/TARGET_PSA/TARGET_TFM/COMPONENT_SPE/secure_fw/core/tfm_secure_api.c b/components/TARGET_PSA/TARGET_TFM/COMPONENT_SPE/secure_fw/core/tfm_secure_api.c index ca0e51c485..951765a163 100644 --- a/components/TARGET_PSA/TARGET_TFM/COMPONENT_SPE/secure_fw/core/tfm_secure_api.c +++ b/components/TARGET_PSA/TARGET_TFM/COMPONENT_SPE/secure_fw/core/tfm_secure_api.c @@ -12,7 +12,6 @@ #include "tfm_secure_api.h" #include "tfm_nspm.h" #include "secure_utilities.h" -#include "uart_stdout.h" #include "secure_fw/spm/spm_api.h" #include "region_defs.h" #include "tfm_api.h" diff --git a/components/TARGET_PSA/TARGET_TFM/COMPONENT_SPE/secure_fw/spm/CMakeLists.inc b/components/TARGET_PSA/TARGET_TFM/COMPONENT_SPE/secure_fw/spm/CMakeLists.inc deleted file mode 100644 index d1e57d888f..0000000000 --- a/components/TARGET_PSA/TARGET_TFM/COMPONENT_SPE/secure_fw/spm/CMakeLists.inc +++ /dev/null @@ -1,61 +0,0 @@ -#------------------------------------------------------------------------------- -# Copyright (c) 2017-2018, Arm Limited. All rights reserved. -# -# SPDX-License-Identifier: BSD-3-Clause -# -#------------------------------------------------------------------------------- - -#Definitions to compile the "spm" module. -#This file assumes it will be included from a project specific cmakefile, and -#will not create a library or executable. -#Inputs: -# TFM_ROOT_DIR - root directory of the TF-M repository. -# -#Outputs: -# Will modify include directories to make the source compile. -# ALL_SRC_C: C source files to be compiled will be added to this list. This shall be added to your add_executable or add_library command. -# ALL_SRC_CXX: C++ source files to be compiled will be added to this list. This shall be added to your add_executable or add_library command. -# ALL_SRC_ASM: assembly source files to be compiled will be added to this list. This shall be added to your add_executable or add_library command. -# Include directories will be modified by using the include_directories() commands as needed. - -#Get the current directory where this file is located. -set(SS_SPM_DIR ${CMAKE_CURRENT_LIST_DIR}) -if(NOT DEFINED TFM_ROOT_DIR) - message(FATAL_ERROR "Please set TFM_ROOT_DIR before including this file.") -endif() - -set (SS_SPM_C_SRC "${SS_SPM_DIR}/spm_api.c") - - -#Append all our source files to global lists. -list(APPEND ALL_SRC_C ${SS_SPM_C_SRC}) -unset(SS_SPM_C_SRC) - -#Setting include directories -embedded_include_directories(PATH ${TFM_ROOT_DIR} ABSOLUTE) -embedded_include_directories(PATH ${TFM_ROOT_DIR}/interface/include ABSOLUTE) -embedded_include_directories(PATH ${TFM_ROOT_DIR}/secure_fw/spm ABSOLUTE) -embedded_include_directories(PATH ${TFM_ROOT_DIR}/secure_fw/core ABSOLUTE) -embedded_include_directories(PATH ${TFM_ROOT_DIR} ABSOLUTE) - -set(BUILD_CMSIS_CORE Off) -set(BUILD_RETARGET Off) -set(BUILD_NATIVE_DRIVERS Off) -set(BUILD_STARTUP Off) -set(BUILD_TARGET_CFG Off) -set(BUILD_TARGET_HARDWARE_KEYS Off) -set(BUILD_TARGET_NV_COUNTERS Off) -set(BUILD_CMSIS_DRIVERS Off) -set(BUILD_TIME Off) -set(BUILD_UART_STDOUT Off) -set(BUILD_FLASH Off) -set(BUILD_BOOT_SEED Off) -set(BUILD_DEVICE_ID Off) -if(NOT DEFINED PLATFORM_CMAKE_FILE) - message (FATAL_ERROR "Platform specific CMake is not defined. Please set PLATFORM_CMAKE_FILE.") -elseif(NOT EXISTS ${PLATFORM_CMAKE_FILE}) - message (FATAL_ERROR "Platform specific CMake \"${PLATFORM_CMAKE_FILE}\" file does not exist. Please fix value of PLATFORM_CMAKE_FILE.") -else() - include(${PLATFORM_CMAKE_FILE}) -endif() - diff --git a/components/TARGET_PSA/TARGET_TFM/COMPONENT_SPE/secure_fw/spm/spm_api.c b/components/TARGET_PSA/TARGET_TFM/COMPONENT_SPE/secure_fw/spm/spm_api.c index 78999a8589..ec70a1ca2e 100644 --- a/components/TARGET_PSA/TARGET_TFM/COMPONENT_SPE/secure_fw/spm/spm_api.c +++ b/components/TARGET_PSA/TARGET_TFM/COMPONENT_SPE/secure_fw/spm/spm_api.c @@ -62,7 +62,7 @@ static void tfm_spm_partition_err_handler( * defined inside tfm_partition_list.inc file. */ static inline enum spm_err_t add_user_defined_partitions(void) { - #include "secure_fw/services/tfm_partition_list.inc" + #include "tfm_partition_list.inc" return SPM_ERR_OK; } diff --git a/components/TARGET_PSA/TARGET_TFM/COMPONENT_SPE/secure_fw/spm/spm_partition_defs.h b/components/TARGET_PSA/TARGET_TFM/COMPONENT_SPE/secure_fw/spm/spm_partition_defs.h index 85ab1eca6e..0533881f87 100644 --- a/components/TARGET_PSA/TARGET_TFM/COMPONENT_SPE/secure_fw/spm/spm_partition_defs.h +++ b/components/TARGET_PSA/TARGET_TFM/COMPONENT_SPE/secure_fw/spm/spm_partition_defs.h @@ -29,7 +29,7 @@ */ #define TFM_SP_CORE_ID (1) -#include "secure_fw/services/tfm_partition_defs.inc" +#include "tfm_partition_defs.inc" /* This limit is only used to define the size of the database reserved for * partitions. There's no requirement that it match the number of partitions From 795e6418d0e73841868b351b605659a05c04e1f6 Mon Sep 17 00:00:00 2001 From: Michael Schwarcz Date: Thu, 7 Feb 2019 12:05:25 +0200 Subject: [PATCH 3/9] TF-M patch: Fix tfm_ns_lock_init issue (TF-M issue #239) - Link to bug tracking: https://developer.trustedfirmware.org/T239 (cherry picked from commit 5f2e4b3911ca3a776fab55a6d12054904614cced) (cherry picked from commit 5d41a2aeae71b13f2763bea4e55899646291e0eb) --- .../COMPONENT_NSPE/interface/src/tfm_ns_lock_rtx.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/components/TARGET_PSA/TARGET_TFM/COMPONENT_NSPE/interface/src/tfm_ns_lock_rtx.c b/components/TARGET_PSA/TARGET_TFM/COMPONENT_NSPE/interface/src/tfm_ns_lock_rtx.c index 14fd76a0d6..0c677623aa 100644 --- a/components/TARGET_PSA/TARGET_TFM/COMPONENT_NSPE/interface/src/tfm_ns_lock_rtx.c +++ b/components/TARGET_PSA/TARGET_TFM/COMPONENT_NSPE/interface/src/tfm_ns_lock_rtx.c @@ -6,9 +6,9 @@ */ #include #include - +#include "cmsis.h" +#include "rtx_os.h" #include "cmsis_os2.h" - #include "tfm_api.h" #include "tfm_ns_lock.h" @@ -29,11 +29,14 @@ static struct ns_lock_state ns_lock = {.init=false, .id=NULL}; /** * \brief Mutex properties, NS lock */ + +static osRtxMutex_t ns_lock_cb = { 0 }; + static const osMutexAttr_t ns_lock_attrib = { .name = "ns_lock", .attr_bits = osMutexPrioInherit, - .cb_mem = NULL, - .cb_size = 0U + .cb_mem = &ns_lock_cb, + .cb_size = sizeof(ns_lock_cb) }; /** From 35938a407133fe0c20c25b6fae2836148d1adfca Mon Sep 17 00:00:00 2001 From: Michael Schwarcz Date: Thu, 7 Feb 2019 12:10:03 +0200 Subject: [PATCH 4/9] TF-M patch: Fix service handles not cleared issue (TF-M issue #230) - Link to bug tracking: https://developer.trustedfirmware.org/T230 (cherry picked from commit 0c23e8698958b6e716114267fbdf6d82a16b6e0c) (cherry picked from commit 9c1e080e39adc7211c8c2c12cd652da3dc124299) --- .../TARGET_TFM/COMPONENT_SPE/secure_fw/core/ipc/tfm_spm.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/components/TARGET_PSA/TARGET_TFM/COMPONENT_SPE/secure_fw/core/ipc/tfm_spm.c b/components/TARGET_PSA/TARGET_TFM/COMPONENT_SPE/secure_fw/core/ipc/tfm_spm.c index e2dbfd13f8..30210d940b 100644 --- a/components/TARGET_PSA/TARGET_TFM/COMPONENT_SPE/secure_fw/core/ipc/tfm_spm.c +++ b/components/TARGET_PSA/TARGET_TFM/COMPONENT_SPE/secure_fw/core/ipc/tfm_spm.c @@ -112,6 +112,8 @@ int32_t tfm_spm_free_conn_handle(struct tfm_spm_service_t *service, /* Remove node from handle list */ tfm_list_del_node(&node->list); + node->rhandle = NULL; + /* Back handle buffer to pool */ tfm_pool_free(node); return IPC_SUCCESS; From 910a402ce6c96b654cb6ae1a5b679e4f856c5419 Mon Sep 17 00:00:00 2001 From: Michael Schwarcz Date: Thu, 7 Feb 2019 12:14:41 +0200 Subject: [PATCH 5/9] TF-M patch: Fix tfm_psa_call_venner wrong argument type (TF-M issue #241) - Link to bug tracking: https://developer.trustedfirmware.org/T241 (cherry picked from commit da01e3411fcf8010f4ae581946cf4b0e7753e024) (cherry picked from commit 280715f9b74ab29459d81edaf02b39e7a6acb13c) --- .../COMPONENT_SPE/secure_fw/ns_callable/tfm_psa_api_veneers.c | 2 +- components/TARGET_PSA/TARGET_TFM/interface/include/tfm_api.h | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/components/TARGET_PSA/TARGET_TFM/COMPONENT_SPE/secure_fw/ns_callable/tfm_psa_api_veneers.c b/components/TARGET_PSA/TARGET_TFM/COMPONENT_SPE/secure_fw/ns_callable/tfm_psa_api_veneers.c index 33e1fdadd5..7d8ff20260 100644 --- a/components/TARGET_PSA/TARGET_TFM/COMPONENT_SPE/secure_fw/ns_callable/tfm_psa_api_veneers.c +++ b/components/TARGET_PSA/TARGET_TFM/COMPONENT_SPE/secure_fw/ns_callable/tfm_psa_api_veneers.c @@ -99,7 +99,7 @@ psa_handle_t tfm_psa_connect_veneer(uint32_t sid, uint32_t minor_version) __tfm_secure_gateway_attributes__ psa_status_t tfm_psa_call_veneer(psa_handle_t handle, const psa_invec *in_vecs, - const psa_invec *out_vecs) + psa_outvec *out_vecs) { TFM_CORE_NS_IPC_REQUEST_VENEER(tfm_svcall_psa_call, handle, in_vecs, out_vecs, 0); diff --git a/components/TARGET_PSA/TARGET_TFM/interface/include/tfm_api.h b/components/TARGET_PSA/TARGET_TFM/interface/include/tfm_api.h index 2ba93c0916..d6ce6893a0 100644 --- a/components/TARGET_PSA/TARGET_TFM/interface/include/tfm_api.h +++ b/components/TARGET_PSA/TARGET_TFM/interface/include/tfm_api.h @@ -110,13 +110,13 @@ psa_handle_t tfm_psa_connect_veneer(uint32_t sid, uint32_t minor_version); * * \param[in] handle Handle to connection * \param[in] in_vecs invec containing pointer/count of input vectors - * \param[in] out_vecs invec containing pointer/count of output vectors + * \param[in] out_vecs outvec containing pointer/count of output vectors * * \return Returns \ref psa_status_t status code */ psa_status_t tfm_psa_call_veneer(psa_handle_t handle, const psa_invec *in_vecs, - const psa_invec *out_vecs); + psa_outvec *out_vecs); /** * \brief Close connection to secure function referenced by a connection handle From cb748c5608cd68a1dbecde5b3b2c1488c3d0d17b Mon Sep 17 00:00:00 2001 From: Devaraj Ranganna Date: Thu, 13 Jun 2019 11:26:31 +0100 Subject: [PATCH 6/9] TF-M patch: Change #if TFM_PSA_API to #ifdef TFM_PSA_API to avoid compiler errors as mbed-cli only generates "-D" macros only for "macros" defined in targets.json TF-M task link: https://developer.trustedfirmware.org/T396 Signed-off-by: Devaraj Ranganna --- .../TARGET_TFM/COMPONENT_SPE/secure_fw/core/tfm_nspm.c | 2 +- .../TARGET_PSA/TARGET_TFM/COMPONENT_SPE/secure_fw/spm/spm_api.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/components/TARGET_PSA/TARGET_TFM/COMPONENT_SPE/secure_fw/core/tfm_nspm.c b/components/TARGET_PSA/TARGET_TFM/COMPONENT_SPE/secure_fw/core/tfm_nspm.c index 3db30c2bc0..027726585c 100644 --- a/components/TARGET_PSA/TARGET_TFM/COMPONENT_SPE/secure_fw/core/tfm_nspm.c +++ b/components/TARGET_PSA/TARGET_TFM/COMPONENT_SPE/secure_fw/core/tfm_nspm.c @@ -9,7 +9,7 @@ #include #include "secure_utilities.h" #include "tfm_api.h" -#if TFM_PSA_API +#ifdef TFM_PSA_API #include "tfm_utils.h" #include "tfm_internal.h" #endif diff --git a/components/TARGET_PSA/TARGET_TFM/COMPONENT_SPE/secure_fw/spm/spm_api.c b/components/TARGET_PSA/TARGET_TFM/COMPONENT_SPE/secure_fw/spm/spm_api.c index ec70a1ca2e..f589cd9a2f 100644 --- a/components/TARGET_PSA/TARGET_TFM/COMPONENT_SPE/secure_fw/spm/spm_api.c +++ b/components/TARGET_PSA/TARGET_TFM/COMPONENT_SPE/secure_fw/spm/spm_api.c @@ -112,7 +112,7 @@ enum spm_err_t tfm_spm_db_init(void) part_ptr = &(g_spm_partition_db.partitions[ g_spm_partition_db.partition_count]); part_ptr->static_data.partition_id = TFM_SP_NON_SECURE_ID; -#if TFM_PSA_API +#ifdef TFM_PSA_API part_ptr->static_data.partition_flags = SPM_PART_FLAG_APP_ROT | SPM_PART_FLAG_IPC; part_ptr->static_data.partition_priority = TFM_PRIORITY_LOW; From 9a5110561a60ec9f663079a25ec54f7ad0832743 Mon Sep 17 00:00:00 2001 From: Devaraj Ranganna Date: Thu, 13 Jun 2019 16:26:09 +0100 Subject: [PATCH 7/9] TF-M patch: Remove secure_fw/core/tfm_func_api.c which is required only when TFM_PSA_API is not set Signed-off-by: Devaraj Ranganna --- .../secure_fw/core/tfm_func_api.c | 1036 ----------------- 1 file changed, 1036 deletions(-) delete mode 100644 components/TARGET_PSA/TARGET_TFM/COMPONENT_SPE/secure_fw/core/tfm_func_api.c diff --git a/components/TARGET_PSA/TARGET_TFM/COMPONENT_SPE/secure_fw/core/tfm_func_api.c b/components/TARGET_PSA/TARGET_TFM/COMPONENT_SPE/secure_fw/core/tfm_func_api.c deleted file mode 100644 index aeaf5f2e3d..0000000000 --- a/components/TARGET_PSA/TARGET_TFM/COMPONENT_SPE/secure_fw/core/tfm_func_api.c +++ /dev/null @@ -1,1036 +0,0 @@ -/* - * Copyright (c) 2017-2019, Arm Limited. All rights reserved. - * - * SPDX-License-Identifier: BSD-3-Clause - * - */ - -#include -#include -#include -#include -#include "tfm_secure_api.h" -#include "tfm_nspm.h" -#include "secure_utilities.h" -#include "uart_stdout.h" -#include "secure_fw/spm/spm_api.h" -#include "region_defs.h" -#include "tfm_api.h" - -#define EXC_RETURN_SECURE_FUNCTION 0xFFFFFFFD - -#ifndef TFM_LVL -#error TFM_LVL is not defined! -#endif - -/* Macros to pick linker symbols and allow references to sections */ -#define REGION(a, b, c) a##b##c -#define REGION_NAME(a, b, c) REGION(a, b, c) -#define REGION_DECLARE(a, b, c) extern uint32_t REGION_NAME(a, b, c) - -REGION_DECLARE(Image$$, TFM_UNPRIV_SCRATCH, $$ZI$$Base); -REGION_DECLARE(Image$$, TFM_UNPRIV_SCRATCH, $$ZI$$Limit); - -#if TFM_LVL == 1 -REGION_DECLARE(Image$$, TFM_SECURE_STACK, $$ZI$$Base); -REGION_DECLARE(Image$$, TFM_SECURE_STACK, $$ZI$$Limit); -#endif - -/* This is the "Big Lock" on the secure side, to guarantee single entry - * to SPE - */ -extern int32_t tfm_secure_lock; -static int32_t tfm_secure_api_initializing = 1; - -static int32_t is_iovec_api_call(void) -{ - uint32_t current_partition_idx = - tfm_spm_partition_get_running_partition_idx(); - const struct spm_partition_runtime_data_t *curr_part_data = - tfm_spm_partition_get_runtime_data(current_partition_idx); - return curr_part_data->iovec_api; -} - -static uint32_t *prepare_partition_ctx( - const struct tfm_exc_stack_t *svc_ctx, - const struct tfm_sfn_req_s *desc_ptr, - uint32_t *dst) -{ - /* XPSR = as was when called, but make sure it's thread mode */ - *(--dst) = svc_ctx->XPSR & 0xFFFFFE00U; - /* ReturnAddress = resume veneer in new context */ - *(--dst) = svc_ctx->RetAddr; - /* LR = sfn address */ - *(--dst) = (uint32_t)desc_ptr->sfn; - /* R12 = don't care */ - *(--dst) = 0; - - /* R0-R3 = sfn arguments */ - int32_t i = 4; - - while (i > 0) { - i--; - *(--dst) = (uint32_t)desc_ptr->args[i]; - } - return dst; -} - -static uint32_t *prepare_partition_iovec_ctx( - const struct tfm_exc_stack_t *svc_ctx, - const struct tfm_sfn_req_s *desc_ptr, - const struct iovec_args_t *iovec_args, - uint32_t *dst) -{ - /* XPSR = as was when called, but make sure it's thread mode */ - *(--dst) = svc_ctx->XPSR & 0xFFFFFE00U; - /* ReturnAddress = resume veneer in new context */ - *(--dst) = svc_ctx->RetAddr; - /* LR = sfn address */ - *(--dst) = (uint32_t)desc_ptr->sfn; - /* R12 = don't care */ - *(--dst) = 0U; - - /* R0-R3 = sfn arguments */ - *(--dst) = iovec_args->out_len; - *(--dst) = (uint32_t)iovec_args->out_vec; - *(--dst) = iovec_args->in_len; - *(--dst) = (uint32_t)iovec_args->in_vec; - - return dst; -} - -static void restore_caller_ctx( - const struct tfm_exc_stack_t *svc_ctx, - struct tfm_exc_stack_t *target_ctx) -{ - /* ReturnAddress = resume veneer after second SVC */ - target_ctx->RetAddr = svc_ctx->RetAddr; - - /* R0 = function return value */ - target_ctx->R0 = svc_ctx->R0; - - return; -} - -/** \brief Check whether the iovec parameters are valid, and the memory ranges - * are in the posession of the calling partition - * - * \param[in] desc_ptr The secure function request descriptor - * - * \return Return /ref TFM_SUCCESS if the iovec parameters are valid, error code - * otherwise as in /ref tfm_status_e - */ -static int32_t tfm_core_check_sfn_parameters( - const struct tfm_sfn_req_s *desc_ptr) -{ - struct psa_invec *in_vec = (psa_invec *)desc_ptr->args[0]; - size_t in_len; - struct psa_outvec *out_vec = (psa_outvec *)desc_ptr->args[2]; - size_t out_len; - - uint32_t i; - - if ((desc_ptr->args[1] < 0) || (desc_ptr->args[3] < 0)) { - return TFM_ERROR_INVALID_PARAMETER; - } - - in_len = (size_t)(desc_ptr->args[1]); - out_len = (size_t)(desc_ptr->args[3]); - - /* The number of vectors are within range. Extra checks to avoid overflow */ - if ((in_len > PSA_MAX_IOVEC) || (out_len > PSA_MAX_IOVEC) || - (in_len + out_len > PSA_MAX_IOVEC)) { - return TFM_ERROR_INVALID_PARAMETER; - } - - /* Check whether the caller partition has at write access to the iovec - * structures themselves. Use the TT instruction for this. - */ - if (in_len > 0) { - if ((in_vec == NULL) || - (tfm_core_has_write_access_to_region(in_vec, - sizeof(psa_invec)*in_len, desc_ptr->ns_caller, - TFM_PARTITION_UNPRIVILEGED_MODE) != TFM_SUCCESS)) { - return TFM_ERROR_INVALID_PARAMETER; - } - } else { - if (in_vec != NULL) { - return TFM_ERROR_INVALID_PARAMETER; - } - } - if (out_len > 0) { - if ((out_vec == NULL) || - (tfm_core_has_write_access_to_region(out_vec, - sizeof(psa_outvec)*out_len, desc_ptr->ns_caller, - TFM_PARTITION_UNPRIVILEGED_MODE) != TFM_SUCCESS)) { - return TFM_ERROR_INVALID_PARAMETER; - } - } else { - if (out_vec != NULL) { - return TFM_ERROR_INVALID_PARAMETER; - } - } - - /* Check whether the caller partition has access to the data inside the - * iovecs - */ - for (i = 0; i < in_len; ++i) { - if (in_vec[i].len > 0) { - if ((in_vec[i].base == NULL) || - (tfm_core_has_read_access_to_region(in_vec[i].base, - in_vec[i].len, desc_ptr->ns_caller, - TFM_PARTITION_UNPRIVILEGED_MODE) != TFM_SUCCESS)) { - return TFM_ERROR_INVALID_PARAMETER; - } - } - } - for (i = 0; i < out_len; ++i) { - if (out_vec[i].len > 0) { - if ((out_vec[i].base == NULL) || - (tfm_core_has_write_access_to_region(out_vec[i].base, - out_vec[i].len, desc_ptr->ns_caller, - TFM_PARTITION_UNPRIVILEGED_MODE) != TFM_SUCCESS)) { - return TFM_ERROR_INVALID_PARAMETER; - } - } - } - - return TFM_SUCCESS; -} - -static void tfm_copy_iovec_parameters(struct iovec_args_t *target, - const struct iovec_args_t *source) -{ - size_t i; - - target->in_len = source->in_len; - for (i = 0; i < source->in_len; ++i) { - target->in_vec[i].base = source->in_vec[i].base; - target->in_vec[i].len = source->in_vec[i].len; - } - target->out_len = source->out_len; - for (i = 0; i < source->out_len; ++i) { - target->out_vec[i].base = source->out_vec[i].base; - target->out_vec[i].len = source->out_vec[i].len; - } -} - -static void tfm_clear_iovec_parameters(struct iovec_args_t *args) -{ - int i; - - args->in_len = 0; - for (i = 0; i < PSA_MAX_IOVEC; ++i) { - args->in_vec[i].base = NULL; - args->in_vec[i].len = 0; - } - args->out_len = 0; - for (i = 0; i < PSA_MAX_IOVEC; ++i) { - args->out_vec[i].base = NULL; - args->out_vec[i].len = 0; - } -} - -static int32_t tfm_start_partition(const struct tfm_sfn_req_s *desc_ptr, - uint32_t excReturn) -{ - uint32_t caller_partition_idx = desc_ptr->caller_part_idx; - const struct spm_partition_runtime_data_t *curr_part_data; - uint32_t caller_flags; - register uint32_t partition_idx; - uint32_t psp; - uint32_t partition_psp, partition_psplim; - uint32_t partition_state; - uint32_t partition_flags; - struct tfm_exc_stack_t *svc_ctx; - uint32_t caller_partition_id; - int32_t client_id; - struct iovec_args_t *iovec_args; - - psp = __get_PSP(); - svc_ctx = (struct tfm_exc_stack_t *)psp; - caller_flags = tfm_spm_partition_get_flags(caller_partition_idx); - - /* Check partition state consistency */ - if (((caller_flags & SPM_PART_FLAG_APP_ROT) != 0) - != (!desc_ptr->ns_caller)) { - /* Partition state inconsistency detected */ - return TFM_SECURE_LOCK_FAILED; - } - - if ((caller_flags & SPM_PART_FLAG_APP_ROT) == 0) { - /* Disable NS exception handling while secure service is running. - * FixMe: - * This restriction is applied to limit the number of possible attack - * vectors. - * To be removed when pre-emption and context management issues have - * been analysed and resolved. - */ - TFM_NS_EXC_DISABLE(); - } - - partition_idx = get_partition_idx(desc_ptr->sp_id); - - curr_part_data = tfm_spm_partition_get_runtime_data(partition_idx); - partition_state = curr_part_data->partition_state; - partition_flags = tfm_spm_partition_get_flags(partition_idx); - caller_partition_id = tfm_spm_partition_get_partition_id( - caller_partition_idx); - - if (tfm_secure_api_initializing) { -#if TFM_LVL != 1 - /* Make thread mode unprivileged while untrusted partition init is - * executed - */ - if ((partition_flags & SPM_PART_FLAG_PSA_ROT) == 0) { - tfm_spm_partition_change_privilege( - TFM_PARTITION_UNPRIVILEGED_MODE); - } -#endif - } else if (partition_state == SPM_PARTITION_STATE_RUNNING || - partition_state == SPM_PARTITION_STATE_SUSPENDED || - partition_state == SPM_PARTITION_STATE_BLOCKED) { - /* Recursion is not permitted! */ - return TFM_ERROR_PARTITION_NON_REENTRANT; - } else if (partition_state != SPM_PARTITION_STATE_IDLE) { - /* The partition to be called is not in a proper state */ - return TFM_SECURE_LOCK_FAILED; - } - -#if TFM_LVL == 1 - /* Prepare switch to shared secure partition stack */ - /* In case the call is coming from the non-secure world, we save the iovecs - * on the stop of the stack. So the memory area, that can actually be used - * as stack by the partitions starts at a lower address - */ - partition_psp = - (uint32_t)®ION_NAME(Image$$, TFM_SECURE_STACK, $$ZI$$Limit)- - sizeof(struct iovec_args_t); - partition_psplim = - (uint32_t)®ION_NAME(Image$$, TFM_SECURE_STACK, $$ZI$$Base); -#else - partition_psp = curr_part_data->stack_ptr; - partition_psplim = tfm_spm_partition_get_stack_bottom(partition_idx); -#endif - /* Store the context for the partition call */ - tfm_spm_partition_set_caller_partition_idx(partition_idx, - caller_partition_idx); - tfm_spm_partition_store_context(caller_partition_idx, psp, excReturn); - - if ((caller_flags & SPM_PART_FLAG_APP_ROT)) { - tfm_spm_partition_set_caller_client_id(partition_idx, - caller_partition_id); - } else { - client_id = tfm_nspm_get_current_client_id(); - if (client_id >= 0) { - return TFM_SECURE_LOCK_FAILED; - } - tfm_spm_partition_set_caller_client_id(partition_idx, client_id); - } - -#if (TFM_LVL != 1) && (TFM_LVL != 2) - /* Dynamic partitioning is only done is TFM level 3 */ - tfm_spm_partition_sandbox_deconfig(caller_partition_idx); - - /* Configure partition execution environment */ - if (tfm_spm_partition_sandbox_config(partition_idx) != SPM_ERR_OK) { - ERROR_MSG("Failed to configure sandbox for partition!"); - tfm_secure_api_error_handler(); - } -#endif - - /* Default share to scratch area in case of partition to partition calls - * this way partitions always get default access to input buffers - */ - /* FixMe: return value/error handling TBD */ - tfm_spm_partition_set_share(partition_idx, desc_ptr->ns_caller ? - TFM_BUFFER_SHARE_NS_CODE : TFM_BUFFER_SHARE_SCRATCH); - -#if TFM_LVL == 1 - /* In level one, only switch context and return from exception if in - * handler mode - */ - if ((desc_ptr->ns_caller) || (tfm_secure_api_initializing)) { - if (desc_ptr->iovec_api == TFM_SFN_API_IOVEC) { - /* Save the iovecs on the common stack. The vectors had been sanity - * checked already, and since then the interrupts have been kept - * disabled. So we can be sure that the vectors haven't been - * tampered with since the check. - */ - iovec_args = (struct iovec_args_t *) - ((uint32_t)®ION_NAME(Image$$, TFM_SECURE_STACK, $$ZI$$Limit)- - sizeof(struct iovec_args_t)); - if (tfm_spm_partition_set_iovec(partition_idx, desc_ptr->args) != - SPM_ERR_OK) { - return TFM_ERROR_GENERIC; - } - tfm_copy_iovec_parameters(iovec_args, - &(curr_part_data->iovec_args)); - - /* Prepare the partition context, update stack ptr */ - psp = (uint32_t)prepare_partition_iovec_ctx(svc_ctx, desc_ptr, - iovec_args, - (uint32_t *)partition_psp); - } else { - /* Prepare the partition context, update stack ptr */ - psp = (uint32_t)prepare_partition_ctx(svc_ctx, desc_ptr, - (uint32_t *)partition_psp); - } - __set_PSP(psp); - __set_PSPLIM(partition_psplim); - } -#else - if (desc_ptr->iovec_api == TFM_SFN_API_IOVEC) { - /* Save the iovecs on the stack of the partition. The vectors had been - * sanity checked already, and since then the interrupts have been kept - * disabled. So we can be sure that the vectors haven't been tampered - * with since the check. - */ - iovec_args = - (struct iovec_args_t *)(tfm_spm_partition_get_stack_top(partition_idx) - - sizeof(struct iovec_args_t)); - if (tfm_spm_partition_set_iovec(partition_idx, desc_ptr->args) != - SPM_ERR_OK) { - return TFM_ERROR_GENERIC; - } - tfm_copy_iovec_parameters(iovec_args, &(curr_part_data->iovec_args)); - - /* Prepare the partition context, update stack ptr */ - psp = (uint32_t)prepare_partition_iovec_ctx(svc_ctx, desc_ptr, - iovec_args, - (uint32_t *)partition_psp); - } else { - /* Prepare the partition context, update stack ptr */ - psp = (uint32_t)prepare_partition_ctx(svc_ctx, desc_ptr, - (uint32_t *)partition_psp); - } - __set_PSP(psp); - __set_PSPLIM(partition_psplim); -#endif - - tfm_spm_partition_set_state(caller_partition_idx, - SPM_PARTITION_STATE_BLOCKED); - tfm_spm_partition_set_state(partition_idx, SPM_PARTITION_STATE_RUNNING); - tfm_secure_lock++; - - return TFM_SUCCESS; -} - -static int32_t tfm_return_from_partition(uint32_t *excReturn) -{ - uint32_t current_partition_idx = - tfm_spm_partition_get_running_partition_idx(); - const struct spm_partition_runtime_data_t *curr_part_data, *ret_part_data; - uint32_t current_partition_flags; - uint32_t return_partition_idx; - uint32_t return_partition_flags; - uint32_t psp = __get_PSP(); - size_t i; - struct tfm_exc_stack_t *svc_ctx = (struct tfm_exc_stack_t *)psp; - struct iovec_args_t *iovec_args; - - if (current_partition_idx == SPM_INVALID_PARTITION_IDX) { - return TFM_SECURE_UNLOCK_FAILED; - } - - curr_part_data = tfm_spm_partition_get_runtime_data(current_partition_idx); - return_partition_idx = curr_part_data->caller_partition_idx; - - if (return_partition_idx == SPM_INVALID_PARTITION_IDX) { - return TFM_SECURE_UNLOCK_FAILED; - } - - ret_part_data = tfm_spm_partition_get_runtime_data(return_partition_idx); - - return_partition_flags = tfm_spm_partition_get_flags(return_partition_idx); - current_partition_flags = tfm_spm_partition_get_flags( - current_partition_idx); - - tfm_secure_lock--; - - if ((return_partition_flags & SPM_PART_FLAG_APP_ROT) == 0) { - /* Re-enable NS exceptions when secure service returns to NS client. - * FixMe: - * To be removed when pre-emption and context management issues have - * been analysed and resolved. - */ - TFM_NS_EXC_ENABLE(); - } - -#if (TFM_LVL != 1) && (TFM_LVL != 2) - /* Deconfigure completed partition environment */ - tfm_spm_partition_sandbox_deconfig(current_partition_idx); - if (tfm_secure_api_initializing) { - /* Restore privilege for thread mode during TF-M init. This is only - * have to be done if the partition is not trusted. - */ - if ((current_partition_flags & SPM_PART_FLAG_PSA_ROT) == 0) { - tfm_spm_partition_change_privilege(TFM_PARTITION_PRIVILEGED_MODE); - } - } else { - /* Configure the caller partition environment in case this was a - * partition to partition call and returning to untrusted partition - */ - if (tfm_spm_partition_sandbox_config(return_partition_idx) - != SPM_ERR_OK) { - ERROR_MSG("Failed to configure sandbox for partition!"); - tfm_secure_api_error_handler(); - } - if (return_partition_flags & SPM_PART_FLAG_APP_ROT) { - /* Restore share status */ - tfm_spm_partition_set_share( - return_partition_idx, - tfm_spm_partition_get_runtime_data( - return_partition_idx)->share); - } - } -#endif - -#if TFM_LVL == 1 - if (!(return_partition_flags & SPM_PART_FLAG_APP_ROT) || - (tfm_secure_api_initializing)) { - /* In TFM level 1 context restore is only done when - * returning to NS or after initialization - */ - /* Restore caller context */ - restore_caller_ctx(svc_ctx, - (struct tfm_exc_stack_t *)ret_part_data->stack_ptr); - *excReturn = ret_part_data->lr; - __set_PSP(ret_part_data->stack_ptr); - extern uint32_t Image$$ARM_LIB_STACK$$ZI$$Base[]; - uint32_t psp_stack_bottom = (uint32_t)Image$$ARM_LIB_STACK$$ZI$$Base; - __set_PSPLIM(psp_stack_bottom); - - /* FIXME: The condition should be removed once all the secure service - * calls are done via the iovec veneers - */ - if (curr_part_data->iovec_api) { - iovec_args = (struct iovec_args_t *) - ((uint32_t)®ION_NAME(Image$$, TFM_SECURE_STACK, $$ZI$$Limit) - - sizeof(struct iovec_args_t)); - - for (i = 0; i < curr_part_data->iovec_args.out_len; ++i) { - curr_part_data->orig_outvec[i].len = iovec_args->out_vec[i].len; - } - tfm_clear_iovec_parameters(iovec_args); - } - } -#else - /* Restore caller context */ - restore_caller_ctx(svc_ctx, - (struct tfm_exc_stack_t *)ret_part_data->stack_ptr); - *excReturn = ret_part_data->lr; - __set_PSP(ret_part_data->stack_ptr); - __set_PSPLIM(tfm_spm_partition_get_stack_bottom(return_partition_idx)); - /* Clear the context entry before returning */ - tfm_spm_partition_set_stack( - current_partition_idx, psp + sizeof(struct tfm_exc_stack_t)); - - /* FIXME: The condition should be removed once all the secure service - * calls are done via the iovec veneers */ - if (curr_part_data->iovec_api) { - iovec_args = (struct iovec_args_t *) - (tfm_spm_partition_get_stack_top(current_partition_idx) - - sizeof(struct iovec_args_t)); - - for (i = 0; i < curr_part_data->iovec_args.out_len; ++i) { - curr_part_data->orig_outvec[i].len = iovec_args->out_vec[i].len; - } - tfm_clear_iovec_parameters(iovec_args); - } -#endif - - tfm_spm_partition_cleanup_context(current_partition_idx); - - tfm_spm_partition_set_state(current_partition_idx, - SPM_PARTITION_STATE_IDLE); - tfm_spm_partition_set_state(return_partition_idx, - SPM_PARTITION_STATE_RUNNING); - - return TFM_SUCCESS; -} - -static int32_t tfm_check_sfn_req_integrity(const struct tfm_sfn_req_s *desc_ptr) -{ - if ((desc_ptr == NULL) || - (desc_ptr->sp_id == 0) || - (desc_ptr->sfn == NULL)) { - /* invalid parameter */ - return TFM_ERROR_INVALID_PARAMETER; - } - return TFM_SUCCESS; -} - -static int32_t tfm_core_check_sfn_req_rules( - const struct tfm_sfn_req_s *desc_ptr) -{ - /* Check partition idx validity */ - if (desc_ptr->caller_part_idx == SPM_INVALID_PARTITION_IDX) { - return TFM_ERROR_NO_ACTIVE_PARTITION; - } - - if ((desc_ptr->ns_caller) && (tfm_secure_lock != 0)) { - /* Secure domain is already locked! - * This should only happen if caller is secure partition! - * FixMe: This scenario is a potential security breach - * Take appropriate action! - */ - return TFM_ERROR_SECURE_DOMAIN_LOCKED; - } - - if (tfm_secure_api_initializing) { - int32_t id = - tfm_spm_partition_get_partition_id(desc_ptr->caller_part_idx); - - if ((id != TFM_SP_CORE_ID) || (tfm_secure_lock != 0)) { - /* Invalid request during system initialization */ - ERROR_MSG("Invalid service request during initialization!"); - return TFM_ERROR_NOT_INITIALIZED; - } - } - - return TFM_SUCCESS; -} - -void tfm_secure_api_init_done(void) -{ - tfm_secure_api_initializing = 0; -#if TFM_LVL != 1 - if (tfm_spm_partition_sandbox_config(TFM_SP_NON_SECURE_ID) != SPM_ERR_OK) { - ERROR_MSG("Failed to configure sandbox for partition!"); - tfm_secure_api_error_handler(); - } -#endif -} - -int32_t tfm_core_sfn_request_handler( - struct tfm_sfn_req_s *desc_ptr, uint32_t excReturn) -{ - int32_t res; - - res = tfm_check_sfn_req_integrity(desc_ptr); - if (res != TFM_SUCCESS) { - ERROR_MSG("Invalid service request!"); - tfm_secure_api_error_handler(); - } - - __disable_irq(); - - desc_ptr->caller_part_idx = tfm_spm_partition_get_running_partition_idx(); - - if (desc_ptr->iovec_api == TFM_SFN_API_IOVEC) { - res = tfm_core_check_sfn_parameters(desc_ptr); - if (res != TFM_SUCCESS) { - /* The sanity check of iovecs failed. */ - __enable_irq(); - tfm_secure_api_error_handler(); - } - } - - res = tfm_core_check_sfn_req_rules(desc_ptr); - if (res != TFM_SUCCESS) { - /* FixMe: error compartmentalization TBD */ - tfm_spm_partition_set_state( - desc_ptr->caller_part_idx, SPM_PARTITION_STATE_CLOSED); - __enable_irq(); - ERROR_MSG("Unauthorized service request!"); - tfm_secure_api_error_handler(); - } - - res = tfm_start_partition(desc_ptr, excReturn); - if (res != TFM_SUCCESS) { - /* FixMe: consider possible fault scenarios */ - __enable_irq(); - ERROR_MSG("Failed to process service request!"); - tfm_secure_api_error_handler(); - } - - __enable_irq(); - - return res; -} - -#if TFM_LVL == 1 -int32_t tfm_core_sfn_request_thread_mode(struct tfm_sfn_req_s *desc_ptr) -{ - int32_t res; - int32_t *args; - int32_t retVal; - - if (desc_ptr->iovec_api == TFM_SFN_API_IOVEC) { - res = tfm_core_check_sfn_parameters(desc_ptr); - if (res != TFM_SUCCESS) { - /* The sanity check of iovecs failed. */ - return res; - } - } - - /* No excReturn value is needed as no exception handling is used */ - res = tfm_core_sfn_request_handler(desc_ptr, 0); - - if (res != TFM_SUCCESS) { - tfm_secure_api_error_handler(); - } - - /* Secure partition to secure partition call in TFM level 1 */ - args = desc_ptr->args; - retVal = desc_ptr->sfn(args[0], args[1], args[2], args[3]); - - /* return handler should restore original exc_return value... */ - res = tfm_return_from_partition(NULL); - if (res == TFM_SUCCESS) { - /* If unlock successful, pass SS return value to caller */ - res = retVal; - } else { - /* Unlock errors indicate ctx database corruption or unknown - * anomalies. Halt execution - */ - ERROR_MSG("Secure API error during unlock!"); - tfm_secure_api_error_handler(); - } - return res; -} -#endif - -void tfm_core_validate_secure_caller_handler(uint32_t *svc_args) -{ - - int32_t res = TFM_ERROR_GENERIC; - uint32_t running_partition_idx = - tfm_spm_partition_get_running_partition_idx(); - const struct spm_partition_runtime_data_t *curr_part_data = - tfm_spm_partition_get_runtime_data(running_partition_idx); - uint32_t running_partition_flags = - tfm_spm_partition_get_flags(running_partition_idx); - uint32_t caller_partition_flags = - tfm_spm_partition_get_flags(curr_part_data->caller_partition_idx); - - if (!(running_partition_flags & SPM_PART_FLAG_APP_ROT)) { - /* This handler shouldn't be called from outside partition context. - * Partitions are only allowed to run while S domain is locked. - */ - svc_args[0] = TFM_ERROR_INVALID_PARAMETER; - return; - } - - /* Store return value in r0 */ - if (caller_partition_flags & SPM_PART_FLAG_APP_ROT) { - res = TFM_SUCCESS; - } - svc_args[0] = res; -} - -int32_t tfm_core_check_buffer_access(uint32_t partition_idx, - void *start_addr, - size_t len, - uint32_t alignment) -{ - uintptr_t start_addr_value = (uintptr_t)start_addr; - uintptr_t end_addr_value = (uintptr_t)start_addr + len; - uintptr_t alignment_mask; - - alignment_mask = (((uintptr_t)1) << alignment) - 1; - - /* Check that the pointer is aligned properly */ - if (start_addr_value & alignment_mask) { - /* not aligned, return error */ - return 0; - } - - /* Protect against overflow (and zero len) */ - if (end_addr_value <= start_addr_value) { - return 0; - } - -#if TFM_LVL == 1 - /* For privileged partition execution, all secure data memory and stack - * is accessible - */ - if (start_addr_value >= S_DATA_START && - end_addr_value <= (S_DATA_START + S_DATA_SIZE)) { - return 1; - } -#else - /* For non-privileged execution the partition's data and stack is - * accessible - */ - if (start_addr_value >= - tfm_spm_partition_get_stack_bottom(partition_idx) && - end_addr_value <= - tfm_spm_partition_get_stack_top(partition_idx)) { - return 1; - } - if (start_addr_value >= - tfm_spm_partition_get_rw_start(partition_idx) && - end_addr_value <= - tfm_spm_partition_get_rw_limit(partition_idx)) { - return 1; - } - if (start_addr_value >= - tfm_spm_partition_get_zi_start(partition_idx) && - end_addr_value <= - tfm_spm_partition_get_zi_limit(partition_idx)) { - return 1; - } -#endif - return 0; -} - -void tfm_core_get_caller_client_id_handler(uint32_t *svc_args) -{ - uintptr_t result_ptr_value = svc_args[0]; - uint32_t running_partition_idx = - tfm_spm_partition_get_running_partition_idx(); - const uint32_t running_partition_flags = - tfm_spm_partition_get_flags(running_partition_idx); - const struct spm_partition_runtime_data_t *curr_part_data = - tfm_spm_partition_get_runtime_data(running_partition_idx); - int res = 0; - - if (!(running_partition_flags & SPM_PART_FLAG_APP_ROT)) { - /* This handler shouldn't be called from outside partition context. - * Partitions are only allowed to run while S domain is locked. - */ - svc_args[0] = TFM_ERROR_INVALID_PARAMETER; - return; - } - - /* Make sure that the output pointer points to a memory area that is owned - * by the partition - */ - res = tfm_core_check_buffer_access(running_partition_idx, - (void *)result_ptr_value, - sizeof(curr_part_data->caller_client_id), - 2); - if (!res) { - /* Not in accessible range, return error */ - svc_args[0] = TFM_ERROR_INVALID_PARAMETER; - return; - } - - *((int32_t *)result_ptr_value) = curr_part_data->caller_client_id; - - /* Store return value in r0 */ - svc_args[0] = TFM_SUCCESS; -} - -void tfm_core_memory_permission_check_handler(uint32_t *svc_args) -{ - uint32_t ptr = svc_args[0]; - uint32_t size = svc_args[1]; - int32_t access = svc_args[2]; - - uint32_t max_buf_size, ptr_start, range_limit, range_check = false; - int32_t res; - uint32_t running_partition_idx = - tfm_spm_partition_get_running_partition_idx(); - const struct spm_partition_runtime_data_t *curr_part_data = - tfm_spm_partition_get_runtime_data(running_partition_idx); - uint32_t running_partition_flags = - tfm_spm_partition_get_flags(running_partition_idx); - int32_t flags = 0; - void *rangeptr; - - if (!(running_partition_flags & SPM_PART_FLAG_APP_ROT) || (size == 0)) { - /* This handler should only be called from a secure partition. */ - svc_args[0] = TFM_ERROR_INVALID_PARAMETER; - return; - } - - if (curr_part_data->share != TFM_BUFFER_SHARE_PRIV) { - flags |= CMSE_MPU_UNPRIV; - } - - if (access == TFM_MEMORY_ACCESS_RW) { - flags |= CMSE_MPU_READWRITE; - } else { - flags |= CMSE_MPU_READ; - } - - /* Check if partition access to address would fail */ - rangeptr = cmse_check_address_range((void *)ptr, size, flags); - - /* Get regions associated with address */ - cmse_address_info_t addr_info = cmse_TT((void *)ptr); - - if (rangeptr == NULL) { - svc_args[0] = TFM_ERROR_INVALID_PARAMETER; - return; - } - - if (addr_info.flags.secure) { -#if TFM_LVL == 1 - /* For privileged partition execution, all secure data memory is - * accessible - */ - max_buf_size = S_DATA_SIZE; - ptr_start = S_DATA_START; - range_limit = S_DATA_LIMIT; -#else - /* Only scratch is permitted in secure memory */ - max_buf_size = (uint32_t)tfm_scratch_area_size; - ptr_start = (uint32_t)tfm_scratch_area; - range_limit = (uint32_t)tfm_scratch_area + tfm_scratch_area_size - 1; -#endif - range_check = true; - } else { - if (!addr_info.flags.sau_region_valid) { - /* If address is NS, TF-M expects SAU to be configured - */ - svc_args[0] = TFM_ERROR_INVALID_PARAMETER; - return; - } - switch (addr_info.flags.sau_region) { - case TFM_NS_REGION_CODE: - if (access == TFM_MEMORY_ACCESS_RW) { - res = TFM_ERROR_INVALID_PARAMETER; - } else { - /* Currently TF-M does not support checks for NS Memory - * accesses by partitions - */ - res = TFM_SUCCESS; - } - break; - case TFM_NS_REGION_DATA: - /* Currently TF-M does not support checks for NS Memory - * accesses by partitions - */ - res = TFM_SUCCESS; - break; - default: - /* Only NS data and code regions can be accessed as buffers */ - res = TFM_ERROR_INVALID_PARAMETER; - break; - } - } - - if (range_check == true) { - if ((size <= max_buf_size) && (ptr >= ptr_start) - && (ptr <= range_limit + 1 - size)) { - res = TFM_SUCCESS; - } else { - res = TFM_ERROR_INVALID_PARAMETER; - } - } - - /* Store return value in r0 */ - svc_args[0] = res; -} - -/* This SVC handler is called if veneer is running in thread mode */ -uint32_t tfm_core_partition_request_svc_handler( - const struct tfm_exc_stack_t *svc_ctx, uint32_t excReturn) -{ - struct tfm_sfn_req_s *desc_ptr; - - if (!(excReturn & EXC_RETURN_STACK_PROCESS)) { - /* Service request SVC called with MSP active. - * Either invalid configuration for Thread mode or SVC called - * from Handler mode, which is not supported. - * FixMe: error severity TBD - */ - ERROR_MSG("Service request SVC called with MSP active!"); - tfm_secure_api_error_handler(); - } - - desc_ptr = (struct tfm_sfn_req_s *)svc_ctx->R0; - - if (tfm_core_sfn_request_handler(desc_ptr, excReturn) != TFM_SUCCESS) { - tfm_secure_api_error_handler(); - } - - return EXC_RETURN_SECURE_FUNCTION; -} - -/* This SVC handler is called when sfn returns */ -uint32_t tfm_core_partition_return_handler(uint32_t lr) -{ - int32_t res; - - if (!(lr & EXC_RETURN_STACK_PROCESS)) { - /* Partition return SVC called with MSP active. - * This should not happen! - */ - ERROR_MSG("Partition return SVC called with MSP active!"); - tfm_secure_api_error_handler(); - } - - /* Store return value from secure partition */ - int32_t retVal = *(int32_t *)__get_PSP(); - - if (!is_iovec_api_call()) { - if ((retVal > TFM_SUCCESS) && - (retVal < TFM_PARTITION_SPECIFIC_ERROR_MIN)) { - /* Secure function returned a reserved value */ -#ifdef TFM_CORE_DEBUG - LOG_MSG("Invalid return value from secure partition!"); -#endif - /* FixMe: error can be traced to specific secure partition - * and Core is not compromised. Error handling flow can be - * refined - */ - tfm_secure_api_error_handler(); - } - } - - res = tfm_return_from_partition(&lr); - if (res != TFM_SUCCESS) { - /* Unlock errors indicate ctx database corruption or unknown anomalies - * Halt execution - */ - ERROR_MSG("Secure API error during unlock!"); - tfm_secure_api_error_handler(); - } - - return lr; -} - -void tfm_core_set_buffer_area_handler(uint32_t *args) -{ - /* r0 is stored in args[0] in exception stack frame - * Store input parameter before writing return value to that address - */ - enum tfm_buffer_share_region_e share; - uint32_t running_partition_idx = - tfm_spm_partition_get_running_partition_idx(); - const struct spm_partition_runtime_data_t *curr_part_data = - tfm_spm_partition_get_runtime_data(running_partition_idx); - uint32_t caller_partition_idx = curr_part_data->caller_partition_idx; - uint32_t running_partition_flags = - tfm_spm_partition_get_flags(running_partition_idx); - uint32_t caller_partition_flags = - tfm_spm_partition_get_flags(caller_partition_idx); - - /* tfm_core_set_buffer_area() returns int32_t */ - int32_t *res_ptr = (int32_t *)&args[0]; - - if (!(running_partition_flags & SPM_PART_FLAG_APP_ROT)) { - /* This handler should only be called from a secure partition. */ - *res_ptr = TFM_ERROR_INVALID_PARAMETER; - return; - } - - switch (args[0]) { - case TFM_BUFFER_SHARE_DEFAULT: - share = (!(caller_partition_flags & SPM_PART_FLAG_APP_ROT)) ? - (TFM_BUFFER_SHARE_NS_CODE) : (TFM_BUFFER_SHARE_SCRATCH); - break; - case TFM_BUFFER_SHARE_SCRATCH: - case TFM_BUFFER_SHARE_NS_CODE: - share = args[0]; - break; - default: - *res_ptr = TFM_ERROR_INVALID_PARAMETER; - return; - } - - if (tfm_spm_partition_set_share(running_partition_idx, share) == - SPM_ERR_OK) { - *res_ptr = TFM_SUCCESS; - } else { - *res_ptr = TFM_ERROR_INVALID_PARAMETER; - } - - return; -} - From 6e899b3cc98c3e1811a160df09abbccddb2fa014 Mon Sep 17 00:00:00 2001 From: Devaraj Ranganna Date: Wed, 26 Jun 2019 14:58:19 +0100 Subject: [PATCH 8/9] TF-M patch/workaround related to (TF-M issue #T240) - Link to bug tracking: https://developer.trustedfirmware.org/T240 The issue is fixed by TF-M team. However they autogenerate region details (code, ro, rw, zi and stack ) using linker scripts and in mbed-os we also autogenerate region details but using mix of service definition in json file and other template files. Signed-off-by: Devaraj Ranganna --- .../COMPONENT_SPE/secure_fw/spm/spm_db.h | 6 +- .../secure_fw/spm/spm_db_setup.h | 102 ++++++++++-------- 2 files changed, 60 insertions(+), 48 deletions(-) diff --git a/components/TARGET_PSA/TARGET_TFM/COMPONENT_SPE/secure_fw/spm/spm_db.h b/components/TARGET_PSA/TARGET_TFM/COMPONENT_SPE/secure_fw/spm/spm_db.h index 6e6e25c801..dfdaf32ca1 100644 --- a/components/TARGET_PSA/TARGET_TFM/COMPONENT_SPE/secure_fw/spm/spm_db.h +++ b/components/TARGET_PSA/TARGET_TFM/COMPONENT_SPE/secure_fw/spm/spm_db.h @@ -68,7 +68,11 @@ struct spm_partition_desc_t { /* Macros to pick linker symbols and allow to form the partition data base */ #define REGION(a, b, c) a##b##c #define REGION_NAME(a, b, c) REGION(a, b, c) -#if (TFM_LVL == 1) && !defined(TFM_PSA_API) +/* Changed from #if (TFM_LVL == 1) && !defined(TFM_PSA_API) to #if (TFM_LVL == 1) to avoid linker error. + TF-M build autogenerates region details (code, ro, rw, zi and stack ) using linker scripts. We do not + hve that in mbed-os build yet. +*/ +#if (TFM_LVL == 1) #define REGION_DECLARE(a, b, c) #else #define REGION_DECLARE(a, b, c) extern uint32_t REGION_NAME(a, b, c) diff --git a/components/TARGET_PSA/TARGET_TFM/COMPONENT_SPE/secure_fw/spm/spm_db_setup.h b/components/TARGET_PSA/TARGET_TFM/COMPONENT_SPE/secure_fw/spm/spm_db_setup.h index db061544e7..2cecfb78b0 100644 --- a/components/TARGET_PSA/TARGET_TFM/COMPONENT_SPE/secure_fw/spm/spm_db_setup.h +++ b/components/TARGET_PSA/TARGET_TFM/COMPONENT_SPE/secure_fw/spm/spm_db_setup.h @@ -38,7 +38,11 @@ struct spm_partition_db_t { data.partition_priority = TFM_PRIORITY(priority); \ } while (0) -#if (TFM_LVL == 1) && !defined(TFM_PSA_API) +/* Changed from #if (TFM_LVL == 1) && !defined(TFM_PSA_API) to #if (TFM_LVL == 1) to avoid linker error. + TF-M build autogenerates region details (code, ro, rw, zi and stack ) using linker scripts. We do not + hve that in mbed-os build yet. +*/ +#if (TFM_LVL == 1) #define PARTITION_INIT_MEMORY_DATA(data, partition) #else #define PARTITION_INIT_MEMORY_DATA(data, partition) \ @@ -75,56 +79,60 @@ struct spm_partition_db_t { } while (0) #endif -#define PARTITION_DECLARE(partition, flag, type, id, priority) \ - do { \ - REGION_DECLARE(Image$$, partition, $$Base); \ - REGION_DECLARE(Image$$, partition, $$Limit); \ - REGION_DECLARE(Image$$, partition, $$RO$$Base); \ - REGION_DECLARE(Image$$, partition, $$RO$$Limit); \ - REGION_DECLARE(Image$$, partition, _DATA$$RW$$Base); \ - REGION_DECLARE(Image$$, partition, _DATA$$RW$$Limit); \ - REGION_DECLARE(Image$$, partition, _DATA$$ZI$$Base); \ - REGION_DECLARE(Image$$, partition, _DATA$$ZI$$Limit); \ - REGION_DECLARE(Image$$, partition, _STACK$$ZI$$Base); \ - REGION_DECLARE(Image$$, partition, _STACK$$ZI$$Limit); \ - int32_t flags = flag; \ - if (tfm_memcmp(type, TFM_PARTITION_TYPE_APP, \ - strlen(TFM_PARTITION_TYPE_APP)) == 0) { \ - flags |= SPM_PART_FLAG_APP_ROT; \ - } else if (tfm_memcmp(type, TFM_PARTITION_TYPE_PSA, \ - strlen(TFM_PARTITION_TYPE_PSA)) == 0) { \ - flags |= SPM_PART_FLAG_PSA_ROT | SPM_PART_FLAG_APP_ROT; \ - } else { \ - return SPM_ERR_INVALID_CONFIG; \ - } \ - struct spm_partition_desc_t *part_ptr; \ - if (g_spm_partition_db.partition_count >= SPM_MAX_PARTITIONS) { \ - return SPM_ERR_INVALID_CONFIG; \ - } \ - part_ptr = &(g_spm_partition_db.partitions[ \ - g_spm_partition_db.partition_count]); \ - PARTITION_INIT_STATIC_DATA(part_ptr->static_data, partition, flags, \ - id, priority); \ - PARTITION_INIT_RUNTIME_DATA(part_ptr->runtime_data, partition); \ - PARTITION_INIT_MEMORY_DATA(part_ptr->memory_data, partition); \ - ++g_spm_partition_db.partition_count; \ +#define PARTITION_DECLARE(partition, flag, type, id, priority, part_stack_size) \ + do { \ + REGION_DECLARE(Image$$, partition, $$Base); \ + REGION_DECLARE(Image$$, partition, $$Limit); \ + REGION_DECLARE(Image$$, partition, $$RO$$Base); \ + REGION_DECLARE(Image$$, partition, $$RO$$Limit); \ + REGION_DECLARE(Image$$, partition, _DATA$$RW$$Base); \ + REGION_DECLARE(Image$$, partition, _DATA$$RW$$Limit); \ + REGION_DECLARE(Image$$, partition, _DATA$$ZI$$Base); \ + REGION_DECLARE(Image$$, partition, _DATA$$ZI$$Limit); \ + REGION_DECLARE(Image$$, partition, _STACK$$ZI$$Base); \ + REGION_DECLARE(Image$$, partition, _STACK$$ZI$$Limit); \ + int32_t flags = flag; \ + if (tfm_memcmp(type, TFM_PARTITION_TYPE_APP, \ + strlen(TFM_PARTITION_TYPE_APP)) == 0) { \ + flags |= SPM_PART_FLAG_APP_ROT; \ + } else if (tfm_memcmp(type, TFM_PARTITION_TYPE_PSA, \ + strlen(TFM_PARTITION_TYPE_PSA)) == 0) { \ + flags |= SPM_PART_FLAG_PSA_ROT | SPM_PART_FLAG_APP_ROT; \ + } else { \ + return SPM_ERR_INVALID_CONFIG; \ + } \ + struct spm_partition_desc_t *part_ptr; \ + if (g_spm_partition_db.partition_count >= SPM_MAX_PARTITIONS) { \ + return SPM_ERR_INVALID_CONFIG; \ + } \ + __attribute__((section(".data.partitions_stacks"))) \ + static uint8_t partition##_stack[part_stack_size] __attribute__((aligned(8))); \ + part_ptr = &(g_spm_partition_db.partitions[ \ + g_spm_partition_db.partition_count]); \ + part_ptr->memory_data.stack_bottom = (uint32_t)partition##_stack; \ + part_ptr->memory_data.stack_top = part_ptr->memory_data.stack_bottom + part_stack_size; \ + PARTITION_INIT_STATIC_DATA(part_ptr->static_data, partition, flags, \ + id, priority); \ + PARTITION_INIT_RUNTIME_DATA(part_ptr->runtime_data, partition); \ + PARTITION_INIT_MEMORY_DATA(part_ptr->memory_data, partition); \ + ++g_spm_partition_db.partition_count; \ } while (0) -#define PARTITION_ADD_INIT_FUNC(partition, init_func) \ - do { \ - extern int32_t init_func(void); \ - uint32_t partition_idx = get_partition_idx(partition##_ID); \ - struct spm_partition_desc_t *part_ptr = \ - &(g_spm_partition_db.partitions[partition_idx]); \ - part_ptr->static_data.partition_init = init_func; \ +#define PARTITION_ADD_INIT_FUNC(partition, init_func) \ + do { \ + extern int32_t init_func(void); \ + uint32_t partition_idx = get_partition_idx(partition##_ID); \ + struct spm_partition_desc_t *part_ptr = \ + &(g_spm_partition_db.partitions[partition_idx]); \ + part_ptr->static_data.partition_init = init_func; \ } while (0) -#define PARTITION_ADD_PERIPHERAL(partition, peripheral) \ - do { \ - uint32_t partition_idx = get_partition_idx(partition##_ID); \ - struct spm_partition_desc_t *part_ptr = \ - &(g_spm_partition_db.partitions[partition_idx]); \ - part_ptr->platform_data = peripheral; \ +#define PARTITION_ADD_PERIPHERAL(partition, peripheral) \ + do { \ + uint32_t partition_idx = get_partition_idx(partition##_ID); \ + struct spm_partition_desc_t *part_ptr = \ + &(g_spm_partition_db.partitions[partition_idx]); \ + part_ptr->platform_data = peripheral; \ } while (0) #endif /* __SPM_DB_SETUP_H__ */ From 98fa63aa1a8364ab5ff619661f64c6aade596cd4 Mon Sep 17 00:00:00 2001 From: Devaraj Ranganna Date: Wed, 26 Jun 2019 17:01:07 +0100 Subject: [PATCH 9/9] Update commit sha's Signed-off-by: Devaraj Ranganna --- tools/importer/tfm_importer.json | 32 ++++++++++++++++++++++++++++---- 1 file changed, 28 insertions(+), 4 deletions(-) diff --git a/tools/importer/tfm_importer.json b/tools/importer/tfm_importer.json index 99da7dcd72..67d44d47f4 100644 --- a/tools/importer/tfm_importer.json +++ b/tools/importer/tfm_importer.json @@ -68,9 +68,33 @@ } ], "commit_sha": [ - "fb068d2cb4e89cacf0e9f413075bb4b211f1484f", - "5d41a2aeae71b13f2763bea4e55899646291e0eb", - "9c1e080e39adc7211c8c2c12cd652da3dc124299", - "280715f9b74ab29459d81edaf02b39e7a6acb13c" + { + "sha": "11bff3f3cbfbd3e2c284e884d0066531e6b47d7e", + "msg": "TF-M patch: General modifications, Remove un-needed files, Disable printf and uart, Modify include paths, Guard macros from mbed_lib with ifndef" + }, + { + "sha": "795e6418d0e73841868b351b605659a05c04e1f6", + "msg": "TF-M patch: Fix tfm_ns_lock_init issue (TF-M issue #239), Link to bug tracking: https://developer.trustedfirmware.org/T239" + }, + { + "sha": "35938a407133fe0c20c25b6fae2836148d1adfca", + "msg": "TF-M patch: Fix service handles not cleared issue (TF-M issue #230), Link to bug tracking: https://developer.trustedfirmware.org/T230" + }, + { + "sha": "910a402ce6c96b654cb6ae1a5b679e4f856c5419", + "msg": "TF-M patch: Fix tfm_psa_call_venner wrong argument type (TF-M issue #241), Link to bug tracking: https://developer.trustedfirmware.org/T241" + }, + { + "sha": "cb748c5608cd68a1dbecde5b3b2c1488c3d0d17b", + "msg": "TF-M patch: Change #if TFM_PSA_API to #ifdef TFM_PSA_API to avoid compiler errors as mbed-cli only generates "-D" macros only for "macros" defined in targets.json, TF-M task link: https://developer.trustedfirmware.org/T396" + }, + { + "sha": "9a5110561a60ec9f663079a25ec54f7ad0832743", + "msg": "TF-M patch: Remove secure_fw/core/tfm_func_api.c which is required only when TFM_PSA_API is not set" + }, + { + "sha": "6e899b3cc98c3e1811a160df09abbccddb2fa014", + "msg": "TF-M patch/workaround related to (TF-M issue #T240), Link to bug tracking: https://developer.trustedfirmware.org/T240, The issue is fixed by TF-M team. However they autogenerate region details (code, ro, rw, zi and stack ) using linker scripts and in mbed-os we also autogenerate region details but using mix of service definition in json file and other template files." + } ] }