xref: /rk3399_rockchip-uboot/lib/optee_clientApi/OpteeClientSMC.c (revision abdd24375050db7ce121b48477cc332d6c8c40f6)
1*abdd2437Shisping /*
2*abdd2437Shisping  * Copyright 2017, Rockchip Electronics Co., Ltd
3*abdd2437Shisping  * hisping lin, <hisping.lin@rock-chips.com>
4*abdd2437Shisping  *
5*abdd2437Shisping  * SPDX-License-Identifier:	GPL-2.0+
6*abdd2437Shisping  */
7*abdd2437Shisping #include <common.h>
8*abdd2437Shisping #include <optee_include/OpteeClientMem.h>
9*abdd2437Shisping #include <optee_include/OpteeClientSMC.h>
10*abdd2437Shisping #include <optee_include/OpteeClientRPC.h>
11*abdd2437Shisping #include <optee_include/teesmc.h>
12*abdd2437Shisping 
13*abdd2437Shisping #define TEEC_SMC_DEFAULT_CACHE_ATTRIBUTES \
14*abdd2437Shisping 	(TEESMC_ATTR_CACHE_DEFAULT << TEESMC_ATTR_CACHE_SHIFT);
15*abdd2437Shisping 
16*abdd2437Shisping static void SetTeeSmc32Params(TEEC_Operation *operation,
17*abdd2437Shisping 	t_teesmc32_param *TeeSmc32Param);
18*abdd2437Shisping static void GetTeeSmc32Params(t_teesmc32_param *TeeSmc32Param,
19*abdd2437Shisping 	TEEC_Operation *operation);
20*abdd2437Shisping static TEEC_Result OpteeSmcCall(t_teesmc32_arg *TeeSmc32Arg);
21*abdd2437Shisping 
22*abdd2437Shisping /*
23*abdd2437Shisping  * This function opens a new Session between the Client application and the
24*abdd2437Shisping  * specified TEE application.
25*abdd2437Shisping  *
26*abdd2437Shisping  * Only connection_method == TEEC_LOGIN_PUBLIC is supported connection_data and
27*abdd2437Shisping  * operation shall be set to NULL.
28*abdd2437Shisping  */
29*abdd2437Shisping TEEC_Result TEEC_SMC_OpenSession(TEEC_Context *context,
30*abdd2437Shisping 				TEEC_Session *session,
31*abdd2437Shisping 				const TEEC_UUID *destination,
32*abdd2437Shisping 				TEEC_Operation  *operation,
33*abdd2437Shisping 				uint32_t *error_origin)
34*abdd2437Shisping {
35*abdd2437Shisping 	TEEC_Result TeecResult = TEEC_SUCCESS;
36*abdd2437Shisping 	uint32_t TeeSmc32ArgLength;
37*abdd2437Shisping 	uint32_t TeeSmcMetaSessionLength;
38*abdd2437Shisping 
39*abdd2437Shisping 	t_teesmc32_arg *TeeSmc32Arg = NULL;
40*abdd2437Shisping 	t_teesmc32_param *TeeSmc32Param = NULL;
41*abdd2437Shisping 	t_teesmc_meta_open_session *TeeSmcMetaSession = NULL;
42*abdd2437Shisping 	static const uint32_t MetaNum = 1;
43*abdd2437Shisping 
44*abdd2437Shisping 	*error_origin = TEEC_ORIGIN_API;
45*abdd2437Shisping 
46*abdd2437Shisping 	TeeSmc32ArgLength =
47*abdd2437Shisping 		TEESMC32_GET_ARG_SIZE(TEEC_CONFIG_PAYLOAD_REF_COUNT + MetaNum);
48*abdd2437Shisping 
49*abdd2437Shisping 	TeeSmc32Arg = (t_teesmc32_arg *)OpteeClientMemAlloc(TeeSmc32ArgLength);
50*abdd2437Shisping 
51*abdd2437Shisping 	if (TeeSmc32Arg == NULL) {
52*abdd2437Shisping 		TeecResult = TEEC_ERROR_OUT_OF_MEMORY;
53*abdd2437Shisping 		goto Exit;
54*abdd2437Shisping 	}
55*abdd2437Shisping 
56*abdd2437Shisping 	memset(TeeSmc32Arg, 0, TeeSmc32ArgLength);
57*abdd2437Shisping 
58*abdd2437Shisping 	TeeSmcMetaSessionLength = sizeof(*TeeSmcMetaSession);
59*abdd2437Shisping 
60*abdd2437Shisping 	TeeSmcMetaSession = (t_teesmc_meta_open_session *)
61*abdd2437Shisping 		OpteeClientMemAlloc(TeeSmcMetaSessionLength);
62*abdd2437Shisping 
63*abdd2437Shisping 	if (TeeSmcMetaSession == NULL) {
64*abdd2437Shisping 		TeecResult = TEEC_ERROR_OUT_OF_MEMORY;
65*abdd2437Shisping 		goto Exit;
66*abdd2437Shisping 	}
67*abdd2437Shisping 
68*abdd2437Shisping 	memset(TeeSmcMetaSession, 0, TeeSmcMetaSessionLength);
69*abdd2437Shisping 
70*abdd2437Shisping 	TeeSmc32Arg->cmd = TEESMC_CMD_OPEN_SESSION;
71*abdd2437Shisping 	TeeSmc32Arg->num_params = TEEC_CONFIG_PAYLOAD_REF_COUNT + MetaNum;
72*abdd2437Shisping 
73*abdd2437Shisping 	TeeSmc32Param = TEESMC32_GET_PARAMS(TeeSmc32Arg);
74*abdd2437Shisping 
75*abdd2437Shisping 	memcpy(&TeeSmcMetaSession->uuid,
76*abdd2437Shisping 		destination,
77*abdd2437Shisping 		sizeof(TeeSmcMetaSession->uuid));
78*abdd2437Shisping 	TeeSmcMetaSession->clnt_login = TEEC_LOGIN_PUBLIC;
79*abdd2437Shisping 
80*abdd2437Shisping 	TeeSmc32Param[0].u.memref.buf_ptr = (uint32_t) TeeSmcMetaSession;
81*abdd2437Shisping 	TeeSmc32Param[0].u.memref.size = sizeof(*TeeSmcMetaSession);
82*abdd2437Shisping 
83*abdd2437Shisping #ifdef CONFIG_ROCKCHIP_RK3328
84*abdd2437Shisping 	TeeSmc32Param[0].attr = TEESMC_ATTR_TYPE_MEMREF_INPUT |
85*abdd2437Shisping 				TEESMC_ATTR_META              |
86*abdd2437Shisping 				TEEC_SMC_DEFAULT_CACHE_ATTRIBUTES;
87*abdd2437Shisping #endif
88*abdd2437Shisping 
89*abdd2437Shisping #ifdef CONFIG_ROCKCHIP_RK322X
90*abdd2437Shisping 	TeeSmc32Param[0].attr = TEESMC_ATTR_TYPE_MEMREF_INPUT |
91*abdd2437Shisping 				TEESMC_ATTR_META;
92*abdd2437Shisping #endif
93*abdd2437Shisping 
94*abdd2437Shisping 	SetTeeSmc32Params(operation, TeeSmc32Param + MetaNum);
95*abdd2437Shisping 
96*abdd2437Shisping 	*error_origin = TEEC_ORIGIN_COMMS;
97*abdd2437Shisping 
98*abdd2437Shisping 	TeecResult = OpteeSmcCall(TeeSmc32Arg);
99*abdd2437Shisping 	if (TeecResult != TEEC_SUCCESS)
100*abdd2437Shisping 		goto Exit;
101*abdd2437Shisping 
102*abdd2437Shisping 	session->id = TeeSmc32Arg->session;
103*abdd2437Shisping 	TeecResult = TeeSmc32Arg->ret;
104*abdd2437Shisping 	*error_origin = TeeSmc32Arg->ret_origin;
105*abdd2437Shisping 
106*abdd2437Shisping 	GetTeeSmc32Params(TeeSmc32Param + MetaNum, operation);
107*abdd2437Shisping 
108*abdd2437Shisping Exit:
109*abdd2437Shisping 	if (TeeSmc32Arg != NULL)
110*abdd2437Shisping 		OpteeClientMemFree(TeeSmc32Arg);
111*abdd2437Shisping 
112*abdd2437Shisping 	if (TeeSmcMetaSession != NULL)
113*abdd2437Shisping 		OpteeClientMemFree(TeeSmcMetaSession);
114*abdd2437Shisping 
115*abdd2437Shisping 	return TeecResult;
116*abdd2437Shisping }
117*abdd2437Shisping 
118*abdd2437Shisping /*
119*abdd2437Shisping  * This function closes a session which has been opened with a TEE
120*abdd2437Shisping  * application.
121*abdd2437Shisping  *
122*abdd2437Shisping  * Note that the GP specification does not allow for this API to fail and return
123*abdd2437Shisping  * a failure code however we'll support this at the SMC level so we can get
124*abdd2437Shisping  * see debug information about such failures.
125*abdd2437Shisping  */
126*abdd2437Shisping TEEC_Result TEEC_SMC_CloseSession(TEEC_Session *session,
127*abdd2437Shisping 				uint32_t *error_origin)
128*abdd2437Shisping {
129*abdd2437Shisping 	TEEC_Result TeecResult = TEEC_SUCCESS;
130*abdd2437Shisping 	uint32_t TeeSmc32ArgLength;
131*abdd2437Shisping 	t_teesmc32_arg *TeeSmc32Arg = NULL;
132*abdd2437Shisping 
133*abdd2437Shisping 	*error_origin = TEEC_ORIGIN_API;
134*abdd2437Shisping 
135*abdd2437Shisping 	TeeSmc32ArgLength =
136*abdd2437Shisping 		TEESMC32_GET_ARG_SIZE(TEEC_CONFIG_PAYLOAD_REF_COUNT);
137*abdd2437Shisping 
138*abdd2437Shisping 	TeeSmc32Arg = (t_teesmc32_arg *)OpteeClientMemAlloc(TeeSmc32ArgLength);
139*abdd2437Shisping 
140*abdd2437Shisping 	if (TeeSmc32Arg == NULL) {
141*abdd2437Shisping 		TeecResult = TEEC_ERROR_OUT_OF_MEMORY;
142*abdd2437Shisping 		goto Exit;
143*abdd2437Shisping 	}
144*abdd2437Shisping 
145*abdd2437Shisping 	memset(TeeSmc32Arg, 0, TeeSmc32ArgLength);
146*abdd2437Shisping 
147*abdd2437Shisping 	TeeSmc32Arg->cmd = TEESMC_CMD_CLOSE_SESSION;
148*abdd2437Shisping 	TeeSmc32Arg->session = session->id;
149*abdd2437Shisping 
150*abdd2437Shisping 	*error_origin = TEEC_ORIGIN_COMMS;
151*abdd2437Shisping 
152*abdd2437Shisping 	TeecResult = OpteeSmcCall(TeeSmc32Arg);
153*abdd2437Shisping 
154*abdd2437Shisping 	if (TeecResult != TEEC_SUCCESS)
155*abdd2437Shisping 		goto Exit;
156*abdd2437Shisping 
157*abdd2437Shisping 	TeecResult = TeeSmc32Arg->ret;
158*abdd2437Shisping 	*error_origin = TeeSmc32Arg->ret_origin;
159*abdd2437Shisping 
160*abdd2437Shisping Exit:
161*abdd2437Shisping 	if (TeeSmc32Arg != NULL)
162*abdd2437Shisping 		OpteeClientMemFree(TeeSmc32Arg);
163*abdd2437Shisping 
164*abdd2437Shisping 	return TeecResult;
165*abdd2437Shisping }
166*abdd2437Shisping 
167*abdd2437Shisping /*
168*abdd2437Shisping  * Invokes a TEE command (secure service, sub-PA or whatever).
169*abdd2437Shisping  */
170*abdd2437Shisping TEEC_Result TEEC_SMC_InvokeCommand(TEEC_Session *session,
171*abdd2437Shisping 				uint32_t cmd_id,
172*abdd2437Shisping 				TEEC_Operation *operation,
173*abdd2437Shisping 				uint32_t *error_origin)
174*abdd2437Shisping {
175*abdd2437Shisping 	TEEC_Result TeecResult = TEEC_SUCCESS;
176*abdd2437Shisping 	uint32_t TeeSmc32ArgLength;
177*abdd2437Shisping 	t_teesmc32_arg *TeeSmc32Arg = NULL;
178*abdd2437Shisping 	t_teesmc32_param *TeeSmc32Param = NULL;
179*abdd2437Shisping 
180*abdd2437Shisping 	*error_origin = TEEC_ORIGIN_API;
181*abdd2437Shisping 
182*abdd2437Shisping 	TeeSmc32ArgLength =
183*abdd2437Shisping 		TEESMC32_GET_ARG_SIZE(TEEC_CONFIG_PAYLOAD_REF_COUNT);
184*abdd2437Shisping 
185*abdd2437Shisping 	TeeSmc32Arg = (t_teesmc32_arg *)OpteeClientMemAlloc(TeeSmc32ArgLength);
186*abdd2437Shisping 
187*abdd2437Shisping 	if (TeeSmc32Arg == NULL) {
188*abdd2437Shisping 		TeecResult = TEEC_ERROR_OUT_OF_MEMORY;
189*abdd2437Shisping 		goto Exit;
190*abdd2437Shisping 	}
191*abdd2437Shisping 
192*abdd2437Shisping 	memset(TeeSmc32Arg, 0, TeeSmc32ArgLength);
193*abdd2437Shisping 
194*abdd2437Shisping 	TeeSmc32Arg->cmd = TEESMC_CMD_INVOKE_COMMAND;
195*abdd2437Shisping 	TeeSmc32Arg->ta_func = cmd_id;
196*abdd2437Shisping 	TeeSmc32Arg->session = session->id;
197*abdd2437Shisping 	TeeSmc32Arg->num_params = TEEC_CONFIG_PAYLOAD_REF_COUNT;
198*abdd2437Shisping 
199*abdd2437Shisping 	TeeSmc32Param = TEESMC32_GET_PARAMS(TeeSmc32Arg);
200*abdd2437Shisping 
201*abdd2437Shisping 	SetTeeSmc32Params(operation, TeeSmc32Param);
202*abdd2437Shisping 
203*abdd2437Shisping 	*error_origin = TEEC_ORIGIN_COMMS;
204*abdd2437Shisping 
205*abdd2437Shisping 	TeecResult = OpteeSmcCall(TeeSmc32Arg);
206*abdd2437Shisping 	if (TeecResult != TEEC_SUCCESS)
207*abdd2437Shisping 		goto Exit;
208*abdd2437Shisping 
209*abdd2437Shisping 	TeecResult = TeeSmc32Arg->ret;
210*abdd2437Shisping 	*error_origin = TeeSmc32Arg->ret_origin;
211*abdd2437Shisping 
212*abdd2437Shisping 	GetTeeSmc32Params(TeeSmc32Param, operation);
213*abdd2437Shisping 
214*abdd2437Shisping Exit:
215*abdd2437Shisping 	if (TeeSmc32Arg != NULL)
216*abdd2437Shisping 		OpteeClientMemFree(TeeSmc32Arg);
217*abdd2437Shisping 
218*abdd2437Shisping 
219*abdd2437Shisping 	return TeecResult;
220*abdd2437Shisping }
221*abdd2437Shisping 
222*abdd2437Shisping /*
223*abdd2437Shisping  * Request a cancellation of a in-progress operation (best effort)
224*abdd2437Shisping  *
225*abdd2437Shisping  * Note that the GP specification does not allow for this API to fail and return
226*abdd2437Shisping  * a failure code however we'll support this at the SMC level so we can get
227*abdd2437Shisping  * see debug information about such failures.
228*abdd2437Shisping  */
229*abdd2437Shisping TEEC_Result TEEC_SMC_RequestCancellation(TEEC_Operation *operation,
230*abdd2437Shisping 					uint32_t *error_origin)
231*abdd2437Shisping {
232*abdd2437Shisping 	return TEEC_ERROR_NOT_IMPLEMENTED;
233*abdd2437Shisping }
234*abdd2437Shisping 
235*abdd2437Shisping /*
236*abdd2437Shisping  * Set the call parameter blocks in the
237*abdd2437Shisping  * SMC call based on the TEEC parameter supplied.
238*abdd2437Shisping  * This only handles the parameters supplied in
239*abdd2437Shisping  * the originating call and not those
240*abdd2437Shisping  * considered internal meta parameters and is
241*abdd2437Shisping  * thus constrained by the build
242*abdd2437Shisping  * constants exposed to callers.
243*abdd2437Shisping  */
244*abdd2437Shisping void SetTeeSmc32Params(TEEC_Operation *operation,
245*abdd2437Shisping 						t_teesmc32_param *TeeSmc32Param)
246*abdd2437Shisping {
247*abdd2437Shisping 	uint32_t ParamCount;
248*abdd2437Shisping 
249*abdd2437Shisping 	for (ParamCount = 0;
250*abdd2437Shisping 		ParamCount < TEEC_CONFIG_PAYLOAD_REF_COUNT;
251*abdd2437Shisping 		ParamCount++) {
252*abdd2437Shisping 		uint32_t attr =
253*abdd2437Shisping 			TEEC_PARAM_TYPE_GET(operation->paramTypes, ParamCount);
254*abdd2437Shisping 
255*abdd2437Shisping 		if (attr == TEEC_MEMREF_TEMP_INPUT ||
256*abdd2437Shisping 			attr == TEEC_MEMREF_TEMP_OUTPUT ||
257*abdd2437Shisping 			attr == TEEC_MEMREF_TEMP_INOUT) {
258*abdd2437Shisping #ifdef CONFIG_ROCKCHIP_RK3328
259*abdd2437Shisping 			attr |= TEEC_SMC_DEFAULT_CACHE_ATTRIBUTES;
260*abdd2437Shisping 			debug(" 3328 attr %x\n", attr);
261*abdd2437Shisping #endif
262*abdd2437Shisping #ifdef CONFIG_ROCKCHIP_RK322X
263*abdd2437Shisping 			debug(" 322X attr %x\n", attr);
264*abdd2437Shisping #endif
265*abdd2437Shisping 			TeeSmc32Param[ParamCount].attr = attr;
266*abdd2437Shisping 			TeeSmc32Param[ParamCount].u.memref.buf_ptr =
267*abdd2437Shisping 			(uint32_t)operation->params[ParamCount].tmpref.buffer;
268*abdd2437Shisping 			TeeSmc32Param[ParamCount].u.memref.size =
269*abdd2437Shisping 				operation->params[ParamCount].tmpref.size;
270*abdd2437Shisping 		} else {
271*abdd2437Shisping 			TeeSmc32Param[ParamCount].attr = attr;
272*abdd2437Shisping 			TeeSmc32Param[ParamCount].u.value.a =
273*abdd2437Shisping 				operation->params[ParamCount].value.a;
274*abdd2437Shisping 			TeeSmc32Param[ParamCount].u.value.b =
275*abdd2437Shisping 				operation->params[ParamCount].value.b;
276*abdd2437Shisping 		}
277*abdd2437Shisping 	}
278*abdd2437Shisping }
279*abdd2437Shisping 
280*abdd2437Shisping /*
281*abdd2437Shisping  * Get the return parameter blocks from
282*abdd2437Shisping  * the SMC call into the TEEC parameter supplied.
283*abdd2437Shisping  * This only handles the parameters supplied
284*abdd2437Shisping  * in the originating call and not those
285*abdd2437Shisping  * considered internal meta parameters and
286*abdd2437Shisping  * is thus constrained by the build
287*abdd2437Shisping  * constants exposed to callers.
288*abdd2437Shisping  */
289*abdd2437Shisping void GetTeeSmc32Params(t_teesmc32_param *TeeSmc32Param,
290*abdd2437Shisping 				TEEC_Operation *operation)
291*abdd2437Shisping {
292*abdd2437Shisping 	uint32_t ParamCount;
293*abdd2437Shisping 
294*abdd2437Shisping 	for (ParamCount = 0;
295*abdd2437Shisping 	ParamCount < TEEC_CONFIG_PAYLOAD_REF_COUNT;
296*abdd2437Shisping 	ParamCount++) {
297*abdd2437Shisping 		operation->params[ParamCount].value.a =
298*abdd2437Shisping 			TeeSmc32Param[ParamCount].u.value.a;
299*abdd2437Shisping 		operation->params[ParamCount].value.b =
300*abdd2437Shisping 			TeeSmc32Param[ParamCount].u.value.b;
301*abdd2437Shisping 	}
302*abdd2437Shisping }
303*abdd2437Shisping 
304*abdd2437Shisping /*
305*abdd2437Shisping  * Populate the SMC registers and make
306*abdd2437Shisping  * the call with OpTEE specific handling.
307*abdd2437Shisping  */
308*abdd2437Shisping TEEC_Result OpteeSmcCall(t_teesmc32_arg *TeeSmc32Arg)
309*abdd2437Shisping {
310*abdd2437Shisping 	TEEC_Result TeecResult = TEEC_SUCCESS;
311*abdd2437Shisping 	ARM_SMC_ARGS ArmSmcArgs = {0};
312*abdd2437Shisping 
313*abdd2437Shisping 	ArmSmcArgs.Arg0 = TEESMC32_CALL_WITH_ARG;
314*abdd2437Shisping 	ArmSmcArgs.Arg1 = (uint32_t) TeeSmc32Arg;
315*abdd2437Shisping 
316*abdd2437Shisping 	while (1) {
317*abdd2437Shisping 		tee_smc_call(&ArmSmcArgs);
318*abdd2437Shisping 
319*abdd2437Shisping 		if (TEESMC_RETURN_IS_RPC(ArmSmcArgs.Arg0)) {
320*abdd2437Shisping 			(void) OpteeRpcCallback(&ArmSmcArgs);
321*abdd2437Shisping 		} else if (ArmSmcArgs.Arg0 == TEESMC_RETURN_UNKNOWN_FUNCTION) {
322*abdd2437Shisping 			TeecResult = TEEC_ERROR_NOT_IMPLEMENTED;
323*abdd2437Shisping 			break;
324*abdd2437Shisping 		} else if (ArmSmcArgs.Arg0 != TEESMC_RETURN_OK) {
325*abdd2437Shisping 			TeecResult = TEEC_ERROR_COMMUNICATION;
326*abdd2437Shisping 			break;
327*abdd2437Shisping 		} else {
328*abdd2437Shisping 			TeecResult = TEEC_SUCCESS;
329*abdd2437Shisping 			break;
330*abdd2437Shisping 		}
331*abdd2437Shisping 	}
332*abdd2437Shisping 
333*abdd2437Shisping 	return TeecResult;
334*abdd2437Shisping }
335*abdd2437Shisping 
336