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