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