15 #include "tfm_spm_hal.h"
20 #include "tfm_hal_defs.h"
21 #include "tfm_hal_isolation.h"
23 #include "tfm_peripherals_def.h"
28 #include "tfm_hal_isolation.h"
31 #include "region_defs.h"
55 #define CLIENT_HANDLE_VALUE_MIN 32
57 #define CONVERSION_FACTOR_BITOFFSET 3
58 #define CONVERSION_FACTOR_VALUE (1 << CONVERSION_FACTOR_BITOFFSET)
60 #define CONVERSION_FACTOR_VALUE_MAX 0x20
62 #if CONVERSION_FACTOR_VALUE > CONVERSION_FACTOR_VALUE_MAX
63 #error "CONVERSION FACTOR OUT OF RANGE"
66 static uint32_t loop_index;
98 user_handle = (
psa_handle_t)((((uintptr_t)handle_instance -
131 (uintptr_t)conn_handle_pool);
133 return handle_instance;
167 (uint8_t *)conn_handle) !=
true) {
172 if (conn_handle->
client_id != client_id) {
274 static uint32_t get_partition_idx(uint32_t partition_id)
300 static uint32_t tfm_spm_partition_get_flags(uint32_t partition_idx)
318 static void tfm_spm_partition_change_privilege(uint32_t privileged)
322 ctrl.w = __get_CONTROL();
330 __set_CONTROL(ctrl.w);
345 uint32_t flags = tfm_spm_partition_get_flags(partition_idx);
356 for (i = 0; i < num; i++) {
374 static struct partition_t *tfm_spm_get_partition_by_id(int32_t partition_id)
376 uint32_t idx = get_partition_idx(partition_id);
462 uint32_t partition_id;
467 conn_handle_pool, (uint8_t *)p_conn_handle) != 1) {
501 int32_t type, int32_t client_id,
529 for (i = 0; i < in_len; i++) {
534 for (i = 0; i < out_len; i++) {
547 msg->
msg.
rhandle = tfm_spm_get_rhandle(service, conn_handle);
600 enum tfm_hal_status_t err;
612 if ((uintptr_t)buffer > (UINTPTR_MAX - len)) {
617 attr |= (TFM_HAL_ACCESS_READABLE | TFM_HAL_ACCESS_WRITABLE);
619 attr |= TFM_HAL_ACCESS_READABLE;
623 attr |= TFM_HAL_ACCESS_UNPRIVILEGED;
625 attr &= ~TFM_HAL_ACCESS_UNPRIVILEGED;
629 attr |= TFM_HAL_ACCESS_NS;
632 err = tfm_hal_memory_has_access((uintptr_t)buffer, len, attr);
634 if (err == TFM_HAL_SUCCESS) {
646 const struct tfm_spm_partition_platform_data_t **platform_data_p;
668 ERROR_MSG(
"Warning: PSA Framework Verison does not match!");
673 if (platform_data_p != NULL) {
674 while ((*platform_data_p) != NULL) {
675 if (tfm_spm_hal_configure_default_isolation(i,
676 *platform_data_p) != TFM_PLAT_ERR_SUCCESS) {
715 p_ns_entry_thread = pth;
716 pth->
param = (
void *)tfm_spm_hal_get_ns_entry_point();
727 for (i = 0; i < num; i++) {
760 uint32_t is_privileged;
765 if (pth_next != NULL && pth_curr != pth_next) {
778 tfm_spm_partition_change_privilege(is_privileged);
787 if (tfm_hal_mpu_update_partition_boundary(
790 != TFM_HAL_SUCCESS) {
848 partition = tfm_spm_get_partition_by_id(partition_id);
877 tfm_spm_hal_disable_irq(irq_line);
901 IRQn_Type irq_line = (IRQn_Type) 0;
916 irq_signal, &irq_line);
922 tfm_spm_hal_enable_irq(irq_line);
929 IRQn_Type irq_line = (IRQn_Type) 0;
944 irq_signal, &irq_line);
950 tfm_spm_hal_disable_irq(irq_line);
954 uint32_t exc_return,
bool ns_caller)
956 uintptr_t stacked_ctx_pos;
972 stacked_ctx_pos = (uintptr_t)p_ctx +
977 #if defined (__FPU_USED) && (__FPU_USED == 1U)
978 if (FPU->FPCCR & FPU_FPCCR_TS_Msk) {
996 uint32_t *res_ptr = (uint32_t *)&svc_ctx->
r0;
997 uint32_t running_partition_flags = 0;
1002 switch (svc_ctx->
r0) {
1008 running_partition_flags = partition->static_data->partition_flags;
struct tfm_list_node_t list
void tfm_irq_handler(uint32_t partition_id, psa_signal_t signal, IRQn_Type irq_line)
assert signal for a given IRQ line.
#define TFM_PARTITION_UNPRIVILEGED_MODE
#define PSA_FRAMEWORK_VERSION
bool tfm_is_partition_privileged(uint32_t partition_idx)
Return whether a secure partition is privileged.
const struct tfm_core_irq_signal_data_t tfm_core_irq_signals[]
__STATIC_INLINE void tfm_list_del_node(struct tfm_list_node_t *node)
Delete one node from list.
const struct tfm_spm_partition_platform_data_t ** platform_data_list_list[]
void tfm_event_wake(struct tfm_event_t *pevnt, uint32_t retval)
enum spm_err_t tfm_spm_db_init(void)
Initialize partition database.
void tfm_pool_free(void *ptr)
Free the allocated memory.
__STATIC_INLINE bool is_stack_alloc_fp_space(uint32_t lr)
Check whether the stack frame for this exception has space allocated for Floating Point(FP) state inf...
void *(* tfm_core_thrd_entry_t)(void *)
const struct tfm_spm_partition_platform_data_t ** platform_data_list
int32_t tfm_spm_check_authorization(uint32_t sid, struct tfm_spm_service_t *service, bool ns_caller)
Check the client access authorization.
void tfm_spm_enable_irq(uint32_t *args)
SVC handler of enabling irq_line of the specified irq_signal.
struct tfm_list_node_t msg_node
void tfm_spm_validate_caller(struct partition_t *p_cur_sp, uint32_t *p_ctx, uint32_t exc_return, bool ns_caller)
Validate the whether NS caller re-enter.
#define TFM_POOL_DECLARE(name, chunksz, num)
struct tfm_list_node_t msg_list
void tfm_spm_request_handler(const struct tfm_state_context_t *svc_ctx)
Handle an SPM request by a secure service.
#define TFM_CLIENT_ID_IS_S(client_id)
Checks if the provided client ID is a secure client ID.
#define TFM_STACK_SEALED_SIZE
psa_outvec outvec[PSA_MAX_IOVEC]
uint32_t tfm_spm_init(void)
SPM initialization implementation.
struct tfm_list_node_t handle_list
#define SPM_INVALID_PARTITION_IDX
struct tfm_spm_service_t service[]
#define TFM_CONN_HANDLE_MAX_NUM
const struct tfm_spm_service_db_t service_db[]
int32_t tfm_spm_set_rhandle(struct tfm_spm_service_t *service, struct tfm_conn_handle_t *conn_handle, void *rhandle)
Set reverse handle value for connection.
struct tfm_spm_service_t * service
psa_outvec * caller_outvec
uint32_t tfm_core_thrd_start(struct tfm_core_thread_t *pth)
#define TFM_LIST_FOR_EACH(node, head)
#define is_tfm_rpc_msg(x)
struct tfm_msg_body_t internal_msg
#define CONVERSION_FACTOR_BITOFFSET
#define TFM_VERSION_POLICY_STRICT
psa_invec invec[PSA_MAX_IOVEC]
const struct spm_partition_static_data_t static_data_list[]
int32_t tfm_spm_validate_conn_handle(const struct tfm_conn_handle_t *conn_handle, int32_t client_id)
Validate connection handle for client connect.
struct tfm_conn_handle_t * tfm_spm_create_conn_handle(struct tfm_spm_service_t *service, int32_t client_id)
Create connection handle for client connect.
void tfm_core_panic(void)
#define IPC_ERROR_VERSION
const struct spm_partition_static_data_t * static_data
int32_t tfm_memory_check(const void *buffer, size_t len, bool ns_caller, enum tfm_memory_access_e access, uint32_t privileged)
Check the memory reference is valid.
struct tfm_arch_ctx_t arch_ctx
void tfm_core_thrd_start_scheduler(struct tfm_core_thread_t *pth)
void * tfm_pool_alloc(struct tfm_pool_instance_t *pool)
Allocate a memory from pool.
#define CONVERSION_FACTOR_VALUE
#define IPC_ERROR_BAD_PARAMETERS
struct partition_t * partition
psa_handle_t tfm_spm_to_user_handle(struct tfm_conn_handle_t *handle_instance)
Converts a handle instance into a corresponded user handle.
const struct tfm_spm_partition_platform_data_t ** platform_data_list
struct partition_t * tfm_spm_get_running_partition(void)
Get current running partition context.
#define IPC_ERROR_GENERIC
#define tfm_rpc_client_call_handler()
#define SPM_PART_FLAG_PSA_ROT
void tfm_event_wait(struct tfm_event_t *pevnt)
const size_t tfm_core_irq_signals_count
void tfm_pendsv_do_schedule(struct tfm_arch_ctx_t *p_actx)
struct tfm_msg_body_t * tfm_spm_get_msg_by_signal(struct partition_t *partition, psa_signal_t signal)
Get the msg context by signal.
const struct tfm_spm_partition_memory_data_t memory_data_list[]
void * spm_memset(void *s, int c, size_t n)
Memory set function for TF-M core.
#define CLIENT_HANDLE_VALUE_MIN
struct spm_partition_db_t g_spm_partition_db
struct tfm_core_thread_t * owner
sp_entry_point partition_init
struct tfm_core_thread_t * tfm_core_thrd_get_curr_thread(void)
uint32_t * p_dependencies
#define TFM_PARTITION_PRIVILEGED_MODE
uint32_t tfm_spm_partition_get_privileged_mode(uint32_t partition_flags)
Get the current partition mode.
size_t in_size[PSA_MAX_IOVEC]
struct tfm_spm_service_t * service
int32_t tfm_pool_init(struct tfm_pool_instance_t *pool, size_t poolsz, size_t chunksz, size_t num)
Register a memory pool.
#define TFM_CORE_ASSERT(cond)
void tfm_core_thrd_switch_context(struct tfm_arch_ctx_t *p_actx, struct tfm_core_thread_t *prev, struct tfm_core_thread_t *next)
uint32_t signals_asserted
uint32_t dependencies_num
#define TFM_GET_CONTAINER_PTR(ptr, type, member)
uint32_t psa_framework_version
struct tfm_msg_body_t * tfm_spm_get_msg_buffer_from_conn_handle(struct tfm_conn_handle_t *conn_handle)
Get message context by connect handle.
int32_t tfm_spm_check_client_version(struct tfm_spm_service_t *service, uint32_t version)
Check the client version according to version policy.
#define POOL_BUFFER_SIZE(name)
struct tfm_spm_service_t * tfm_spm_get_service_by_sid(uint32_t sid)
Get the service context by service ID.
void notify_with_signal(int32_t partition_id, psa_signal_t signal)
notify the partition with the signal.
#define TFM_VERSION_POLICY_RELAXED
#define TFM_HANDLE_STATUS_IDLE
#define tfm_rpc_set_caller_data(msg, client_id)
const struct partition_static_t * static_data
#define TFM_CLIENT_ID_IS_NS(client_id)
Checks if the provided client ID is a non-secure client ID.
#define SPM_PART_FLAG_IPC
#define TFM_SP_NON_SECURE_ID
__STATIC_INLINE void tfm_list_init(struct tfm_list_node_t *head)
Initialize list head.
void __STATIC_INLINE tfm_event_init(struct tfm_event_t *pevnt)
#define TFM_BASIC_FP_CONTEXT_WORDS
size_t out_size[PSA_MAX_IOVEC]
#define INVALID_PARTITION_ID
void tfm_spm_disable_irq(uint32_t *args)
SVC handler of disabling irq_line of the specified irq_signal.
int32_t get_irq_line_for_signal(int32_t partition_id, psa_signal_t signal, IRQn_Type *irq_line)
Return the IRQ line number associated with a signal.
struct tfm_event_t ack_evnt
void update_caller_outvec_len(struct tfm_msg_body_t *msg)
#define IPC_ERROR_MEMORY_CHECK
struct spm_partition_desc_t * partitions
struct tfm_msg_body_t * tfm_spm_get_msg_from_handle(psa_handle_t msg_handle)
Get message context by message handle.
struct tfm_core_thread_t sp_thread
int32_t tfm_spm_send_event(struct tfm_spm_service_t *service, struct tfm_msg_body_t *msg)
Send message and wake up the SP who is waiting on message queue, block the current thread and schedul...
const struct tfm_spm_partition_memory_data_t * memory_data
const struct tfm_spm_service_db_t * service_db
int32_t tfm_spm_free_conn_handle(struct tfm_spm_service_t *service, struct tfm_conn_handle_t *conn_handle)
Free connection handle which not used anymore.
struct tfm_conn_handle_t * tfm_spm_to_handle_instance(psa_handle_t user_handle)
Converts a user handle into a corresponded handle instance.
__STATIC_INLINE int32_t tfm_list_is_empty(struct tfm_list_node_t *head)
Check if a list is empty.
__STATIC_INLINE void tfm_list_add_tail(struct tfm_list_node_t *head, struct tfm_list_node_t *node)
Add one node to list tail.
psa_signal_t signal_value
struct tfm_core_thread_t * tfm_core_thrd_get_next_thread(void)
void tfm_core_thrd_init(struct tfm_core_thread_t *pth, tfm_core_thrd_entry_t pfn, void *param, uintptr_t stk_top, uintptr_t stk_btm)
bool tfm_is_one_bit_set(uint32_t n)
bool is_valid_chunk_data_in_pool(struct tfm_pool_instance_t *pool, uint8_t *data)
Checks whether a pointer points to a chunk data in the pool.
#define TFM_ADDTIONAL_FP_CONTEXT_WORDS
void tfm_spm_fill_msg(struct tfm_msg_body_t *msg, struct tfm_spm_service_t *service, psa_handle_t handle, int32_t type, int32_t client_id, psa_invec *invec, size_t in_len, psa_outvec *outvec, size_t out_len, psa_outvec *caller_outvec)
Fill the message for PSA client call.
uint32_t partition_priority
uint32_t tfm_spm_partition_get_running_partition_id(void)
Get the running partition ID.