1 /*
2 * Copyright (c) 2023 EPAM Systems
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7 /**
8 * @addtogroup t_optee_driver
9 * @{
10 * @defgroup t_optee_driver test_optee_driver
11 * @}
12 */
13
14 #include <zephyr/arch/arm64/arm-smccc.h>
15 #include <zephyr/kernel.h>
16 #include <zephyr/ztest.h>
17 #include <zephyr/device.h>
18
19 #include <zephyr/drivers/tee.h>
20 #include <optee_msg.h>
21 #include <optee_smc.h>
22 #include <optee_rpc_cmd.h>
23
24 /*
25 * TODO: Test shm_register/shm_register API to work with huge
26 * buffers (more than 512K) to ensure that optee_construct_page_list
27 * builds correct page list.
28 */
29
30 #define TEE_OPTEE_CAP_TZ BIT(0)
31
32 typedef void (*smc_cb_t)(unsigned long a0, unsigned long a1, unsigned long a2, unsigned long a3,
33 unsigned long a4, unsigned long a5, unsigned long a6, unsigned long a7,
34 struct arm_smccc_res *res);
35
36 static struct test_call {
37 int num;
38 int pending;
39 smc_cb_t smc_cb;
40 uint32_t a0;
41 uint32_t a1;
42 uint32_t a2;
43 uint32_t a3;
44 uint32_t a4;
45 uint32_t a5;
46 uint32_t a6;
47 uint32_t a7;
48 k_tid_t th_id;
49 } t_call;
50
51 static struct test_call wait_call;
52 static struct test_call send_call;
53
arm_smccc_smc(unsigned long a0,unsigned long a1,unsigned long a2,unsigned long a3,unsigned long a4,unsigned long a5,unsigned long a6,unsigned long a7,struct arm_smccc_res * res)54 void arm_smccc_smc(unsigned long a0, unsigned long a1, unsigned long a2, unsigned long a3,
55 unsigned long a4, unsigned long a5, unsigned long a6, unsigned long a7,
56 struct arm_smccc_res *res)
57 {
58 if (a0 == OPTEE_SMC_CALLS_UID) {
59 res->a0 = OPTEE_MSG_UID_0;
60 res->a1 = OPTEE_MSG_UID_1;
61 res->a2 = OPTEE_MSG_UID_2;
62 res->a3 = OPTEE_MSG_UID_3;
63 return;
64 }
65
66 if (a0 == OPTEE_SMC_EXCHANGE_CAPABILITIES) {
67 res->a1 = OPTEE_SMC_SEC_CAP_DYNAMIC_SHM;
68 return;
69 }
70 if (a0 == OPTEE_SMC_GET_THREAD_COUNT) {
71 res->a1 = 5;
72 return;
73 }
74 if (t_call.pending && t_call.smc_cb) {
75 t_call.smc_cb(a0, a1, a2, a3, a4, a5, a6, a7, res);
76 }
77 if (wait_call.pending && wait_call.smc_cb && (k_current_get() == wait_call.th_id)) {
78 wait_call.smc_cb(a0, a1, a2, a3, a4, a5, a6, a7, res);
79 }
80 if (send_call.pending && send_call.smc_cb) {
81 send_call.smc_cb(a0, a1, a2, a3, a4, a5, a6, a7, res);
82 }
83 }
84
85 /* Allocate dummy arm_smccc_hvc function for the tests */
arm_smccc_hvc(unsigned long a0,unsigned long a1,unsigned long a2,unsigned long a3,unsigned long a4,unsigned long a5,unsigned long a6,unsigned long a7,struct arm_smccc_res * res)86 void arm_smccc_hvc(unsigned long a0, unsigned long a1, unsigned long a2, unsigned long a3,
87 unsigned long a4, unsigned long a5, unsigned long a6, unsigned long a7,
88 struct arm_smccc_res *res)
89 {
90 }
91
ZTEST(optee_test_suite,test_get_version)92 ZTEST(optee_test_suite, test_get_version)
93 {
94 int ret;
95 struct tee_version_info info;
96 const struct device *const dev = DEVICE_DT_GET_ONE(linaro_optee_tz);
97
98 zassert_not_null(dev, "Unable to get dev");
99
100 ret = tee_get_version(dev, NULL);
101 zassert_equal(ret, -EINVAL, "tee_get_version failed with code %d", ret);
102
103 ret = tee_get_version(dev, &info);
104 zassert_ok(ret, "tee_get_version failed with code %d", ret);
105 zassert_equal(info.impl_id, 1, "Wrong impl_id");
106 zassert_equal(info.impl_caps, TEE_OPTEE_CAP_TZ, "Wrong impl_caps");
107 zassert_equal(info.gen_caps, TEE_GEN_CAP_GP | TEE_GEN_CAP_REG_MEM,
108 "Wrong gen_caps");
109
110 ret = tee_get_version(dev, NULL);
111 zassert_equal(ret, -EINVAL, "tee_get_version failed with code %d", ret);
112 }
113
fast_call(unsigned long a0,unsigned long a1,unsigned long a2,unsigned long a3,unsigned long a4,unsigned long a5,unsigned long a6,unsigned long a7,struct arm_smccc_res * res)114 void fast_call(unsigned long a0, unsigned long a1, unsigned long a2, unsigned long a3,
115 unsigned long a4, unsigned long a5, unsigned long a6, unsigned long a7,
116 struct arm_smccc_res *res)
117 {
118 t_call.a0 = a0;
119 t_call.a1 = a1;
120 t_call.a2 = a2;
121 t_call.a3 = a3;
122 t_call.a4 = a4;
123 t_call.a5 = a5;
124 t_call.a6 = a6;
125 t_call.a7 = a7;
126
127 res->a0 = OPTEE_SMC_RETURN_OK;
128 }
129
fail_call(unsigned long a0,unsigned long a1,unsigned long a2,unsigned long a3,unsigned long a4,unsigned long a5,unsigned long a6,unsigned long a7,struct arm_smccc_res * res)130 void fail_call(unsigned long a0, unsigned long a1, unsigned long a2, unsigned long a3,
131 unsigned long a4, unsigned long a5, unsigned long a6, unsigned long a7,
132 struct arm_smccc_res *res)
133 {
134 res->a0 = OPTEE_SMC_RETURN_EBUSY;
135 }
136
ZTEST(optee_test_suite,test_fast_calls)137 ZTEST(optee_test_suite, test_fast_calls)
138 {
139 int ret;
140 uint32_t session_id;
141 struct tee_open_session_arg arg = {};
142 struct tee_param param = {};
143 const struct device *const dev = DEVICE_DT_GET_ONE(linaro_optee_tz);
144
145 zassert_not_null(dev, "Unable to get dev");
146
147 t_call.pending = 1;
148 t_call.num = 0;
149 t_call.smc_cb = fast_call;
150
151 /* Fail pass */
152 ret = tee_open_session(dev, NULL, 0, NULL, &session_id);
153 zassert_equal(ret, -EINVAL, "tee_open_session failed with code %d", ret);
154
155 ret = tee_open_session(dev, NULL, 0, NULL, NULL);
156 zassert_equal(ret, -EINVAL, "tee_open_session failed with code %d", ret);
157
158 /* Happy pass */
159 arg.uuid[0] = 111;
160 arg.clnt_uuid[0] = 222;
161 arg.clnt_login = TEEC_LOGIN_PUBLIC;
162 param.attr = TEE_PARAM_ATTR_TYPE_NONE;
163 param.a = 3333;
164 ret = tee_open_session(dev, &arg, 1, ¶m, &session_id);
165 zassert_ok(ret, "tee_open_session failed with code %d", ret);
166
167 ret = tee_close_session(dev, session_id);
168 zassert_ok(ret, "close_session failed with code %d", ret);
169 t_call.pending = 0;
170 }
171
ZTEST(optee_test_suite,test_invoke_fn)172 ZTEST(optee_test_suite, test_invoke_fn)
173 {
174 int ret;
175 uint32_t session_id;
176 struct tee_open_session_arg arg = {};
177 struct tee_invoke_func_arg invoke_arg = {};
178 struct tee_param param = {};
179 const struct device *const dev = DEVICE_DT_GET_ONE(linaro_optee_tz);
180
181 zassert_not_null(dev, "Unable to get dev");
182
183 t_call.pending = 1;
184 t_call.num = 0;
185 t_call.smc_cb = fast_call;
186
187 /* Fail pass */
188 ret = tee_invoke_func(dev, NULL, 0, NULL);
189 zassert_equal(ret, -EINVAL, "tee_invoke_fn failed with code %d", ret);
190
191 t_call.smc_cb = fail_call;
192
193 invoke_arg.func = 12;
194 invoke_arg.session = 1;
195 ret = tee_invoke_func(dev, &invoke_arg, 0, NULL);
196 zassert_equal(ret, -EINVAL, "tee_invoke_fn failed with code %d", ret);
197
198 t_call.smc_cb = fast_call;
199
200 /* Happy pass */
201 arg.uuid[0] = 111;
202 arg.clnt_uuid[0] = 222;
203 arg.clnt_login = TEEC_LOGIN_PUBLIC;
204 param.attr = TEE_PARAM_ATTR_TYPE_NONE;
205 param.a = 3333;
206 ret = tee_open_session(dev, &arg, 1, ¶m, &session_id);
207 zassert_ok(ret, "tee_open_session failed with code %d", ret);
208
209 invoke_arg.func = 12;
210 invoke_arg.session = 1;
211 ret = tee_invoke_func(dev, &invoke_arg, 1, ¶m);
212 zassert_ok(ret, "tee_invoke_fn failed with code %d", ret);
213
214 ret = tee_close_session(dev, session_id);
215 zassert_ok(ret, "close_session failed with code %d", ret);
216 t_call.pending = 0;
217 }
218
ZTEST(optee_test_suite,test_cancel)219 ZTEST(optee_test_suite, test_cancel)
220 {
221 int ret;
222 uint32_t session_id;
223 struct tee_open_session_arg arg = {};
224 struct tee_param param = {};
225 const struct device *const dev = DEVICE_DT_GET_ONE(linaro_optee_tz);
226
227 zassert_not_null(dev, "Unable to get dev");
228
229 t_call.pending = 1;
230 t_call.num = 0;
231 t_call.smc_cb = fast_call;
232
233 arg.uuid[0] = 111;
234 arg.clnt_uuid[0] = 222;
235 arg.clnt_login = TEEC_LOGIN_PUBLIC;
236 param.attr = TEE_PARAM_ATTR_TYPE_NONE;
237 param.a = 3333;
238 ret = tee_open_session(dev, &arg, 1, ¶m, &session_id);
239 zassert_ok(ret, "tee_open_session failed with code %d", ret);
240
241 ret = tee_cancel(dev, 1, 25);
242 zassert_ok(ret, "tee_cancel failed with code %d", ret);
243
244 ret = tee_close_session(dev, session_id);
245 zassert_ok(ret, "close_session failed with code %d", ret);
246 t_call.pending = 0;
247 }
248
normal_call(unsigned long a0,unsigned long a1,unsigned long a2,unsigned long a3,unsigned long a4,unsigned long a5,unsigned long a6,unsigned long a7,struct arm_smccc_res * res)249 void normal_call(unsigned long a0, unsigned long a1, unsigned long a2, unsigned long a3,
250 unsigned long a4, unsigned long a5, unsigned long a6, unsigned long a7,
251 struct arm_smccc_res *res)
252 {
253 t_call.a0 = a0;
254 t_call.a1 = a1;
255 t_call.a2 = a2;
256 t_call.a3 = a3;
257 t_call.a4 = a4;
258 t_call.a5 = a5;
259 t_call.a6 = a6;
260 t_call.a7 = a7;
261
262 switch (t_call.num) {
263 case 0:
264 res->a0 = OPTEE_SMC_RETURN_RPC_PREFIX | OPTEE_SMC_RPC_FUNC_ALLOC;
265 res->a1 = a4;
266 res->a2 = a5;
267 res->a3 = a3;
268 res->a4 = 0;
269 res->a5 = 0;
270 break;
271 case 1:
272 zassert_equal(a0, 0x32000003, "%s failed with ret %lx", __func__, a0);
273 res->a0 = OPTEE_SMC_RETURN_RPC_PREFIX | OPTEE_SMC_RPC_FUNC_FREE;
274 res->a1 = a1;
275 res->a2 = a2;
276 res->a3 = a3;
277 res->a4 = a4;
278 res->a5 = a5;
279 break;
280 case 2:
281 zassert_equal(a0, 0x32000003, "%s failed with ret %lx", __func__, a0);
282 res->a0 = OPTEE_SMC_RETURN_RPC_PREFIX | OPTEE_SMC_RPC_FUNC_FOREIGN_INTR;
283 break;
284 default:
285 zassert_equal(a0, 0x32000003, "%s failed with ret %lx", __func__, a0);
286 res->a0 = OPTEE_SMC_RETURN_OK;
287 }
288
289 t_call.num++;
290 }
291
ZTEST(optee_test_suite,test_normal_calls)292 ZTEST(optee_test_suite, test_normal_calls)
293 {
294 int ret;
295 uint32_t session_id;
296 struct tee_open_session_arg arg = {};
297 struct tee_param param = {};
298 const struct device *const dev = DEVICE_DT_GET_ONE(linaro_optee_tz);
299
300 zassert_not_null(dev, "Unable to get dev");
301
302 t_call.pending = 1;
303 t_call.num = 0;
304 t_call.smc_cb = normal_call;
305
306 arg.uuid[0] = 111;
307 arg.clnt_uuid[0] = 222;
308 arg.clnt_login = TEEC_LOGIN_PUBLIC;
309 param.attr = TEE_PARAM_ATTR_TYPE_NONE;
310 param.a = 3333;
311 ret = tee_open_session(dev, &arg, 1, ¶m, &session_id);
312 zassert_ok(ret, "tee_open_session failed with code %d", ret);
313
314 t_call.num = 0;
315
316 ret = tee_close_session(dev, session_id);
317 zassert_ok(ret, "close_session failed with code %d", ret);
318 t_call.pending = 0;
319 }
320
ZTEST(optee_test_suite,test_reg_unreg)321 ZTEST(optee_test_suite, test_reg_unreg)
322 {
323 int ret;
324 int addr;
325 struct tee_shm *shm = NULL;
326 const struct device *const dev = DEVICE_DT_GET_ONE(linaro_optee_tz);
327
328 t_call.pending = 1;
329 t_call.num = 0;
330 t_call.smc_cb = normal_call;
331 zassert_not_null(dev, "Unable to get dev");
332
333 /* Fail pass */
334 ret = tee_shm_register(dev, &addr, 1, 0, NULL);
335 zassert_equal(ret, -EINVAL, "tee_shm_register failed with code %d", ret);
336 t_call.num = 0;
337
338 ret = tee_shm_register(dev, NULL, 1, 0, &shm);
339 zassert_equal(ret, -ENOMEM, "tee_shm_register failed with code %d", ret);
340
341 t_call.num = 0;
342 ret = tee_shm_register(dev, &addr, 1, 0, NULL);
343 zassert_equal(ret, -EINVAL, "tee_shm_register failed with code %d", ret);
344
345 t_call.num = 0;
346 ret = tee_shm_register(dev, &addr, 0, 0, &shm);
347 zassert_equal(ret, 0, "tee_shm_register failed with code %d", ret);
348
349 t_call.num = 0;
350 ret = tee_shm_unregister(dev, NULL);
351 zassert_equal(ret, -EINVAL, "tee_shm_unregister failed with code %d", ret);
352
353 /* Happy pass */
354 t_call.num = 0;
355 ret = tee_shm_register(dev, &addr, 1, 0, &shm);
356 zassert_ok(ret, "tee_shm_register failed with code %d", ret);
357
358 t_call.num = 0;
359 ret = tee_shm_unregister(dev, shm);
360 zassert_ok(ret, "tee_shm_unregister failed with code %d", ret);
361
362 t_call.num = 0;
363 ret = tee_shm_alloc(dev, 1, 0, &shm);
364 zassert_ok(ret, "tee_shm_alloc failed with code %d", ret);
365
366 t_call.num = 0;
367 ret = tee_shm_free(dev, shm);
368 zassert_ok(ret, "tee_shm_free failed with code %d", ret);
369 t_call.pending = 0;
370 }
371
regs_to_u64(uint32_t reg0,uint32_t reg1)372 static uint64_t regs_to_u64(uint32_t reg0, uint32_t reg1)
373 {
374 return (uint64_t)(((uint64_t)reg0 << 32) | reg1);
375 }
376
u64_to_regs(uint64_t val,unsigned long * reg0,unsigned long * reg1)377 static void u64_to_regs(uint64_t val, unsigned long *reg0, unsigned long *reg1)
378 {
379 *reg0 = val >> 32;
380 *reg1 = val;
381 }
382
383 uint64_t g_shm_ref;
384 uint64_t g_func_shm_ref;
385
cmd_alloc_free_call(unsigned long a0,unsigned long a1,unsigned long a2,unsigned long a3,unsigned long a4,unsigned long a5,unsigned long a6,unsigned long a7,struct arm_smccc_res * res)386 void cmd_alloc_free_call(unsigned long a0, unsigned long a1, unsigned long a2, unsigned long a3,
387 unsigned long a4, unsigned long a5, unsigned long a6, unsigned long a7,
388 struct arm_smccc_res *res)
389 {
390 struct optee_msg_arg *arg;
391 struct tee_shm *shm;
392
393 t_call.a0 = a0;
394 t_call.a1 = a1;
395 t_call.a2 = a2;
396 t_call.a3 = a3;
397 t_call.a4 = a4;
398 t_call.a5 = a5;
399 t_call.a6 = a6;
400 t_call.a7 = a7;
401
402 res->a1 = a1;
403 res->a2 = a2;
404 res->a3 = a3;
405 res->a4 = a4;
406 res->a5 = a5;
407
408 switch (t_call.num) {
409 case 0:
410 res->a0 = OPTEE_SMC_RETURN_RPC_PREFIX | OPTEE_SMC_RPC_FUNC_ALLOC;
411 res->a1 = 1;
412 break;
413 case 1:
414 zassert_equal(a0, 0x32000003, "%s failed with ret %lx", __func__, a0);
415 res->a0 = OPTEE_SMC_RETURN_RPC_PREFIX | OPTEE_SMC_RPC_FUNC_CMD;
416 arg = (struct optee_msg_arg *)regs_to_u64(a1, a2);
417 arg->cmd = OPTEE_RPC_CMD_SHM_ALLOC;
418 arg->num_params = 1;
419 arg->params[0].attr = OPTEE_MSG_ATTR_TYPE_VALUE_INPUT;
420 arg->params[0].u.value.b = 4096;
421 arg->params[0].u.value.a = OPTEE_RPC_SHM_TYPE_KERNEL;
422 res->a1 = a4;
423 res->a2 = a5;
424 g_shm_ref = regs_to_u64(a4, a5);
425 break;
426 case 2:
427 zassert_equal(a0, 0x32000003, "%s failed with ret %lx", __func__, a0);
428 res->a0 = OPTEE_SMC_RETURN_RPC_PREFIX | OPTEE_SMC_RPC_FUNC_CMD;
429 printk("a1 %lx, a2 %lx a4 %lx a5 %lx\n", a1, a2);
430 shm = (struct tee_shm *)regs_to_u64(a1, a2);
431 arg = (struct optee_msg_arg *)shm->addr;
432 arg->cmd = OPTEE_RPC_CMD_SHM_FREE;
433 arg->num_params = 1;
434 arg->params[0].attr = OPTEE_MSG_ATTR_TYPE_VALUE_INPUT;
435 arg->params[0].u.value.a = OPTEE_RPC_SHM_TYPE_KERNEL;
436 arg->params[0].u.value.b = g_func_shm_ref;
437 u64_to_regs(g_shm_ref, &res->a1, &res->a2);
438 break;
439 case 3:
440 zassert_equal(a0, 0x32000003, "%s failed with ret %lx", __func__, a0);
441 u64_to_regs(g_shm_ref, &res->a1, &res->a2);
442 res->a0 = OPTEE_SMC_RETURN_RPC_PREFIX | OPTEE_SMC_RPC_FUNC_FREE;
443 break;
444 case 4:
445 zassert_equal(a0, 0x32000003, "%s failed with ret %lx", __func__, a0);
446 res->a0 = OPTEE_SMC_RETURN_OK;
447 break;
448 default:
449 zassert_equal(a0, 0x32000003, "%s failed with ret %lx", __func__, a0);
450 res->a0 = OPTEE_SMC_RETURN_OK;
451 }
452
453 t_call.num++;
454 }
455
ZTEST(optee_test_suite,test_func_shm_alloc)456 ZTEST(optee_test_suite, test_func_shm_alloc)
457 {
458 int ret;
459 uint32_t session_id;
460 struct tee_open_session_arg arg = {};
461 struct tee_invoke_func_arg invoke_arg = {};
462 struct tee_param param = {};
463 const struct device *const dev = DEVICE_DT_GET_ONE(linaro_optee_tz);
464
465 zassert_not_null(dev, "Unable to get dev");
466
467 t_call.pending = 1;
468 t_call.num = 0;
469 t_call.smc_cb = fast_call;
470
471 arg.uuid[0] = 111;
472 arg.clnt_uuid[0] = 222;
473 arg.clnt_login = TEEC_LOGIN_PUBLIC;
474 param.attr = TEE_PARAM_ATTR_TYPE_NONE;
475 param.a = 3333;
476 ret = tee_open_session(dev, &arg, 1, ¶m, &session_id);
477 zassert_ok(ret, "tee_open_session failed with code %d", ret);
478
479 t_call.num = 0;
480 t_call.smc_cb = cmd_alloc_free_call;
481
482 invoke_arg.func = 12;
483 invoke_arg.session = 1;
484 ret = tee_invoke_func(dev, &invoke_arg, 1, ¶m);
485 zassert_ok(ret, "tee_invoke_fn failed with code %d", ret);
486
487 t_call.num = 0;
488 t_call.smc_cb = fast_call;
489
490 ret = tee_close_session(dev, session_id);
491 zassert_ok(ret, "close_session failed with code %d", ret);
492
493 t_call.pending = 0;
494 }
495
496 K_KERNEL_STACK_DEFINE(supp_stack, 8192);
497 #define TEE_NUM_PARAMS 5
498 static struct k_thread supp_thread_data;
499 volatile int supp_thread_ok;
500
cmd_rpc_call(unsigned long a0,unsigned long a1,unsigned long a2,unsigned long a3,unsigned long a4,unsigned long a5,unsigned long a6,unsigned long a7,struct arm_smccc_res * res)501 void cmd_rpc_call(unsigned long a0, unsigned long a1, unsigned long a2, unsigned long a3,
502 unsigned long a4, unsigned long a5, unsigned long a6, unsigned long a7,
503 struct arm_smccc_res *res)
504 {
505 struct optee_msg_arg *arg;
506 struct tee_shm *shm;
507
508 t_call.a0 = a0;
509 t_call.a1 = a1;
510 t_call.a2 = a2;
511 t_call.a3 = a3;
512 t_call.a4 = a4;
513 t_call.a5 = a5;
514 t_call.a6 = a6;
515 t_call.a7 = a7;
516
517 res->a1 = a1;
518 res->a2 = a2;
519 res->a3 = a3;
520 res->a4 = a4;
521 res->a5 = a5;
522
523 switch (t_call.num) {
524 case 0:
525 res->a0 = OPTEE_SMC_RETURN_RPC_PREFIX | OPTEE_SMC_RPC_FUNC_ALLOC;
526 res->a1 = 1;
527 break;
528 case 1:
529 zassert_equal(a0, 0x32000003, "%s failed with ret %lx", __func__, a0);
530 res->a0 = OPTEE_SMC_RETURN_RPC_PREFIX | OPTEE_SMC_RPC_FUNC_CMD;
531 arg = (struct optee_msg_arg *)regs_to_u64(a1, a2);
532 /* Fall back to supplicant branch */
533 arg->cmd = 555;
534 arg->num_params = 2;
535 arg->params[0].attr = OPTEE_MSG_ATTR_TYPE_VALUE_INPUT;
536 arg->params[0].u.value.a = 1111;
537 arg->params[0].u.value.b = 3;
538 arg->params[1].attr = OPTEE_MSG_ATTR_TYPE_VALUE_OUTPUT;
539 res->a1 = a4;
540 res->a2 = a5;
541 break;
542 case 2:
543 zassert_equal(a0, 0x32000003, "%s failed with ret %lx", __func__, a0);
544 shm = (struct tee_shm *)regs_to_u64(a1, a2);
545 arg = (struct optee_msg_arg *)shm->addr;
546 zassert_equal(arg->params[1].attr, OPTEE_MSG_ATTR_TYPE_VALUE_OUTPUT,
547 "%s failed wrong attr %lx", __func__, arg->params[0].attr);
548 zassert_equal(arg->params[1].u.value.a, 0x1234, "%s failed wrong a %lx",
549 __func__, arg->params[0].u.value.a);
550 zassert_equal(arg->params[1].u.value.b, 0x5678, "%s failed wrong b %lx",
551 __func__, arg->params[0].u.value.b);
552 res->a0 = OPTEE_SMC_RETURN_OK;
553 break;
554 default:
555 zassert_equal(a0, 0x32000003, "%s failed with ret %lx", __func__, a0);
556 res->a0 = OPTEE_SMC_RETURN_OK;
557 }
558
559 t_call.num++;
560 }
561
supp_thread_comm(void)562 static void supp_thread_comm(void)
563 {
564 const struct device *const dev = DEVICE_DT_GET_ONE(linaro_optee_tz);
565 struct tee_param params[TEE_NUM_PARAMS];
566 unsigned int num_params = TEE_NUM_PARAMS;
567 uint32_t func;
568 int ret;
569
570 supp_thread_ok = true;
571
572 ret = tee_suppl_recv(dev, &func, &num_params, params);
573
574 if (ret != 0) {
575 printk("tee_suppl_recv failed with %d\n", ret);
576 supp_thread_ok = false;
577 }
578
579 if (func != 555 || num_params != 2) {
580 printk("Unexpected func & num_params %d %d\n", func, num_params);
581 supp_thread_ok = false;
582 }
583
584 if (params[0].attr != OPTEE_MSG_ATTR_TYPE_VALUE_INPUT ||
585 params[1].attr != OPTEE_MSG_ATTR_TYPE_VALUE_OUTPUT ||
586 params[0].a != 1111 ||
587 params[0].b != 3) {
588 printk("Unexpected params %d %d %d\n", params[0].attr,
589 params[0].a, params[0].b);
590 supp_thread_ok = false;
591 }
592
593 params[1].a = 0x1234;
594 params[1].b = 0x5678;
595 tee_suppl_send(dev, 0, 2, params);
596 }
597
ZTEST(optee_test_suite,test_func_rpc_supp_cmd)598 ZTEST(optee_test_suite, test_func_rpc_supp_cmd)
599 {
600 int ret;
601 uint32_t session_id;
602 struct tee_open_session_arg arg = {};
603 struct tee_invoke_func_arg invoke_arg = {};
604 struct tee_param param = {};
605 const struct device *const dev = DEVICE_DT_GET_ONE(linaro_optee_tz);
606 k_tid_t tid;
607
608 tid = k_thread_create(&supp_thread_data, supp_stack,
609 K_KERNEL_STACK_SIZEOF(supp_stack),
610 (k_thread_entry_t)supp_thread_comm, NULL, NULL, NULL,
611 K_PRIO_PREEMPT(CONFIG_NUM_PREEMPT_PRIORITIES - 1), 0, K_NO_WAIT);
612 zassert_not_null(dev, "Unable to get dev");
613
614 t_call.pending = 1;
615 t_call.num = 0;
616 t_call.smc_cb = fast_call;
617
618 arg.uuid[0] = 111;
619 arg.clnt_uuid[0] = 222;
620 arg.clnt_login = TEEC_LOGIN_PUBLIC;
621 param.attr = TEE_PARAM_ATTR_TYPE_NONE;
622 param.a = 3333;
623 ret = tee_open_session(dev, &arg, 1, ¶m, &session_id);
624 zassert_ok(ret, "tee_open_session failed with code %d", ret);
625
626 t_call.num = 0;
627 t_call.smc_cb = cmd_rpc_call;
628
629 invoke_arg.func = 12;
630 invoke_arg.session = 1;
631 ret = tee_invoke_func(dev, &invoke_arg, 1, ¶m);
632 zassert_ok(ret, "tee_invoke_fn failed with code %d", ret);
633
634 t_call.num = 0;
635 t_call.smc_cb = fast_call;
636
637 ret = tee_close_session(dev, session_id);
638 zassert_ok(ret, "close_session failed with code %d", ret);
639 zassert_true(supp_thread_ok, "supp_thread_comm failed");
640 t_call.pending = 0;
641 k_thread_abort(tid);
642 }
643
cmd_shm_alloc_appl(unsigned long a0,unsigned long a1,unsigned long a2,unsigned long a3,unsigned long a4,unsigned long a5,unsigned long a6,unsigned long a7,struct arm_smccc_res * res)644 void cmd_shm_alloc_appl(unsigned long a0, unsigned long a1, unsigned long a2, unsigned long a3,
645 unsigned long a4, unsigned long a5, unsigned long a6, unsigned long a7,
646 struct arm_smccc_res *res)
647 {
648 struct optee_msg_arg *arg;
649 struct tee_shm *shm;
650
651 t_call.a0 = a0;
652 t_call.a1 = a1;
653 t_call.a2 = a2;
654 t_call.a3 = a3;
655 t_call.a4 = a4;
656 t_call.a5 = a5;
657 t_call.a6 = a6;
658 t_call.a7 = a7;
659
660 res->a1 = a1;
661 res->a2 = a2;
662 res->a3 = a3;
663 res->a4 = a4;
664 res->a5 = a5;
665
666 switch (t_call.num) {
667 case 0:
668 res->a0 = OPTEE_SMC_RETURN_RPC_PREFIX | OPTEE_SMC_RPC_FUNC_ALLOC;
669 res->a1 = 1;
670 break;
671 case 1:
672 zassert_equal(a0, 0x32000003, "%s failed with ret %lx", __func__, a0);
673 res->a0 = OPTEE_SMC_RETURN_RPC_PREFIX | OPTEE_SMC_RPC_FUNC_CMD;
674 arg = (struct optee_msg_arg *)regs_to_u64(a1, a2);
675 arg->cmd = OPTEE_RPC_CMD_SHM_ALLOC;
676 arg->num_params = 1;
677 arg->params[0].attr = OPTEE_MSG_ATTR_TYPE_VALUE_INPUT;
678 arg->params[0].u.value.b = 4096;
679 arg->params[0].u.value.a = OPTEE_RPC_SHM_TYPE_APPL;
680 res->a1 = a4;
681 res->a2 = a5;
682 g_shm_ref = regs_to_u64(a4, a5);
683 break;
684 case 2:
685 res->a0 = OPTEE_SMC_RETURN_OK;
686 break;
687 case 3:
688 zassert_equal(a0, 0x32000003, "%s failed with ret %lx", __func__, a0);
689 res->a0 = OPTEE_SMC_RETURN_RPC_PREFIX | OPTEE_SMC_RPC_FUNC_CMD;
690 shm = (struct tee_shm *)regs_to_u64(a1, a2);
691 arg = (struct optee_msg_arg *)shm->addr;
692 arg->cmd = OPTEE_RPC_CMD_SHM_FREE;
693 arg->num_params = 1;
694 arg->params[0].attr = OPTEE_MSG_ATTR_TYPE_VALUE_INPUT;
695 arg->params[0].u.value.a = OPTEE_RPC_SHM_TYPE_APPL;
696 arg->params[0].u.value.b = g_shm_ref;
697 u64_to_regs(g_shm_ref, &res->a1, &res->a2);
698 break;
699 case 4:
700 u64_to_regs(g_shm_ref, &res->a1, &res->a2);
701 res->a0 = OPTEE_SMC_RETURN_OK;
702 break;
703 case 5:
704 zassert_equal(a0, 0x32000003, "%s failed with ret %lx", __func__, a0);
705 res->a0 = OPTEE_SMC_RETURN_OK;
706 break;
707 default:
708 zassert_equal(a0, 0x32000003, "%s failed with ret %lx", __func__, a0);
709 res->a0 = OPTEE_SMC_RETURN_OK;
710 }
711
712 t_call.num++;
713 }
714
supp_thread_alloc(void)715 static void supp_thread_alloc(void)
716 {
717 const struct device *const dev = DEVICE_DT_GET_ONE(linaro_optee_tz);
718 struct tee_param params[TEE_NUM_PARAMS];
719 void *mem;
720 unsigned int num_params = TEE_NUM_PARAMS;
721 uint32_t func;
722 int ret;
723
724 supp_thread_ok = true;
725
726 ret = tee_suppl_recv(dev, &func, &num_params, params);
727
728 if (ret != 0) {
729 printk("tee_suppl_recv failed with %d\n", ret);
730 supp_thread_ok = false;
731 goto fail1;
732 }
733
734 if (func != OPTEE_RPC_CMD_SHM_ALLOC || num_params != 1) {
735 printk("Unexpected func & num_params %d %d\n", func, num_params);
736 supp_thread_ok = false;
737 goto fail1;
738 }
739
740 if (params[0].attr != OPTEE_MSG_ATTR_TYPE_VALUE_INOUT ||
741 params[0].a != OPTEE_RPC_SHM_TYPE_APPL) {
742 printk("Unexpected params %d %d\n", params[0].attr,
743 params[0].a);
744 supp_thread_ok = false;
745 goto fail1;
746 }
747
748 mem = k_malloc(params[0].b);
749
750 if (!mem) {
751 printk("k_malloc failed\n");
752 supp_thread_ok = false;
753 goto fail1;
754 }
755
756 params[0].c = (uint64_t)mem;
757 tee_suppl_send(dev, 0, 1, params);
758
759 ret = tee_suppl_recv(dev, &func, &num_params, params);
760 if (func != OPTEE_RPC_CMD_SHM_FREE || num_params != 1) {
761 printk("Unexpected func & num_params %d %d\n", func, num_params);
762 supp_thread_ok = false;
763 goto fail2;
764 }
765
766 tee_suppl_send(dev, 0, 1, params);
767 k_free(mem);
768
769 return;
770 fail1:
771 tee_suppl_send(dev, -1, 1, params);
772 fail2:
773 tee_suppl_send(dev, -1, 1, params);
774 }
775
ZTEST(optee_test_suite,test_func_rpc_shm_alloc_appl)776 ZTEST(optee_test_suite, test_func_rpc_shm_alloc_appl)
777 {
778 int ret;
779 uint32_t session_id;
780 struct tee_open_session_arg arg = {};
781 struct tee_invoke_func_arg invoke_arg = {};
782 struct tee_param param = {};
783 const struct device *const dev = DEVICE_DT_GET_ONE(linaro_optee_tz);
784 k_tid_t tid;
785
786 tid = k_thread_create(&supp_thread_data, supp_stack,
787 K_KERNEL_STACK_SIZEOF(supp_stack),
788 (k_thread_entry_t)supp_thread_alloc, NULL, NULL, NULL,
789 K_PRIO_PREEMPT(CONFIG_NUM_PREEMPT_PRIORITIES - 1), 0, K_NO_WAIT);
790 zassert_not_null(dev, "Unable to get dev");
791
792 t_call.pending = 1;
793 t_call.num = 0;
794 t_call.smc_cb = fast_call;
795
796 arg.uuid[0] = 111;
797 arg.clnt_uuid[0] = 222;
798 arg.clnt_login = TEEC_LOGIN_PUBLIC;
799 param.attr = TEE_PARAM_ATTR_TYPE_NONE;
800 param.a = 3333;
801 ret = tee_open_session(dev, &arg, 1, ¶m, &session_id);
802 zassert_ok(ret, "tee_open_session failed with code %d", ret);
803
804 t_call.num = 0;
805 t_call.smc_cb = cmd_shm_alloc_appl;
806
807 invoke_arg.func = 12;
808 invoke_arg.session = 1;
809 ret = tee_invoke_func(dev, &invoke_arg, 1, ¶m);
810 zassert_ok(ret, "tee_invoke_fn failed with code %d", ret);
811 zassert_true(supp_thread_ok, "supp_thread failed");
812
813 t_call.num = 0;
814 t_call.smc_cb = fast_call;
815
816 ret = tee_close_session(dev, session_id);
817 zassert_ok(ret, "close_session failed with code %d", ret);
818 t_call.pending = 0;
819 k_thread_abort(tid);
820 }
821
cmd_gettime_call(unsigned long a0,unsigned long a1,unsigned long a2,unsigned long a3,unsigned long a4,unsigned long a5,unsigned long a6,unsigned long a7,struct arm_smccc_res * res)822 void cmd_gettime_call(unsigned long a0, unsigned long a1, unsigned long a2, unsigned long a3,
823 unsigned long a4, unsigned long a5, unsigned long a6, unsigned long a7,
824 struct arm_smccc_res *res)
825 {
826 struct optee_msg_arg *arg;
827 struct tee_shm *shm;
828
829 res->a1 = a1;
830 res->a2 = a2;
831 res->a3 = a3;
832 res->a4 = a4;
833 res->a5 = a5;
834
835 switch (t_call.num) {
836 case 0:
837 res->a0 = OPTEE_SMC_RETURN_RPC_PREFIX | OPTEE_SMC_RPC_FUNC_ALLOC;
838 res->a1 = 1;
839 break;
840 case 1:
841 zassert_equal(a0, 0x32000003, "%s failed with ret %lx", __func__, a0);
842 res->a0 = OPTEE_SMC_RETURN_RPC_PREFIX | OPTEE_SMC_RPC_FUNC_CMD;
843 arg = (struct optee_msg_arg *)regs_to_u64(a1, a2);
844 arg->cmd = OPTEE_RPC_CMD_GET_TIME;
845 arg->num_params = 1;
846 arg->params[0].attr = OPTEE_MSG_ATTR_TYPE_VALUE_OUTPUT;
847 res->a1 = a4;
848 res->a2 = a5;
849 g_shm_ref = regs_to_u64(a4, a5);
850 break;
851 case 2:
852 zassert_equal(a0, 0x32000003, "%s failed with ret %lx", __func__, a0);
853 res->a0 = OPTEE_SMC_RETURN_RPC_PREFIX | OPTEE_SMC_RPC_FUNC_FREE;
854 shm = (struct tee_shm *)regs_to_u64(a1, a2);
855 arg = (struct optee_msg_arg *)shm->addr;
856
857 t_call.a6 = arg->params[0].u.value.a;
858 t_call.a7 = arg->params[0].u.value.b;
859 u64_to_regs(g_shm_ref, &res->a1, &res->a2);
860 break;
861 case 3:
862 zassert_equal(a0, 0x32000003, "%s failed with ret %lx", __func__, a0);
863 res->a0 = OPTEE_SMC_RETURN_OK;
864 break;
865 default:
866 zassert_equal(a0, 0x32000003, "%s failed with ret %lx", __func__, a0);
867 res->a0 = OPTEE_SMC_RETURN_OK;
868 }
869
870 t_call.num++;
871 }
872
873 #define TICKS 0xDEADBEEF
874 #define TEST_SEC 37359285
875 #define TEST_NSEC 590000000
876 extern void z_vrfy_sys_clock_tick_set(uint64_t tick);
877
ZTEST(optee_test_suite,test_gettime)878 ZTEST(optee_test_suite, test_gettime)
879 {
880 int ret;
881 uint32_t session_id;
882 struct tee_open_session_arg arg = {};
883 struct tee_invoke_func_arg invoke_arg = {};
884 struct tee_param param = {};
885 const struct device *const dev = DEVICE_DT_GET_ONE(linaro_optee_tz);
886
887 zassert_not_null(dev, "Unable to get dev");
888
889 t_call.pending = 1;
890 t_call.num = 0;
891 t_call.smc_cb = fast_call;
892
893 arg.uuid[0] = 111;
894 arg.clnt_uuid[0] = 222;
895 arg.clnt_login = TEEC_LOGIN_PUBLIC;
896 param.attr = TEE_PARAM_ATTR_TYPE_NONE;
897 param.a = 3333;
898 ret = tee_open_session(dev, &arg, 1, ¶m, &session_id);
899 zassert_ok(ret, "tee_open_session failed with code %d", ret);
900
901 t_call.num = 0;
902 t_call.smc_cb = cmd_gettime_call;
903
904 z_vrfy_sys_clock_tick_set(TICKS);
905
906 invoke_arg.func = 12;
907 invoke_arg.session = 1;
908 ret = tee_invoke_func(dev, &invoke_arg, 1, ¶m);
909 zassert_ok(ret, "tee_invoke_fn failed with code %d", ret);
910
911 zassert_equal(t_call.a6, TEST_SEC, "Unexpected secs");
912 zassert_equal(t_call.a7, TEST_NSEC, "Unexpected nsecs");
913
914 t_call.num = 0;
915 t_call.smc_cb = fast_call;
916
917 ret = tee_close_session(dev, session_id);
918 zassert_ok(ret, "close_session failed with code %d", ret);
919 t_call.pending = 0;
920 }
921
cmd_suspend_call(unsigned long a0,unsigned long a1,unsigned long a2,unsigned long a3,unsigned long a4,unsigned long a5,unsigned long a6,unsigned long a7,struct arm_smccc_res * res)922 void cmd_suspend_call(unsigned long a0, unsigned long a1, unsigned long a2, unsigned long a3,
923 unsigned long a4, unsigned long a5, unsigned long a6, unsigned long a7,
924 struct arm_smccc_res *res)
925 {
926 struct optee_msg_arg *arg;
927 struct tee_shm *shm;
928
929 res->a1 = a1;
930 res->a2 = a2;
931 res->a3 = a3;
932 res->a4 = a4;
933 res->a5 = a5;
934
935 switch (t_call.num) {
936 case 0:
937 res->a0 = OPTEE_SMC_RETURN_RPC_PREFIX | OPTEE_SMC_RPC_FUNC_ALLOC;
938 res->a1 = 1;
939 break;
940 case 1:
941 zassert_equal(a0, 0x32000003, "%s failed with ret %lx", __func__, a0);
942 res->a0 = OPTEE_SMC_RETURN_RPC_PREFIX | OPTEE_SMC_RPC_FUNC_CMD;
943 arg = (struct optee_msg_arg *)regs_to_u64(a1, a2);
944 arg->cmd = OPTEE_RPC_CMD_SUSPEND;
945 arg->num_params = 1;
946 arg->params[0].attr = OPTEE_MSG_ATTR_TYPE_VALUE_INPUT;
947 arg->params[0].u.value.a = t_call.a0;
948 res->a1 = a4;
949 res->a2 = a5;
950 g_shm_ref = regs_to_u64(a4, a5);
951 break;
952 case 2:
953 zassert_equal(a0, 0x32000003, "%s failed with ret %lx", __func__, a0);
954 res->a0 = OPTEE_SMC_RETURN_RPC_PREFIX | OPTEE_SMC_RPC_FUNC_FREE;
955 shm = (struct tee_shm *)regs_to_u64(a1, a2);
956 arg = (struct optee_msg_arg *)shm->addr;
957
958 t_call.a6 = arg->params[0].u.value.a;
959 t_call.a7 = arg->params[0].u.value.b;
960 u64_to_regs(g_shm_ref, &res->a1, &res->a2);
961 break;
962 case 3:
963 zassert_equal(a0, 0x32000003, "%s failed with ret %lx", __func__, a0);
964 res->a0 = OPTEE_SMC_RETURN_OK;
965 break;
966 default:
967 zassert_equal(a0, 0x32000003, "%s failed with ret %lx", __func__, a0);
968 res->a0 = OPTEE_SMC_RETURN_OK;
969 }
970
971 t_call.num++;
972 }
973
ZTEST(optee_test_suite,test_suspend)974 ZTEST(optee_test_suite, test_suspend)
975 {
976 int ret;
977 uint32_t session_id;
978 struct tee_open_session_arg arg = {};
979 struct tee_invoke_func_arg invoke_arg = {};
980 struct tee_param param = {};
981 const struct device *const dev = DEVICE_DT_GET_ONE(linaro_optee_tz);
982
983 zassert_not_null(dev, "Unable to get dev");
984
985 t_call.pending = 1;
986 t_call.num = 0;
987 t_call.smc_cb = fast_call;
988
989 arg.uuid[0] = 111;
990 arg.clnt_uuid[0] = 222;
991 arg.clnt_login = TEEC_LOGIN_PUBLIC;
992 param.attr = TEE_PARAM_ATTR_TYPE_NONE;
993 param.a = 3333;
994 ret = tee_open_session(dev, &arg, 1, ¶m, &session_id);
995 zassert_ok(ret, "tee_open_session failed with code %d", ret);
996
997 t_call.num = 0;
998 t_call.a0 = 4000; /* Set timeout 4000 ms */
999 t_call.smc_cb = cmd_suspend_call;
1000
1001 invoke_arg.func = 12;
1002 invoke_arg.session = 1;
1003 ret = tee_invoke_func(dev, &invoke_arg, 1, ¶m);
1004 zassert_ok(ret, "tee_invoke_fn failed with code %d", ret);
1005
1006 t_call.num = 0;
1007 t_call.smc_cb = fast_call;
1008
1009 ret = tee_close_session(dev, session_id);
1010 zassert_ok(ret, "close_session failed with code %d", ret);
1011 t_call.pending = 0;
1012 }
1013
cmd_notify_alloc_call(unsigned long a0,unsigned long a1,unsigned long a2,unsigned long a3,unsigned long a4,unsigned long a5,unsigned long a6,unsigned long a7,struct arm_smccc_res * res)1014 void cmd_notify_alloc_call(unsigned long a0, unsigned long a1, unsigned long a2, unsigned long a3,
1015 unsigned long a4, unsigned long a5, unsigned long a6, unsigned long a7,
1016 struct arm_smccc_res *res)
1017 {
1018 res->a1 = a1;
1019 res->a2 = a2;
1020 res->a3 = a3;
1021 res->a4 = a4;
1022 res->a5 = a5;
1023
1024 switch (t_call.num) {
1025 case 0:
1026 res->a0 = OPTEE_SMC_RETURN_RPC_PREFIX | OPTEE_SMC_RPC_FUNC_ALLOC;
1027 res->a1 = 1;
1028 break;
1029 case 1:
1030 zassert_equal(a0, 0x32000003, "%s failed with ret %lx", __func__, a0);
1031 res->a0 = OPTEE_SMC_RETURN_OK;
1032 /* res->a1 = a4; */
1033 /* res->a2 = a5; */
1034 g_shm_ref = regs_to_u64(a4, a5);
1035 break;
1036 default:
1037 zassert_equal(a0, 0x32000004, "%s failed with ret %lx", __func__, a0);
1038 res->a0 = OPTEE_SMC_RETURN_OK;
1039 }
1040
1041 t_call.num++;
1042 }
1043
cmd_notify_free_call(unsigned long a0,unsigned long a1,unsigned long a2,unsigned long a3,unsigned long a4,unsigned long a5,unsigned long a6,unsigned long a7,struct arm_smccc_res * res)1044 void cmd_notify_free_call(unsigned long a0, unsigned long a1, unsigned long a2, unsigned long a3,
1045 unsigned long a4, unsigned long a5, unsigned long a6, unsigned long a7,
1046 struct arm_smccc_res *res)
1047 {
1048 res->a1 = a1;
1049 res->a2 = a2;
1050 res->a3 = a3;
1051 res->a4 = a4;
1052 res->a5 = a5;
1053
1054 switch (t_call.num) {
1055 case 0:
1056 zassert_equal(a0, 0x32000004, "%s failed with ret %lx", __func__, a0);
1057 u64_to_regs(g_shm_ref, &res->a1, &res->a2);
1058 res->a0 = OPTEE_SMC_RETURN_RPC_PREFIX | OPTEE_SMC_RPC_FUNC_FREE;
1059 break;
1060 case 1:
1061 zassert_equal(a0, 0x32000003, "%s failed with ret %lx", __func__, a0);
1062 res->a0 = OPTEE_SMC_RETURN_OK;
1063 res->a1 = a4;
1064 res->a2 = a5;
1065 break;
1066 default:
1067 zassert_equal(a0, 0x32000003, "%s failed with ret %lx", __func__, a0);
1068 res->a0 = OPTEE_SMC_RETURN_OK;
1069 }
1070
1071 t_call.num++;
1072 }
1073
1074 static struct test_call wait_call;
1075 static struct test_call send_call;
1076
cmd_notify_wait_call(unsigned long a0,unsigned long a1,unsigned long a2,unsigned long a3,unsigned long a4,unsigned long a5,unsigned long a6,unsigned long a7,struct arm_smccc_res * res)1077 void cmd_notify_wait_call(unsigned long a0, unsigned long a1, unsigned long a2, unsigned long a3,
1078 unsigned long a4, unsigned long a5, unsigned long a6, unsigned long a7,
1079 struct arm_smccc_res *res)
1080 {
1081 struct optee_msg_arg *arg;
1082 struct tee_shm *shm;
1083
1084 res->a1 = a1;
1085 res->a2 = a2;
1086 res->a3 = a3;
1087 res->a4 = a4;
1088 res->a5 = a5;
1089
1090 switch (wait_call.num) {
1091 case 0:
1092 zassert_equal(a0, 0x32000004, "%s failed with ret %lx", __func__, a0);
1093 res->a0 = OPTEE_SMC_RETURN_RPC_PREFIX | OPTEE_SMC_RPC_FUNC_CMD;
1094 shm = (struct tee_shm *)g_shm_ref;
1095 arg = (struct optee_msg_arg *)shm->addr;
1096 arg->cmd = OPTEE_RPC_CMD_NOTIFICATION;
1097 arg->num_params = 1;
1098 arg->params[0].attr = OPTEE_MSG_ATTR_TYPE_VALUE_INPUT;
1099 arg->params[0].u.value.a = OPTEE_RPC_NOTIFICATION_WAIT;
1100 arg->params[0].u.value.b = wait_call.a0; /* Set notification key */
1101 u64_to_regs(g_shm_ref, &res->a1, &res->a2);
1102 break;
1103 default:
1104 zassert_equal(a0, 0x32000003, "%s failed with ret %lx", __func__, a0);
1105 res->a0 = OPTEE_SMC_RETURN_OK;
1106 wait_call.a6 = 1;
1107 }
1108
1109 wait_call.num++;
1110 }
1111
cmd_notify_send_call(unsigned long a0,unsigned long a1,unsigned long a2,unsigned long a3,unsigned long a4,unsigned long a5,unsigned long a6,unsigned long a7,struct arm_smccc_res * res)1112 void cmd_notify_send_call(unsigned long a0, unsigned long a1, unsigned long a2, unsigned long a3,
1113 unsigned long a4, unsigned long a5, unsigned long a6, unsigned long a7,
1114 struct arm_smccc_res *res)
1115 {
1116 struct optee_msg_arg *arg;
1117 struct tee_shm *shm;
1118
1119 res->a1 = a1;
1120 res->a2 = a2;
1121 res->a3 = a3;
1122 res->a4 = a4;
1123 res->a5 = a5;
1124
1125 switch (send_call.num) {
1126 case 0:
1127 zassert_equal(a0, 0x32000004, "%s failed with ret %lx", __func__, a0);
1128 res->a0 = OPTEE_SMC_RETURN_RPC_PREFIX | OPTEE_SMC_RPC_FUNC_CMD;
1129 shm = (struct tee_shm *)g_shm_ref;
1130 arg = (struct optee_msg_arg *)shm->addr;
1131 arg->cmd = OPTEE_RPC_CMD_NOTIFICATION;
1132 arg->num_params = 1;
1133 arg->params[0].attr = OPTEE_MSG_ATTR_TYPE_VALUE_INPUT;
1134 arg->params[0].u.value.a = OPTEE_RPC_NOTIFICATION_SEND;
1135 arg->params[0].u.value.b = send_call.a0; /* Set notification key */
1136 u64_to_regs(g_shm_ref, &res->a1, &res->a2);
1137 break;
1138 default:
1139 zassert_equal(a0, 0x32000003, "%s failed with ret %lx", __func__, a0);
1140 res->a0 = OPTEE_SMC_RETURN_OK;
1141 send_call.a6 = 1;
1142 }
1143
1144 send_call.num++;
1145 }
1146
test_invoke_fn(const struct device * const dev,uint32_t session_id)1147 static int test_invoke_fn(const struct device *const dev, uint32_t session_id)
1148 {
1149 struct tee_invoke_func_arg invoke_arg = {};
1150 struct tee_param param = {};
1151
1152 invoke_arg.func = 12;
1153 invoke_arg.session = session_id;
1154
1155 return tee_invoke_func(dev, &invoke_arg, 1, ¶m);
1156 }
1157
wait_handler(void * arg0,void * arg1,void * arg2)1158 static void wait_handler(void *arg0, void *arg1, void *arg2)
1159 {
1160 int ret;
1161 const struct device *const dev = DEVICE_DT_GET_ONE(linaro_optee_tz);
1162
1163 ARG_UNUSED(arg0);
1164 ARG_UNUSED(arg1);
1165 ARG_UNUSED(arg2);
1166
1167 /* This expects wait_call.a0 to be set as key and wait_call.a4 as session_id */
1168 wait_call.pending = 1;
1169 wait_call.th_id = k_current_get();
1170 wait_call.num = 0;
1171 wait_call.a6 = 0; /* result */
1172
1173 wait_call.smc_cb = cmd_notify_wait_call;
1174
1175 ret = test_invoke_fn(dev, t_call.a4);
1176 zassert_ok(ret, "tee_invoke_fn failed with code %d", ret);
1177 wait_call.a6 = 1;
1178 wait_call.pending = 0;
1179 }
1180
1181 #define WAIT_STACKSIZE 512
1182 #define WAIT_PRIORITY 4
1183
1184 static K_THREAD_STACK_DEFINE(wait_stack, WAIT_STACKSIZE);
1185 static struct k_thread wait_thread;
1186
do_wait(int key,uint32_t session_id)1187 static void do_wait(int key, uint32_t session_id)
1188 {
1189 wait_call.a0 = key;
1190 wait_call.a4 = session_id;
1191 k_thread_create(&wait_thread, wait_stack, WAIT_STACKSIZE, wait_handler,
1192 INT_TO_POINTER(1) /* key */,
1193 NULL, NULL, K_PRIO_COOP(WAIT_PRIORITY), 0, K_NO_WAIT);
1194 }
1195
ZTEST(optee_test_suite,test_notify)1196 ZTEST(optee_test_suite, test_notify)
1197 {
1198 int ret;
1199 uint32_t session_id;
1200 struct tee_open_session_arg arg = {};
1201 struct tee_param param = {};
1202 const struct device *const dev = DEVICE_DT_GET_ONE(linaro_optee_tz);
1203
1204 zassert_not_null(dev, "Unable to get dev");
1205
1206 t_call.pending = 1;
1207 t_call.num = 0;
1208 t_call.smc_cb = fast_call;
1209
1210 arg.uuid[0] = 111;
1211 arg.clnt_uuid[0] = 222;
1212 arg.clnt_login = TEEC_LOGIN_PUBLIC;
1213 param.attr = TEE_PARAM_ATTR_TYPE_NONE;
1214 param.a = 3333;
1215 ret = tee_open_session(dev, &arg, 1, ¶m, &session_id);
1216 zassert_ok(ret, "tee_open_session failed with code %d", ret);
1217
1218 t_call.num = 0;
1219 t_call.smc_cb = cmd_notify_alloc_call;
1220
1221 ret = test_invoke_fn(dev, session_id);
1222 zassert_ok(ret, "tee_invoke_fn failed with code %d", ret);
1223 t_call.pending = 0;
1224
1225 /* Wait then send */
1226 do_wait(1, session_id);
1227 k_sleep(K_MSEC(100));
1228
1229 send_call.pending = 1;
1230 send_call.num = 0;
1231 send_call.a0 = 1; /* key */
1232 send_call.smc_cb = cmd_notify_send_call;
1233
1234 ret = test_invoke_fn(dev, session_id);
1235 zassert_ok(ret, "tee_invoke_fn failed with code %d", ret);
1236 send_call.pending = 0;
1237
1238 k_sleep(K_MSEC(100));
1239 zassert_equal(wait_call.a6, 1, "Notify wait is still in progress");
1240
1241 /* Test send then wait */
1242 send_call.pending = 1;
1243 send_call.num = 0;
1244 send_call.a0 = 2; /* key */
1245 send_call.smc_cb = cmd_notify_send_call;
1246
1247 ret = test_invoke_fn(dev, session_id);
1248 zassert_ok(ret, "tee_invoke_fn failed with code %d", ret);
1249 send_call.pending = 0;
1250
1251 wait_call.pending = 1;
1252 wait_call.th_id = k_current_get();
1253 wait_call.num = 0;
1254 wait_call.a0 = 2; /* key */
1255
1256 wait_call.smc_cb = cmd_notify_wait_call;
1257
1258 ret = test_invoke_fn(dev, session_id);
1259 zassert_ok(ret, "tee_invoke_fn failed with code %d", ret);
1260
1261 wait_call.pending = 0;
1262 /* End of test section */
1263
1264 t_call.pending = 1;
1265 t_call.num = 0;
1266 t_call.smc_cb = cmd_notify_free_call;
1267
1268 ret = test_invoke_fn(dev, session_id);
1269 zassert_ok(ret, "tee_invoke_fn failed with code %d", ret);
1270
1271 t_call.num = 0;
1272 t_call.smc_cb = fast_call;
1273
1274 ret = tee_close_session(dev, session_id);
1275 zassert_ok(ret, "close_session failed with code %d", ret);
1276 t_call.pending = 0;
1277 }
1278
1279 ZTEST_SUITE(optee_test_suite, NULL, NULL, NULL, NULL, NULL);
1280