diff options
author | Pascal Brand <pascal.brand@st.com> | 2014-06-12 15:56:20 +0200 |
---|---|---|
committer | Pascal Brand <pascal.brand@st.com> | 2014-06-12 15:56:20 +0200 |
commit | b01047730e77127c23a36591643eeb8bb0487d68 (patch) | |
tree | c6460d72a0f05fb1b9655b3fb0b434ff8c7be053 /core/arch/arm32/tee |
Open-source the TEE Core
Signed-off-by: Pascal Brand <pascal.brand@st.com>
Diffstat (limited to 'core/arch/arm32/tee')
-rw-r--r-- | core/arch/arm32/tee/entry.c | 448 | ||||
-rw-r--r-- | core/arch/arm32/tee/sub.mk | 2 | ||||
-rw-r--r-- | core/arch/arm32/tee/tee_svc_asm.S | 257 |
3 files changed, 707 insertions, 0 deletions
diff --git a/core/arch/arm32/tee/entry.c b/core/arch/arm32/tee/entry.c new file mode 100644 index 0000000..710ee13 --- /dev/null +++ b/core/arch/arm32/tee/entry.c @@ -0,0 +1,448 @@ +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include <tee/entry.h> +#include <sm/teesmc.h> +#include <sm/teesmc_st.h> +#include <kernel/tee_common_unpg.h> +#include <kernel/tee_dispatch.h> +#include <kernel/panic.h> +#include <mm/core_mmu.h> + +#include <assert.h> + +#define SHM_CACHE_ATTRS \ + (core_mmu_is_shm_cached() ? \ + (TEESMC_ATTR_CACHE_DEFAULT << TEESMC_ATTR_CACHE_SHIFT) : 0 ) + +static bool copy_in_params(const struct teesmc32_param *params, + uint32_t num_params, uint32_t *param_types, + uint32_t param_attr[TEE_NUM_PARAMS], + TEE_Param tee_params[TEE_NUM_PARAMS]) +{ + size_t n; + uint8_t pt[4]; + + *param_types = 0; + + if (num_params > TEE_NUM_PARAMS) + return false; + + for (n = 0; n < num_params; n++) { + if (params[n].attr & TEESMC_ATTR_META) + return false; + + pt[n] = params[n].attr & TEESMC_ATTR_TYPE_MASK; + + param_attr[n] = (params[n].attr >> TEESMC_ATTR_CACHE_SHIFT) & + TEESMC_ATTR_CACHE_MASK; + + if ((params[n].attr & TEESMC_ATTR_TYPE_MASK) == + TEESMC_ATTR_TYPE_NONE) { + tee_params[n].value.a = 0; + tee_params[n].value.b = 0; + } else { + tee_params[n].value.a = params[n].u.value.a; + tee_params[n].value.b = params[n].u.value.b; + } + } + for (; n < TEE_NUM_PARAMS; n++) { + pt[n] = TEE_PARAM_TYPE_NONE; + param_attr[n] = 0; + tee_params[n].value.a = 0; + tee_params[n].value.b = 0; + } + + *param_types = TEE_PARAM_TYPES(pt[0], pt[1], pt[2], pt[3]); + + return true; +} + +static void copy_out_param(const TEE_Param tee_params[TEE_NUM_PARAMS], + uint32_t param_types, uint32_t num_params, + struct teesmc32_param *params) +{ + size_t n; + + for (n = 0; n < num_params; n++) { + switch (TEE_PARAM_TYPE_GET(param_types, n)) { + case TEE_PARAM_TYPE_MEMREF_OUTPUT: + case TEE_PARAM_TYPE_MEMREF_INOUT: + params[n].u.memref.size = tee_params[n].memref.size; + break; + case TEE_PARAM_TYPE_VALUE_OUTPUT: + case TEE_PARAM_TYPE_VALUE_INOUT: + params[n].u.value.a = tee_params[n].value.a; + params[n].u.value.b = tee_params[n].value.b; + break; + default: + break; + } + } +} + +/* + * Extracts mandatory parameter for open session. + * + * Returns + * false : mandatory parameter wasn't found or malformatted + * true : paramater found and OK + */ +static bool get_open_session_meta(struct teesmc32_arg *arg32, + uint32_t num_params, size_t *num_meta, + struct teesmc_meta_open_session **meta) +{ + struct teesmc32_param *params = TEESMC32_GET_PARAMS(arg32); + uint32_t phmeta; + const uint8_t req_attr = TEESMC_ATTR_META | + TEESMC_ATTR_TYPE_MEMREF_INPUT | + SHM_CACHE_ATTRS; + + if (num_params < (*num_meta + 1)) + return false; + + if (params[*num_meta].attr != req_attr) + return false; + + if (params[*num_meta].u.memref.size != + sizeof(struct teesmc_meta_open_session)) + return false; + + phmeta = params[*num_meta].u.memref.buf_ptr; + if (!tee_pbuf_is_non_sec(phmeta, + sizeof(struct teesmc_meta_open_session))) + return false; + + if (core_pa2va(phmeta, (void *)meta)) + return false; + + (*num_meta)++; + return true; +} + +/* + * Extracts optional pointer to a Trusted Application. + * + * Returns + * false : malformatted TA parameter + * true : if TA parameter wasn't found or if it was found and OK + */ +static bool get_open_session_ta(struct teesmc32_arg *arg32, size_t num_params, + size_t *num_meta, kta_signed_header_t **ta) +{ + struct teesmc32_param *params = TEESMC32_GET_PARAMS(arg32); + uint32_t ph; + size_t len; + const uint8_t req_attr = TEESMC_ATTR_META | + TEESMC_ATTR_TYPE_MEMREF_INPUT | + SHM_CACHE_ATTRS; + + if (num_params < (*num_meta + 1)) + return false; + + if (!(params[*num_meta].attr & TEESMC_ATTR_META)) + return true; + + if (params[*num_meta].attr != req_attr) + return false; + + ph = params[*num_meta].u.memref.buf_ptr; + if (params[*num_meta].u.memref.size < sizeof(kta_signed_header_t)) + return false; + + if (!tee_pbuf_is_non_sec(ph, sizeof(kta_signed_header_t))) + return false; + + if (core_pa2va(ph, (void *)ta)) + return false; + + len = (*ta)->size_of_signed_header + (*ta)->size_of_payload; + if (params[*num_meta].u.memref.size < len) + return false; + + if (!tee_pbuf_is_non_sec(ph, len)) + return false; + + (*num_meta)++; + return true; +} + +static void entry_open_session(struct thread_smc_args *args, + struct teesmc32_arg *arg32, uint32_t num_params) +{ + struct tee_dispatch_open_session_in in; + struct tee_dispatch_open_session_out out; + struct teesmc_meta_open_session *meta; + struct teesmc32_param *params = TEESMC32_GET_PARAMS(arg32); + size_t num_meta = 0; + + if (!get_open_session_meta(arg32, num_params, &num_meta, &meta)) + goto bad_params; + + in.ta = NULL; + if (!get_open_session_ta(arg32, num_params, &num_meta, &in.ta)) + goto bad_params; + + TEE_COMPILE_TIME_ASSERT(sizeof(TEE_UUID) == TEESMC_UUID_LEN); + memcpy(&in.uuid, &meta->uuid, sizeof(TEE_UUID)); + memcpy(&in.clnt_id.uuid, &meta->clnt_uuid, sizeof(TEE_UUID)); + in.clnt_id.login = meta->clnt_login; + + if (!copy_in_params(params + num_meta, num_params - num_meta, + &in.param_types, in.param_attr, in.params)) + goto bad_params; + + (void)tee_dispatch_open_session(&in, &out); + if (out.msg.res == TEE_STE_ERROR_SYSTEM_BUSY) { + args->a0 = TEESMC_RETURN_EBUSY; + return; + } + + copy_out_param(out.params, in.param_types, num_params - num_meta, + params + num_meta); + + arg32->session = (uint32_t)out.sess; + arg32->ret = out.msg.res; + arg32->ret_origin = out.msg.err; + args->a0 = TEESMC_RETURN_OK; + return; + +bad_params: + DMSG("Bad params"); + arg32->ret = TEE_ERROR_BAD_PARAMETERS; + arg32->ret_origin = TEE_ORIGIN_TEE; + args->a0 = TEESMC_RETURN_OK; +} + +static void entry_close_session(struct thread_smc_args *args, + struct teesmc32_arg *arg32, uint32_t num_params) +{ + + if (num_params == 0) { + struct tee_close_session_in in; + uint32_t ret; + + in.sess = arg32->session; + ret = tee_dispatch_close_session(&in); + if (ret == TEE_STE_ERROR_SYSTEM_BUSY) { + args->a0 = TEESMC_RETURN_EBUSY; + return; + } + arg32->ret = ret; + } else { + arg32->ret = TEE_ERROR_BAD_PARAMETERS; + } + + arg32->ret_origin = TEE_ORIGIN_TEE; + args->a0 = TEESMC_RETURN_OK; +} + +static void entry_invoke_command(struct thread_smc_args *args, + struct teesmc32_arg *arg32, uint32_t num_params) +{ + struct tee_dispatch_invoke_command_in in; + struct tee_dispatch_invoke_command_out out; + struct teesmc32_param *params = TEESMC32_GET_PARAMS(arg32); + + if (!copy_in_params(params, num_params, + &in.param_types, in.param_attr, in.params)) { + arg32->ret = TEE_ERROR_BAD_PARAMETERS; + arg32->ret_origin = TEE_ORIGIN_TEE; + args->a0 = TEESMC_RETURN_OK; + return; + } + + in.sess = (TEE_Session *)arg32->session; + in.cmd = arg32->ta_func; + (void)tee_dispatch_invoke_command(&in, &out); + if (out.msg.res == TEE_STE_ERROR_SYSTEM_BUSY) { + args->a0 = TEESMC_RETURN_EBUSY; + return; + } + + copy_out_param(out.params, in.param_types, num_params, params); + + arg32->ret = out.msg.res; + arg32->ret_origin = out.msg.err; + args->a0 = TEESMC_RETURN_OK; +} + +static void entry_cancel(struct thread_smc_args *args, + struct teesmc32_arg *arg32, uint32_t num_params) +{ + + if (num_params == 0) { + struct tee_dispatch_cancel_command_in in; + struct tee_dispatch_cancel_command_out out; + + in.sess = (TEE_Session *)arg32->session; + (void)tee_dispatch_cancel_command(&in, &out); + + if (out.msg.res == TEE_STE_ERROR_SYSTEM_BUSY) { + args->a0 = TEESMC_RETURN_EBUSY; + return; + } + + arg32->ret = out.msg.res; + arg32->ret_origin = out.msg.err; + } else { + arg32->ret = TEE_ERROR_BAD_PARAMETERS; + arg32->ret_origin = TEE_ORIGIN_TEE; + } + + args->a0 = TEESMC_RETURN_OK; +} + + + +static void tee_entry_call_with_arg(struct thread_smc_args *args) +{ + struct teesmc32_arg *arg32; + uint32_t num_params; + + if (args->a0 != TEESMC32_CALL_WITH_ARG && + args->a0 != TEESMC32_FASTCALL_WITH_ARG) { + EMSG("Unknown SMC 0x%x\n", args->a0); + DMSG("Expected 0x%x or 0x%x\n", + TEESMC32_CALL_WITH_ARG, TEESMC32_FASTCALL_WITH_ARG); + args->a0 = TEESMC_RETURN_UNKNOWN_FUNCTION; + return; + } + + if (args->a0 == TEESMC32_CALL_WITH_ARG) + thread_set_irq(true); /* Enable IRQ for STD calls */ + + if (!tee_pbuf_is_non_sec(args->a1, sizeof(struct teesmc32_arg)) || + !TEE_ALIGNMENT_IS_OK(args->a1, struct teesmc32_arg) || + core_pa2va(args->a1, (void *)&arg32)) { + EMSG("Bad arg address 0x%x\n", args->a1); + args->a0 = TEESMC_RETURN_EBADADDR; + return; + } + + num_params = arg32->num_params; + if (!tee_pbuf_is_non_sec(args->a1, TEESMC32_GET_ARG_SIZE(num_params))) { + EMSG("Bad arg address 0x%x\n", args->a1); + args->a0 = TEESMC_RETURN_EBADADDR; + return; + } + + if (args->a0 == TEESMC32_CALL_WITH_ARG) { + switch (arg32->cmd) { + case TEESMC_CMD_OPEN_SESSION: + entry_open_session(args, arg32, num_params); + break; + case TEESMC_CMD_CLOSE_SESSION: + entry_close_session(args, arg32, num_params); + break; + case TEESMC_CMD_INVOKE_COMMAND: + entry_invoke_command(args, arg32, num_params); + break; + case TEESMC_CMD_CANCEL: + entry_cancel(args, arg32, num_params); + break; + default: + EMSG("Unknown cmd 0x%x\n", arg32->cmd); + args->a0 = TEESMC_RETURN_EBADCMD; + } + } else { + EMSG("Unknown fastcall cmd 0x%x\n", arg32->cmd); + args->a0 = TEESMC_RETURN_EBADCMD; + } +} + +void tee_entry(struct thread_smc_args *args) +{ + switch (args->a0) { + case TEESMC32_CALLS_COUNT: + tee_entry_get_api_call_count(args); + break; + case TEESMC32_CALLS_UID: + tee_entry_get_api_uuid(args); + break; + case TEESMC32_CALLS_REVISION: + tee_entry_get_api_revision(args); + break; + case TEESMC32_CALL_GET_OS_UUID: + tee_entry_get_os_uuid(args); + break; + case TEESMC32_CALL_GET_OS_REVISION: + tee_entry_get_os_revision(args); + break; + case TEESMC32_CALL_WITH_ARG: + case TEESMC64_CALL_WITH_ARG: + tee_entry_call_with_arg(args); + break; + default: + args->a0 = TEESMC_RETURN_UNKNOWN_FUNCTION; + break; + } +} + +size_t tee_entry_generic_get_api_call_count(void) +{ + /* + * All the differnt calls handled in this file. If the specific + * target has additional calls it will call this function and + * add the number of calls the target has added. + */ + return 7; +} + +void __attribute__((weak)) tee_entry_get_api_call_count( + struct thread_smc_args *args) +{ + args->a0 = tee_entry_generic_get_api_call_count(); +} + +void __attribute__((weak)) tee_entry_get_api_uuid(struct thread_smc_args *args) +{ + args->a0 = TEESMC_UID_R0; + args->a1 = TEESMC_UID_R1; + args->a2 = TEESMC_UID_R2; + args->a3 = TEESMC_UID32_R3; +} + +void __attribute__((weak)) tee_entry_get_api_revision( + struct thread_smc_args *args) +{ + args->a0 = TEESMC_REVISION_MAJOR; + args->a1 = TEESMC_REVISION_MINOR; +} + +void __attribute__((weak)) tee_entry_get_os_uuid(struct thread_smc_args *args) +{ + /* Not implemented */ + args->a0 = TEESMC_RETURN_UNKNOWN_FUNCTION; +} + +void __attribute__((weak)) tee_entry_get_os_revision( + struct thread_smc_args *args) +{ + /* Not implemented */ + args->a0 = TEESMC_RETURN_UNKNOWN_FUNCTION; +} diff --git a/core/arch/arm32/tee/sub.mk b/core/arch/arm32/tee/sub.mk new file mode 100644 index 0000000..9b9b940 --- /dev/null +++ b/core/arch/arm32/tee/sub.mk @@ -0,0 +1,2 @@ +srcs-y += tee_svc_asm.S +srcs-y += entry.c diff --git a/core/arch/arm32/tee/tee_svc_asm.S b/core/arch/arm32/tee/tee_svc_asm.S new file mode 100644 index 0000000..a4156d4 --- /dev/null +++ b/core/arch/arm32/tee/tee_svc_asm.S @@ -0,0 +1,257 @@ +/* + * Copyright (c) 2014, STMicroelectronics International N.V. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +#include "tee_syscall_numbers.h" + +.global tee_svc_enter_user_mode +.global tee_svc_sys_return +.global tee_svc_syscall + +.set SPSR_T_BIT, (1 << 5) +.set SPSR_IT_MASK, 0x0600FC00 +.set SPSR_IT_MASK1, 0x06000000 +.set SPSR_IT_MASK2, 0x0000FC00 + +.section .text +.balign 4 +.code 32 + +/* + * Function called from the vector table when a svc exception is received. + * This function handles entry and exit from a system call. + */ +.func tee_svc_syscall +tee_svc_syscall: + push {r4 - r12, lr} + mov r8, sp + + /* Restore IRQ which are disabled on exception entry */ + push {r0-r3} + blx thread_restore_irq + pop {r0-r3} + + /* + * Copy eventual arguments passed on the user stack. + * + * r5 holds the address of the first word + * r6 holds the number of words + * + * TODO figure out how to avoid stack overflow because of too much data + * passed on the stack. + */ + sub sp, sp, r6, lsl #2 + cmp r6, #0 + beq .Lno_args + push {r0} + push {r1-r3} + mov r0, #0 + mov r2, r5 + add r1, sp, #(4 * 4) + mov r3, r6, lsl #2 + ldr lr, =tee_svc_copy_from_user + blx lr + + /* If copy failed return the error */ + cmp r0, #0 + pop {r1-r3} + addne sp, sp, #4 + popeq {r0} + bne .Lret +.Lno_args: + + /* + * Find the system call and call the function. + * + * System call number is passed in r7. + */ + ldr r12, =tee_svc_syscall_table + cmp r7, #TEE_SCN_MAX + /* Either syscall function should return to cleanup (.Lret) */ + ldr lr, =.Lret + ldrls pc, [r12, r7, lsl #2] /* if valid syscall number */ + ldr pc, =tee_svc_sys_nocall /* if invalid syscall number */ +.Lret: + mov sp, r8 + pop {r4 - r12, lr} + movs pc, lr +.endfunc + + + +@ TEE_Result tee_svc_enter_user_mode( +@ uint32_t a0, uint32_t a1, uint32_t a2, uint32_t a3, +@ tee_uaddr_t sp, tee_uaddr_t user_func, +@ uint32_t *panicked, uint32_t *panic_code); +.func tee_svc_enter_user_mode +tee_svc_enter_user_mode: + /* + * Save all registers to allow tee_svc_sys_return() to + * resume execution as if this function would have returned. + * This is also used in tee_svc_sys_panic(). + * + * If stack usage of this function is changed tee_svc_sys_return() + * and tee_svc_sys_panic() has to be updated. + */ + push {r4-r12,lr} + + ldr r4, [sp, #(10 * 0x4)] /* user stack pointer */ + ldr r5, [sp, #(11 * 0x4)] /* user function */ + + /* Save user sp */ + stmfd sp, {sp}^ /* store r13 user mode */ + nop + sub sp, sp, #4 /* update stack pointer */ + + /* Switch from Supervisor mode to System mode */ + mrs r6, cpsr + mrs r7, cpsr + orr r6, #0xF + msr cpsr, r6 + + /* Setup user stack */ + mov sp, r4 + + /* Switch back to Supervisor mode to have a spsr to modify */ + msr cpsr, r7 + + /* + * Set the saved Processors Status Register to user mode to allow entry + * of user mode through movs below. Also update thumbstate since movs + * doesn't do that automatically. + */ + bic r6, #0xF + tst r5, #1 /* If it's odd we should switch to thumb mode */ + orrne r6, #SPSR_T_BIT /* Enable thumb mode */ + biceq r6, #SPSR_T_BIT /* Disable thumb mode */ + bicne r6, #SPSR_IT_MASK1 /* Clear IT state for thumb mode */ + bicne r6, #SPSR_IT_MASK2 /* Clear IT state for thumb mode */ + msr spsr_cxsf, r6 + + /* + * Don't allow return from this function, return is done through + * tee_svc_sys_return() below. + */ + mov lr, #0 + /* Call the user function with its arguments */ + movs pc, r5 +.endfunc + +@ tee_svc_sys_return(uint32_t ret, uint32_t param_types, void *params); +.func tee_svc_sys_return +tee_svc_sys_return: + mov sp, r8 /* Restore sp in case extra parameters was passed */ + pop {r4-r12,lr} /* Match the push in tee_svc_syscall() */ + + /* Restore user sp */ + ldmfd sp, {sp}^ /* store r13 user mode */ + nop + add sp, sp, #4 /* update stack pointer */ + + pop {r4-r12,pc} /* Match the push in tee_svc_enter_user_mode() */ +.endfunc + +@ void tee_svc_sys_panic(uint32_t code); +.func tee_svc_sys_panic +tee_svc_sys_panic: + mov sp, r8 /* Restore sp in case extra parameters was passed */ + pop {r4-r12,lr} /* Match the push in tee_svc_syscall() */ + +.global tee_svc_user_ta_panic_from_pager +tee_svc_user_ta_panic_from_pager: + ldr r1, [sp, #(13 * 0x4)] /* &session->panicked */ + mov r2, #1 /* true */ + str r2, [r1] /* update session->panicked */ + + ldr r1, [sp, #(14 * 0x4)] /* &session->panic_code */ + str r0, [r1] /* update session->panic_code */ + + /* Restore user sp */ + ldmfd sp, {sp}^ /* store r13 user mode */ + nop + add sp, sp, #4 /* update stack pointer */ + + pop {r4-r12,pc} /* Match the push in tee_svc_enter_user_mode() */ +.endfunc + + + .section .rodata +tee_svc_syscall_table: +.word tee_svc_sys_return +.word tee_svc_sys_log +.word tee_svc_sys_panic +.word tee_svc_sys_dummy +.word tee_svc_sys_dummy_7args +.word tee_svc_sys_get_property +.word tee_svc_open_ta_session +.word tee_svc_close_ta_session +.word tee_svc_invoke_ta_command +.word tee_svc_check_access_rights +.word tee_svc_get_cancellation_flag +.word tee_svc_unmask_cancellation +.word tee_svc_mask_cancellation +.word tee_svc_wait +.word tee_svc_get_time +.word tee_svc_set_ta_time +.word tee_svc_cryp_state_alloc +.word tee_svc_cryp_state_copy +.word tee_svc_cryp_state_free +.word tee_svc_hash_init +.word tee_svc_hash_update +.word tee_svc_hash_final +.word tee_svc_cipher_init +.word tee_svc_cipher_update +.word tee_svc_cipher_final +.word tee_svc_cryp_obj_get_info +.word tee_svc_cryp_obj_restrict_usage +.word tee_svc_cryp_obj_get_attr +.word tee_svc_cryp_obj_alloc +.word tee_svc_cryp_obj_close +.word tee_svc_cryp_obj_reset +.word tee_svc_cryp_obj_populate +.word tee_svc_cryp_obj_copy +.word tee_svc_cryp_derive_key +.word tee_svc_cryp_random_number_generate +.word tee_svc_authenc_init +.word tee_svc_authenc_update_aad +.word tee_svc_authenc_update_payload +.word tee_svc_authenc_enc_final +.word tee_svc_authenc_dec_final +.word tee_svc_asymm_operate +.word tee_svc_asymm_verify +.word tee_svc_storage_obj_open +.word tee_svc_storage_obj_create +.word tee_svc_storage_obj_del +.word tee_svc_storage_obj_rename +.word tee_svc_storage_alloc_enum +.word tee_svc_storage_free_enum +.word tee_svc_storage_reset_enum +.word tee_svc_storage_start_enum +.word tee_svc_storage_next_enum +.word tee_svc_storage_obj_read +.word tee_svc_storage_obj_write +.word tee_svc_storage_obj_trunc +.word tee_svc_storage_obj_seek +.word tee_svc_obj_generate_key |