1 // SPDX-License-Identifier: BSD-2-Clause 2 /* 3 * Copyright (c) 2020, Open Mobile Platform LLC 4 */ 5 6 #include <assert.h> 7 #include <kernel/thread.h> 8 #include <kernel/user_access.h> 9 #include <mm/mobj.h> 10 #include <optee_rpc_cmd.h> 11 #include <stddef.h> 12 #include <stdint.h> 13 #include <stdlib.h> 14 #include <string.h> 15 #include <tee/tee_supp_plugin_rpc.h> 16 #include <tee/uuid.h> 17 #include <trace.h> 18 19 TEE_Result tee_invoke_supp_plugin_rpc(const TEE_UUID *uuid, uint32_t cmd, 20 uint32_t sub_cmd, void *buf_core, 21 void *buf_user, size_t len, 22 size_t *outlen) 23 { 24 TEE_Result res = TEE_ERROR_GENERIC; 25 struct thread_param params[THREAD_RPC_MAX_NUM_PARAMS]; 26 uint32_t uuid_words[4] = { }; 27 void *va = NULL; 28 struct mobj *mobj = NULL; 29 30 /* 31 * sizeof 'TEE_UUID' and array 'uuid_words' must be same size, 32 * because 'tee_uuid_to_octets()' is used to copy variable 33 * with one type to another. 34 * 35 * Array 'uuid_words' is used just for convenient work with 36 * 'TEE_UUID' as with uint32_t values. 37 */ 38 COMPILE_TIME_ASSERT(sizeof(TEE_UUID) == sizeof(uuid_words)); 39 40 if (!uuid || (len && !buf_core && !buf_user) || 41 (!len && (buf_core || buf_user)) || (buf_core && buf_user)) 42 return TEE_ERROR_BAD_PARAMETERS; 43 44 if (len) { 45 mobj = thread_rpc_alloc_payload(len); 46 if (!mobj) { 47 EMSG("can't create mobj for plugin data"); 48 return TEE_ERROR_OUT_OF_MEMORY; 49 } 50 51 va = mobj_get_va(mobj, 0, len); 52 if (!va) { 53 EMSG("can't get va from mobj"); 54 goto out; 55 } 56 57 if (buf_core) 58 memcpy(va, buf_core, len); 59 if (buf_user) { 60 res = copy_from_user(va, buf_user, len); 61 if (res) 62 goto out; 63 } 64 } 65 66 tee_uuid_to_octets((uint8_t *)uuid_words, uuid); 67 68 params[0] = THREAD_PARAM_VALUE(IN, OPTEE_RPC_SUPP_PLUGIN_INVOKE, 69 uuid_words[0], uuid_words[1]); 70 params[1] = THREAD_PARAM_VALUE(IN, uuid_words[2], uuid_words[3], cmd); 71 params[2] = THREAD_PARAM_VALUE(INOUT, sub_cmd, 0, 0); 72 params[3] = THREAD_PARAM_MEMREF(INOUT, mobj, 0, len); 73 74 res = thread_rpc_cmd(OPTEE_RPC_CMD_SUPP_PLUGIN, 4, params); 75 76 if (outlen) 77 *outlen = params[2].u.value.b; 78 79 if (len && outlen && *outlen) { 80 if (buf_core) 81 memcpy(buf_core, va, *outlen <= len ? *outlen : len); 82 if (buf_user) 83 res = copy_to_user(buf_user, va, len); 84 } 85 86 out: 87 if (len) 88 thread_rpc_free_payload(mobj); 89 90 return res; 91 } 92