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