17 #include "tfm_peripherals_def.h"
19 #include "tfm_spm_hal.h"
22 #include "region_defs.h"
29 #define EXC_RETURN_SECURE_FUNCTION 0xFFFFFFFD
30 #define EXC_RETURN_SECURE_HANDLER 0xFFFFFFF1
33 #error TFM_LVL is not defined!
36 #ifdef TFM_MULTI_CORE_TOPOLOGY
37 #error Multi core is not supported by Function mode
43 static uint32_t *tfm_secure_stack_seal =
44 ((uint32_t *)®ION_NAME(Image$$, TFM_SECURE_STACK, $$ZI$$Limit)[-1]) - 2;
77 uint32_t *arm_lib_stck_seal_base = (uint32_t *)®ION_NAME(Image$$,
78 ARM_LIB_STACK_SEAL, $$ZI$$Base);
88 static int32_t tfm_secure_lock;
89 static int32_t tfm_secure_api_initializing = 1;
91 static uint32_t *prepare_partition_iovec_ctx(
98 *(--dst) = svc_ctx->
xpsr & 0xFFFFFE00U;
100 *(--dst) = svc_ctx->
ra;
102 *(--dst) = (uint32_t)desc_ptr->
sfn;
107 *(--dst) = iovec_args->
out_len;
108 *(--dst) = (uint32_t)iovec_args->
out_vec;
109 *(--dst) = iovec_args->
in_len;
110 *(--dst) = (uint32_t)iovec_args->
in_vec;
127 static int32_t *prepare_partition_irq_ctx(
129 sfn_t unpriv_handler,
135 *(--dst) = svc_ctx->
xpsr & 0xFFFFFE00;
139 *(--dst) = svc_ctx->
ra;
141 *(--dst) = (int32_t)unpriv_handler;
144 for (i = 0; i < 5; ++i) {
155 target_ctx->
ra = svc_ctx->
ra;
158 target_ctx->
r0 = svc_ctx->
r0;
182 if ((desc_ptr->
args[1] < 0) || (desc_ptr->
args[3] < 0)) {
186 in_len = (size_t)(desc_ptr->
args[1]);
187 out_len = (size_t)(desc_ptr->
args[3]);
210 if ((in_vec == NULL) ||
217 if (in_vec != NULL) {
222 if ((out_vec == NULL) ||
229 if (out_vec != NULL) {
237 for (i = 0; i < in_len; ++i) {
238 if (in_vec[i].
len > 0) {
239 if ((in_vec[i].
base == NULL) ||
247 for (i = 0; i < out_len; ++i) {
248 if (out_vec[i].
len > 0) {
249 if ((out_vec[i].
base == NULL) ||
261 static void tfm_copy_iovec_parameters(
struct iovec_args_t *target,
273 for (i = 0; i < source->
in_len; ++i) {
278 for (i = 0; i < source->
out_len; ++i) {
284 static void tfm_clear_iovec_parameters(
struct iovec_args_t *args)
309 static enum tfm_status_e check_partition_state(uint32_t curr_partition_state,
310 uint32_t caller_partition_state)
341 uint32_t called_partition_state)
361 static struct iovec_args_t *get_iovec_args_stack_address(uint32_t partition_idx)
364 return ®ION_NAME(Image$$, TFM_SECURE_STACK, $$ZI$$Limit)[-1];
375 static uint32_t get_partition_idx(uint32_t partition_id)
401 static uint32_t tfm_spm_partition_get_flags(uint32_t partition_idx)
415 uint32_t caller_flags;
416 register uint32_t partition_idx;
418 uint32_t partition_psp, partition_psplim;
420 uint32_t caller_partition_state;
422 uint32_t caller_partition_id;
428 caller_flags = tfm_spm_partition_get_flags(caller_partition_idx);
437 partition_idx = get_partition_idx(desc_ptr->
sp_id);
444 caller_partition_idx);
446 if (!tfm_secure_api_initializing) {
447 res = check_partition_state(partition_state, caller_partition_state);
459 partition_psp = (uint32_t) tfm_secure_stack_seal;
461 (uint32_t)®ION_NAME(Image$$, TFM_SECURE_STACK, $$ZI$$Base);
465 caller_partition_idx);
468 if ((caller_flags & SPM_PART_FLAG_APP_ROT)) {
470 caller_partition_id);
473 if (client_id >= 0) {
482 if ((desc_ptr->
ns_caller) || (tfm_secure_api_initializing)) {
487 iovec_args = get_iovec_args_stack_address(partition_idx);
488 tfm_copy_iovec_parameters(iovec_args, &(curr_part_data->
iovec_args));
491 psp = (uint32_t)prepare_partition_iovec_ctx(svc_ctx, desc_ptr,
493 (uint32_t *)partition_psp);
506 static enum tfm_status_e tfm_start_partition_for_irq_handling(
510 uint32_t handler_partition_id = svc_ctx->
r0;
512 uint32_t irq_signal = svc_ctx->
r2;
513 IRQn_Type irq_line = (IRQn_Type) svc_ctx->
r3;
515 uint32_t psp = __get_PSP();
516 uint32_t handler_partition_psp;
517 uint32_t handler_partition_state;
518 uint32_t interrupted_partition_idx =
521 uint32_t handler_partition_idx;
523 handler_partition_idx = get_partition_idx(handler_partition_id);
525 handler_partition_idx);
528 res = check_irq_partition_state(handler_partition_state);
535 handler_partition_idx,
538 tfm_spm_hal_disable_irq(irq_line);
543 handler_partition_psp = psp;
550 interrupted_partition_idx);
552 psp = (uint32_t)prepare_partition_irq_ctx(svc_ctx, unpriv_handler,
553 (int32_t *)handler_partition_psp);
564 static enum tfm_status_e tfm_return_from_partition(uint32_t *excReturn)
566 uint32_t current_partition_idx =
569 uint32_t return_partition_idx;
570 uint32_t return_partition_flags;
571 uint32_t psp = __get_PSP();
589 return_partition_flags = tfm_spm_partition_get_flags(return_partition_idx);
593 if (!(return_partition_flags & SPM_PART_FLAG_APP_ROT) ||
594 (tfm_secure_api_initializing)) {
599 restore_caller_ctx(svc_ctx,
601 *excReturn = ret_part_data->
lr;
604 uint32_t psp_stack_bottom =
605 (uint32_t)REGION_NAME(Image$$, ARM_LIB_STACK, $$ZI$$Base);
608 iovec_args = ®ION_NAME(Image$$, TFM_SECURE_STACK, $$ZI$$Limit)[-1];
613 tfm_clear_iovec_parameters(iovec_args);
626 static enum tfm_status_e tfm_return_from_partition_irq_handling(
629 uint32_t handler_partition_idx =
632 uint32_t interrupted_partition_idx;
633 uint32_t psp = __get_PSP();
641 handler_partition_idx);
652 *excReturn = svc_ctx->
ra;
666 if ((desc_ptr == NULL) ||
667 (desc_ptr->
sp_id == 0) ||
668 (desc_ptr->
sfn == NULL)) {
683 if ((desc_ptr->
ns_caller) && (tfm_secure_lock != 0)) {
693 if (tfm_secure_api_initializing) {
699 ERROR_MSG(
"Invalid service request during initialization!");
724 uint32_t flags = tfm_spm_partition_get_flags(partition_idx);
732 tfm_secure_api_initializing = 0;
740 res = tfm_check_sfn_req_integrity(desc_ptr);
750 res = tfm_core_check_sfn_parameters(desc_ptr);
757 res = tfm_core_check_sfn_req_rules(desc_ptr);
763 ERROR_MSG(
"Unauthorized service request!");
767 res = tfm_start_partition(desc_ptr, excReturn);
771 ERROR_MSG(
"Failed to process service request!");
786 res = tfm_core_check_sfn_parameters(desc_ptr);
800 args = desc_ptr->
args;
801 retVal = desc_ptr->
sfn(args[0], args[1], args[2], args[3]);
804 res = tfm_return_from_partition(NULL);
812 ERROR_MSG(
"Secure API error during unlock!");
823 uintptr_t start_addr_value = (uintptr_t)start_addr;
824 uintptr_t end_addr_value = (uintptr_t)start_addr + len;
825 uintptr_t alignment_mask;
827 alignment_mask = (((uintptr_t)1) << alignment) - 1;
830 if (start_addr_value & alignment_mask) {
836 if (end_addr_value <= start_addr_value) {
843 if (start_addr_value >= S_DATA_START &&
844 end_addr_value <= (S_DATA_START + S_DATA_SIZE)) {
853 uintptr_t result_ptr_value = svc_args[0];
854 uint32_t running_partition_idx =
856 const uint32_t running_partition_flags =
857 tfm_spm_partition_get_flags(running_partition_idx);
862 if (!(running_partition_flags & SPM_PART_FLAG_APP_ROT) ||
878 (
void *)result_ptr_value,
895 const uint32_t *svc_ctx, uint32_t excReturn)
905 ERROR_MSG(
"Service request SVC called with MSP active!");
930 ERROR_MSG(
"Partition request SVC called with PSP active!");
934 res = tfm_start_partition_for_irq_handling(excReturn, svc_ctx);
957 ERROR_MSG(
"Partition return SVC called with MSP active!");
961 res = tfm_return_from_partition(&lr);
966 ERROR_MSG(
"Secure API error during unlock!");
990 ERROR_MSG(
"Partition request SVC called with MSP active!");
994 res = tfm_return_from_partition_irq_handling(&lr);
999 ERROR_MSG(
"Secure API error during unlock!");
1003 irq_svc_ctx->
ra =
lr;
1019 static IRQn_Type get_irq_line_for_signal(int32_t partition_id,
1030 return (IRQn_Type) -1;
1038 uint32_t running_partition_idx =
1040 uint32_t running_partition_id =
1050 irq_line = get_irq_line_for_signal(running_partition_id, irq_signal);
1057 tfm_spm_hal_enable_irq(irq_line);
1065 uint32_t running_partition_idx =
1067 uint32_t running_partition_id =
1077 irq_line = get_irq_line_for_signal(running_partition_id, irq_signal);
1084 tfm_spm_hal_disable_irq(irq_line);
1092 uint32_t running_partition_idx;
1096 uint32_t timeout = svc_ctx->
r1;
1123 uint32_t signal_mask;
1124 uint32_t running_partition_idx;
1125 uint32_t running_partition_id;
1130 running_partition_id =
1139 irq_line = get_irq_line_for_signal(running_partition_id, irq_signal);
1146 tfm_spm_hal_clear_pending_irq(irq_line);
1147 tfm_spm_hal_enable_irq(irq_line);
1149 signal_mask = curr_part_data->
signal_mask & ~irq_signal;
1158 static void tfm_spm_partition_err_handler(
1172 int32_t args[4] = {0};
1173 int32_t fail_cnt = 0;
1175 const struct tfm_spm_partition_platform_data_t **platform_data_p;
1181 if (platform_data_p != NULL) {
1182 while ((*platform_data_p) != NULL) {
1183 if (tfm_spm_hal_configure_default_isolation(idx,
1184 *platform_data_p) != TFM_PLAT_ERR_SUCCESS) {
1205 tfm_spm_partition_err_handler(part, res);
1213 if (fail_cnt == 0) {
1245 stack_frame->partition_state = 0;
1276 stack_frame->partition_state = 0;
1278 partition_idx, stack_frame->caller_partition_idx);
1279 stack_frame->caller_partition_idx = 0;
1283 uint32_t stack_ptr, uint32_t lr)
1286 runtime_data.stack_ptr = stack_ptr;
1288 runtime_data.lr = lr;
1308 uint32_t caller_partition_idx)
1329 const int32_t *args)
1335 if ((args[1] < 0) || (args[3] < 0)) {
1384 uint32_t *res_ptr = (uint32_t *)&svc_ctx->
r0;
1385 uint32_t running_partition_flags = 0;
1386 uint32_t running_partition_idx;
1390 switch (svc_ctx->
r0) {
1392 running_partition_idx =
1394 running_partition_flags = tfm_spm_partition_get_flags(
1395 running_partition_idx);
#define SPM_PARTITION_STATE_CLOSED
#define TFM_PARTITION_UNPRIVILEGED_MODE
void tfm_spm_partition_push_interrupted_ctx(uint32_t partition_idx)
Save interrupted partition context on ctx stack.
void tfm_spm_secure_api_init_done(void)
Signal that secure partition initialisation is finished.
void tfm_spm_psa_eoi(uint32_t *svc_args)
Handle request to record IRQ processed.
__STATIC_INLINE void tfm_arch_set_psplim(uint32_t psplim)
Set PSP limit value.
#define SPM_PARTITION_STATE_UNINIT
const struct tfm_core_irq_signal_data_t tfm_core_irq_signals[]
#define EXC_RETURN_STACK_PROCESS
const struct tfm_spm_partition_platform_data_t ** platform_data_list_list[]
uint32_t tfm_spm_partition_return_handler(uint32_t lr)
Called when secure service returns.
#define EXC_RETURN_SECURE_HANDLER
enum spm_err_t tfm_spm_db_init(void)
Initialize partition database.
void tfm_secure_api_error_handler(void)
uint32_t caller_partition_idx
int32_t(* sfn_t)(int32_t, int32_t, int32_t, int32_t)
const struct tfm_spm_partition_platform_data_t ** platform_data_list
void tfm_spm_psa_wait(uint32_t *svc_args)
Handle signal wait request.
uint32_t tfm_spm_depriv_req_handler(uint32_t *svc_args, uint32_t excReturn)
Handle deprivileged request.
#define EXC_RETURN_SECURE_FUNCTION
#define SPM_PARTITION_STATE_IDLE
REGION_DECLARE_T(Image $$, TFM_SECURE_STACK,$$ZI $$Base, uint32_t)
void tfm_spm_partition_push_handler_ctx(uint32_t partition_idx)
Save handler partition context on ctx stack.
int32_t tfm_core_sfn_request(const struct tfm_sfn_req_s *desc_ptr)
struct spm_partition_runtime_data_t runtime_data
#define SPM_INVALID_PARTITION_IDX
void tfm_spm_disable_irq_handler(uint32_t *svc_args)
Handle IRQ disable request.
sp_entry_point partition_init
void tfm_spm_partition_set_caller_client_id(uint32_t partition_idx, int32_t caller_client_id)
Set the caller client ID for a given partition.
enum tfm_status_e tfm_core_has_read_access_to_region(const void *p, size_t s, bool ns_caller, uint32_t privileged)
Check whether the current partition has read access to a memory range.
void tfm_spm_partition_pop_interrupted_ctx(uint32_t partition_idx)
Restores interrupted partition context on ctx stack.
void tfm_spm_partition_pop_handler_ctx(uint32_t partition_idx)
Restores handler partition context on ctx stack.
void tfm_spm_request_handler(const struct tfm_state_context_t *svc_ctx)
Handle an SPM request by a secure service.
#define SPM_PARTITION_STATE_HANDLING_IRQ
const struct spm_partition_static_data_t static_data_list[]
psa_outvec out_vec[PSA_MAX_IOVEC]
uint32_t tfm_spm_depriv_return_handler(uint32_t *irq_svc_args, uint32_t lr)
Handle request to return to privileged.
const struct spm_partition_static_data_t * static_data
uint32_t tfm_spm_partition_request_svc_handler(const uint32_t *svc_ctx, uint32_t excReturn)
Called if veneer is running in thread mode.
void tfm_spm_get_caller_client_id_handler(uint32_t *svc_args)
Stores caller's client id in state context.
uint32_t running_partition_idx
enum spm_err_t tfm_spm_partition_init(void)
Execute partition init function.
Runtime context information of a partition.
bool tfm_is_partition_privileged(uint32_t partition_idx)
Return whether a secure partition is privileged.
enum tfm_status_e tfm_core_has_write_access_to_region(const void *p, size_t s, bool ns_caller, uint32_t privileged)
Check whether the current partition has write access to a memory range.
#define SPM_PART_FLAG_PSA_ROT
int32_t tfm_nspm_get_current_client_id(void)
Get the client ID of the current NS client.
void tfm_spm_enable_irq_handler(uint32_t *svc_args)
Handle IRQ enable request.
int32_t tfm_spm_sfn_request_thread_mode(struct tfm_sfn_req_s *desc_ptr)
const size_t tfm_core_irq_signals_count
#define SPM_PART_FLAG_APP_ROT
struct spm_partition_db_t g_spm_partition_db
int32_t tfm_spm_check_buffer_access(uint32_t partition_idx, void *start_addr, size_t len, uint32_t alignment)
Check whether a buffer is ok for writing to by the privileged API function.
#define TFM_PARTITION_PRIVILEGED_MODE
void tfm_spm_partition_set_state(uint32_t partition_idx, uint32_t state)
Set the current state of a partition.
enum spm_err_t tfm_spm_partition_set_iovec(uint32_t partition_idx, const int32_t *args)
Set the iovec parameters for the partition.
enum tfm_status_e tfm_spm_sfn_request_handler(struct tfm_sfn_req_s *desc_ptr, uint32_t excReturn)
void tfm_spm_seal_psp_stacks(void)
Function to seal the PSP stacks for Function mode.
void tfm_spm_partition_cleanup_context(uint32_t partition_idx)
Clears the context info from the database for a partition.
uint32_t tfm_spm_partition_get_partition_id(uint32_t partition_idx)
Get the id of the partition for its index from the db.
#define SPM_PARTITION_STATE_BLOCKED
void tfm_spm_partition_store_context(uint32_t partition_idx, uint32_t stack_ptr, uint32_t lr)
Save stack pointer and link register for partition in database.
void tfm_spm_partition_set_caller_partition_idx(uint32_t partition_idx, uint32_t caller_partition_idx)
Set the caller partition index for a given partition.
void tfm_spm_partition_set_signal_mask(uint32_t partition_idx, uint32_t signal_mask)
Set the signal mask for a given partition.
#define TFM_STACK_SEAL_VALUE
struct iovec_args_t iovec_args
void tfm_nspm_configure_clients(void)
initialise the NS context database
#define INVALID_PARTITION_ID
uint32_t tfm_spm_partition_get_running_partition_idx(void)
Returns the index of the partition that has running state.
struct spm_partition_desc_t * partitions
uint32_t tfm_spm_partition_get_privileged_mode(uint32_t partition_flags)
Get the current partition mode.
const struct spm_partition_runtime_data_t * tfm_spm_partition_get_runtime_data(uint32_t partition_idx)
Get the current runtime data of a partition.
#define TFM_INVALID_CLIENT_ID
Holds the iovec parameters that are passed to a service.
uint32_t * ctx_stack_list[]
#define SPM_PARTITION_STATE_RUNNING
psa_invec in_vec[PSA_MAX_IOVEC]
bool tfm_is_one_bit_set(uint32_t n)
uint32_t caller_partition_idx
#define SPM_PARTITION_STATE_SUSPENDED