2 * Copyright (c) 2015-2016, Linaro Limited
4 * Copyright (c) 2014, STMicroelectronics International N.V.
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions are met:
10 * 1. Redistributions of source code must retain the above copyright notice,
11 * this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright notice,
14 * this list of conditions and the following disclaimer in the documentation
15 * and/or other materials provided with the distribution.
17 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
18 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
21 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
25 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
26 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27 * POSSIBILITY OF SUCH DAMAGE.
33 #include <kernel/panic.h>
34 #include <kernel/tee_misc.h>
35 #include <mm/core_memprot.h>
36 #include <mm/core_mmu.h>
38 #include <optee_msg.h>
39 #include <sm/optee_smc.h>
41 #include <tee/entry_std.h>
42 #include <tee/tee_cryp_utl.h>
46 #define SHM_CACHE_ATTRS \
47 (uint32_t)(core_mmu_is_shm_cached() ? OPTEE_SMC_SHM_CACHED : 0)
49 /* Sessions opened from normal world */
50 static struct tee_ta_session_head tee_open_sessions =
51 TAILQ_HEAD_INITIALIZER(tee_open_sessions);
53 static struct mobj *shm_mobj;
55 static TEE_Result set_mem_param(const struct optee_msg_param *param,
56 struct param_mem *mem)
62 if (mobj_get_pa(shm_mobj, 0, 0, &b) != TEE_SUCCESS)
63 panic("Failed to be PA of shared memory MOBJ");
66 tsz = param->u.tmem.size;
67 if (param->u.tmem.buf_ptr && !tsz)
69 if (!core_is_buffer_inside(param->u.tmem.buf_ptr, tsz, b, sz))
70 return TEE_ERROR_BAD_PARAMETERS;
73 mem->offs = param->u.tmem.buf_ptr - b;
74 mem->size = param->u.tmem.size;
78 static TEE_Result copy_in_params(const struct optee_msg_param *params,
79 uint32_t num_params, struct tee_ta_param *ta_param)
83 uint8_t pt[TEE_NUM_PARAMS];
85 if (num_params > TEE_NUM_PARAMS)
86 return TEE_ERROR_BAD_PARAMETERS;
88 memset(ta_param, 0, sizeof(*ta_param));
90 for (n = 0; n < num_params; n++) {
93 if (params[n].attr & OPTEE_MSG_ATTR_META)
94 return TEE_ERROR_BAD_PARAMETERS;
95 if (params[n].attr & OPTEE_MSG_ATTR_FRAGMENT)
96 return TEE_ERROR_BAD_PARAMETERS;
98 attr = params[n].attr & OPTEE_MSG_ATTR_TYPE_MASK;
101 case OPTEE_MSG_ATTR_TYPE_NONE:
102 pt[n] = TEE_PARAM_TYPE_NONE;
103 memset(&ta_param->u[n], 0, sizeof(ta_param->u[n]));
105 case OPTEE_MSG_ATTR_TYPE_VALUE_INPUT:
106 case OPTEE_MSG_ATTR_TYPE_VALUE_OUTPUT:
107 case OPTEE_MSG_ATTR_TYPE_VALUE_INOUT:
108 pt[n] = TEE_PARAM_TYPE_VALUE_INPUT + attr -
109 OPTEE_MSG_ATTR_TYPE_VALUE_INPUT;
110 ta_param->u[n].val.a = params[n].u.value.a;
111 ta_param->u[n].val.b = params[n].u.value.b;
113 case OPTEE_MSG_ATTR_TYPE_TMEM_INPUT:
114 case OPTEE_MSG_ATTR_TYPE_TMEM_OUTPUT:
115 case OPTEE_MSG_ATTR_TYPE_TMEM_INOUT:
116 pt[n] = TEE_PARAM_TYPE_MEMREF_INPUT + attr -
117 OPTEE_MSG_ATTR_TYPE_TMEM_INPUT;
118 res = set_mem_param(params + n, &ta_param->u[n].mem);
119 if (res != TEE_SUCCESS)
123 return TEE_ERROR_BAD_PARAMETERS;
127 ta_param->types = TEE_PARAM_TYPES(pt[0], pt[1], pt[2], pt[3]);
132 static void copy_out_param(struct tee_ta_param *ta_param, uint32_t num_params,
133 struct optee_msg_param *params)
137 for (n = 0; n < num_params; n++) {
138 switch (TEE_PARAM_TYPE_GET(ta_param->types, n)) {
139 case TEE_PARAM_TYPE_MEMREF_OUTPUT:
140 case TEE_PARAM_TYPE_MEMREF_INOUT:
141 params[n].u.tmem.size = ta_param->u[n].mem.size;
143 case TEE_PARAM_TYPE_VALUE_OUTPUT:
144 case TEE_PARAM_TYPE_VALUE_INOUT:
145 params[n].u.value.a = ta_param->u[n].val.a;
146 params[n].u.value.b = ta_param->u[n].val.b;
155 * Extracts mandatory parameter for open session.
158 * false : mandatory parameter wasn't found or malformatted
159 * true : paramater found and OK
161 static TEE_Result get_open_session_meta(size_t num_params,
162 struct optee_msg_param *params,
163 size_t *num_meta, TEE_UUID *uuid,
164 TEE_Identity *clnt_id)
166 const uint32_t req_attr = OPTEE_MSG_ATTR_META |
167 OPTEE_MSG_ATTR_TYPE_VALUE_INPUT;
170 return TEE_ERROR_BAD_PARAMETERS;
172 if (params[0].attr != req_attr || params[1].attr != req_attr)
173 return TEE_ERROR_BAD_PARAMETERS;
175 tee_uuid_from_octets(uuid, (void *)¶ms[0].u.value);
176 clnt_id->login = params[1].u.value.c;
177 switch (clnt_id->login) {
178 case TEE_LOGIN_PUBLIC:
179 memset(&clnt_id->uuid, 0, sizeof(clnt_id->uuid));
182 case TEE_LOGIN_GROUP:
183 case TEE_LOGIN_APPLICATION:
184 case TEE_LOGIN_APPLICATION_USER:
185 case TEE_LOGIN_APPLICATION_GROUP:
186 tee_uuid_from_octets(&clnt_id->uuid,
187 (void *)¶ms[1].u.value);
190 return TEE_ERROR_BAD_PARAMETERS;
197 static void entry_open_session(struct thread_smc_args *smc_args,
198 struct optee_msg_arg *arg, uint32_t num_params)
201 struct optee_msg_param *params = OPTEE_MSG_GET_PARAMS(arg);
202 TEE_ErrorOrigin err_orig = TEE_ORIGIN_TEE;
203 struct tee_ta_session *s = NULL;
204 TEE_Identity clnt_id;
206 struct tee_ta_param param;
209 res = get_open_session_meta(num_params, params, &num_meta, &uuid,
211 if (res != TEE_SUCCESS)
214 res = copy_in_params(params + num_meta, num_params - num_meta, ¶m);
215 if (res != TEE_SUCCESS)
218 res = tee_ta_open_session(&err_orig, &s, &tee_open_sessions, &uuid,
219 &clnt_id, TEE_TIMEOUT_INFINITE, ¶m);
220 if (res != TEE_SUCCESS)
222 copy_out_param(¶m, num_params - num_meta, params + num_meta);
225 * The occurrence of open/close session command is usually
226 * un-predictable, using this property to increase randomness
229 plat_prng_add_jitter_entropy();
233 arg->session = (vaddr_t)s;
237 arg->ret_origin = err_orig;
238 smc_args->a0 = OPTEE_SMC_RETURN_OK;
241 static void entry_close_session(struct thread_smc_args *smc_args,
242 struct optee_msg_arg *arg, uint32_t num_params)
245 struct tee_ta_session *s;
248 res = TEE_ERROR_BAD_PARAMETERS;
252 plat_prng_add_jitter_entropy();
254 s = (struct tee_ta_session *)(vaddr_t)arg->session;
255 res = tee_ta_close_session(s, &tee_open_sessions, NSAPP_IDENTITY);
258 arg->ret_origin = TEE_ORIGIN_TEE;
259 smc_args->a0 = OPTEE_SMC_RETURN_OK;
262 static void entry_invoke_command(struct thread_smc_args *smc_args,
263 struct optee_msg_arg *arg, uint32_t num_params)
266 struct optee_msg_param *params = OPTEE_MSG_GET_PARAMS(arg);
267 TEE_ErrorOrigin err_orig = TEE_ORIGIN_TEE;
268 struct tee_ta_session *s;
269 struct tee_ta_param param;
271 res = copy_in_params(params, num_params, ¶m);
272 if (res != TEE_SUCCESS)
275 s = tee_ta_get_session(arg->session, true, &tee_open_sessions);
277 res = TEE_ERROR_BAD_PARAMETERS;
281 res = tee_ta_invoke_command(&err_orig, s, NSAPP_IDENTITY,
282 TEE_TIMEOUT_INFINITE, arg->func, ¶m);
284 tee_ta_put_session(s);
286 copy_out_param(¶m, num_params, params);
290 arg->ret_origin = err_orig;
291 smc_args->a0 = OPTEE_SMC_RETURN_OK;
294 static void entry_cancel(struct thread_smc_args *smc_args,
295 struct optee_msg_arg *arg, uint32_t num_params)
298 TEE_ErrorOrigin err_orig = TEE_ORIGIN_TEE;
299 struct tee_ta_session *s;
302 res = TEE_ERROR_BAD_PARAMETERS;
306 s = tee_ta_get_session(arg->session, false, &tee_open_sessions);
308 res = TEE_ERROR_BAD_PARAMETERS;
312 res = tee_ta_cancel_command(&err_orig, s, NSAPP_IDENTITY);
313 tee_ta_put_session(s);
317 arg->ret_origin = err_orig;
318 smc_args->a0 = OPTEE_SMC_RETURN_OK;
321 void tee_entry_std(struct thread_smc_args *smc_args)
324 struct optee_msg_arg *arg = NULL; /* fix gcc warning */
327 if (smc_args->a0 != OPTEE_SMC_CALL_WITH_ARG) {
328 EMSG("Unknown SMC 0x%" PRIx64, (uint64_t)smc_args->a0);
329 DMSG("Expected 0x%x\n", OPTEE_SMC_CALL_WITH_ARG);
330 smc_args->a0 = OPTEE_SMC_RETURN_EBADCMD;
333 parg = (uint64_t)smc_args->a1 << 32 | smc_args->a2;
334 if (!tee_pbuf_is_non_sec(parg, sizeof(struct optee_msg_arg)) ||
335 !ALIGNMENT_IS_OK(parg, struct optee_msg_arg) ||
336 !(arg = phys_to_virt(parg, MEM_AREA_NSEC_SHM))) {
337 EMSG("Bad arg address 0x%" PRIxPA, parg);
338 smc_args->a0 = OPTEE_SMC_RETURN_EBADADDR;
342 num_params = arg->num_params;
343 if (!tee_pbuf_is_non_sec(parg, OPTEE_MSG_GET_ARG_SIZE(num_params))) {
344 EMSG("Bad arg address 0x%" PRIxPA, parg);
345 smc_args->a0 = OPTEE_SMC_RETURN_EBADADDR;
349 thread_set_irq(true); /* Enable IRQ for STD calls */
351 case OPTEE_MSG_CMD_OPEN_SESSION:
352 entry_open_session(smc_args, arg, num_params);
354 case OPTEE_MSG_CMD_CLOSE_SESSION:
355 entry_close_session(smc_args, arg, num_params);
357 case OPTEE_MSG_CMD_INVOKE_COMMAND:
358 entry_invoke_command(smc_args, arg, num_params);
360 case OPTEE_MSG_CMD_CANCEL:
361 entry_cancel(smc_args, arg, num_params);
364 EMSG("Unknown cmd 0x%x\n", arg->cmd);
365 smc_args->a0 = OPTEE_SMC_RETURN_EBADCMD;
369 static TEE_Result default_mobj_init(void)
371 shm_mobj = mobj_phys_alloc(default_nsec_shm_paddr,
372 default_nsec_shm_size, SHM_CACHE_ATTRS,
375 panic("Failed to register shared memory");
377 mobj_sec_ddr = mobj_phys_alloc(tee_mm_sec_ddr.lo,
378 tee_mm_sec_ddr.hi - tee_mm_sec_ddr.lo,
379 SHM_CACHE_ATTRS, CORE_MEM_TA_RAM);
381 panic("Failed to register secure ta ram");
386 driver_init_late(default_mobj_init);