mirror of https://github.com/ARMmbed/mbed-os.git
[trusted-firmware-m]: Updated to 0101fd37
# Conflicts: # components/TARGET_PSA/TARGET_TFM/COMPONENT_NSPE/interface/src/tfm_ns_lock_rtx.cpull/10467/head
parent
e53795189c
commit
abd60fc341
|
@ -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
|
* SPDX-License-Identifier: BSD-3-Clause
|
||||||
*
|
*
|
||||||
|
@ -11,6 +11,8 @@
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
#include <limits.h>
|
#include <limits.h>
|
||||||
|
#include "../ext/mcuboot/bootutil/include/bootutil/image.h"
|
||||||
|
#include "../ext/mcuboot/include/flash_map/flash_map.h"
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
|
@ -30,6 +32,16 @@ enum shared_memory_err_t {
|
||||||
TLV_TYPE_MAX = INT_MAX
|
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
|
* \brief Add a data item to the shared data area between bootloader and
|
||||||
* runtime SW
|
* runtime SW
|
||||||
|
@ -43,10 +55,25 @@ enum shared_memory_err_t {
|
||||||
*/
|
*/
|
||||||
enum shared_memory_err_t
|
enum shared_memory_err_t
|
||||||
boot_add_data_to_shared_area(uint8_t major_type,
|
boot_add_data_to_shared_area(uint8_t major_type,
|
||||||
uint8_t minor_type,
|
uint16_t minor_type,
|
||||||
size_t size,
|
size_t size,
|
||||||
const uint8_t *data);
|
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
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -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
|
* SPDX-License-Identifier: BSD-3-Clause
|
||||||
*
|
*
|
||||||
|
@ -16,43 +16,165 @@
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Major numbers to identify the consumer of shared data in runtime SW */
|
/* Major numbers (4 bit) to identify
|
||||||
#define TLV_MAJOR_CORE 0x0
|
* the consumer of shared data in runtime SW
|
||||||
#define TLV_MAJOR_IAS 0x1
|
*/
|
||||||
|
#define TLV_MAJOR_CORE 0x0
|
||||||
|
#define TLV_MAJOR_IAS 0x1
|
||||||
|
|
||||||
/* PSA Root of Trust */
|
/**
|
||||||
#define TLV_MINOR_IAS_PRoT_SHA256 0x00
|
* The shared data between boot loader and runtime SW is TLV encoded. The
|
||||||
#define TLV_MINOR_IAS_PRoT_SW_VERSION 0x01
|
* shared data is stored in a well known location in secure memory and this is
|
||||||
#define TLV_MINOR_IAS_PRoT_EPOCH 0x02
|
* a contract between boot loader and runtime SW.
|
||||||
|
*
|
||||||
|
* The structure of shared data must be the following:
|
||||||
|
* - At the beginning there must be a header: struct shared_data_tlv_header
|
||||||
|
* This contains a magic number and a size field which covers the entire
|
||||||
|
* size of the shared data area including this header.
|
||||||
|
* - After the header there come the entries which are composed from an entry
|
||||||
|
* header structure: struct shared_data_tlv_entry and the data. In the entry
|
||||||
|
* header is a type field (tly_type) which identify the consumer of the
|
||||||
|
* entry in the runtime SW and specify the subtype of that data item. There
|
||||||
|
* is a size field (tlv_len) which covers the size of the entry header and
|
||||||
|
* the data. After this structure comes the actual data.
|
||||||
|
* - Arbitrary number and size of data entry can be in the shared memory area.
|
||||||
|
*
|
||||||
|
* This table gives of overview about the tlv_type field in the entry header.
|
||||||
|
* The tlv_type always composed from a major and minor number. Major number
|
||||||
|
* identifies the addressee in runtime SW, who should process the data entry.
|
||||||
|
* Minor number used to encode more info about the data entry. The actual
|
||||||
|
* definition of minor number could change per major number. In case of boot
|
||||||
|
* status data, which is going to be processed by initial attestation service
|
||||||
|
* the minor number is split further to two part: sw_module and claim. The
|
||||||
|
* sw_module identifies the SW component in the system which the data item
|
||||||
|
* belongs to and the claim part identifies the exact type of the data.
|
||||||
|
*
|
||||||
|
* |---------------------------------------|
|
||||||
|
* | tlv_type (16) |
|
||||||
|
* |---------------------------------------|
|
||||||
|
* | tlv_major(4)| tlv_minor(12) |
|
||||||
|
* |---------------------------------------|
|
||||||
|
* | MAJOR_IAS | sw_module(6) | claim(6) |
|
||||||
|
* |---------------------------------------|
|
||||||
|
* | MAJOR_CORE | TBD |
|
||||||
|
* |---------------------------------------|
|
||||||
|
*/
|
||||||
|
|
||||||
/* Application Root of Trust */
|
/* Initial attestation: SW components / SW modules
|
||||||
#define TLV_MINOR_IAS_ARoT_SHA256 0x03
|
* This list is intended to be adjusted per device. It contains more SW
|
||||||
#define TLV_MINOR_IAS_ARoT_SW_VERSION 0x04
|
* components than currently available in TF-M project. It serves as an example,
|
||||||
#define TLV_MINOR_IAS_ARoT_EPOCH 0x05
|
* what kind of SW components might be available.
|
||||||
|
*/
|
||||||
|
#define SW_GENERAL 0x00
|
||||||
|
#define SW_BL2 0x01
|
||||||
|
#define SW_PROT 0x02
|
||||||
|
#define SW_AROT 0x03
|
||||||
|
#define SW_SPE 0x04
|
||||||
|
#define SW_NSPE 0x05
|
||||||
|
#define SW_S_NS 0x06
|
||||||
|
#define SW_MAX 0x07
|
||||||
|
|
||||||
/* Non-secure processing environment: single non-secure image */
|
/* Initial attestation: Claim per SW components / SW modules */
|
||||||
#define TLV_MINOR_IAS_NSPE_SHA256 0x06
|
/* Bits: 0-2 */
|
||||||
#define TLV_MINOR_IAS_NSPE_SW_VERSION 0x07
|
#define SW_VERSION 0x00
|
||||||
#define TLV_MINOR_IAS_NSPE_EPOCH 0x08
|
#define SW_SIGNER_ID 0x01
|
||||||
|
#define SW_EPOCH 0x02
|
||||||
|
#define SW_TYPE 0x03
|
||||||
|
/* Bits: 3-5 */
|
||||||
|
#define SW_MEASURE_VALUE 0x08
|
||||||
|
#define SW_MEASURE_TYPE 0x09
|
||||||
|
|
||||||
/* ARoT + PRoT: single secure image */
|
/* Initial attestation: General claim does not belong any particular SW
|
||||||
#define TLV_MINOR_IAS_S_SHA256 0x09
|
* component. But they might be part of the boot status.
|
||||||
#define TLV_MINOR_IAS_S_SW_VERSION 0x0a
|
*/
|
||||||
#define TLV_MINOR_IAS_S_EPOCH 0x0b
|
#define BOOT_SEED 0x00
|
||||||
|
#define HW_VERSION 0x01
|
||||||
|
#define SECURITY_LIFECYCLE 0x02
|
||||||
|
|
||||||
/* S + NS: combined secure and non-secure image */
|
/* Minor numbers (12 bit) to identify attestation service related data */
|
||||||
#define TLV_MINOR_IAS_S_NS_SHA256 0x0c
|
#define TLV_MINOR_IAS_BOOT_SEED ((SW_GENERAL << 6) | BOOT_SEED)
|
||||||
#define TLV_MINOR_IAS_S_NS_SW_VERSION 0x0d
|
#define TLV_MINOR_IAS_HW_VERSION ((SW_GENERAL << 6) | HW_VERSION)
|
||||||
#define TLV_MINOR_IAS_S_NS_EPOCH 0x0e
|
#define TLV_MINOR_IAS_SLC ((SW_GENERAL << 6) | SECURITY_LIFECYCLE)
|
||||||
|
|
||||||
|
/* Bootloader - It can be more stage */
|
||||||
|
#define TLV_MINOR_IAS_BL2_MEASURE_VALUE ((SW_BL2 << 6) | SW_MEASURE_VALUE)
|
||||||
|
#define TLV_MINOR_IAS_BL2_MEASURE_TYPE ((SW_BL2 << 6) | SW_MEASURE_TYPE)
|
||||||
|
#define TLV_MINOR_IAS_BL2_VERSION ((SW_BL2 << 6) | SW_VERSION)
|
||||||
|
#define TLV_MINOR_IAS_BL2_SIGNER_ID ((SW_BL2 << 6) | SW_SIGNER_ID)
|
||||||
|
#define TLV_MINOR_IAS_BL2_EPOCH ((SW_BL2 << 6) | SW_EPOCH)
|
||||||
|
#define TLV_MINOR_IAS_BL2_TYPE ((SW_BL2 << 6) | SW_TYPE)
|
||||||
|
|
||||||
|
/* PROT: PSA Root of Trust */
|
||||||
|
#define TLV_MINOR_IAS_PROT_MEASURE_VALUE ((SW_PROT << 6) | SW_MEASURE_VALUE)
|
||||||
|
#define TLV_MINOR_IAS_PROT_MEASURE_TYPE ((SW_PROT << 6) | SW_MEASURE_TYPE)
|
||||||
|
#define TLV_MINOR_IAS_PROT_VERSION ((SW_PROT << 6) | SW_VERSION)
|
||||||
|
#define TLV_MINOR_IAS_PROT_SIGNER_ID ((SW_PROT << 6) | SW_SIGNER_ID)
|
||||||
|
#define TLV_MINOR_IAS_PROT_EPOCH ((SW_PROT << 6) | SW_EPOCH)
|
||||||
|
#define TLV_MINOR_IAS_PROT_TYPE ((SW_PROT << 6) | SW_TYPE)
|
||||||
|
|
||||||
|
/* AROT: Application Root of Trust */
|
||||||
|
#define TLV_MINOR_IAS_AROT_MEASURE_VALUE ((SW_AROT << 6) | SW_MEASURE_VALUE)
|
||||||
|
#define TLV_MINOR_IAS_AROT_MEASURE_TYPE ((SW_AROT << 6) | SW_MEASURE_TYPE)
|
||||||
|
#define TLV_MINOR_IAS_AROT_VERSION ((SW_AROT << 6) | SW_VERSION)
|
||||||
|
#define TLV_MINOR_IAS_AROT_SIGNER_ID ((SW_AROT << 6) | SW_SIGNER_ID)
|
||||||
|
#define TLV_MINOR_IAS_AROT_EPOCH ((SW_AROT << 6) | SW_EPOCH)
|
||||||
|
#define TLV_MINOR_IAS_AROT_TYPE ((SW_AROT << 6) | SW_TYPE)
|
||||||
|
|
||||||
|
/* Non-secure processing environment - single non-secure image */
|
||||||
|
#define TLV_MINOR_IAS_NSPE_MEASURE_VALUE ((SW_NSPE << 6) | SW_MEASURE_VALUE)
|
||||||
|
#define TLV_MINOR_IAS_NSPE_MEASURE_TYPE ((SW_NSPE << 6) | SW_MEASURE_TYPE)
|
||||||
|
#define TLV_MINOR_IAS_NSPE_VERSION ((SW_NSPE << 6) | SW_VERSION)
|
||||||
|
#define TLV_MINOR_IAS_NSPE_SIGNER_ID ((SW_NSPE << 6) | SW_SIGNER_ID)
|
||||||
|
#define TLV_MINOR_IAS_NSPE_EPOCH ((SW_NSPE << 6) | SW_EPOCH)
|
||||||
|
#define TLV_MINOR_IAS_NSPE_TYPE ((SW_NSPE << 6) | SW_TYPE)
|
||||||
|
|
||||||
|
/* Secure processing environment (ARoT + PRoT) - single secure image */
|
||||||
|
#define TLV_MINOR_IAS_SPE_MEASURE_VALUE ((SW_SPE << 6) | SW_MEASURE_VALUE)
|
||||||
|
#define TLV_MINOR_IAS_SPE_MEASURE_TYPE ((SW_SPE << 6) | SW_MEASURE_TYPE)
|
||||||
|
#define TLV_MINOR_IAS_SPE_VERSION ((SW_SPE << 6) | SW_VERSION)
|
||||||
|
#define TLV_MINOR_IAS_SPE_SIGNER_ID ((SW_SPE << 6) | SW_SIGNER_ID)
|
||||||
|
#define TLV_MINOR_IAS_SPE_EPOCH ((SW_SPE << 6) | SW_EPOCH)
|
||||||
|
#define TLV_MINOR_IAS_SPE_TYPE ((SW_SPE << 6) | SW_TYPE)
|
||||||
|
|
||||||
|
/* SPE + NSPE - combined secure and non-secure image */
|
||||||
|
#define TLV_MINOR_IAS_S_NS_MEASURE_VALUE ((SW_S_NS << 6) | SW_MEASURE_VALUE)
|
||||||
|
#define TLV_MINOR_IAS_S_NS_MEASURE_TYPE ((SW_S_NS << 6) | SW_MEASURE_TYPE)
|
||||||
|
#define TLV_MINOR_IAS_S_NS_VERSION ((SW_S_NS << 6) | SW_VERSION)
|
||||||
|
#define TLV_MINOR_IAS_S_NS_SIGNER_ID ((SW_S_NS << 6) | SW_SIGNER_ID)
|
||||||
|
#define TLV_MINOR_IAS_S_NS_EPOCH ((SW_S_NS << 6) | SW_EPOCH)
|
||||||
|
#define TLV_MINOR_IAS_S_NS_TYPE ((SW_S_NS << 6) | SW_TYPE)
|
||||||
|
|
||||||
|
/* General macros to handle TLV type */
|
||||||
|
#define MAJOR_MASK 0xF /* 4 bit */
|
||||||
|
#define MAJOR_POS 12 /* 12 bit */
|
||||||
|
#define MINOR_MASK 0xFFF /* 12 bit */
|
||||||
|
|
||||||
|
#define SET_TLV_TYPE(major, minor) \
|
||||||
|
((((major) & MAJOR_MASK) << MAJOR_POS) | ((minor) & MINOR_MASK))
|
||||||
|
#define GET_MAJOR(tlv_type) ((tlv_type) >> MAJOR_POS)
|
||||||
|
#define GET_MINOR(tlv_type) ((tlv_type) & MINOR_MASK)
|
||||||
|
|
||||||
|
/* Initial attestation specific macros */
|
||||||
|
#define MODULE_POS 6 /* 6 bit */
|
||||||
|
#define CLAIM_MASK 0x3F /* 6 bit */
|
||||||
|
#define MEASUREMENT_CLAIM_POS 3 /* 3 bit */
|
||||||
|
|
||||||
|
#define GET_IAS_MODULE(tlv_type) (GET_MINOR(tlv_type) >> MODULE_POS)
|
||||||
|
#define GET_IAS_CLAIM(tlv_type) (GET_MINOR(tlv_type) & CLAIM_MASK)
|
||||||
|
#define SET_IAS_MINOR(sw_module, claim) (((sw_module) << 6) | (claim))
|
||||||
|
|
||||||
|
#define GET_IAS_MEASUREMENT_CLAIM(ias_claim) ((ias_claim) >> \
|
||||||
|
MEASUREMENT_CLAIM_POS)
|
||||||
|
|
||||||
|
/* Magic value which marks the beginning of shared data area in memory */
|
||||||
#define SHARED_DATA_TLV_INFO_MAGIC 0x2016
|
#define SHARED_DATA_TLV_INFO_MAGIC 0x2016
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Shared data TLV header. All fields in little endian.
|
* Shared data TLV header. All fields in little endian.
|
||||||
*
|
*
|
||||||
* ---------------------------
|
* -----------------------------------
|
||||||
* | tlv_magic | tlv_tot_len |
|
* | tlv_magic(16) | tlv_tot_len(16) |
|
||||||
* ---------------------------
|
* -----------------------------------
|
||||||
*/
|
*/
|
||||||
struct shared_data_tlv_header {
|
struct shared_data_tlv_header {
|
||||||
uint16_t tlv_magic;
|
uint16_t tlv_magic;
|
||||||
|
@ -64,15 +186,14 @@ struct shared_data_tlv_header {
|
||||||
/**
|
/**
|
||||||
* Shared data TLV entry header format. All fields in little endian.
|
* Shared data TLV entry header format. All fields in little endian.
|
||||||
*
|
*
|
||||||
* ---------------------------------------------
|
* -------------------------------
|
||||||
* | tlv_major_type | tlv_minor_type | tlv_len |
|
* | tlv_type(16) | tlv_len(16) |
|
||||||
* ---------------------------------------------
|
* -------------------------------
|
||||||
* | Raw data |
|
* | Raw data |
|
||||||
* ---------------------------------------------
|
* -------------------------------
|
||||||
*/
|
*/
|
||||||
struct shared_data_tlv_entry {
|
struct shared_data_tlv_entry {
|
||||||
uint8_t tlv_major_type;
|
uint16_t tlv_type;
|
||||||
uint8_t tlv_minor_type;
|
|
||||||
uint16_t tlv_len; /* size of single TLV entry (including this header). */
|
uint16_t tlv_len; /* size of single TLV entry (including this header). */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,71 @@
|
||||||
|
#-------------------------------------------------------------------------------
|
||||||
|
# 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_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()
|
|
@ -0,0 +1,16 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2018-2019, Arm Limited. All rights reserved.
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: BSD-3-Clause
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
//This file holds description for the current directory. This documentation
|
||||||
|
//will be included in the Doxygen output.
|
||||||
|
|
||||||
|
/*!
|
||||||
|
\dir
|
||||||
|
\brief Source code for the TF-M core.
|
||||||
|
\details This directory holds the source code of the "TF-M core" module.
|
||||||
|
|
||||||
|
*/
|
|
@ -0,0 +1,74 @@
|
||||||
|
#-------------------------------------------------------------------------------
|
||||||
|
# Copyright (c) 2018, 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_psa_api_client.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()
|
|
@ -7,16 +7,14 @@
|
||||||
#ifndef __TFM_MESSAGE_QUEUE_H__
|
#ifndef __TFM_MESSAGE_QUEUE_H__
|
||||||
#define __TFM_MESSAGE_QUEUE_H__
|
#define __TFM_MESSAGE_QUEUE_H__
|
||||||
|
|
||||||
#ifndef TFM_MSG_QUEUE_MAX_MSG_NUM
|
|
||||||
#define TFM_MSG_QUEUE_MAX_MSG_NUM 128
|
#define TFM_MSG_QUEUE_MAX_MSG_NUM 128
|
||||||
#endif
|
|
||||||
#define TFM_MSG_MAGIC 0x15154343
|
#define TFM_MSG_MAGIC 0x15154343
|
||||||
/* Message struct to collect parameter from client */
|
/* Message struct to collect parameter from client */
|
||||||
struct tfm_msg_body_t {
|
struct tfm_msg_body_t {
|
||||||
int32_t magic;
|
int32_t magic;
|
||||||
struct tfm_spm_service_t *service; /* RoT service pointer */
|
struct tfm_spm_service_t *service; /* RoT service pointer */
|
||||||
psa_handle_t handle; /* Connected Service handle */
|
psa_handle_t handle; /* Connected Service handle */
|
||||||
struct tfm_event_ctx ack_mtx; /* Event for ack reponse */
|
struct tfm_event_t ack_evnt; /* Event for ack reponse */
|
||||||
psa_msg_t msg; /* PSA message body */
|
psa_msg_t msg; /* PSA message body */
|
||||||
psa_invec invec[PSA_MAX_IOVEC]; /* Put in/out vectors in msg body */
|
psa_invec invec[PSA_MAX_IOVEC]; /* Put in/out vectors in msg body */
|
||||||
psa_outvec outvec[PSA_MAX_IOVEC];
|
psa_outvec outvec[PSA_MAX_IOVEC];
|
||||||
|
|
|
@ -10,15 +10,11 @@
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
#include "tfm_list.h"
|
#include "tfm_list.h"
|
||||||
|
|
||||||
#ifndef TFM_SPM_MAX_ROT_SERV_NUM
|
|
||||||
#define TFM_SPM_MAX_ROT_SERV_NUM 28
|
#define TFM_SPM_MAX_ROT_SERV_NUM 28
|
||||||
#endif
|
|
||||||
#define TFM_VERSION_POLICY_RELAXED 0
|
#define TFM_VERSION_POLICY_RELAXED 0
|
||||||
#define TFM_VERSION_POLICY_STRICT 1
|
#define TFM_VERSION_POLICY_STRICT 1
|
||||||
|
|
||||||
#ifndef TFM_CONN_HANDLE_MAX_NUM
|
|
||||||
#define TFM_CONN_HANDLE_MAX_NUM 32
|
#define TFM_CONN_HANDLE_MAX_NUM 32
|
||||||
#endif
|
|
||||||
|
|
||||||
/* RoT connection handle list */
|
/* RoT connection handle list */
|
||||||
struct tfm_conn_handle_t {
|
struct tfm_conn_handle_t {
|
||||||
|
@ -59,7 +55,7 @@ struct tfm_spm_service_t {
|
||||||
struct tfm_spm_ipc_partition_t {
|
struct tfm_spm_ipc_partition_t {
|
||||||
int32_t index; /* Partition index */
|
int32_t index; /* Partition index */
|
||||||
int32_t id; /* Secure partition ID */
|
int32_t id; /* Secure partition ID */
|
||||||
struct tfm_event_ctx signal_event; /* Event signal */
|
struct tfm_event_t signal_evnt; /* Event signal */
|
||||||
uint32_t signals; /* Service signals had been triggered*/
|
uint32_t signals; /* Service signals had been triggered*/
|
||||||
uint32_t signal_mask; /* Service signal mask passed by psa_wait() */
|
uint32_t signal_mask; /* Service signal mask passed by psa_wait() */
|
||||||
struct tfm_list_node_t service_list;/* Service list */
|
struct tfm_list_node_t service_list;/* Service list */
|
||||||
|
|
|
@ -0,0 +1,14 @@
|
||||||
|
/*
|
||||||
|
* 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"
|
||||||
|
|
||||||
|
#endif
|
|
@ -58,7 +58,7 @@ psa_handle_t tfm_svcall_psa_connect(uint32_t *args, int32_t ns_caller);
|
||||||
* handle, in_vec, in_len, out_vec, out_len.
|
* handle, in_vec, in_len, out_vec, out_len.
|
||||||
* \param[in] ns_caller If 'non-zero', call from non-secure client.
|
* \param[in] ns_caller If 'non-zero', call from non-secure client.
|
||||||
* Or from secure client.
|
* Or from secure client.
|
||||||
* \param[in] lr Link register to be stored
|
* \param[in] lr EXC_RETURN value of the SVC.
|
||||||
*
|
*
|
||||||
* \retval >=0 RoT Service-specific status value.
|
* \retval >=0 RoT Service-specific status value.
|
||||||
* \retval <0 RoT Service-specific error code.
|
* \retval <0 RoT Service-specific error code.
|
||||||
|
@ -74,7 +74,8 @@ psa_handle_t tfm_svcall_psa_connect(uint32_t *args, int32_t ns_caller);
|
||||||
* \arg The message is unrecognized by the RoT
|
* \arg The message is unrecognized by the RoT
|
||||||
* Service or incorrectly formatted.
|
* Service or incorrectly formatted.
|
||||||
*/
|
*/
|
||||||
psa_status_t tfm_svcall_psa_call(uint32_t *args, int32_t ns_caller, uint32_t lr);
|
psa_status_t tfm_svcall_psa_call(uint32_t *args, int32_t ns_caller,
|
||||||
|
uint32_t lr);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \brief SVC handler for \ref psa_close.
|
* \brief SVC handler for \ref psa_close.
|
||||||
|
@ -97,7 +98,7 @@ void tfm_svcall_psa_close(uint32_t *args, int32_t ns_caller);
|
||||||
*
|
*
|
||||||
* \param[in] svc_num SVC number
|
* \param[in] svc_num SVC number
|
||||||
* \param[in] ctx Argument context
|
* \param[in] ctx Argument context
|
||||||
* \param[in] lr Link register to be stored
|
* \param[in] lr EXC_RETURN value of the SVC.
|
||||||
*
|
*
|
||||||
* \returns Return values from those who has,
|
* \returns Return values from those who has,
|
||||||
* or PSA_SUCCESS.
|
* or PSA_SUCCESS.
|
||||||
|
|
|
@ -9,78 +9,47 @@
|
||||||
|
|
||||||
#include "cmsis_compiler.h"
|
#include "cmsis_compiler.h"
|
||||||
|
|
||||||
#define EVENT_MAGIC 0x65766e74
|
/* The magic number has two purposes: corruption detection and debug */
|
||||||
#define EVENT_STAT_WAITED 0x0
|
#define TFM_EVENT_MAGIC 0x65766e74
|
||||||
#define EVENT_STAT_SIGNALED 0x1
|
|
||||||
|
|
||||||
struct tfm_event_ctx {
|
struct tfm_event_t {
|
||||||
uint32_t magic; /* 'evnt' */
|
uint32_t magic; /* 'evnt' */
|
||||||
struct tfm_thrd_ctx *owner; /* waiting thread */
|
struct tfm_thrd_ctx *owner; /* Event blocked thread */
|
||||||
uint32_t status; /* status */
|
|
||||||
uint32_t retval; /* return value */
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Initialize an event context.
|
* Initialize an event object.
|
||||||
*
|
*
|
||||||
* Parameters :
|
* Parameters:
|
||||||
* pevt - pointer of event context caller provided
|
* pevnt - The pointer of event object allocated by the caller
|
||||||
* stat - initial status (EVENT_STAT_WAITED or EVENT_STAT_SIGNALED)
|
|
||||||
*/
|
*/
|
||||||
void __STATIC_INLINE tfm_event_init(struct tfm_event_ctx *pevt, uint32_t stat)
|
void __STATIC_INLINE tfm_event_init(struct tfm_event_t *pevnt)
|
||||||
{
|
{
|
||||||
pevt->magic = EVENT_MAGIC;
|
pevnt->magic = TFM_EVENT_MAGIC;
|
||||||
pevt->status = stat;
|
pevnt->owner = NULL;
|
||||||
pevt->owner = NULL;
|
|
||||||
pevt->retval = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Wait on an event.
|
* Wait on an event object.
|
||||||
*
|
*
|
||||||
* Parameters :
|
* Parameters:
|
||||||
* pevt - pointer of event context
|
* pevnt - The pointer of event object allocated by the caller
|
||||||
*
|
*
|
||||||
* Notes :
|
* Notes:
|
||||||
* Thread is blocked if event is not signaled.
|
* Block caller thread by calling this function.
|
||||||
*/
|
*/
|
||||||
void tfm_event_wait(struct tfm_event_ctx *pevt);
|
void tfm_event_wait(struct tfm_event_t *pevnt);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Signal an event.
|
* Wake up an event object.
|
||||||
*
|
*
|
||||||
* Parameters :
|
* Parameters :
|
||||||
* pevt - pointer of event context
|
* pevnt - The pointer of event object allocated by the caller
|
||||||
|
* retval - Value to be returned to owner
|
||||||
*
|
*
|
||||||
* Notes :
|
* Notes:
|
||||||
* Waiting thread on this event will be running.
|
* Wake up the blocked thread and set parameter 'retval' as the return value.
|
||||||
*/
|
*/
|
||||||
void tfm_event_signal(struct tfm_event_ctx *pevt);
|
void tfm_event_wake(struct tfm_event_t *pevnt, uint32_t retval);
|
||||||
|
|
||||||
/*
|
|
||||||
* Peek an event status.
|
|
||||||
*
|
|
||||||
* Parameters :
|
|
||||||
* pevt - pointer of event context
|
|
||||||
*
|
|
||||||
* Return :
|
|
||||||
* Status of event.
|
|
||||||
*
|
|
||||||
* Notes :
|
|
||||||
* This function is used for getting event status without blocking thread.
|
|
||||||
*/
|
|
||||||
uint32_t tfm_event_peek(struct tfm_event_ctx *pevt);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Set event owner return value.
|
|
||||||
*
|
|
||||||
* Parameters :
|
|
||||||
* pevt - pointer of event context
|
|
||||||
* retval - return value of blocked owner thread
|
|
||||||
*
|
|
||||||
* Notes :
|
|
||||||
* Thread return value is set while thread is to be running.
|
|
||||||
*/
|
|
||||||
void tfm_event_owner_retval(struct tfm_event_ctx *pevt, uint32_t retval);
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -11,9 +11,9 @@
|
||||||
#include "cmsis.h"
|
#include "cmsis.h"
|
||||||
#include "psa_client.h"
|
#include "psa_client.h"
|
||||||
#include "psa_service.h"
|
#include "psa_service.h"
|
||||||
#include "secure_utilities.h"
|
|
||||||
#include "tfm_utils.h"
|
#include "tfm_utils.h"
|
||||||
#include "tfm_thread.h"
|
#include "tfm_thread.h"
|
||||||
|
#include "tfm_memory_utils.h"
|
||||||
|
|
||||||
/* This file contains the ARCH code for ARM V8M */
|
/* This file contains the ARCH code for ARM V8M */
|
||||||
|
|
||||||
|
@ -91,6 +91,7 @@ void tfm_initialize_context(struct tfm_state_context *ctx,
|
||||||
* thread SP/SP_LIMIT. R2 holds dummy data due to stack operation is 8 bytes
|
* thread SP/SP_LIMIT. R2 holds dummy data due to stack operation is 8 bytes
|
||||||
* aligned.
|
* aligned.
|
||||||
*/
|
*/
|
||||||
|
#if defined(__ARM_ARCH_8M_MAIN__)
|
||||||
__attribute__((naked)) void PendSV_Handler(void)
|
__attribute__((naked)) void PendSV_Handler(void)
|
||||||
{
|
{
|
||||||
__ASM(
|
__ASM(
|
||||||
|
@ -107,6 +108,37 @@ __attribute__((naked)) void PendSV_Handler(void)
|
||||||
"bx lr \n"
|
"bx lr \n"
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
#elif defined(__ARM_ARCH_8M_BASE__)
|
||||||
|
__attribute__((naked)) void PendSV_Handler(void)
|
||||||
|
{
|
||||||
|
__ASM(
|
||||||
|
"mrs r0, psp \n"
|
||||||
|
"mrs r1, psplim \n"
|
||||||
|
"push {r0, r1, r2, lr} \n"
|
||||||
|
"push {r4-r7} \n"
|
||||||
|
"mov r4, r8 \n"
|
||||||
|
"mov r5, r9 \n"
|
||||||
|
"mov r6, r10 \n"
|
||||||
|
"mov r7, r11 \n"
|
||||||
|
"push {r4-r7} \n"
|
||||||
|
"mov r0, sp \n"
|
||||||
|
"bl tfm_pendsv_do_schedule \n"
|
||||||
|
"pop {r4-r7} \n"
|
||||||
|
"mov r8, r4 \n"
|
||||||
|
"mov r9, r5 \n"
|
||||||
|
"mov r10, r6 \n"
|
||||||
|
"mov r11, r7 \n"
|
||||||
|
"pop {r4-r7} \n"
|
||||||
|
"pop {r0-r3} \n"
|
||||||
|
"mov lr, r3 \n"
|
||||||
|
"msr psp, r0 \n"
|
||||||
|
"msr psplim, r1 \n"
|
||||||
|
"bx lr \n"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
#error "Unsupported ARM Architecture."
|
||||||
|
#endif
|
||||||
|
|
||||||
/* Reserved for future usage */
|
/* Reserved for future usage */
|
||||||
__attribute__((naked)) void MemManage_Handler(void)
|
__attribute__((naked)) void MemManage_Handler(void)
|
||||||
|
|
|
@ -17,7 +17,7 @@
|
||||||
#include "tfm_utils.h"
|
#include "tfm_utils.h"
|
||||||
#include "tfm_list.h"
|
#include "tfm_list.h"
|
||||||
#include "tfm_pools.h"
|
#include "tfm_pools.h"
|
||||||
#include "secure_utilities.h"
|
#include "tfm_memory_utils.h"
|
||||||
|
|
||||||
int32_t tfm_pool_init(struct tfm_pool_instance_t *pool, size_t poolsz,
|
int32_t tfm_pool_init(struct tfm_pool_instance_t *pool, size_t poolsz,
|
||||||
size_t chunksz, size_t num)
|
size_t chunksz, size_t num)
|
||||||
|
|
|
@ -25,6 +25,7 @@
|
||||||
#include "tfm_thread.h"
|
#include "tfm_thread.h"
|
||||||
#include "region_defs.h"
|
#include "region_defs.h"
|
||||||
#include "tfm_nspm.h"
|
#include "tfm_nspm.h"
|
||||||
|
#include "tfm_memory_utils.h"
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* IPC partitions.
|
* IPC partitions.
|
||||||
|
@ -45,7 +46,7 @@ TFM_POOL_DECLARE(msg_db_pool, sizeof(struct tfm_msg_body_t),
|
||||||
TFM_MSG_QUEUE_MAX_MSG_NUM);
|
TFM_MSG_QUEUE_MAX_MSG_NUM);
|
||||||
|
|
||||||
static struct tfm_spm_service_db_t g_spm_service_db[] = {
|
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 ***********************/
|
/********************** SPM functions for handler mode ***********************/
|
||||||
|
@ -108,8 +109,6 @@ int32_t tfm_spm_free_conn_handle(struct tfm_spm_service_t *service,
|
||||||
/* Remove node from handle list */
|
/* Remove node from handle list */
|
||||||
tfm_list_del_node(&node->list);
|
tfm_list_del_node(&node->list);
|
||||||
|
|
||||||
node->rhandle = NULL;
|
|
||||||
|
|
||||||
/* Back handle buffer to pool */
|
/* Back handle buffer to pool */
|
||||||
tfm_pool_free(node);
|
tfm_pool_free(node);
|
||||||
return IPC_SUCCESS;
|
return IPC_SUCCESS;
|
||||||
|
@ -272,7 +271,7 @@ int32_t tfm_spm_check_client_version(struct tfm_spm_service_t *service,
|
||||||
|
|
||||||
switch (service->service_db->minor_policy) {
|
switch (service->service_db->minor_policy) {
|
||||||
case TFM_VERSION_POLICY_RELAXED:
|
case TFM_VERSION_POLICY_RELAXED:
|
||||||
if (minor_version > service->service_db->minor_version) {
|
if (minor_version < service->service_db->minor_version) {
|
||||||
return IPC_ERROR_VERSION;
|
return IPC_ERROR_VERSION;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -348,7 +347,7 @@ struct tfm_msg_body_t *tfm_spm_create_msg(struct tfm_spm_service_t *service,
|
||||||
/* Clear message buffer before using it */
|
/* Clear message buffer before using it */
|
||||||
tfm_memset(msg, 0, sizeof(struct tfm_msg_body_t));
|
tfm_memset(msg, 0, sizeof(struct tfm_msg_body_t));
|
||||||
|
|
||||||
tfm_event_init(&msg->ack_mtx, EVENT_STAT_WAITED);
|
tfm_event_init(&msg->ack_evnt);
|
||||||
msg->magic = TFM_MSG_MAGIC;
|
msg->magic = TFM_MSG_MAGIC;
|
||||||
msg->service = service;
|
msg->service = service;
|
||||||
msg->handle = handle;
|
msg->handle = handle;
|
||||||
|
@ -405,15 +404,11 @@ int32_t tfm_spm_send_event(struct tfm_spm_service_t *service,
|
||||||
/* Messages put. Update signals */
|
/* Messages put. Update signals */
|
||||||
service->partition->signals |= service->service_db->signal;
|
service->partition->signals |= service->service_db->signal;
|
||||||
|
|
||||||
/* Save return value for blocked threads */
|
tfm_event_wake(&service->partition->signal_evnt,
|
||||||
tfm_event_owner_retval(&service->partition->signal_event,
|
(service->partition->signals &
|
||||||
service->partition->signals &
|
service->partition->signal_mask));
|
||||||
service->partition->signal_mask);
|
|
||||||
|
|
||||||
/* Wake waiting thread up */
|
tfm_event_wait(&msg->ack_evnt);
|
||||||
tfm_event_signal(&service->partition->signal_event);
|
|
||||||
|
|
||||||
tfm_event_wait(&msg->ack_mtx);
|
|
||||||
|
|
||||||
return IPC_SUCCESS;
|
return IPC_SUCCESS;
|
||||||
}
|
}
|
||||||
|
@ -435,19 +430,15 @@ tfm_spm_partition_get_thread_info_ext(uint32_t partition_idx)
|
||||||
return &g_spm_partition_db.partitions[partition_idx].sp_thrd;
|
return &g_spm_partition_db.partitions[partition_idx].sp_thrd;
|
||||||
}
|
}
|
||||||
|
|
||||||
static uint32_t tfm_spm_partition_get_stack_size_ext(uint32_t partition_idx)
|
static uint32_t tfm_spm_partition_get_stack_base_ext(uint32_t partition_idx)
|
||||||
{
|
{
|
||||||
return g_spm_partition_db.partitions[partition_idx].stack_size;
|
return (uint32_t)&(g_spm_partition_db.partitions[partition_idx].
|
||||||
|
stack[TFM_STACK_SIZE]);
|
||||||
}
|
}
|
||||||
|
|
||||||
static uint32_t tfm_spm_partition_get_stack_limit_ext(uint32_t partition_idx)
|
static uint32_t tfm_spm_partition_get_stack_limit_ext(uint32_t partition_idx)
|
||||||
{
|
{
|
||||||
return g_spm_partition_db.partitions[partition_idx].stack_limit;
|
return (uint32_t)&g_spm_partition_db.partitions[partition_idx].stack;
|
||||||
}
|
|
||||||
|
|
||||||
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
|
static tfm_thrd_func_t
|
||||||
|
@ -466,8 +457,6 @@ static uint32_t tfm_spm_partition_get_priority_ext(uint32_t partition_idx)
|
||||||
/* Macros to pick linker symbols and allow references to sections in all level*/
|
/* Macros to pick linker symbols and allow references to sections in all level*/
|
||||||
#define REGION_DECLARE_EXT(a, b, c) extern uint32_t REGION_NAME(a, b, c)
|
#define REGION_DECLARE_EXT(a, b, c) extern uint32_t REGION_NAME(a, b, c)
|
||||||
|
|
||||||
REGION_DECLARE_EXT(Image$$, ARM_LIB_HEAP, $$ZI$$Base);
|
|
||||||
REGION_DECLARE_EXT(Image$$, ARM_LIB_HEAP, $$ZI$$Limit);
|
|
||||||
REGION_DECLARE_EXT(Image$$, ER_TFM_DATA, $$ZI$$Base);
|
REGION_DECLARE_EXT(Image$$, ER_TFM_DATA, $$ZI$$Base);
|
||||||
REGION_DECLARE_EXT(Image$$, ER_TFM_DATA, $$ZI$$Limit);
|
REGION_DECLARE_EXT(Image$$, ER_TFM_DATA, $$ZI$$Limit);
|
||||||
REGION_DECLARE_EXT(Image$$, ER_TFM_DATA, $$RW$$Base);
|
REGION_DECLARE_EXT(Image$$, ER_TFM_DATA, $$RW$$Base);
|
||||||
|
@ -523,19 +512,7 @@ int32_t tfm_memory_check(void *buffer, size_t len, int32_t ns_caller)
|
||||||
if (memory_check_range(buffer, len, base, limit) == IPC_SUCCESS) {
|
if (memory_check_range(buffer, len, base, limit) == IPC_SUCCESS) {
|
||||||
return IPC_SUCCESS;
|
return IPC_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
base = (uintptr_t)NS_CODE_START;
|
|
||||||
limit = (uintptr_t)(NS_CODE_START + NS_CODE_SIZE);
|
|
||||||
if (memory_check_range(buffer, len, base, limit) == IPC_SUCCESS) {
|
|
||||||
return IPC_SUCCESS;
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
base = (uintptr_t)®ION_NAME(Image$$, ARM_LIB_HEAP, $$ZI$$Base);
|
|
||||||
limit = (uintptr_t)®ION_NAME(Image$$, ARM_LIB_HEAP, $$ZI$$Limit);
|
|
||||||
if (memory_check_range(buffer, len, base, limit) == IPC_SUCCESS) {
|
|
||||||
return IPC_SUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
base = (uintptr_t)®ION_NAME(Image$$, ER_TFM_DATA, $$RW$$Base);
|
base = (uintptr_t)®ION_NAME(Image$$, ER_TFM_DATA, $$RW$$Base);
|
||||||
limit = (uintptr_t)®ION_NAME(Image$$, ER_TFM_DATA, $$RW$$Limit);
|
limit = (uintptr_t)®ION_NAME(Image$$, ER_TFM_DATA, $$RW$$Limit);
|
||||||
if (memory_check_range(buffer, len, base, limit) == IPC_SUCCESS) {
|
if (memory_check_range(buffer, len, base, limit) == IPC_SUCCESS) {
|
||||||
|
@ -560,12 +537,6 @@ int32_t tfm_memory_check(void *buffer, size_t len, int32_t ns_caller)
|
||||||
if (memory_check_range(buffer, len, base, limit) == IPC_SUCCESS) {
|
if (memory_check_range(buffer, len, base, limit) == IPC_SUCCESS) {
|
||||||
return IPC_SUCCESS;
|
return IPC_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
base = (uintptr_t)S_CODE_START;
|
|
||||||
limit = (uintptr_t)(S_CODE_START + S_CODE_SIZE);
|
|
||||||
if (memory_check_range(buffer, len, base, limit) == IPC_SUCCESS) {
|
|
||||||
return IPC_SUCCESS;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return IPC_ERROR_MEMORY_CHECK;
|
return IPC_ERROR_MEMORY_CHECK;
|
||||||
|
@ -598,7 +569,8 @@ void tfm_spm_init(void)
|
||||||
}
|
}
|
||||||
g_spm_ipc_partition[i].index = i;
|
g_spm_ipc_partition[i].index = i;
|
||||||
g_spm_ipc_partition[i].id = tfm_spm_partition_get_partition_id(i);
|
g_spm_ipc_partition[i].id = tfm_spm_partition_get_partition_id(i);
|
||||||
tfm_event_init(&g_spm_ipc_partition[i].signal_event, EVENT_STAT_WAITED);
|
|
||||||
|
tfm_event_init(&g_spm_ipc_partition[i].signal_evnt);
|
||||||
tfm_list_init(&g_spm_ipc_partition[i].service_list);
|
tfm_list_init(&g_spm_ipc_partition[i].service_list);
|
||||||
|
|
||||||
pth = tfm_spm_partition_get_thread_info_ext(i);
|
pth = tfm_spm_partition_get_thread_info_ext(i);
|
||||||
|
|
|
@ -18,9 +18,9 @@
|
||||||
#include "tfm_internal_defines.h"
|
#include "tfm_internal_defines.h"
|
||||||
#include "tfm_message_queue.h"
|
#include "tfm_message_queue.h"
|
||||||
#include "tfm_spm.h"
|
#include "tfm_spm.h"
|
||||||
#include "secure_utilities.h"
|
|
||||||
#include "tfm_api.h"
|
#include "tfm_api.h"
|
||||||
#include "tfm_secure_api.h"
|
#include "tfm_secure_api.h"
|
||||||
|
#include "tfm_memory_utils.h"
|
||||||
|
|
||||||
#define PSA_TIMEOUT_MASK PSA_BLOCK
|
#define PSA_TIMEOUT_MASK PSA_BLOCK
|
||||||
|
|
||||||
|
@ -124,17 +124,25 @@ psa_status_t tfm_svcall_psa_call(uint32_t *args, int32_t ns_caller, uint32_t lr)
|
||||||
in_num = (size_t)args[2];
|
in_num = (size_t)args[2];
|
||||||
outptr = (psa_outvec *)args[3];
|
outptr = (psa_outvec *)args[3];
|
||||||
/*
|
/*
|
||||||
* 5th parameter is pushed at stack top before SVC; plus exception stacked contents,
|
* 5th parameter is pushed at stack top before SVC, then PE hardware
|
||||||
* 5th parameter is now at 8th position in SVC handler.
|
* stacks the execution context. The size of the context depends on
|
||||||
* However, if thread mode applies FloatPoint, then FloatPoint context is pushed into
|
* various settings:
|
||||||
* stack and then 5th parameter will be args[26].
|
* - if FP is not used, 5th parameter is at 8th position counting
|
||||||
|
* from SP;
|
||||||
|
* - if FP is used and FPCCR_S.TS is 0, 5th parameter is at 26th
|
||||||
|
* position counting from SP;
|
||||||
|
* - if FP is used and FPCCR_S.TS is 1, 5th parameter is at 42th
|
||||||
|
* position counting from SP.
|
||||||
*/
|
*/
|
||||||
if (lr & EXC_RETURN_FPU_FRAME_BASIC) {
|
if (lr & EXC_RETURN_FPU_FRAME_BASIC) {
|
||||||
out_num = (size_t)args[8];
|
out_num = (size_t)args[8];
|
||||||
}
|
#if defined (__FPU_USED) && (__FPU_USED == 1U)
|
||||||
else {
|
} else if (FPU->FPCCR & FPU_FPCCR_TS_Msk) {
|
||||||
|
out_num = (size_t)args[42];
|
||||||
|
#endif
|
||||||
|
} else {
|
||||||
out_num = (size_t)args[26];
|
out_num = (size_t)args[26];
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
/*
|
/*
|
||||||
* FixMe: From non-secure caller, vec and len are composed into a new
|
* FixMe: From non-secure caller, vec and len are composed into a new
|
||||||
|
@ -307,8 +315,8 @@ static psa_signal_t tfm_svcall_psa_wait(uint32_t *args)
|
||||||
* runtime context. After new signal(s) are available, the return value
|
* runtime context. After new signal(s) are available, the return value
|
||||||
* is updated with the available signal(s) and blocked thread gets to run.
|
* is updated with the available signal(s) and blocked thread gets to run.
|
||||||
*/
|
*/
|
||||||
if ((timeout == PSA_BLOCK) && ((partition->signals & signal_mask) == 0)) {
|
if (timeout == PSA_BLOCK && (partition->signals & signal_mask) == 0) {
|
||||||
tfm_event_wait(&partition->signal_event);
|
tfm_event_wait(&partition->signal_evnt);
|
||||||
}
|
}
|
||||||
|
|
||||||
return partition->signals & signal_mask;
|
return partition->signals & signal_mask;
|
||||||
|
@ -683,7 +691,7 @@ static void update_caller_outvec_len(struct tfm_msg_body_t *msg)
|
||||||
* FixeMe: abstract these part into dedicated functions to avoid
|
* FixeMe: abstract these part into dedicated functions to avoid
|
||||||
* accessing thread context in psa layer
|
* accessing thread context in psa layer
|
||||||
*/
|
*/
|
||||||
TFM_ASSERT(msg->ack_mtx.owner->status == THRD_STAT_BLOCK);
|
TFM_ASSERT(msg->ack_evnt.owner->status == THRD_STAT_BLOCK);
|
||||||
|
|
||||||
while (msg->msg.out_size[i] != 0) {
|
while (msg->msg.out_size[i] != 0) {
|
||||||
TFM_ASSERT(msg->caller_outvec[i].base == msg->outvec[i].base);
|
TFM_ASSERT(msg->caller_outvec[i].base == msg->outvec[i].base);
|
||||||
|
@ -800,11 +808,7 @@ static void tfm_svcall_psa_reply(uint32_t *args)
|
||||||
tfm_panic();
|
tfm_panic();
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Save return value for blocked threads */
|
tfm_event_wake(&msg->ack_evnt, ret);
|
||||||
tfm_event_owner_retval(&msg->ack_mtx, ret);
|
|
||||||
|
|
||||||
/* Wake waiting thread up */
|
|
||||||
tfm_event_signal(&msg->ack_mtx);
|
|
||||||
|
|
||||||
/* Message should not be unsed anymore */
|
/* Message should not be unsed anymore */
|
||||||
tfm_spm_free_msg(msg);
|
tfm_spm_free_msg(msg);
|
||||||
|
@ -852,11 +856,8 @@ static void tfm_svcall_psa_notify(uint32_t *args)
|
||||||
* called psa_wait(). Set the return value with the available signals
|
* called psa_wait(). Set the return value with the available signals
|
||||||
* before wake it up with tfm_event_signal().
|
* before wake it up with tfm_event_signal().
|
||||||
*/
|
*/
|
||||||
tfm_event_owner_retval(&partition->signal_event,
|
tfm_event_wake(&partition->signal_evnt,
|
||||||
partition->signals & partition->signal_mask);
|
partition->signals & partition->signal_mask);
|
||||||
|
|
||||||
/* Wake waiting thread up */
|
|
||||||
tfm_event_signal(&partition->signal_event);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -9,7 +9,7 @@
|
||||||
#include "tfm_arch_v8m.h"
|
#include "tfm_arch_v8m.h"
|
||||||
#include "tfm_thread.h"
|
#include "tfm_thread.h"
|
||||||
#include "tfm_utils.h"
|
#include "tfm_utils.h"
|
||||||
#include "secure_utilities.h"
|
#include "tfm_memory_utils.h"
|
||||||
|
|
||||||
/* Force ZERO in case ZI(bss) clear is missing */
|
/* Force ZERO in case ZI(bss) clear is missing */
|
||||||
static struct tfm_thrd_ctx *p_thrd_head = NULL;
|
static struct tfm_thrd_ctx *p_thrd_head = NULL;
|
||||||
|
|
|
@ -4,59 +4,27 @@
|
||||||
* SPDX-License-Identifier: BSD-3-Clause
|
* SPDX-License-Identifier: BSD-3-Clause
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
#include <inttypes.h>
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include "tfm_arch_v8m.h"
|
|
||||||
#include "tfm_thread.h"
|
#include "tfm_thread.h"
|
||||||
#include "tfm_utils.h"
|
#include "tfm_utils.h"
|
||||||
#include "tfm_wait.h"
|
#include "tfm_wait.h"
|
||||||
|
|
||||||
void tfm_event_wait(struct tfm_event_ctx *pevt)
|
void tfm_event_wait(struct tfm_event_t *pevnt)
|
||||||
{
|
{
|
||||||
struct tfm_thrd_ctx *curr_thrd = tfm_thrd_curr_thread();
|
TFM_ASSERT(pevnt && pevnt->magic == TFM_EVENT_MAGIC);
|
||||||
|
|
||||||
TFM_ASSERT(pevt && pevt->magic == EVENT_MAGIC);
|
pevnt->owner = tfm_thrd_curr_thread();
|
||||||
|
tfm_thrd_set_status(pevnt->owner, THRD_STAT_BLOCK);
|
||||||
if (pevt->status == EVENT_STAT_WAITED) {
|
tfm_thrd_activate_schedule();
|
||||||
pevt->owner = curr_thrd;
|
|
||||||
pevt->retval = TFM_STATE_1ST_ARG(&pevt->owner->state_ctx);
|
|
||||||
tfm_thrd_set_status(pevt->owner, THRD_STAT_BLOCK);
|
|
||||||
tfm_thrd_activate_schedule();
|
|
||||||
}
|
|
||||||
|
|
||||||
pevt->status = EVENT_STAT_WAITED;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Peek the status to see if caller would block. */
|
void tfm_event_wake(struct tfm_event_t *pevnt, uint32_t retval)
|
||||||
uint32_t tfm_event_peek(struct tfm_event_ctx *pevt)
|
|
||||||
{
|
{
|
||||||
TFM_ASSERT(pevt && pevt->magic == EVENT_MAGIC);
|
TFM_ASSERT(pevnt && pevnt->magic == TFM_EVENT_MAGIC);
|
||||||
|
|
||||||
return pevt->status;
|
if (pevnt->owner && pevnt->owner->status == THRD_STAT_BLOCK) {
|
||||||
}
|
tfm_thrd_set_status(pevnt->owner, THRD_STAT_RUNNING);
|
||||||
|
tfm_thrd_set_retval(pevnt->owner, retval);
|
||||||
void tfm_event_signal(struct tfm_event_ctx *pevt)
|
|
||||||
{
|
|
||||||
TFM_ASSERT(pevt && pevt->magic == EVENT_MAGIC);
|
|
||||||
|
|
||||||
pevt->status = EVENT_STAT_SIGNALED;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Wake the blocked owner up and keep the status as EVENT_STAT_WAITED
|
|
||||||
* if there is an owner. Or the second event wait caller will return
|
|
||||||
* without block since status is EVENT_STAT_SIGNALED.
|
|
||||||
*/
|
|
||||||
if (pevt->owner && pevt->owner->status == THRD_STAT_BLOCK) {
|
|
||||||
tfm_thrd_set_status(pevt->owner, THRD_STAT_RUNNING);
|
|
||||||
tfm_thrd_set_retval(pevt->owner, pevt->retval);
|
|
||||||
pevt->status = EVENT_STAT_WAITED;
|
|
||||||
tfm_thrd_activate_schedule();
|
tfm_thrd_activate_schedule();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void tfm_event_owner_retval(struct tfm_event_ctx *pmtx, uint32_t retval)
|
|
||||||
{
|
|
||||||
TFM_ASSERT(pmtx && pmtx->magic == EVENT_MAGIC);
|
|
||||||
|
|
||||||
pmtx->retval = retval;
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2017-2018, Arm Limited. All rights reserved.
|
* Copyright (c) 2017-2019, Arm Limited. All rights reserved.
|
||||||
*
|
*
|
||||||
* SPDX-License-Identifier: BSD-3-Clause
|
* SPDX-License-Identifier: BSD-3-Clause
|
||||||
*
|
*
|
||||||
|
@ -8,9 +8,9 @@
|
||||||
#ifndef __SECURE_UTILITIES_H__
|
#ifndef __SECURE_UTILITIES_H__
|
||||||
#define __SECURE_UTILITIES_H__
|
#define __SECURE_UTILITIES_H__
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
#include "cmsis_compiler.h"
|
#include "cmsis_compiler.h"
|
||||||
#include "tfm_svc.h"
|
#include "tfm_svc.h"
|
||||||
#include "string.h"
|
|
||||||
|
|
||||||
#define EXC_RETURN_INDICATOR (0xF << 28)
|
#define EXC_RETURN_INDICATOR (0xF << 28)
|
||||||
#define EXC_RETURN_SECURITY_STACK_STATUS_MASK (0x3 << 5)
|
#define EXC_RETURN_SECURITY_STACK_STATUS_MASK (0x3 << 5)
|
||||||
|
@ -25,8 +25,6 @@
|
||||||
#define EXC_NUM_PENDSV (14)
|
#define EXC_NUM_PENDSV (14)
|
||||||
#define EXC_NUM_SYSTICK (15)
|
#define EXC_NUM_SYSTICK (15)
|
||||||
|
|
||||||
#define printf(...)
|
|
||||||
|
|
||||||
/* Disable NS exceptions by setting NS PRIMASK to 1 */
|
/* Disable NS exceptions by setting NS PRIMASK to 1 */
|
||||||
#define TFM_NS_EXC_DISABLE() __TZ_set_PRIMASK_NS(1)
|
#define TFM_NS_EXC_DISABLE() __TZ_set_PRIMASK_NS(1)
|
||||||
/* Enable NS exceptions by setting NS PRIMASK to 0 */
|
/* Enable NS exceptions by setting NS PRIMASK to 0 */
|
||||||
|
@ -106,27 +104,4 @@ __STATIC_INLINE void __set_CONTROL_SPSEL(int32_t SPSEL)
|
||||||
__asm("ISB");
|
__asm("ISB");
|
||||||
}
|
}
|
||||||
|
|
||||||
/* FIXME: The following functions are wrappers around standard C library
|
|
||||||
* functions: memcpy, memcmp, memset
|
|
||||||
* In long term standard C library might be removed from TF-M project or
|
|
||||||
* replaced with a secure implementation due to security concerns.
|
|
||||||
*/
|
|
||||||
__attribute__ ((always_inline)) __STATIC_INLINE
|
|
||||||
void tfm_memcpy(void *dest, const void *src, uint32_t size)
|
|
||||||
{
|
|
||||||
memcpy(dest, src, size);
|
|
||||||
}
|
|
||||||
|
|
||||||
__attribute__ ((always_inline)) __STATIC_INLINE
|
|
||||||
int32_t tfm_memcmp(const void * ptr1, const void * ptr2, size_t num)
|
|
||||||
{
|
|
||||||
return (memcmp(ptr1, ptr2, num));
|
|
||||||
}
|
|
||||||
|
|
||||||
__attribute__ ((always_inline)) __STATIC_INLINE
|
|
||||||
void * tfm_memset(void * ptr, int value, size_t num)
|
|
||||||
{
|
|
||||||
return (memset(ptr, value, num));
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif /* __SECURE_UTILITIES_H__ */
|
#endif /* __SECURE_UTILITIES_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
|
* SPDX-License-Identifier: BSD-3-Clause
|
||||||
*
|
*
|
||||||
|
@ -7,7 +7,7 @@
|
||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include "bl2/include/tfm_boot_status.h"
|
#include "bl2/include/tfm_boot_status.h"
|
||||||
#include "secure_utilities.h"
|
#include "tfm_memory_utils.h"
|
||||||
#include "tfm_internal.h"
|
#include "tfm_internal.h"
|
||||||
#include "tfm_api.h"
|
#include "tfm_api.h"
|
||||||
#include "flash_layout.h"
|
#include "flash_layout.h"
|
||||||
|
@ -57,13 +57,13 @@ void tfm_core_validate_boot_data(void)
|
||||||
void tfm_core_get_boot_data_handler(uint32_t args[])
|
void tfm_core_get_boot_data_handler(uint32_t args[])
|
||||||
{
|
{
|
||||||
uint8_t tlv_major = (uint8_t)args[0];
|
uint8_t tlv_major = (uint8_t)args[0];
|
||||||
uint8_t *ptr = (uint8_t *)args[1];
|
uint8_t *buf_start = (uint8_t *)args[1];
|
||||||
uint16_t buf_size = (uint16_t)args[2];
|
uint16_t buf_size = (uint16_t)args[2];
|
||||||
uint8_t *buf_start = ptr;
|
uint8_t *ptr;
|
||||||
uint32_t running_partition_idx =
|
uint32_t running_partition_idx =
|
||||||
tfm_spm_partition_get_running_partition_idx();
|
tfm_spm_partition_get_running_partition_idx();
|
||||||
struct shared_data_tlv_header *tlv_header;
|
struct shared_data_tlv_header *tlv_header;
|
||||||
struct shared_data_tlv_entry *tlv_entry;
|
struct shared_data_tlv_entry tlv_entry;
|
||||||
uintptr_t tlv_end, offset;
|
uintptr_t tlv_end, offset;
|
||||||
uint32_t res;
|
uint32_t res;
|
||||||
|
|
||||||
|
@ -71,9 +71,9 @@ void tfm_core_get_boot_data_handler(uint32_t args[])
|
||||||
* by the partition
|
* by the partition
|
||||||
*/
|
*/
|
||||||
res = tfm_core_check_buffer_access(running_partition_idx,
|
res = tfm_core_check_buffer_access(running_partition_idx,
|
||||||
(void*)buf_start,
|
(void *)buf_start,
|
||||||
buf_size,
|
buf_size,
|
||||||
2);
|
2); /* Check 4 bytes alignment */
|
||||||
if (!res) {
|
if (!res) {
|
||||||
/* Not in accessible range, return error */
|
/* Not in accessible range, return error */
|
||||||
args[0] = TFM_ERROR_INVALID_PARAMETER;
|
args[0] = TFM_ERROR_INVALID_PARAMETER;
|
||||||
|
@ -97,26 +97,31 @@ void tfm_core_get_boot_data_handler(uint32_t args[])
|
||||||
args[0] = TFM_ERROR_INVALID_PARAMETER;
|
args[0] = TFM_ERROR_INVALID_PARAMETER;
|
||||||
return;
|
return;
|
||||||
} else {
|
} else {
|
||||||
tfm_memcpy(ptr, tlv_header, SHARED_DATA_HEADER_SIZE);
|
tlv_header = (struct shared_data_tlv_header *)buf_start;
|
||||||
ptr += SHARED_DATA_HEADER_SIZE;
|
tlv_header->tlv_magic = SHARED_DATA_TLV_INFO_MAGIC;
|
||||||
|
tlv_header->tlv_tot_len = SHARED_DATA_HEADER_SIZE;
|
||||||
|
ptr = (uint8_t *)tlv_header + SHARED_DATA_HEADER_SIZE;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Iterates over the TLV section and copy TLVs with requested major
|
/* Iterates over the TLV section and copy TLVs with requested major
|
||||||
* type to the provided buffer.
|
* type to the provided buffer.
|
||||||
*/
|
*/
|
||||||
for(; offset < tlv_end; offset += tlv_entry->tlv_len) {
|
for (; offset < tlv_end; offset += tlv_entry.tlv_len) {
|
||||||
tlv_entry = (struct shared_data_tlv_entry *)offset;
|
/* Create local copy to avoid unaligned access */
|
||||||
if (tlv_entry->tlv_major_type == tlv_major) {
|
tfm_memcpy(&tlv_entry,
|
||||||
|
(const void *)offset,
|
||||||
|
SHARED_DATA_ENTRY_HEADER_SIZE);
|
||||||
|
if (GET_MAJOR(tlv_entry.tlv_type) == tlv_major) {
|
||||||
/* Check buffer overflow */
|
/* Check buffer overflow */
|
||||||
if ((ptr - buf_start + tlv_entry->tlv_len) > buf_size) {
|
if ((ptr - buf_start + tlv_entry.tlv_len) > buf_size) {
|
||||||
args[0] = TFM_ERROR_INVALID_PARAMETER;
|
args[0] = TFM_ERROR_INVALID_PARAMETER;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
tfm_memcpy(ptr, (const void *)tlv_entry, tlv_entry->tlv_len);
|
tfm_memcpy(ptr, (const void *)offset, tlv_entry.tlv_len);
|
||||||
|
|
||||||
ptr += tlv_entry->tlv_len;
|
ptr += tlv_entry.tlv_len;
|
||||||
tlv_header->tlv_tot_len += tlv_entry->tlv_len;
|
tlv_header->tlv_tot_len += tlv_entry.tlv_len;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
args[0] = TFM_SUCCESS;
|
args[0] = TFM_SUCCESS;
|
||||||
|
|
|
@ -11,6 +11,7 @@
|
||||||
#include "tfm_internal.h"
|
#include "tfm_internal.h"
|
||||||
#include "tfm_api.h"
|
#include "tfm_api.h"
|
||||||
#include "platform/include/tfm_spm_hal.h"
|
#include "platform/include/tfm_spm_hal.h"
|
||||||
|
#include "uart_stdout.h"
|
||||||
#include "secure_utilities.h"
|
#include "secure_utilities.h"
|
||||||
#include "secure_fw/spm/spm_api.h"
|
#include "secure_fw/spm/spm_api.h"
|
||||||
#include "secure_fw/include/tfm_spm_services_api.h"
|
#include "secure_fw/include/tfm_spm_services_api.h"
|
||||||
|
@ -87,6 +88,7 @@ int32_t tfm_core_init(void)
|
||||||
|
|
||||||
__enable_irq();
|
__enable_irq();
|
||||||
|
|
||||||
|
stdio_init();
|
||||||
LOG_MSG("Secure image initializing!");
|
LOG_MSG("Secure image initializing!");
|
||||||
|
|
||||||
#ifdef TFM_CORE_DEBUG
|
#ifdef TFM_CORE_DEBUG
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2017-2018, Arm Limited. All rights reserved.
|
* Copyright (c) 2017-2019, Arm Limited. All rights reserved.
|
||||||
*
|
*
|
||||||
* SPDX-License-Identifier: BSD-3-Clause
|
* SPDX-License-Identifier: BSD-3-Clause
|
||||||
*
|
*
|
||||||
|
@ -8,7 +8,6 @@
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
#include "cmsis.h"
|
|
||||||
#include "secure_utilities.h"
|
#include "secure_utilities.h"
|
||||||
#include "arm_acle.h"
|
#include "arm_acle.h"
|
||||||
#include "tfm_svc.h"
|
#include "tfm_svc.h"
|
||||||
|
@ -16,6 +15,7 @@
|
||||||
#include "region_defs.h"
|
#include "region_defs.h"
|
||||||
#include "tfm_api.h"
|
#include "tfm_api.h"
|
||||||
#include "tfm_internal.h"
|
#include "tfm_internal.h"
|
||||||
|
#include "tfm_memory_utils.h"
|
||||||
#ifdef TFM_PSA_API
|
#ifdef TFM_PSA_API
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
#include "tfm_svcalls.h"
|
#include "tfm_svcalls.h"
|
||||||
|
|
|
@ -0,0 +1,45 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2019, Arm Limited. All rights reserved.
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: BSD-3-Clause
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __TFM_MEMORY_UTILS_H__
|
||||||
|
#define __TFM_MEMORY_UTILS_H__
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
#include "cmsis_compiler.h"
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* FIXME: The following functions are wrappers around standard C library
|
||||||
|
* functions: memcpy, memcmp, memset
|
||||||
|
* In long term standard C library might be removed from TF-M project or
|
||||||
|
* replaced with a secure implementation due to security concerns.
|
||||||
|
*/
|
||||||
|
__attribute__ ((always_inline)) __STATIC_INLINE
|
||||||
|
void *tfm_memcpy(void *dest, const void *src, size_t num)
|
||||||
|
{
|
||||||
|
return (memcpy(dest, src, num));
|
||||||
|
}
|
||||||
|
|
||||||
|
__attribute__ ((always_inline)) __STATIC_INLINE
|
||||||
|
int tfm_memcmp(const void *ptr1, const void *ptr2, size_t num)
|
||||||
|
{
|
||||||
|
return (memcmp(ptr1, ptr2, num));
|
||||||
|
}
|
||||||
|
|
||||||
|
__attribute__ ((always_inline)) __STATIC_INLINE
|
||||||
|
void *tfm_memset(void *ptr, int value, size_t num)
|
||||||
|
{
|
||||||
|
return (memset(ptr, value, num));
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* __TFM_MEMORY_UTILS_H__ */
|
|
@ -48,8 +48,7 @@ int32_t tfm_core_ns_ipc_request(void *fn, int32_t arg1, int32_t arg2,
|
||||||
int32_t arg3, int32_t arg4)
|
int32_t arg3, int32_t arg4)
|
||||||
{
|
{
|
||||||
int32_t args[4] = {arg1, arg2, arg3, arg4};
|
int32_t args[4] = {arg1, arg2, arg3, arg4};
|
||||||
volatile struct tfm_sfn_req_s desc;
|
struct tfm_sfn_req_s desc, *desc_ptr = &desc;
|
||||||
struct tfm_sfn_req_s *desc_ptr = &desc;
|
|
||||||
int32_t res;
|
int32_t res;
|
||||||
|
|
||||||
desc.sfn = fn;
|
desc.sfn = fn;
|
||||||
|
@ -99,7 +98,7 @@ psa_handle_t tfm_psa_connect_veneer(uint32_t sid, uint32_t minor_version)
|
||||||
__tfm_secure_gateway_attributes__
|
__tfm_secure_gateway_attributes__
|
||||||
psa_status_t tfm_psa_call_veneer(psa_handle_t handle,
|
psa_status_t tfm_psa_call_veneer(psa_handle_t handle,
|
||||||
const psa_invec *in_vecs,
|
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,
|
TFM_CORE_NS_IPC_REQUEST_VENEER(tfm_svcall_psa_call, handle, in_vecs,
|
||||||
out_vecs, 0);
|
out_vecs, 0);
|
||||||
|
|
|
@ -8,10 +8,11 @@
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
#include "cmsis.h"
|
#include <arm_cmse.h>
|
||||||
#include "tfm_secure_api.h"
|
#include "tfm_secure_api.h"
|
||||||
#include "tfm_nspm.h"
|
#include "tfm_nspm.h"
|
||||||
#include "secure_utilities.h"
|
#include "secure_utilities.h"
|
||||||
|
#include "uart_stdout.h"
|
||||||
#include "secure_fw/spm/spm_api.h"
|
#include "secure_fw/spm/spm_api.h"
|
||||||
#include "region_defs.h"
|
#include "region_defs.h"
|
||||||
#include "tfm_api.h"
|
#include "tfm_api.h"
|
||||||
|
@ -22,12 +23,15 @@
|
||||||
#error TFM_LVL is not defined!
|
#error TFM_LVL is not defined!
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if TFM_LVL == 1
|
|
||||||
/* Macros to pick linker symbols and allow references to sections */
|
/* Macros to pick linker symbols and allow references to sections */
|
||||||
#define REGION(a, b, c) a##b##c
|
#define REGION(a, b, c) a##b##c
|
||||||
#define REGION_NAME(a, b, c) REGION(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)
|
#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$$Base);
|
||||||
REGION_DECLARE(Image$$, TFM_SECURE_STACK, $$ZI$$Limit);
|
REGION_DECLARE(Image$$, TFM_SECURE_STACK, $$ZI$$Limit);
|
||||||
#endif
|
#endif
|
||||||
|
@ -38,6 +42,15 @@ REGION_DECLARE(Image$$, TFM_SECURE_STACK, $$ZI$$Limit);
|
||||||
int32_t tfm_secure_lock;
|
int32_t tfm_secure_lock;
|
||||||
static int32_t tfm_secure_api_initializing = 1;
|
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 int32_t *prepare_partition_ctx(
|
static int32_t *prepare_partition_ctx(
|
||||||
struct tfm_exc_stack_t *svc_ctx,
|
struct tfm_exc_stack_t *svc_ctx,
|
||||||
struct tfm_sfn_req_s *desc_ptr,
|
struct tfm_sfn_req_s *desc_ptr,
|
||||||
|
@ -62,6 +75,30 @@ static int32_t *prepare_partition_ctx(
|
||||||
return dst;
|
return dst;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int32_t *prepare_partition_iovec_ctx(
|
||||||
|
struct tfm_exc_stack_t *svc_ctx,
|
||||||
|
struct tfm_sfn_req_s *desc_ptr,
|
||||||
|
struct iovec_args_t *iovec_args,
|
||||||
|
int32_t *dst)
|
||||||
|
{
|
||||||
|
/* XPSR = as was when called, but make sure it's thread mode */
|
||||||
|
*(--dst) = svc_ctx->XPSR & 0xFFFFFE00;
|
||||||
|
/* ReturnAddress = resume veneer in new context */
|
||||||
|
*(--dst) = svc_ctx->RetAddr;
|
||||||
|
/* LR = sfn address */
|
||||||
|
*(--dst) = (int32_t)desc_ptr->sfn;
|
||||||
|
/* R12 = don't care */
|
||||||
|
*(--dst) = 0;
|
||||||
|
|
||||||
|
/* 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(
|
static void restore_caller_ctx(
|
||||||
struct tfm_exc_stack_t *svc_ctx,
|
struct tfm_exc_stack_t *svc_ctx,
|
||||||
struct tfm_exc_stack_t *target_ctx)
|
struct tfm_exc_stack_t *target_ctx)
|
||||||
|
@ -75,6 +112,241 @@ static void restore_caller_ctx(
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Check whether a memory range is inside a memory region.
|
||||||
|
*
|
||||||
|
* \param[in] p The start address of the range to check
|
||||||
|
* \param[in] s The size of the range to check
|
||||||
|
* \param[in] region_start The start address of the region, which should
|
||||||
|
* contain the range
|
||||||
|
* \param[in] region_len The size of the region, which should contain the
|
||||||
|
* range
|
||||||
|
*
|
||||||
|
* \return 1 if the region contains the range, 0 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;
|
||||||
|
|
||||||
|
/* Check for overflow in the range parameters */
|
||||||
|
if ((uintptr_t)p > UINTPTR_MAX-s) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* We trust the region parameters, and don't check for overflow */
|
||||||
|
|
||||||
|
/* Calculate the result */
|
||||||
|
range_in_region = ((uintptr_t)p >= region_start) &&
|
||||||
|
((uintptr_t)p+s <= region_start+region_len);
|
||||||
|
|
||||||
|
return range_in_region;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Check whether the current partition has access to a memory range
|
||||||
|
*
|
||||||
|
* This function assumes, that the current MPU configuration is set for the
|
||||||
|
* partition to be checked. The flags should contain information of the
|
||||||
|
* execution mode of the partition code (priv/unpriv), and access type
|
||||||
|
* (read/write) as specified in "ARMv8-M Security Extensions: Requirements on
|
||||||
|
* Development Tools" chapter "Address range check intrinsic"
|
||||||
|
*
|
||||||
|
* \param[in] p The start address of the range to check
|
||||||
|
* \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.
|
||||||
|
*/
|
||||||
|
static int32_t has_access_to_region(const void *p, size_t s, uint32_t flags)
|
||||||
|
{
|
||||||
|
int32_t range_access_allowed_by_mpu;
|
||||||
|
|
||||||
|
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);
|
||||||
|
|
||||||
|
/* 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 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);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Check whether the current partition has read access to a memory range
|
||||||
|
*
|
||||||
|
* 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
|
||||||
|
*
|
||||||
|
* \return 1 if the partition has access to the memory range, 0 otherwise.
|
||||||
|
*/
|
||||||
|
static int32_t has_read_access_to_region(const void *p, size_t s,
|
||||||
|
int32_t ns_caller)
|
||||||
|
{
|
||||||
|
uint32_t flags = CMSE_MPU_UNPRIV|CMSE_MPU_READ;
|
||||||
|
|
||||||
|
if (ns_caller) {
|
||||||
|
flags |= CMSE_NONSECURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
return has_access_to_region(p, s, flags);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Check whether the current partition has write access to a memory range
|
||||||
|
*
|
||||||
|
* 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
|
||||||
|
*
|
||||||
|
* \return 1 if the partition has access to the memory range, 0 otherwise.
|
||||||
|
*/
|
||||||
|
static int32_t has_write_access_to_region(void *p, size_t s, int32_t ns_caller)
|
||||||
|
{
|
||||||
|
uint32_t flags = CMSE_MPU_UNPRIV|CMSE_MPU_READWRITE;
|
||||||
|
|
||||||
|
if (ns_caller) {
|
||||||
|
flags |= CMSE_NONSECURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
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(struct tfm_sfn_req_s *desc_ptr)
|
||||||
|
{
|
||||||
|
struct psa_invec *in_vec = (psa_invec *)desc_ptr->args[0];
|
||||||
|
size_t in_len = desc_ptr->args[1];
|
||||||
|
struct psa_outvec *out_vec = (psa_outvec *)desc_ptr->args[2];
|
||||||
|
size_t out_len = desc_ptr->args[3];
|
||||||
|
|
||||||
|
uint32_t i;
|
||||||
|
|
||||||
|
/* 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) ||
|
||||||
|
(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) ||
|
||||||
|
(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) ||
|
||||||
|
(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) ||
|
||||||
|
(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)
|
||||||
|
{
|
||||||
|
int 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(struct tfm_sfn_req_s *desc_ptr,
|
static int32_t tfm_start_partition(struct tfm_sfn_req_s *desc_ptr,
|
||||||
uint32_t excReturn)
|
uint32_t excReturn)
|
||||||
{
|
{
|
||||||
|
@ -89,6 +361,7 @@ static int32_t tfm_start_partition(struct tfm_sfn_req_s *desc_ptr,
|
||||||
struct tfm_exc_stack_t *svc_ctx = (struct tfm_exc_stack_t *)psp;
|
struct tfm_exc_stack_t *svc_ctx = (struct tfm_exc_stack_t *)psp;
|
||||||
uint32_t caller_partition_id;
|
uint32_t caller_partition_id;
|
||||||
int32_t client_id;
|
int32_t client_id;
|
||||||
|
struct iovec_args_t *iovec_args;
|
||||||
|
|
||||||
caller_flags = tfm_spm_partition_get_flags(caller_partition_idx);
|
caller_flags = tfm_spm_partition_get_flags(caller_partition_idx);
|
||||||
|
|
||||||
|
@ -145,8 +418,13 @@ static int32_t tfm_start_partition(struct tfm_sfn_req_s *desc_ptr,
|
||||||
|
|
||||||
#if TFM_LVL == 1
|
#if TFM_LVL == 1
|
||||||
/* Prepare switch to shared secure partition stack */
|
/* 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 =
|
partition_psp =
|
||||||
(uint32_t)®ION_NAME(Image$$, TFM_SECURE_STACK, $$ZI$$Limit);
|
(uint32_t)®ION_NAME(Image$$, TFM_SECURE_STACK, $$ZI$$Limit)-
|
||||||
|
sizeof(struct iovec_args_t);
|
||||||
partition_psplim =
|
partition_psplim =
|
||||||
(uint32_t)®ION_NAME(Image$$, TFM_SECURE_STACK, $$ZI$$Base);
|
(uint32_t)®ION_NAME(Image$$, TFM_SECURE_STACK, $$ZI$$Base);
|
||||||
#else
|
#else
|
||||||
|
@ -193,16 +471,53 @@ static int32_t tfm_start_partition(struct tfm_sfn_req_s *desc_ptr,
|
||||||
* handler mode
|
* handler mode
|
||||||
*/
|
*/
|
||||||
if ((desc_ptr->ns_caller) || (tfm_secure_api_initializing)) {
|
if ((desc_ptr->ns_caller) || (tfm_secure_api_initializing)) {
|
||||||
/* Prepare the partition context, update stack ptr */
|
if (desc_ptr->iovec_api == TFM_SFN_API_IOVEC) {
|
||||||
psp = (uint32_t)prepare_partition_ctx(
|
/* Save the iovecs on the common stack. The vectors had been sanity
|
||||||
svc_ctx, desc_ptr, (int32_t *)partition_psp);
|
* 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));
|
||||||
|
tfm_spm_partition_set_iovec(partition_idx, desc_ptr->args);
|
||||||
|
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,
|
||||||
|
(int32_t *)partition_psp);
|
||||||
|
} else {
|
||||||
|
/* Prepare the partition context, update stack ptr */
|
||||||
|
psp = (uint32_t)prepare_partition_ctx(svc_ctx, desc_ptr,
|
||||||
|
(int32_t *)partition_psp);
|
||||||
|
}
|
||||||
__set_PSP(psp);
|
__set_PSP(psp);
|
||||||
__set_PSPLIM(partition_psplim);
|
__set_PSPLIM(partition_psplim);
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
/* Prepare the partition context, update stack ptr */
|
if (desc_ptr->iovec_api == TFM_SFN_API_IOVEC) {
|
||||||
psp = (uint32_t)prepare_partition_ctx(svc_ctx, desc_ptr,
|
/* Save the iovecs on the stack of the partition. The vectors had been
|
||||||
(int32_t *)partition_psp);
|
* 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));
|
||||||
|
tfm_spm_partition_set_iovec(partition_idx, desc_ptr->args);
|
||||||
|
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,
|
||||||
|
(int32_t *)partition_psp);
|
||||||
|
} else {
|
||||||
|
/* Prepare the partition context, update stack ptr */
|
||||||
|
psp = (uint32_t)prepare_partition_ctx(svc_ctx, desc_ptr,
|
||||||
|
(int32_t *)partition_psp);
|
||||||
|
}
|
||||||
__set_PSP(psp);
|
__set_PSP(psp);
|
||||||
__set_PSPLIM(partition_psplim);
|
__set_PSPLIM(partition_psplim);
|
||||||
#endif
|
#endif
|
||||||
|
@ -224,7 +539,9 @@ static int32_t tfm_return_from_partition(uint32_t *excReturn)
|
||||||
uint32_t return_partition_idx;
|
uint32_t return_partition_idx;
|
||||||
uint32_t return_partition_flags;
|
uint32_t return_partition_flags;
|
||||||
uint32_t psp = __get_PSP();
|
uint32_t psp = __get_PSP();
|
||||||
|
int i;
|
||||||
struct tfm_exc_stack_t *svc_ctx = (struct tfm_exc_stack_t *)psp;
|
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) {
|
if (current_partition_idx == SPM_INVALID_PARTITION_IDX) {
|
||||||
return TFM_SECURE_UNLOCK_FAILED;
|
return TFM_SECURE_UNLOCK_FAILED;
|
||||||
|
@ -304,6 +621,18 @@ static int32_t tfm_return_from_partition(uint32_t *excReturn)
|
||||||
uint32_t psp_stack_bottom = (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);
|
__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
|
#else
|
||||||
/* Restore caller context */
|
/* Restore caller context */
|
||||||
|
@ -314,7 +643,20 @@ static int32_t tfm_return_from_partition(uint32_t *excReturn)
|
||||||
__set_PSPLIM(tfm_spm_partition_get_stack_bottom(return_partition_idx));
|
__set_PSPLIM(tfm_spm_partition_get_stack_bottom(return_partition_idx));
|
||||||
/* Clear the context entry before returning */
|
/* Clear the context entry before returning */
|
||||||
tfm_spm_partition_set_stack(
|
tfm_spm_partition_set_stack(
|
||||||
current_partition_idx, psp - sizeof(struct tfm_exc_stack_t));
|
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
|
#endif
|
||||||
|
|
||||||
tfm_spm_partition_cleanup_context(current_partition_idx);
|
tfm_spm_partition_cleanup_context(current_partition_idx);
|
||||||
|
@ -396,12 +738,22 @@ int32_t tfm_core_sfn_request_handler(
|
||||||
res = tfm_check_sfn_req_integrity(desc_ptr);
|
res = tfm_check_sfn_req_integrity(desc_ptr);
|
||||||
if (res != TFM_SUCCESS) {
|
if (res != TFM_SUCCESS) {
|
||||||
ERROR_MSG("Invalid service request!");
|
ERROR_MSG("Invalid service request!");
|
||||||
return TFM_ERROR_STATUS(res);
|
tfm_secure_api_error_handler();
|
||||||
}
|
}
|
||||||
|
|
||||||
__disable_irq();
|
__disable_irq();
|
||||||
|
|
||||||
desc_ptr->caller_part_idx = tfm_spm_partition_get_running_partition_idx();
|
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);
|
res = tfm_core_check_sfn_req_rules(desc_ptr);
|
||||||
if (res != TFM_SUCCESS) {
|
if (res != TFM_SUCCESS) {
|
||||||
/* FixMe: error compartmentalization TBD */
|
/* FixMe: error compartmentalization TBD */
|
||||||
|
@ -409,7 +761,7 @@ int32_t tfm_core_sfn_request_handler(
|
||||||
desc_ptr->caller_part_idx, SPM_PARTITION_STATE_CLOSED);
|
desc_ptr->caller_part_idx, SPM_PARTITION_STATE_CLOSED);
|
||||||
__enable_irq();
|
__enable_irq();
|
||||||
ERROR_MSG("Unauthorized service request!");
|
ERROR_MSG("Unauthorized service request!");
|
||||||
return TFM_ERROR_STATUS(res);
|
tfm_secure_api_error_handler();
|
||||||
}
|
}
|
||||||
|
|
||||||
res = tfm_start_partition(desc_ptr, excReturn);
|
res = tfm_start_partition(desc_ptr, excReturn);
|
||||||
|
@ -417,7 +769,7 @@ int32_t tfm_core_sfn_request_handler(
|
||||||
/* FixMe: consider possible fault scenarios */
|
/* FixMe: consider possible fault scenarios */
|
||||||
__enable_irq();
|
__enable_irq();
|
||||||
ERROR_MSG("Failed to process service request!");
|
ERROR_MSG("Failed to process service request!");
|
||||||
return TFM_ERROR_STATUS(res);
|
tfm_secure_api_error_handler();
|
||||||
}
|
}
|
||||||
|
|
||||||
__enable_irq();
|
__enable_irq();
|
||||||
|
@ -432,6 +784,14 @@ int32_t tfm_core_sfn_request_thread_mode(struct tfm_sfn_req_s *desc_ptr)
|
||||||
int32_t *args;
|
int32_t *args;
|
||||||
int32_t retVal;
|
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 */
|
/* No excReturn value is needed as no exception handling is used */
|
||||||
res = tfm_core_sfn_request_handler(desc_ptr, 0);
|
res = tfm_core_sfn_request_handler(desc_ptr, 0);
|
||||||
|
|
||||||
|
@ -689,6 +1049,8 @@ void tfm_core_memory_permission_check_handler(uint32_t *svc_args)
|
||||||
uint32_t tfm_core_partition_request_svc_handler(
|
uint32_t tfm_core_partition_request_svc_handler(
|
||||||
struct tfm_exc_stack_t *svc_ctx, uint32_t excReturn)
|
struct tfm_exc_stack_t *svc_ctx, uint32_t excReturn)
|
||||||
{
|
{
|
||||||
|
struct tfm_sfn_req_s *desc_ptr;
|
||||||
|
|
||||||
if (!(excReturn & EXC_RETURN_STACK_PROCESS)) {
|
if (!(excReturn & EXC_RETURN_STACK_PROCESS)) {
|
||||||
/* Service request SVC called with MSP active.
|
/* Service request SVC called with MSP active.
|
||||||
* Either invalid configuration for Thread mode or SVC called
|
* Either invalid configuration for Thread mode or SVC called
|
||||||
|
@ -699,7 +1061,7 @@ uint32_t tfm_core_partition_request_svc_handler(
|
||||||
tfm_secure_api_error_handler();
|
tfm_secure_api_error_handler();
|
||||||
}
|
}
|
||||||
|
|
||||||
struct tfm_sfn_req_s *desc_ptr = (struct tfm_sfn_req_s *)svc_ctx->R0;
|
desc_ptr = (struct tfm_sfn_req_s *)svc_ctx->R0;
|
||||||
|
|
||||||
if (tfm_core_sfn_request_handler(desc_ptr, excReturn) != TFM_SUCCESS) {
|
if (tfm_core_sfn_request_handler(desc_ptr, excReturn) != TFM_SUCCESS) {
|
||||||
tfm_secure_api_error_handler();
|
tfm_secure_api_error_handler();
|
||||||
|
@ -724,17 +1086,19 @@ uint32_t tfm_core_partition_return_handler(uint32_t lr)
|
||||||
/* Store return value from secure partition */
|
/* Store return value from secure partition */
|
||||||
int32_t retVal = *(int32_t *)__get_PSP();
|
int32_t retVal = *(int32_t *)__get_PSP();
|
||||||
|
|
||||||
if ((retVal > TFM_SUCCESS) &&
|
if (!is_iovec_api_call()) {
|
||||||
(retVal < TFM_PARTITION_SPECIFIC_ERROR_MIN)) {
|
if ((retVal > TFM_SUCCESS) &&
|
||||||
/* Secure function returned a reserved value */
|
(retVal < TFM_PARTITION_SPECIFIC_ERROR_MIN)) {
|
||||||
|
/* Secure function returned a reserved value */
|
||||||
#ifdef TFM_CORE_DEBUG
|
#ifdef TFM_CORE_DEBUG
|
||||||
LOG_MSG("Invalid return value from secure partition!");
|
LOG_MSG("Invalid return value from secure partition!");
|
||||||
#endif
|
#endif
|
||||||
/* FixMe: error can be traced to specific secure partition
|
/* FixMe: error can be traced to specific secure partition
|
||||||
* and Core is not compromised. Error handling flow can be
|
* and Core is not compromised. Error handling flow can be
|
||||||
* refined
|
* refined
|
||||||
*/
|
*/
|
||||||
tfm_secure_api_error_handler();
|
tfm_secure_api_error_handler();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
res = tfm_return_from_partition(&lr);
|
res = tfm_return_from_partition(&lr);
|
||||||
|
|
|
@ -29,6 +29,9 @@
|
||||||
#define TFM_ERROR_STATUS(status) (TFM_PARTITION_BUSY)
|
#define TFM_ERROR_STATUS(status) (TFM_PARTITION_BUSY)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#define TFM_SFN_API_LEGACY 0
|
||||||
|
#define TFM_SFN_API_IOVEC 1
|
||||||
|
|
||||||
#ifndef TFM_LVL
|
#ifndef TFM_LVL
|
||||||
#error TFM_LVL is not defined!
|
#error TFM_LVL is not defined!
|
||||||
#endif
|
#endif
|
||||||
|
@ -42,6 +45,7 @@ struct tfm_sfn_req_s {
|
||||||
sfn_t sfn;
|
sfn_t sfn;
|
||||||
int32_t *args;
|
int32_t *args;
|
||||||
uint32_t caller_part_idx;
|
uint32_t caller_part_idx;
|
||||||
|
int32_t iovec_api;
|
||||||
int32_t ns_caller : 1;
|
int32_t ns_caller : 1;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -73,8 +77,9 @@ extern int32_t tfm_core_validate_secure_caller(void);
|
||||||
|
|
||||||
extern int32_t tfm_core_get_caller_client_id(int32_t *caller_client_id);
|
extern int32_t tfm_core_get_caller_client_id(int32_t *caller_client_id);
|
||||||
|
|
||||||
extern int32_t tfm_core_memory_permission_check(
|
extern int32_t tfm_core_memory_permission_check(const void *ptr,
|
||||||
void *ptr, uint32_t size, int32_t access);
|
uint32_t size,
|
||||||
|
int32_t access);
|
||||||
|
|
||||||
extern int32_t tfm_core_get_boot_data(uint8_t major_type, void *ptr,
|
extern int32_t tfm_core_get_boot_data(uint8_t major_type, void *ptr,
|
||||||
uint32_t len);
|
uint32_t len);
|
||||||
|
@ -83,12 +88,16 @@ int32_t tfm_core_sfn_request(struct tfm_sfn_req_s *desc_ptr);
|
||||||
|
|
||||||
int32_t tfm_core_sfn_request_thread_mode(struct tfm_sfn_req_s *desc_ptr);
|
int32_t tfm_core_sfn_request_thread_mode(struct tfm_sfn_req_s *desc_ptr);
|
||||||
|
|
||||||
|
#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)
|
||||||
|
|
||||||
#define TFM_CORE_SFN_REQUEST(id, fn, a, b, c, d) \
|
#define TFM_CORE_SFN_REQUEST(id, fn, a, b, c, d) \
|
||||||
return tfm_core_partition_request(id, fn, (int32_t)a, (int32_t)b, \
|
return tfm_core_partition_request(id, fn, TFM_SFN_API_LEGACY, \
|
||||||
(int32_t)c, (int32_t)d)
|
(int32_t)a, (int32_t)b, (int32_t)c, (int32_t)d)
|
||||||
|
|
||||||
__attribute__ ((always_inline)) __STATIC_INLINE
|
__attribute__ ((always_inline)) __STATIC_INLINE
|
||||||
int32_t tfm_core_partition_request(uint32_t id, void *fn,
|
int32_t tfm_core_partition_request(uint32_t id, void *fn, int32_t iovec_api,
|
||||||
int32_t arg1, int32_t arg2, int32_t arg3, int32_t arg4)
|
int32_t arg1, int32_t arg2, int32_t arg3, int32_t arg4)
|
||||||
{
|
{
|
||||||
int32_t args[4] = {arg1, arg2, arg3, arg4};
|
int32_t args[4] = {arg1, arg2, arg3, arg4};
|
||||||
|
@ -98,6 +107,7 @@ int32_t tfm_core_partition_request(uint32_t id, void *fn,
|
||||||
desc.sfn = fn;
|
desc.sfn = fn;
|
||||||
desc.args = args;
|
desc.args = args;
|
||||||
desc.ns_caller = cmse_nonsecure_caller();
|
desc.ns_caller = cmse_nonsecure_caller();
|
||||||
|
desc.iovec_api = iovec_api;
|
||||||
if (__get_active_exc_num() != EXC_NUM_THREAD_MODE) {
|
if (__get_active_exc_num() != EXC_NUM_THREAD_MODE) {
|
||||||
/* FixMe: Error severity TBD */
|
/* FixMe: Error severity TBD */
|
||||||
return TFM_ERROR_GENERIC;
|
return TFM_ERROR_GENERIC;
|
||||||
|
|
|
@ -100,8 +100,9 @@ __attribute__((naked)) int32_t tfm_core_sfn_request(
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
__attribute__((naked))
|
__attribute__((naked))
|
||||||
int32_t tfm_core_memory_permission_check(
|
int32_t tfm_core_memory_permission_check(const void *ptr,
|
||||||
void *ptr, uint32_t len, int32_t access)
|
uint32_t len,
|
||||||
|
int32_t access)
|
||||||
{
|
{
|
||||||
__ASM(
|
__ASM(
|
||||||
"SVC %0\n"
|
"SVC %0\n"
|
||||||
|
|
|
@ -0,0 +1,17 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2019, Arm Limited. All rights reserved.
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: BSD-3-Clause
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
//This file holds description for the current directory. This documentation
|
||||||
|
//will be included in the Doxygen output.
|
||||||
|
|
||||||
|
/*!
|
||||||
|
\dir
|
||||||
|
\brief Include files for the TF-M.
|
||||||
|
\details This directory currently only holds the include file for the SPM
|
||||||
|
module.
|
||||||
|
|
||||||
|
*/
|
|
@ -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()
|
||||||
|
|
|
@ -0,0 +1,16 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2018-2019, Arm Limited. All rights reserved.
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: BSD-3-Clause
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
//This file holds description for the current directory. This documentation
|
||||||
|
//will be included in the Doxygen output.
|
||||||
|
|
||||||
|
/*!
|
||||||
|
\dir
|
||||||
|
\brief Source code for the Secure Partition Manager.
|
||||||
|
\details This directory holds the source code of the "TF-M SPM" module.
|
||||||
|
|
||||||
|
*/
|
|
@ -11,13 +11,12 @@
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include "spm_api.h"
|
#include "spm_api.h"
|
||||||
#include "platform/include/tfm_spm_hal.h"
|
#include "platform/include/tfm_spm_hal.h"
|
||||||
#include "secure_utilities.h"
|
#include "tfm_memory_utils.h"
|
||||||
#include "spm_db_setup.h"
|
#include "spm_db_setup.h"
|
||||||
#include "tfm_internal.h"
|
#include "tfm_internal.h"
|
||||||
#include "tfm_api.h"
|
#include "tfm_api.h"
|
||||||
#include "tfm_nspm.h"
|
#include "tfm_nspm.h"
|
||||||
#include "secure_fw/core/tfm_core.h"
|
#include "secure_fw/core/tfm_core.h"
|
||||||
#include "platform_retarget.h"
|
|
||||||
#include "tfm_peripherals_def.h"
|
#include "tfm_peripherals_def.h"
|
||||||
#include "spm_partition_defs.h"
|
#include "spm_partition_defs.h"
|
||||||
|
|
||||||
|
@ -123,7 +122,7 @@ enum spm_err_t tfm_spm_db_init(void)
|
||||||
++g_spm_partition_db.partition_count;
|
++g_spm_partition_db.partition_count;
|
||||||
|
|
||||||
/* Add user-defined secure partitions */
|
/* Add user-defined secure partitions */
|
||||||
#include "tfm_partition_list.inc"
|
#include "secure_fw/services/tfm_partition_list.inc"
|
||||||
|
|
||||||
g_spm_partition_db.is_init = 1;
|
g_spm_partition_db.is_init = 1;
|
||||||
|
|
||||||
|
@ -156,6 +155,7 @@ enum spm_err_t tfm_spm_partition_init(void)
|
||||||
|
|
||||||
desc.args = args;
|
desc.args = args;
|
||||||
desc.ns_caller = 0;
|
desc.ns_caller = 0;
|
||||||
|
desc.iovec_api = TFM_SFN_API_IOVEC;
|
||||||
desc.sfn = (sfn_t)part->static_data.partition_init;
|
desc.sfn = (sfn_t)part->static_data.partition_init;
|
||||||
desc.sp_id = part->static_data.partition_id;
|
desc.sp_id = part->static_data.partition_id;
|
||||||
res = tfm_core_sfn_request(&desc);
|
res = tfm_core_sfn_request(&desc);
|
||||||
|
@ -314,6 +314,29 @@ enum spm_err_t tfm_spm_partition_set_share(uint32_t partition_idx,
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void tfm_spm_partition_set_iovec(uint32_t partition_idx, int32_t *args)
|
||||||
|
{
|
||||||
|
struct spm_partition_runtime_data_t *runtime_data =
|
||||||
|
&g_spm_partition_db.partitions[partition_idx].runtime_data;
|
||||||
|
int32_t i;
|
||||||
|
|
||||||
|
runtime_data->iovec_args.in_len = args[1];
|
||||||
|
for (i = 0; i < runtime_data->iovec_args.in_len; ++i) {
|
||||||
|
runtime_data->iovec_args.in_vec[i].base =
|
||||||
|
((psa_invec *)args[0])[i].base;
|
||||||
|
runtime_data->iovec_args.in_vec[i].len = ((psa_invec *)args[0])[i].len;
|
||||||
|
}
|
||||||
|
runtime_data->iovec_args.out_len = args[3];
|
||||||
|
for (i = 0; i < runtime_data->iovec_args.out_len; ++i) {
|
||||||
|
runtime_data->iovec_args.out_vec[i].base =
|
||||||
|
((psa_outvec *)args[2])[i].base;
|
||||||
|
runtime_data->iovec_args.out_vec[i].len =
|
||||||
|
((psa_outvec *)args[2])[i].len;
|
||||||
|
}
|
||||||
|
runtime_data->orig_outvec = (psa_outvec *)args[2];
|
||||||
|
runtime_data->iovec_api = 1;
|
||||||
|
}
|
||||||
|
|
||||||
uint32_t tfm_spm_partition_get_running_partition_idx(void)
|
uint32_t tfm_spm_partition_get_running_partition_idx(void)
|
||||||
{
|
{
|
||||||
return g_spm_partition_db.running_partition_idx;
|
return g_spm_partition_db.running_partition_idx;
|
||||||
|
@ -323,6 +346,20 @@ void tfm_spm_partition_cleanup_context(uint32_t partition_idx)
|
||||||
{
|
{
|
||||||
struct spm_partition_desc_t *partition =
|
struct spm_partition_desc_t *partition =
|
||||||
&(g_spm_partition_db.partitions[partition_idx]);
|
&(g_spm_partition_db.partitions[partition_idx]);
|
||||||
|
int32_t i;
|
||||||
|
|
||||||
partition->runtime_data.caller_partition_idx = SPM_INVALID_PARTITION_IDX;
|
partition->runtime_data.caller_partition_idx = SPM_INVALID_PARTITION_IDX;
|
||||||
partition->runtime_data.share = 0;
|
partition->runtime_data.share = 0;
|
||||||
|
partition->runtime_data.iovec_args.in_len = 0;
|
||||||
|
for (i = 0; i < PSA_MAX_IOVEC; ++i) {
|
||||||
|
partition->runtime_data.iovec_args.in_vec[i].base = 0;
|
||||||
|
partition->runtime_data.iovec_args.in_vec[i].len = 0;
|
||||||
|
}
|
||||||
|
partition->runtime_data.iovec_args.out_len = 0;
|
||||||
|
for (i = 0; i < PSA_MAX_IOVEC; ++i) {
|
||||||
|
partition->runtime_data.iovec_args.out_vec[i].base = 0;
|
||||||
|
partition->runtime_data.iovec_args.out_vec[i].len = 0;
|
||||||
|
}
|
||||||
|
partition->runtime_data.orig_outvec = 0;
|
||||||
|
partition->runtime_data.iovec_api = 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,6 +9,7 @@
|
||||||
#define __SPM_API_H__
|
#define __SPM_API_H__
|
||||||
|
|
||||||
/* This file contains the apis exported by the SPM to tfm core */
|
/* This file contains the apis exported by the SPM to tfm core */
|
||||||
|
#include "tfm_api.h"
|
||||||
#include "spm_partition_defs.h"
|
#include "spm_partition_defs.h"
|
||||||
#include "secure_fw/core/tfm_secure_api.h"
|
#include "secure_fw/core/tfm_secure_api.h"
|
||||||
|
|
||||||
|
@ -37,6 +38,20 @@ enum spm_part_flag_mask_t {
|
||||||
SPM_PART_FLAG_IPC = 0x04
|
SPM_PART_FLAG_IPC = 0x04
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Holds the iovec parameters that are passed to a service
|
||||||
|
*
|
||||||
|
* \note The size of the structure is (and have to be) multiple of 8 bytes
|
||||||
|
*/
|
||||||
|
struct iovec_args_t {
|
||||||
|
psa_invec in_vec[PSA_MAX_IOVEC]; /*!< Array of psa_invec objects */
|
||||||
|
size_t in_len; /*!< Number psa_invec objects in in_vec
|
||||||
|
*/
|
||||||
|
psa_outvec out_vec[PSA_MAX_IOVEC]; /*!< Array of psa_outvec objects */
|
||||||
|
size_t out_len; /*!< Number psa_outvec objects in out_vec
|
||||||
|
*/
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \brief Runtime context information of a partition
|
* \brief Runtime context information of a partition
|
||||||
*/
|
*/
|
||||||
|
@ -47,6 +62,13 @@ struct spm_partition_runtime_data_t {
|
||||||
uint32_t share;
|
uint32_t share;
|
||||||
uint32_t stack_ptr;
|
uint32_t stack_ptr;
|
||||||
uint32_t lr;
|
uint32_t lr;
|
||||||
|
int32_t iovec_api; /*!< Whether the function in the partition
|
||||||
|
* had been called using the iovec API.
|
||||||
|
* FIXME: Remove the field once this is the
|
||||||
|
* only option
|
||||||
|
*/
|
||||||
|
struct iovec_args_t iovec_args;
|
||||||
|
psa_outvec *orig_outvec;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -60,6 +82,7 @@ struct spm_partition_runtime_data_t {
|
||||||
*/
|
*/
|
||||||
uint32_t get_partition_idx(uint32_t partition_id);
|
uint32_t get_partition_idx(uint32_t partition_id);
|
||||||
|
|
||||||
|
#if TFM_LVL != 1
|
||||||
/**
|
/**
|
||||||
* \brief Configure isolated sandbox for a partition
|
* \brief Configure isolated sandbox for a partition
|
||||||
*
|
*
|
||||||
|
@ -104,28 +127,6 @@ uint32_t tfm_spm_partition_get_stack_bottom(uint32_t partition_idx);
|
||||||
*/
|
*/
|
||||||
uint32_t tfm_spm_partition_get_stack_top(uint32_t partition_idx);
|
uint32_t tfm_spm_partition_get_stack_top(uint32_t partition_idx);
|
||||||
|
|
||||||
/**
|
|
||||||
* \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
|
|
||||||
*
|
|
||||||
* \param[in] partition_idx Partition index
|
|
||||||
*
|
|
||||||
* \return Flags associated with the partition
|
|
||||||
*
|
|
||||||
* \note This function doesn't check if partition_idx is valid.
|
|
||||||
*/
|
|
||||||
uint32_t tfm_spm_partition_get_flags(uint32_t partition_idx);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \brief Get the start of the zero-initialised region for a partition
|
* \brief Get the start of the zero-initialised region for a partition
|
||||||
*
|
*
|
||||||
|
@ -172,6 +173,28 @@ uint32_t tfm_spm_partition_get_rw_start(uint32_t partition_idx);
|
||||||
*/
|
*/
|
||||||
uint32_t tfm_spm_partition_get_rw_limit(uint32_t partition_idx);
|
uint32_t tfm_spm_partition_get_rw_limit(uint32_t partition_idx);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Save stack pointer for partition in database
|
||||||
|
*
|
||||||
|
* \param[in] partition_idx Partition index
|
||||||
|
* \param[in] stack_ptr Stack pointer to be stored
|
||||||
|
*
|
||||||
|
* \note This function doesn't check if partition_idx is valid.
|
||||||
|
*/
|
||||||
|
void tfm_spm_partition_set_stack(uint32_t partition_idx, uint32_t stack_ptr);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Get the flags associated with a partition
|
||||||
|
*
|
||||||
|
* \param[in] partition_idx Partition index
|
||||||
|
*
|
||||||
|
* \return Flags associated with the partition
|
||||||
|
*
|
||||||
|
* \note This function doesn't check if partition_idx is valid.
|
||||||
|
*/
|
||||||
|
uint32_t tfm_spm_partition_get_flags(uint32_t partition_idx);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \brief Get the current runtime data of a partition
|
* \brief Get the current runtime data of a partition
|
||||||
*
|
*
|
||||||
|
@ -192,16 +215,6 @@ const struct spm_partition_runtime_data_t *
|
||||||
*/
|
*/
|
||||||
uint32_t tfm_spm_partition_get_running_partition_idx(void);
|
uint32_t tfm_spm_partition_get_running_partition_idx(void);
|
||||||
|
|
||||||
/**
|
|
||||||
* \brief Save stack pointer for partition in database
|
|
||||||
*
|
|
||||||
* \param[in] partition_idx Partition index
|
|
||||||
* \param[in] stack_ptr Stack pointer to be stored
|
|
||||||
*
|
|
||||||
* \note This function doesn't check if partition_idx is valid.
|
|
||||||
*/
|
|
||||||
void tfm_spm_partition_set_stack(uint32_t partition_id, uint32_t stack_ptr);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \brief Save stack pointer and link register for partition in database
|
* \brief Save stack pointer and link register for partition in database
|
||||||
*
|
*
|
||||||
|
@ -214,6 +227,17 @@ void tfm_spm_partition_set_stack(uint32_t partition_id, uint32_t stack_ptr);
|
||||||
void tfm_spm_partition_store_context(uint32_t partition_idx,
|
void tfm_spm_partition_store_context(uint32_t partition_idx,
|
||||||
uint32_t stack_ptr, uint32_t lr);
|
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
|
* \brief Set the current state of a partition
|
||||||
*
|
*
|
||||||
|
@ -221,7 +245,7 @@ void tfm_spm_partition_store_context(uint32_t partition_idx,
|
||||||
* \param[in] state The state to be set
|
* \param[in] state The state to be set
|
||||||
*
|
*
|
||||||
* \note This function doesn't check if partition_idx is valid.
|
* \note This function doesn't check if partition_idx is valid.
|
||||||
* \note The \ref state has to have the value set of \ref spm_part_state_t.
|
* \note The state has to have the value set of \ref spm_part_state_t.
|
||||||
*/
|
*/
|
||||||
void tfm_spm_partition_set_state(uint32_t partition_idx, uint32_t state);
|
void tfm_spm_partition_set_state(uint32_t partition_idx, uint32_t state);
|
||||||
|
|
||||||
|
@ -261,6 +285,24 @@ void tfm_spm_partition_set_caller_client_id(uint32_t partition_idx,
|
||||||
enum spm_err_t tfm_spm_partition_set_share(uint32_t partition_idx,
|
enum spm_err_t tfm_spm_partition_set_share(uint32_t partition_idx,
|
||||||
uint32_t share);
|
uint32_t share);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Set the iovec parameters for the partition
|
||||||
|
*
|
||||||
|
* \param[in] partition_idx Partition index
|
||||||
|
* \param[in] args The arguments of the secure function
|
||||||
|
*
|
||||||
|
* args is expected to be of type int32_t[4] where:
|
||||||
|
* args[0] is in_vec
|
||||||
|
* args[1] is in_len
|
||||||
|
* args[2] is out_vec
|
||||||
|
* args[3] is out_len
|
||||||
|
*
|
||||||
|
* \note This function doesn't check if partition_idx is valid.
|
||||||
|
* \note This function assumes that the iovecs that are passed in args are
|
||||||
|
* valid, and does no sanity check on them at all.
|
||||||
|
*/
|
||||||
|
void tfm_spm_partition_set_iovec(uint32_t partition_idx, int32_t *args);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \brief Initialize partition database
|
* \brief Initialize partition database
|
||||||
*
|
*
|
||||||
|
|
|
@ -8,6 +8,7 @@
|
||||||
#ifndef __SPM_DB_H__
|
#ifndef __SPM_DB_H__
|
||||||
#define __SPM_DB_H__
|
#define __SPM_DB_H__
|
||||||
|
|
||||||
|
|
||||||
#ifdef TFM_PSA_API
|
#ifdef TFM_PSA_API
|
||||||
#include "tfm_thread.h"
|
#include "tfm_thread.h"
|
||||||
#endif
|
#endif
|
||||||
|
@ -15,9 +16,7 @@
|
||||||
struct spm_partition_desc_t;
|
struct spm_partition_desc_t;
|
||||||
struct spm_partition_db_t;
|
struct spm_partition_db_t;
|
||||||
|
|
||||||
uint32_t get_partition_idx(uint32_t partition_id);
|
typedef psa_status_t(*sp_init_function)(void);
|
||||||
|
|
||||||
typedef int32_t(*sp_init_function)(void);
|
|
||||||
|
|
||||||
#define TFM_PARTITION_TYPE_APP "APPLICATION-ROT"
|
#define TFM_PARTITION_TYPE_APP "APPLICATION-ROT"
|
||||||
#define TFM_PARTITION_TYPE_PSA "PSA-ROT"
|
#define TFM_PARTITION_TYPE_PSA "PSA-ROT"
|
||||||
|
@ -66,10 +65,11 @@ struct spm_partition_desc_t {
|
||||||
#ifdef TFM_PSA_API
|
#ifdef TFM_PSA_API
|
||||||
struct tfm_thrd_ctx sp_thrd;
|
struct tfm_thrd_ctx sp_thrd;
|
||||||
/*
|
/*
|
||||||
* stack_limit points to starting address of the partitions' stack plus the partitions' stack size.
|
* FixMe: Hard code stack is not aligned with the definition in the
|
||||||
|
* manifest. It will use the partition stacks in the linker scripts/sct
|
||||||
|
* files include Level 1 to 3.
|
||||||
*/
|
*/
|
||||||
uint32_t stack_limit;
|
uint8_t stack[TFM_STACK_SIZE] __attribute__((aligned(8)));
|
||||||
uint32_t stack_size;
|
|
||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -17,10 +17,10 @@
|
||||||
* Gets the index of a partition in the partition db based on the partition ID
|
* Gets the index of a partition in the partition db based on the partition ID
|
||||||
* provided as a parameter.
|
* provided as a parameter.
|
||||||
*
|
*
|
||||||
* \param[in] partition_id The ID of the partition
|
* \param[in] partition_idx The index of the partition
|
||||||
*
|
*
|
||||||
* \return \ref INVALID_PARTITION_IDX if the provided ID is invalid. The index
|
* \return \ref INVALID_PARTITION_IDX if the provided index is invalid. The
|
||||||
* of the partition otherwise.
|
* index of the partition otherwise.
|
||||||
*/
|
*/
|
||||||
uint32_t get_partition_idx(uint32_t partition_id);
|
uint32_t get_partition_idx(uint32_t partition_id);
|
||||||
|
|
||||||
|
@ -66,12 +66,17 @@ struct spm_partition_db_t {
|
||||||
#define PARTITION_INIT_RUNTIME_DATA(data, partition) \
|
#define PARTITION_INIT_RUNTIME_DATA(data, partition) \
|
||||||
do { \
|
do { \
|
||||||
data.partition_state = SPM_PARTITION_STATE_UNINIT; \
|
data.partition_state = SPM_PARTITION_STATE_UNINIT; \
|
||||||
|
/* The top of the stack is reserved for the iovec */ \
|
||||||
|
/* parameters of the service called. That's why in */ \
|
||||||
|
/* data.stack_ptr we extract sizeof(struct iovec_args_t) */ \
|
||||||
|
/* from the limit. */ \
|
||||||
data.stack_ptr = \
|
data.stack_ptr = \
|
||||||
PART_REGION_ADDR(partition, _STACK$$ZI$$Limit); \
|
PART_REGION_ADDR(partition, _STACK$$ZI$$Limit - \
|
||||||
|
sizeof(struct iovec_args_t)); \
|
||||||
} while (0)
|
} while (0)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define PARTITION_DECLARE(partition, flag, type, id, priority, part_stack_size) \
|
#define PARTITION_DECLARE(partition, flag, type, id, priority) \
|
||||||
do { \
|
do { \
|
||||||
REGION_DECLARE(Image$$, partition, $$Base); \
|
REGION_DECLARE(Image$$, partition, $$Base); \
|
||||||
REGION_DECLARE(Image$$, partition, $$Limit); \
|
REGION_DECLARE(Image$$, partition, $$Limit); \
|
||||||
|
@ -97,12 +102,8 @@ struct spm_partition_db_t {
|
||||||
if (g_spm_partition_db.partition_count >= SPM_MAX_PARTITIONS) { \
|
if (g_spm_partition_db.partition_count >= SPM_MAX_PARTITIONS) { \
|
||||||
return SPM_ERR_INVALID_CONFIG; \
|
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[ \
|
part_ptr = &(g_spm_partition_db.partitions[ \
|
||||||
g_spm_partition_db.partition_count]); \
|
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, \
|
PARTITION_INIT_STATIC_DATA(part_ptr->static_data, partition, flags, \
|
||||||
id, priority); \
|
id, priority); \
|
||||||
PARTITION_INIT_RUNTIME_DATA(part_ptr->runtime_data, partition); \
|
PARTITION_INIT_RUNTIME_DATA(part_ptr->runtime_data, partition); \
|
||||||
|
|
|
@ -29,7 +29,7 @@
|
||||||
*/
|
*/
|
||||||
#define TFM_SP_CORE_ID (1)
|
#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
|
/* 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
|
* partitions. There's no requirement that it match the number of partitions
|
||||||
|
|
|
@ -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
|
* SPDX-License-Identifier: BSD-3-Clause
|
||||||
*
|
*
|
||||||
|
|
|
@ -223,8 +223,6 @@ void psa_notify(int32_t partition_id);
|
||||||
/**
|
/**
|
||||||
* \brief Clear the PSA_DOORBELL signal.
|
* \brief Clear the PSA_DOORBELL signal.
|
||||||
*
|
*
|
||||||
* \param[in] void
|
|
||||||
*
|
|
||||||
* \retval void Success.
|
* \retval void Success.
|
||||||
* \retval "Does not return" The Secure Partition's doorbell signal is not
|
* \retval "Does not return" The Secure Partition's doorbell signal is not
|
||||||
* currently asserted.
|
* currently asserted.
|
||||||
|
|
|
@ -13,7 +13,7 @@ extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include "interface/include/psa_client.h"
|
#include "psa_client.h"
|
||||||
|
|
||||||
#define TFM_INVALID_CLIENT_ID 0
|
#define TFM_INVALID_CLIENT_ID 0
|
||||||
|
|
||||||
|
@ -35,13 +35,18 @@ extern "C" {
|
||||||
*/
|
*/
|
||||||
#define TFM_CLIENT_ID_IS_NS(client_id) ((client_id)<0)
|
#define TFM_CLIENT_ID_IS_NS(client_id) ((client_id)<0)
|
||||||
|
|
||||||
|
/* Maximum number of input and output vectors */
|
||||||
|
#define PSA_MAX_IOVEC (4)
|
||||||
|
|
||||||
/* FixMe: sort out DEBUG compile option and limit return value options
|
/* FixMe: sort out DEBUG compile option and limit return value options
|
||||||
* on external interfaces */
|
* on external interfaces */
|
||||||
/* Note:
|
/* For secure functions using prorietary signatures
|
||||||
* TFM will only return values recognized and parsed by TFM core.
|
* TFM will only return values recognized and parsed by TFM core.
|
||||||
* Service return codes are not automatically passed on to REE.
|
* Service return codes are not automatically passed on to REE.
|
||||||
* Any non-zero return value is interpreted as an error that may trigger
|
* Any non-zero return value is interpreted as an error that may trigger
|
||||||
* TEE error handling flow.
|
* TEE error handling flow.
|
||||||
|
* For secure functions using the veneers in secure_fw/ns_callable/tfm_veneers.c
|
||||||
|
* (iovec API) this limitation does not apply.
|
||||||
*/
|
*/
|
||||||
enum tfm_status_e
|
enum tfm_status_e
|
||||||
{
|
{
|
||||||
|
@ -105,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] handle Handle to connection
|
||||||
* \param[in] in_vecs invec containing pointer/count of input vectors
|
* \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
|
* \return Returns \ref psa_status_t status code
|
||||||
*/
|
*/
|
||||||
psa_status_t tfm_psa_call_veneer(psa_handle_t handle,
|
psa_status_t tfm_psa_call_veneer(psa_handle_t handle,
|
||||||
const psa_invec *in_vecs,
|
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
|
* \brief Close connection to secure function referenced by a connection handle
|
||||||
|
|
Loading…
Reference in New Issue