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