In current trusted-firmware-m version, secure functions such as secure storage service functions can only be called from handler mode.
But I have a question about the call sequence, when none secure side call sst_get_handle sevice function, it will first call svc instruction to enter handler mode, and in the svc handler, there will be the call sequence as follows:
svc hanlder() -> sst_veneer_get_handle->TFM_CORE_SFN_REQUEST(tfm_core_partition_request) __attribute__ ((always_inline)) __STATIC_INLINE int32_t tfm_core_partition_request(uint32_t id, void *fn, int32_t arg1, int32_t arg2, int32_t arg3, int32_t arg4) { int32_t args[4] = {arg1, arg2, arg3, arg4}; struct tfm_sfn_req_s desc, *desc_ptr = &desc; desc.sp_id = id; desc.sfn = fn; desc.args = args; desc.ns_caller = cmse_nonsecure_caller(); desc.exc_num = __get_active_exc_num(); // what is the exc_num here? I guess it will not be EXC_NUM_THREAD_MODE, right? ... return tfm_core_sfn_request_function(desc_ptr); } ->tfm_core_sfn_request_function ->tfm_core_call_sfn(desc_ptr){ #if TFM_LVL == 1 if ((desc_ptr->exc_num == EXC_NUM_THREAD_MODE) && (!tfm_secure_api_init)) { /* Secure partition to secure partition call in TFM level 1 */ int32_t res; int32_t *args = desc_ptr->args; int32_t retVal = desc_ptr->sfn(args[0], args[1], args[2], args[3]); /* return handler should restore original exc_return value... */ res = tfm_pop_lock(NULL); if (res == TFM_SUCCESS) { /* If unlock successful, pass SS return value to caller */ res = retVal; } else { /* Unlock errors indicate ctx database corruption or unknown * anomalies. Halt execution */ ERROR_MSG("Secure API error during unlock!"); tfm_secure_api_error_handler(); } return res; } #endif /* Exception return to partition start */ return tfm_core_exc_return_to_sfn(); }
My question is whether desc_ptr->sfn(args[0], args[1], args[2], args[3]); can be executed or not in the last tfm_core_call_sfn call if TFM_LVL =1. I think desc_ptr->exc_num is not EXC_NUM_THREAD_MODE because the call sequence is from none-secure side svc handler, please let me know if I am wrong, thanks.
matt-ma said:desc.exc_num = __get_active_exc_num(); // what is the exc_num here? I guess it will not be EXC_NUM_THREAD_MODE, right?
That is correct. exc_num, i.e. exception number will be the ISR value at the point of call. ISR is not mapped between security states, so the non-secure SVC handler call to this veneer will result in an exc_num value of 11 (EXC_NUM_SVCALL).
In tfm_core_call_sfn(desc_ptr), since desc_ptr->exc_num != EXC_NUM_THREAD_MODE, the entire
if ((desc_ptr->exc_num == EXC_NUM_THREAD_MODE) && (!tfm_secure_api_init)) {
block is skipped (note that there's no corresponding else statement). This results in the code below being executed:
/* Exception return to partition start */ return tfm_core_exc_return_to_sfn();
That will perform a secure exception return to the context prepared for secure function execution, so desc_ptr->sfn(…) will be executed.
Regards
Miklos