1 /*
2  * Copyright 2023 EPAM Systems
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #include <zephyr/arch/arm64/arm-smccc.h>
8 #include <zephyr/drivers/tee.h>
9 #include <zephyr/logging/log.h>
10 #include <zephyr/sys/bitarray.h>
11 #include <zephyr/sys/dlist.h>
12 
13 #include "optee_msg.h"
14 #include "optee_rpc_cmd.h"
15 #include "optee_smc.h"
16 LOG_MODULE_REGISTER(optee);
17 
18 #define DT_DRV_COMPAT linaro_optee_tz
19 
20 /* amount of physical addresses that can be stored in one page */
21 #define OPTEE_NUMBER_OF_ADDR_PER_PAGE (OPTEE_MSG_NONCONTIG_PAGE_SIZE / sizeof(uint64_t))
22 
23 /*
24  * TEE Implementation ID
25  */
26 #define TEE_IMPL_ID_OPTEE 1
27 
28 /*
29  * OP-TEE specific capabilities
30  */
31 #define TEE_OPTEE_CAP_TZ  BIT(0)
32 
33 struct optee_rpc_param {
34 	uint32_t a0;
35 	uint32_t a1;
36 	uint32_t a2;
37 	uint32_t a3;
38 	uint32_t a4;
39 	uint32_t a5;
40 	uint32_t a6;
41 	uint32_t a7;
42 };
43 
44 typedef void (*smc_call_t)(unsigned long a0, unsigned long a1, unsigned long a2, unsigned long a3,
45 			   unsigned long a4, unsigned long a5, unsigned long a6, unsigned long a7,
46 			   struct arm_smccc_res *res);
47 
48 struct optee_driver_config {
49 	const char *method;
50 };
51 
52 struct optee_notify {
53 	sys_dnode_t node;
54 	uint32_t key;
55 	struct k_sem wait;
56 };
57 
58 struct optee_supp_req {
59 	sys_dnode_t link;
60 
61 	bool in_queue;
62 	uint32_t func;
63 	uint32_t ret;
64 	size_t num_params;
65 	struct tee_param *param;
66 
67 	struct k_sem complete;
68 };
69 
70 struct optee_supp {
71 	/* Serializes access to this struct */
72 	struct k_mutex mutex;
73 
74 	int req_id;
75 	sys_dlist_t reqs;
76 	struct optee_supp_req *current;
77 	struct k_sem reqs_c;
78 };
79 
80 struct optee_driver_data {
81 	smc_call_t smc_call;
82 
83 	sys_bitarray_t *notif_bitmap;
84 
85 	sys_dlist_t notif;
86 	struct k_spinlock notif_lock;
87 	struct optee_supp supp;
88 	unsigned long sec_caps;
89 	struct k_sem call_sem;
90 };
91 
92 /* Wrapping functions so function pointer can be used */
optee_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)93 static void optee_smccc_smc(unsigned long a0, unsigned long a1, unsigned long a2, unsigned long a3,
94 			    unsigned long a4, unsigned long a5, unsigned long a6, unsigned long a7,
95 			    struct arm_smccc_res *res)
96 {
97 	arm_smccc_smc(a0, a1, a2, a3, a4, a5, a6, a7, res);
98 }
99 
optee_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)100 static void optee_smccc_hvc(unsigned long a0, unsigned long a1, unsigned long a2, unsigned long a3,
101 			    unsigned long a4, unsigned long a5, unsigned long a6, unsigned long a7,
102 			    struct arm_smccc_res *res)
103 {
104 	arm_smccc_hvc(a0, a1, a2, a3, a4, a5, a6, a7, res);
105 }
106 
param_to_msg_param(const struct tee_param * param,unsigned int num_param,struct optee_msg_param * msg_param)107 static int param_to_msg_param(const struct tee_param *param, unsigned int num_param,
108 			      struct optee_msg_param *msg_param)
109 {
110 	int i;
111 	const struct tee_param *tp = param;
112 	struct optee_msg_param *mtp = msg_param;
113 
114 	if (!param || !msg_param) {
115 		return -EINVAL;
116 	}
117 
118 	for (i = 0; i < num_param; i++, tp++, mtp++) {
119 		if (!tp || !mtp) {
120 			LOG_ERR("Wrong param on %d iteration", i);
121 			return -EINVAL;
122 		}
123 
124 		switch (tp->attr) {
125 		case TEE_PARAM_ATTR_TYPE_NONE:
126 			mtp->attr = OPTEE_MSG_ATTR_TYPE_NONE;
127 			memset(&mtp->u, 0, sizeof(mtp->u));
128 			break;
129 		case TEE_PARAM_ATTR_TYPE_VALUE_INPUT:
130 		case TEE_PARAM_ATTR_TYPE_VALUE_OUTPUT:
131 		case TEE_PARAM_ATTR_TYPE_VALUE_INOUT:
132 			mtp->attr = OPTEE_MSG_ATTR_TYPE_VALUE_INPUT + tp->attr -
133 				TEE_PARAM_ATTR_TYPE_VALUE_INPUT;
134 			mtp->u.value.a = tp->a;
135 			mtp->u.value.b = tp->b;
136 			mtp->u.value.c = tp->c;
137 			break;
138 		case TEE_PARAM_ATTR_TYPE_MEMREF_INPUT:
139 		case TEE_PARAM_ATTR_TYPE_MEMREF_OUTPUT:
140 		case TEE_PARAM_ATTR_TYPE_MEMREF_INOUT:
141 			mtp->attr = OPTEE_MSG_ATTR_TYPE_RMEM_INPUT + tp->attr -
142 				TEE_PARAM_ATTR_TYPE_MEMREF_INPUT;
143 			mtp->u.rmem.shm_ref = tp->c;
144 			mtp->u.rmem.size = tp->b;
145 			mtp->u.rmem.offs = tp->a;
146 			break;
147 		default:
148 			return -EINVAL;
149 		}
150 	}
151 
152 	return 0;
153 }
154 
msg_param_to_tmp_mem(struct tee_param * p,uint32_t attr,const struct optee_msg_param * mp)155 static void msg_param_to_tmp_mem(struct tee_param *p, uint32_t attr,
156 				 const struct optee_msg_param *mp)
157 {
158 	struct tee_shm *shm = (struct tee_shm *)mp->u.tmem.shm_ref;
159 
160 	p->attr = TEE_PARAM_ATTR_TYPE_MEMREF_INPUT + attr - OPTEE_MSG_ATTR_TYPE_TMEM_INPUT;
161 	p->b = mp->u.tmem.size;
162 
163 	if (!shm) {
164 		p->a = 0;
165 		p->c = 0;
166 		return;
167 	}
168 
169 	p->a = mp->u.tmem.buf_ptr - k_mem_phys_addr(shm->addr);
170 	p->c = mp->u.tmem.shm_ref;
171 }
172 
msg_param_to_param(struct tee_param * param,unsigned int num_param,const struct optee_msg_param * msg_param)173 static int msg_param_to_param(struct tee_param *param, unsigned int num_param,
174 			      const struct optee_msg_param *msg_param)
175 {
176 	int i;
177 	struct tee_param *tp = param;
178 	const struct optee_msg_param *mtp = msg_param;
179 
180 	if (!param || !msg_param) {
181 		return -EINVAL;
182 	}
183 
184 	for (i = 0; i < num_param; i++, tp++, mtp++) {
185 		uint32_t attr = mtp->attr & OPTEE_MSG_ATTR_TYPE_MASK;
186 
187 		if (!tp || !mtp) {
188 			LOG_ERR("Wrong param on %d iteration", i);
189 			return -EINVAL;
190 		}
191 
192 		switch (attr) {
193 		case OPTEE_MSG_ATTR_TYPE_NONE:
194 			memset(tp, 0, sizeof(*tp));
195 			tp->attr = TEE_PARAM_ATTR_TYPE_NONE;
196 			break;
197 		case OPTEE_MSG_ATTR_TYPE_VALUE_INPUT:
198 		case OPTEE_MSG_ATTR_TYPE_VALUE_OUTPUT:
199 		case OPTEE_MSG_ATTR_TYPE_VALUE_INOUT:
200 			tp->attr = TEE_PARAM_ATTR_TYPE_VALUE_INPUT + attr -
201 				OPTEE_MSG_ATTR_TYPE_VALUE_INPUT;
202 			tp->a = mtp->u.value.a;
203 			tp->b = mtp->u.value.b;
204 			tp->c = mtp->u.value.c;
205 			break;
206 		case OPTEE_MSG_ATTR_TYPE_RMEM_INPUT:
207 		case OPTEE_MSG_ATTR_TYPE_RMEM_OUTPUT:
208 		case OPTEE_MSG_ATTR_TYPE_RMEM_INOUT:
209 			tp->attr = TEE_PARAM_ATTR_TYPE_MEMREF_INPUT + attr -
210 				OPTEE_MSG_ATTR_TYPE_RMEM_INPUT;
211 			tp->b = mtp->u.rmem.size;
212 
213 			if (!mtp->u.rmem.shm_ref) {
214 				tp->a = 0;
215 				tp->c = 0;
216 			} else {
217 				tp->a = mtp->u.rmem.offs;
218 				tp->c = mtp->u.rmem.shm_ref;
219 			}
220 
221 			break;
222 		case OPTEE_MSG_ATTR_TYPE_TMEM_INPUT:
223 		case OPTEE_MSG_ATTR_TYPE_TMEM_OUTPUT:
224 		case OPTEE_MSG_ATTR_TYPE_TMEM_INOUT:
225 			msg_param_to_tmp_mem(tp, attr, mtp);
226 			break;
227 		default:
228 			return -EINVAL;
229 		}
230 	}
231 
232 	return 0;
233 }
234 
regs_to_u64(uint32_t reg0,uint32_t reg1)235 static uint64_t regs_to_u64(uint32_t reg0, uint32_t reg1)
236 {
237 	return (uint64_t)(((uint64_t)reg0 << 32) | reg1);
238 }
239 
u64_to_regs(uint64_t val,uint32_t * reg0,uint32_t * reg1)240 static void u64_to_regs(uint64_t val, uint32_t *reg0, uint32_t *reg1)
241 {
242 	*reg0 = val >> 32;
243 	*reg1 = val;
244 }
245 
check_param_input(struct optee_msg_arg * arg)246 static inline bool check_param_input(struct optee_msg_arg *arg)
247 {
248 	return arg->num_params == 1 &&
249 		 arg->params[0].attr == OPTEE_MSG_ATTR_TYPE_VALUE_INPUT;
250 }
251 
252 static void *optee_construct_page_list(void *buf, uint32_t len, uint64_t *phys_buf);
253 
optee_call_supp(const struct device * dev,uint32_t func,size_t num_params,struct tee_param * param)254 static uint32_t optee_call_supp(const struct device *dev, uint32_t func, size_t num_params,
255 				struct tee_param *param)
256 {
257 	struct optee_driver_data *data = (struct optee_driver_data *)dev->data;
258 	struct optee_supp *supp = &data->supp;
259 	struct optee_supp_req *req;
260 	uint32_t ret;
261 
262 	req = k_malloc(sizeof(*req));
263 	if (!req) {
264 		return TEEC_ERROR_OUT_OF_MEMORY;
265 	}
266 
267 	k_sem_init(&req->complete, 0, 1);
268 	req->func = func;
269 	req->num_params = num_params;
270 	req->param = param;
271 
272 	/* Insert the request in the request list */
273 	k_mutex_lock(&supp->mutex, K_FOREVER);
274 	sys_dlist_append(&supp->reqs, &req->link);
275 	k_mutex_unlock(&supp->mutex);
276 
277 	/* Tell an event listener there's a new request */
278 	k_sem_give(&supp->reqs_c);
279 
280 	/*
281 	 * Wait for supplicant to process and return result, once we've
282 	 * returned from k_sem_take(&req->c) successfully we have
283 	 * exclusive access again.
284 	 */
285 
286 	k_sem_take(&req->complete, K_FOREVER);
287 
288 	ret = req->ret;
289 	k_free(req);
290 
291 	return ret;
292 }
293 
cmd_alloc_suppl(const struct device * dev,size_t sz,struct tee_shm ** shm)294 static int cmd_alloc_suppl(const struct device *dev, size_t sz, struct tee_shm **shm)
295 {
296 	uint32_t ret;
297 	struct tee_param param;
298 
299 	param.attr = TEE_PARAM_ATTR_TYPE_VALUE_INOUT;
300 	param.a = OPTEE_RPC_SHM_TYPE_APPL;
301 	param.b = sz;
302 	param.c = 0;
303 
304 	ret = optee_call_supp(dev, OPTEE_RPC_CMD_SHM_ALLOC, 1, &param);
305 
306 	if (ret) {
307 		return ret;
308 	}
309 
310 	ret = tee_add_shm(dev, (void *)param.c, 0, param.b, 0, shm);
311 
312 	return ret;
313 }
314 
cmd_free_suppl(const struct device * dev,struct tee_shm * shm)315 static void cmd_free_suppl(const struct device *dev, struct tee_shm *shm)
316 {
317 	struct tee_param param;
318 
319 	param.attr = TEE_PARAM_ATTR_TYPE_VALUE_INOUT;
320 	param.a = OPTEE_RPC_SHM_TYPE_APPL;
321 	param.b = (uint64_t)shm;
322 	param.c = 0;
323 
324 	optee_call_supp(dev, OPTEE_RPC_CMD_SHM_FREE, 1, &param);
325 	tee_rm_shm(dev, shm);
326 }
327 
handle_cmd_alloc(const struct device * dev,struct optee_msg_arg * arg,void ** pages)328 static void handle_cmd_alloc(const struct device *dev, struct optee_msg_arg *arg,
329 			     void **pages)
330 {
331 	int rc;
332 	struct tee_shm *shm = NULL;
333 	void *pl;
334 	uint64_t pl_phys_and_offset;
335 
336 	arg->ret_origin = TEEC_ORIGIN_COMMS;
337 
338 	if (!check_param_input(arg)) {
339 		arg->ret = TEEC_ERROR_BAD_PARAMETERS;
340 		return;
341 	}
342 
343 	switch (arg->params[0].u.value.a) {
344 	case OPTEE_RPC_SHM_TYPE_KERNEL:
345 		/* TODO handle situation when shm was allocated statically so buffer can be reused*/
346 		rc = tee_add_shm(dev, NULL, 0, arg->params[0].u.value.b, TEE_SHM_ALLOC, &shm);
347 		break;
348 	case OPTEE_RPC_SHM_TYPE_APPL:
349 		rc = cmd_alloc_suppl(dev, arg->params[0].u.value.b, &shm);
350 		break;
351 	default:
352 		arg->ret = TEEC_ERROR_BAD_PARAMETERS;
353 		return;
354 	}
355 
356 	if (rc) {
357 		if (rc == -ENOMEM) {
358 			arg->ret = TEEC_ERROR_OUT_OF_MEMORY;
359 		} else {
360 			arg->ret = TEEC_ERROR_GENERIC;
361 		}
362 		return;
363 	}
364 
365 	pl = optee_construct_page_list(shm->addr, shm->size, &pl_phys_and_offset);
366 	if (!pl) {
367 		arg->ret = TEEC_ERROR_OUT_OF_MEMORY;
368 		goto out;
369 	}
370 
371 	*pages = pl;
372 	arg->params[0].attr = OPTEE_MSG_ATTR_TYPE_TMEM_OUTPUT | OPTEE_MSG_ATTR_NONCONTIG;
373 	arg->params[0].u.tmem.buf_ptr = pl_phys_and_offset;
374 	arg->params[0].u.tmem.size = shm->size;
375 	arg->params[0].u.tmem.shm_ref = (uint64_t)shm;
376 	arg->ret = TEEC_SUCCESS;
377 	return;
378 out:
379 	tee_shm_free(dev, shm);
380 }
381 
handle_cmd_free(const struct device * dev,struct optee_msg_arg * arg)382 static void handle_cmd_free(const struct device *dev, struct optee_msg_arg *arg)
383 {
384 	int rc = 0;
385 
386 	if (!check_param_input(arg)) {
387 		arg->ret = TEEC_ERROR_BAD_PARAMETERS;
388 		return;
389 	}
390 
391 	switch (arg->params[0].u.value.a) {
392 	case OPTEE_RPC_SHM_TYPE_KERNEL:
393 		rc = tee_rm_shm(dev, (struct tee_shm *)arg->params[0].u.value.b);
394 		break;
395 	case OPTEE_RPC_SHM_TYPE_APPL:
396 		cmd_free_suppl(dev, (struct tee_shm *)arg->params[0].u.value.b);
397 		break;
398 	default:
399 		arg->ret = TEEC_ERROR_BAD_PARAMETERS;
400 		return;
401 	}
402 
403 	if (rc) {
404 		arg->ret = TEEC_ERROR_OUT_OF_MEMORY;
405 		return;
406 	}
407 
408 	arg->ret = TEEC_SUCCESS;
409 }
410 
handle_cmd_get_time(const struct device * dev,struct optee_msg_arg * arg)411 static void handle_cmd_get_time(const struct device *dev, struct optee_msg_arg *arg)
412 {
413 	int64_t ticks;
414 	int64_t up_secs;
415 	int64_t up_nsecs;
416 
417 	if (arg->num_params != 1 ||
418 	    (arg->params[0].attr & OPTEE_MSG_ATTR_TYPE_MASK)
419 	    != OPTEE_MSG_ATTR_TYPE_VALUE_OUTPUT) {
420 		arg->ret = TEEC_ERROR_BAD_PARAMETERS;
421 		return;
422 	}
423 
424 	ticks = k_uptime_ticks();
425 
426 	up_secs = ticks / CONFIG_SYS_CLOCK_TICKS_PER_SEC;
427 	up_nsecs = k_ticks_to_ns_floor64(ticks - up_secs * CONFIG_SYS_CLOCK_TICKS_PER_SEC);
428 	arg->params[0].u.value.a = up_secs;
429 	arg->params[0].u.value.b = up_nsecs;
430 
431 	arg->ret = TEEC_SUCCESS;
432 }
433 
434 /* This should be called under notif_lock */
key_is_pending(struct optee_driver_data * data,uint32_t key)435 static inline bool key_is_pending(struct optee_driver_data *data, uint32_t key)
436 {
437 	struct optee_notify *iter;
438 
439 	SYS_DLIST_FOR_EACH_CONTAINER(&data->notif, iter, node) {
440 		if (iter->key == key) {
441 			k_sem_give(&iter->wait);
442 			return true;
443 		}
444 	}
445 
446 	return false;
447 }
448 
optee_notif_send(const struct device * dev,uint32_t key)449 static int optee_notif_send(const struct device *dev, uint32_t key)
450 {
451 	struct optee_driver_data *data = dev->data;
452 	k_spinlock_key_t sp_key;
453 
454 	if (key > CONFIG_OPTEE_MAX_NOTIF) {
455 		return -EINVAL;
456 	}
457 
458 	sp_key = k_spin_lock(&data->notif_lock);
459 	if (!key_is_pending(data, key)) {
460 		/* If nobody is waiting for key - set bit in the bitmap */
461 		sys_bitarray_set_bit(data->notif_bitmap, key);
462 	}
463 	k_spin_unlock(&data->notif_lock, sp_key);
464 
465 	return 0;
466 }
467 
optee_notif_wait(const struct device * dev,uint32_t key)468 static int optee_notif_wait(const struct device *dev, uint32_t key)
469 {
470 	int rc = 0;
471 	struct optee_driver_data *data = dev->data;
472 	struct optee_notify *entry;
473 	k_spinlock_key_t sp_key;
474 	int prev_val;
475 
476 	if (key > CONFIG_OPTEE_MAX_NOTIF) {
477 		return -EINVAL;
478 	}
479 
480 	entry = k_malloc(sizeof(*entry));
481 	if (!entry) {
482 		return -ENOMEM;
483 	}
484 
485 	k_sem_init(&entry->wait, 0, 1);
486 	entry->key = key;
487 
488 	sp_key = k_spin_lock(&data->notif_lock);
489 
490 	/*
491 	 * If notif bit was set then SEND command was already received.
492 	 * Skipping wait.
493 	 */
494 	rc = sys_bitarray_test_and_clear_bit(data->notif_bitmap, key, &prev_val);
495 	if (rc || prev_val) {
496 		goto out;
497 	}
498 
499 	/*
500 	 * If key is already registred, then skip.
501 	 */
502 	if (key_is_pending(data, key)) {
503 		rc = -EBUSY;
504 		goto out;
505 	}
506 
507 	sys_dlist_append(&data->notif, &entry->node);
508 
509 	k_spin_unlock(&data->notif_lock, sp_key);
510 	k_sem_take(&entry->wait, K_FOREVER);
511 	sp_key = k_spin_lock(&data->notif_lock);
512 
513 	sys_dlist_remove(&entry->node);
514 out:
515 	k_spin_unlock(&data->notif_lock, sp_key);
516 
517 	k_free(entry);
518 
519 	return rc;
520 }
521 
handle_cmd_notify(const struct device * dev,struct optee_msg_arg * arg)522 static void handle_cmd_notify(const struct device *dev, struct optee_msg_arg *arg)
523 {
524 	if (!check_param_input(arg)) {
525 		arg->ret = TEEC_ERROR_BAD_PARAMETERS;
526 		return;
527 	}
528 
529 	switch (arg->params[0].u.value.a) {
530 	case OPTEE_RPC_NOTIFICATION_SEND:
531 		if (optee_notif_send(dev, arg->params[0].u.value.b)) {
532 			goto err;
533 		}
534 		break;
535 	case OPTEE_RPC_NOTIFICATION_WAIT:
536 		if (optee_notif_wait(dev, arg->params[0].u.value.b)) {
537 			goto err;
538 		}
539 		break;
540 	default:
541 		goto err;
542 	}
543 
544 	arg->ret = TEEC_SUCCESS;
545 	return;
546 
547 err:
548 	arg->ret = TEEC_ERROR_BAD_PARAMETERS;
549 }
550 
handle_cmd_wait(const struct device * dev,struct optee_msg_arg * arg)551 static void handle_cmd_wait(const struct device *dev, struct optee_msg_arg *arg)
552 {
553 	if (!check_param_input(arg)) {
554 		arg->ret = TEEC_ERROR_BAD_PARAMETERS;
555 		return;
556 	}
557 
558 	k_sleep(K_MSEC(arg->params[0].u.value.a));
559 
560 	arg->ret = TEEC_SUCCESS;
561 }
562 
free_shm_pages(void ** pages)563 static void free_shm_pages(void **pages)
564 {
565 	/*
566 	 * Clean allocated pages if needed. Some function calls requires pages
567 	 * allocation which should be freed after processing new request.
568 	 * It is safe to free this list when another SHM op (e,g. another alloc
569 	 * or free) was received.
570 	 */
571 	if (*pages) {
572 		k_free(*pages);
573 		*pages = NULL;
574 	}
575 }
576 
handle_rpc_supp_cmd(const struct device * dev,struct optee_msg_arg * arg)577 static void handle_rpc_supp_cmd(const struct device *dev, struct optee_msg_arg *arg)
578 {
579 	struct tee_param *params;
580 	int ret;
581 
582 	arg->ret_origin = TEEC_ORIGIN_COMMS;
583 
584 	params = k_malloc(sizeof(*params) * arg->num_params);
585 	if (!params) {
586 		arg->ret = TEEC_ERROR_OUT_OF_MEMORY;
587 		return;
588 	}
589 
590 	ret = msg_param_to_param(params, arg->num_params, arg->params);
591 	if (ret) {
592 		arg->ret = TEEC_ERROR_BAD_PARAMETERS;
593 		arg->ret_origin = TEEC_ORIGIN_COMMS;
594 		goto out;
595 	}
596 
597 	arg->ret = optee_call_supp(dev, arg->cmd, arg->num_params, params);
598 
599 	ret = param_to_msg_param(params, arg->num_params, arg->params);
600 	if (ret) {
601 		arg->ret = TEEC_ERROR_GENERIC;
602 		arg->ret_origin = TEEC_ORIGIN_COMMS;
603 	}
604 out:
605 	k_free(params);
606 }
607 
handle_func_rpc_call(const struct device * dev,struct tee_shm * shm,void ** pages)608 static uint32_t handle_func_rpc_call(const struct device *dev, struct tee_shm *shm,
609 				     void **pages)
610 {
611 	struct optee_msg_arg *arg = shm->addr;
612 
613 	switch (arg->cmd) {
614 	case OPTEE_RPC_CMD_SHM_ALLOC:
615 		free_shm_pages(pages);
616 		handle_cmd_alloc(dev, arg, pages);
617 		break;
618 	case OPTEE_RPC_CMD_SHM_FREE:
619 		handle_cmd_free(dev, arg);
620 		break;
621 	case OPTEE_RPC_CMD_GET_TIME:
622 		handle_cmd_get_time(dev, arg);
623 		break;
624 	case OPTEE_RPC_CMD_NOTIFICATION:
625 		handle_cmd_notify(dev, arg);
626 		break;
627 	case OPTEE_RPC_CMD_SUSPEND:
628 		handle_cmd_wait(dev, arg);
629 		break;
630 	case OPTEE_RPC_CMD_I2C_TRANSFER:
631 		/* TODO: i2c transfer case is not implemented right now */
632 		return TEEC_ERROR_NOT_IMPLEMENTED;
633 	default:
634 		handle_rpc_supp_cmd(dev, arg);
635 		break;
636 	}
637 
638 	return OPTEE_SMC_CALL_RETURN_FROM_RPC;
639 }
640 
handle_rpc_call(const struct device * dev,struct optee_rpc_param * param,void ** pages)641 static void handle_rpc_call(const struct device *dev, struct optee_rpc_param *param,
642 			    void **pages)
643 {
644 	struct tee_shm *shm = NULL;
645 	uint32_t res = OPTEE_SMC_CALL_RETURN_FROM_RPC;
646 
647 	switch (OPTEE_SMC_RETURN_GET_RPC_FUNC(param->a0)) {
648 	case OPTEE_SMC_RPC_FUNC_ALLOC:
649 		if (!tee_add_shm(dev, NULL, OPTEE_MSG_NONCONTIG_PAGE_SIZE,
650 				 param->a1,
651 				 TEE_SHM_ALLOC, &shm)) {
652 			u64_to_regs((uint64_t)k_mem_phys_addr(shm->addr), &param->a1, &param->a2);
653 			u64_to_regs((uint64_t)shm, &param->a4, &param->a5);
654 		} else {
655 			param->a1 = 0;
656 			param->a2 = 0;
657 			param->a4 = 0;
658 			param->a5 = 0;
659 		}
660 		break;
661 	case OPTEE_SMC_RPC_FUNC_FREE:
662 		shm = (struct tee_shm *)regs_to_u64(param->a1, param->a2);
663 		tee_rm_shm(dev, shm);
664 		break;
665 	case OPTEE_SMC_RPC_FUNC_FOREIGN_INTR:
666 		/* Foreign interrupt was raised */
667 		break;
668 	case OPTEE_SMC_RPC_FUNC_CMD:
669 		shm = (struct tee_shm *)regs_to_u64(param->a1, param->a2);
670 		res = handle_func_rpc_call(dev, shm, pages);
671 		break;
672 	default:
673 		break;
674 	}
675 
676 	param->a0 = res;
677 }
678 
optee_call(const struct device * dev,struct optee_msg_arg * arg)679 static int optee_call(const struct device *dev, struct optee_msg_arg *arg)
680 {
681 	struct optee_driver_data *data = (struct optee_driver_data *)dev->data;
682 	struct optee_rpc_param param = {
683 		.a0 = OPTEE_SMC_CALL_WITH_ARG
684 	};
685 	void *pages = NULL;
686 
687 	u64_to_regs((uint64_t)k_mem_phys_addr(arg), &param.a1, &param.a2);
688 
689 	k_sem_take(&data->call_sem, K_FOREVER);
690 	while (true) {
691 		struct arm_smccc_res res;
692 
693 		data->smc_call(param.a0, param.a1, param.a2, param.a3,
694 			       param.a4, param.a5, param.a6, param.a7, &res);
695 
696 		if (OPTEE_SMC_RETURN_IS_RPC(res.a0)) {
697 			param.a0 = res.a0;
698 			param.a1 = res.a1;
699 			param.a2 = res.a2;
700 			param.a3 = res.a3;
701 			handle_rpc_call(dev, &param, &pages);
702 		} else {
703 			free_shm_pages(&pages);
704 			k_sem_give(&data->call_sem);
705 			return res.a0 == OPTEE_SMC_RETURN_OK ? TEEC_SUCCESS :
706 				TEEC_ERROR_BAD_PARAMETERS;
707 		}
708 	}
709 }
710 
optee_get_version(const struct device * dev,struct tee_version_info * info)711 static int optee_get_version(const struct device *dev, struct tee_version_info *info)
712 {
713 	if (!info) {
714 		return -EINVAL;
715 	}
716 
717 	/*
718 	 * TODO Version and capabilities should be requested from
719 	 * OP-TEE OS.
720 	 */
721 
722 	info->impl_id = TEE_IMPL_ID_OPTEE;
723 	info->impl_caps = TEE_OPTEE_CAP_TZ;
724 	info->gen_caps = TEE_GEN_CAP_GP | TEE_GEN_CAP_REG_MEM;
725 
726 	return 0;
727 }
728 
optee_close_session(const struct device * dev,uint32_t session_id)729 static int optee_close_session(const struct device *dev, uint32_t session_id)
730 {
731 	int rc;
732 	struct tee_shm *shm;
733 	struct optee_msg_arg *marg;
734 
735 	rc = tee_add_shm(dev, NULL, OPTEE_MSG_NONCONTIG_PAGE_SIZE,
736 			 OPTEE_MSG_GET_ARG_SIZE(0),
737 			 TEE_SHM_ALLOC, &shm);
738 	if (rc) {
739 		LOG_ERR("Unable to get shared memory, rc = %d", rc);
740 		return rc;
741 	}
742 
743 	marg = shm->addr;
744 	marg->num_params = 0;
745 	marg->cmd = OPTEE_MSG_CMD_CLOSE_SESSION;
746 	marg->session = session_id;
747 
748 	rc = optee_call(dev, marg);
749 
750 	if (tee_rm_shm(dev, shm)) {
751 		LOG_ERR("Unable to free shared memory");
752 	}
753 
754 	return rc;
755 }
756 
optee_open_session(const struct device * dev,struct tee_open_session_arg * arg,unsigned int num_param,struct tee_param * param,uint32_t * session_id)757 static int optee_open_session(const struct device *dev, struct tee_open_session_arg *arg,
758 			      unsigned int num_param, struct tee_param *param,
759 			      uint32_t *session_id)
760 {
761 	int rc, ret;
762 	struct tee_shm *shm;
763 	struct optee_msg_arg *marg;
764 
765 	if (!arg || !session_id) {
766 		return -EINVAL;
767 	}
768 
769 	rc = tee_add_shm(dev, NULL, OPTEE_MSG_NONCONTIG_PAGE_SIZE,
770 			 OPTEE_MSG_GET_ARG_SIZE(num_param + 2),
771 			 TEE_SHM_ALLOC, &shm);
772 	if (rc) {
773 		LOG_ERR("Unable to get shared memory, rc = %d", rc);
774 		return rc;
775 	}
776 
777 	marg = shm->addr;
778 	memset(marg, 0, OPTEE_MSG_GET_ARG_SIZE(num_param + 2));
779 
780 	marg->num_params = num_param + 2;
781 	marg->cmd = OPTEE_MSG_CMD_OPEN_SESSION;
782 	marg->params[0].attr = OPTEE_MSG_ATTR_TYPE_VALUE_INPUT | OPTEE_MSG_ATTR_META;
783 	marg->params[1].attr = OPTEE_MSG_ATTR_TYPE_VALUE_INPUT | OPTEE_MSG_ATTR_META;
784 
785 	memcpy(&marg->params[0].u.value, arg->uuid, sizeof(arg->uuid));
786 	memcpy(&marg->params[1].u.value, arg->uuid, sizeof(arg->clnt_uuid));
787 
788 	marg->params[1].u.value.c = arg->clnt_login;
789 
790 	rc = param_to_msg_param(param, num_param, marg->params + 2);
791 	if (rc) {
792 		goto out;
793 	}
794 
795 	arg->ret = optee_call(dev, marg);
796 	if (arg->ret) {
797 		arg->ret_origin = TEEC_ORIGIN_COMMS;
798 		goto out;
799 	}
800 
801 	rc = msg_param_to_param(param, num_param, marg->params);
802 	if (rc) {
803 		arg->ret = TEEC_ERROR_COMMUNICATION;
804 		arg->ret_origin = TEEC_ORIGIN_COMMS;
805 		/*
806 		 * Ret is needed here only to print an error. Param conversion error
807 		 * should be returned from the function.
808 		 */
809 		ret = optee_close_session(dev, marg->session);
810 		if (ret) {
811 			LOG_ERR("Unable to close session: %d", ret);
812 		}
813 		goto out;
814 	}
815 
816 	*session_id = marg->session;
817 
818 	arg->ret = marg->ret;
819 	arg->ret_origin = marg->ret_origin;
820 out:
821 	ret = tee_rm_shm(dev, shm);
822 	if (ret) {
823 		LOG_ERR("Unable to free shared memory");
824 	}
825 
826 	return (rc) ? rc : ret;
827 }
828 
optee_cancel(const struct device * dev,uint32_t session_id,uint32_t cancel_id)829 static int optee_cancel(const struct device *dev, uint32_t session_id, uint32_t cancel_id)
830 {
831 	int rc;
832 	struct tee_shm *shm;
833 	struct optee_msg_arg *marg;
834 
835 	rc = tee_add_shm(dev, NULL, OPTEE_MSG_NONCONTIG_PAGE_SIZE,
836 			 OPTEE_MSG_GET_ARG_SIZE(0),
837 			 TEE_SHM_ALLOC, &shm);
838 	if (rc) {
839 		LOG_ERR("Unable to get shared memory, rc = %d", rc);
840 		return rc;
841 	}
842 
843 	marg = shm->addr;
844 	marg->num_params = 0;
845 	marg->cmd = OPTEE_MSG_CMD_CANCEL;
846 	marg->cancel_id = cancel_id;
847 	marg->session = session_id;
848 
849 	rc = optee_call(dev, marg);
850 
851 	if (tee_rm_shm(dev, shm)) {
852 		LOG_ERR("Unable to free shared memory");
853 	}
854 
855 	return rc;
856 }
857 
optee_invoke_func(const struct device * dev,struct tee_invoke_func_arg * arg,unsigned int num_param,struct tee_param * param)858 static int optee_invoke_func(const struct device *dev, struct tee_invoke_func_arg *arg,
859 			     unsigned int num_param, struct tee_param *param)
860 {
861 	int rc, ret;
862 	struct tee_shm *shm;
863 	struct optee_msg_arg *marg;
864 
865 	if (!arg) {
866 		return -EINVAL;
867 	}
868 
869 	rc = tee_add_shm(dev, NULL, OPTEE_MSG_NONCONTIG_PAGE_SIZE,
870 			 OPTEE_MSG_GET_ARG_SIZE(num_param),
871 			 TEE_SHM_ALLOC, &shm);
872 	if (rc) {
873 		LOG_ERR("Unable to get shared memory, rc = %d", rc);
874 		return rc;
875 	}
876 
877 	marg = shm->addr;
878 	memset(marg, 0, OPTEE_MSG_GET_ARG_SIZE(num_param));
879 
880 	marg->num_params = num_param;
881 	marg->cmd = OPTEE_MSG_CMD_INVOKE_COMMAND;
882 	marg->func = arg->func;
883 	marg->session = arg->session;
884 
885 	rc = param_to_msg_param(param, num_param, marg->params);
886 	if (rc) {
887 		goto out;
888 	}
889 
890 	arg->ret = optee_call(dev, marg);
891 	if (arg->ret) {
892 		arg->ret_origin = TEEC_ORIGIN_COMMS;
893 		goto out;
894 	}
895 
896 	rc = msg_param_to_param(param, num_param, marg->params);
897 	if (rc) {
898 		arg->ret = TEEC_ERROR_COMMUNICATION;
899 		arg->ret_origin = TEEC_ORIGIN_COMMS;
900 		goto out;
901 	}
902 
903 	arg->ret = marg->ret;
904 	arg->ret_origin = marg->ret_origin;
905 out:
906 	ret = tee_rm_shm(dev, shm);
907 	if (ret) {
908 		LOG_ERR("Unable to free shared memory");
909 	}
910 
911 	return (rc) ? rc : ret;
912 }
913 
optee_construct_page_list(void * buf,uint32_t len,uint64_t * phys_buf)914 static void *optee_construct_page_list(void *buf, uint32_t len, uint64_t *phys_buf)
915 {
916 	const size_t page_size = OPTEE_MSG_NONCONTIG_PAGE_SIZE;
917 	const size_t num_pages_in_pl = OPTEE_NUMBER_OF_ADDR_PER_PAGE - 1;
918 	uint32_t page_offset = (uintptr_t)buf & (page_size - 1);
919 
920 	uint8_t *buf_page;
921 	uint32_t num_pages;
922 	uint32_t list_size;
923 
924 	/* see description of OPTEE_MSG_ATTR_NONCONTIG */
925 	struct {
926 		uint64_t pages[OPTEE_NUMBER_OF_ADDR_PER_PAGE - 1];
927 		uint64_t next_page;
928 	} *pl;
929 
930 	BUILD_ASSERT(sizeof(*pl) == OPTEE_MSG_NONCONTIG_PAGE_SIZE);
931 
932 	num_pages = ROUND_UP(page_offset + len, page_size) / page_size;
933 	list_size = DIV_ROUND_UP(num_pages, num_pages_in_pl) * page_size;
934 
935 	pl = k_aligned_alloc(page_size, list_size);
936 	if (!pl) {
937 		return NULL;
938 	}
939 
940 	memset(pl, 0, list_size);
941 
942 	buf_page = (uint8_t *)ROUND_DOWN((uintptr_t)buf, page_size);
943 
944 	for (uint32_t pl_idx = 0; pl_idx < list_size / page_size; pl_idx++) {
945 		for (uint32_t page_idx = 0; num_pages && page_idx < num_pages_in_pl; page_idx++) {
946 			pl[pl_idx].pages[page_idx] = k_mem_phys_addr(buf_page);
947 			buf_page += page_size;
948 			num_pages--;
949 		}
950 
951 		if (!num_pages) {
952 			break;
953 		}
954 
955 		pl[pl_idx].next_page = k_mem_phys_addr(pl + 1);
956 	}
957 
958 	/* 12 least significant bits of optee_msg_param.u.tmem.buf_ptr should hold page offset
959 	 * of user buffer
960 	 */
961 	*phys_buf = k_mem_phys_addr(pl) | page_offset;
962 
963 	return pl;
964 }
965 
optee_shm_register(const struct device * dev,struct tee_shm * shm)966 static int optee_shm_register(const struct device *dev, struct tee_shm *shm)
967 {
968 	struct tee_shm *shm_arg;
969 	struct optee_msg_arg *msg_arg;
970 	void *pl;
971 	uint64_t pl_phys_and_offset;
972 	int rc;
973 
974 	rc = tee_add_shm(dev, NULL, OPTEE_MSG_NONCONTIG_PAGE_SIZE, OPTEE_MSG_GET_ARG_SIZE(1),
975 			 TEE_SHM_ALLOC, &shm_arg);
976 	if (rc) {
977 		return rc;
978 	}
979 
980 	msg_arg = shm_arg->addr;
981 
982 	memset(msg_arg, 0, OPTEE_MSG_GET_ARG_SIZE(1));
983 
984 	pl = optee_construct_page_list(shm->addr, shm->size, &pl_phys_and_offset);
985 	if (!pl) {
986 		rc = -ENOMEM;
987 		goto out;
988 	}
989 
990 	/* for this command op-tee os should support CFG_CORE_DYN_SHM */
991 	msg_arg->cmd = OPTEE_MSG_CMD_REGISTER_SHM;
992 	/* op-tee OS ingnore this cmd in case when TYPE_TMEM_OUTPUT and NONCONTIG aren't set */
993 	msg_arg->params->attr = OPTEE_MSG_ATTR_TYPE_TMEM_OUTPUT | OPTEE_MSG_ATTR_NONCONTIG;
994 	msg_arg->num_params = 1;
995 	msg_arg->params->u.tmem.buf_ptr = pl_phys_and_offset;
996 	msg_arg->params->u.tmem.shm_ref = (uint64_t)shm;
997 	msg_arg->params->u.tmem.size = shm->size;
998 
999 	if (optee_call(dev, msg_arg)) {
1000 		rc = -EINVAL;
1001 	}
1002 
1003 	k_free(pl);
1004 out:
1005 	tee_rm_shm(dev, shm_arg);
1006 
1007 	return rc;
1008 }
1009 
optee_shm_unregister(const struct device * dev,struct tee_shm * shm)1010 static int optee_shm_unregister(const struct device *dev, struct tee_shm *shm)
1011 {
1012 	struct tee_shm *shm_arg;
1013 	struct optee_msg_arg *msg_arg;
1014 	int rc;
1015 
1016 	rc = tee_add_shm(dev, NULL, OPTEE_MSG_NONCONTIG_PAGE_SIZE, OPTEE_MSG_GET_ARG_SIZE(1),
1017 			 TEE_SHM_ALLOC, &shm_arg);
1018 	if (rc) {
1019 		return rc;
1020 	}
1021 
1022 	msg_arg = shm_arg->addr;
1023 
1024 	memset(msg_arg, 0, OPTEE_MSG_GET_ARG_SIZE(1));
1025 
1026 	msg_arg->cmd = OPTEE_MSG_CMD_UNREGISTER_SHM;
1027 	msg_arg->num_params = 1;
1028 	msg_arg->params[0].attr = OPTEE_MSG_ATTR_TYPE_RMEM_INPUT;
1029 	msg_arg->params[0].u.rmem.shm_ref = (uint64_t)shm;
1030 
1031 	if (optee_call(dev, msg_arg)) {
1032 		rc = -EINVAL;
1033 	}
1034 
1035 	tee_rm_shm(dev, shm_arg);
1036 	return rc;
1037 }
1038 
optee_suppl_recv(const struct device * dev,uint32_t * func,unsigned int * num_params,struct tee_param * param)1039 static int optee_suppl_recv(const struct device *dev, uint32_t *func, unsigned int *num_params,
1040 			    struct tee_param *param)
1041 {
1042 	struct optee_driver_data *data = (struct optee_driver_data *)dev->data;
1043 	struct optee_supp *supp = &data->supp;
1044 	struct optee_supp_req *req = NULL;
1045 
1046 	while (true) {
1047 		k_mutex_lock(&supp->mutex, K_FOREVER);
1048 		req = (struct optee_supp_req *)sys_dlist_peek_head(&supp->reqs);
1049 
1050 		if (req) {
1051 			if (supp->current) {
1052 				LOG_ERR("Concurrent supp_recv calls are not supported");
1053 				k_mutex_unlock(&supp->mutex);
1054 				return -EBUSY;
1055 			}
1056 
1057 			if (*num_params < req->num_params) {
1058 				LOG_ERR("Not enough space for params, need at least %lu",
1059 					req->num_params);
1060 				k_mutex_unlock(&supp->mutex);
1061 				return -EINVAL;
1062 			}
1063 
1064 			supp->current = req;
1065 			sys_dlist_remove(&req->link);
1066 		}
1067 		k_mutex_unlock(&supp->mutex);
1068 
1069 		if (req) {
1070 			break;
1071 		}
1072 
1073 		k_sem_take(&supp->reqs_c, K_FOREVER);
1074 	}
1075 
1076 	*func = req->func;
1077 	*num_params = req->num_params;
1078 	memcpy(param, req->param, sizeof(struct tee_param) * req->num_params);
1079 
1080 	return 0;
1081 }
1082 
optee_suppl_send(const struct device * dev,unsigned int ret,unsigned int num_params,struct tee_param * param)1083 static int optee_suppl_send(const struct device *dev, unsigned int ret, unsigned int num_params,
1084 			    struct tee_param *param)
1085 {
1086 	struct optee_driver_data *data = (struct optee_driver_data *)dev->data;
1087 	struct optee_supp *supp = &data->supp;
1088 	struct optee_supp_req *req = NULL;
1089 	size_t n;
1090 
1091 	k_mutex_lock(&supp->mutex, K_FOREVER);
1092 	if (supp->current && num_params >= supp->current->num_params) {
1093 		req = supp->current;
1094 		supp->current = NULL;
1095 	} else {
1096 		LOG_ERR("Invalid number of parameters, expected %lu got %u", req->num_params,
1097 			num_params);
1098 	}
1099 	k_mutex_unlock(&supp->mutex);
1100 
1101 	if (!req) {
1102 		return -EINVAL;
1103 	}
1104 
1105 	/* Update out and in/out parameters */
1106 	for (n = 0; n < req->num_params; n++) {
1107 		struct tee_param *p = req->param + n;
1108 
1109 		switch (p->attr & TEE_PARAM_ATTR_TYPE_MASK) {
1110 		case TEE_PARAM_ATTR_TYPE_VALUE_OUTPUT:
1111 		case TEE_PARAM_ATTR_TYPE_VALUE_INOUT:
1112 			p->a = param[n].a;
1113 			p->b = param[n].b;
1114 			p->c = param[n].c;
1115 			break;
1116 		case TEE_PARAM_ATTR_TYPE_MEMREF_OUTPUT:
1117 		case TEE_PARAM_ATTR_TYPE_MEMREF_INOUT:
1118 			LOG_WRN("Memref params are not fully tested");
1119 			p->a = param[n].a;
1120 			p->b = param[n].b;
1121 			p->c = param[n].c;
1122 			break;
1123 		default:
1124 			break;
1125 		}
1126 	}
1127 	req->ret = ret;
1128 
1129 	/* Let the requesting thread continue */
1130 	k_mutex_lock(&supp->mutex, K_FOREVER);
1131 	supp->current = NULL;
1132 	k_mutex_unlock(&supp->mutex);
1133 	k_sem_give(&req->complete);
1134 
1135 	return 0;
1136 }
1137 
set_optee_method(const struct device * dev)1138 static int set_optee_method(const struct device *dev)
1139 {
1140 	const struct optee_driver_config *conf = dev->config;
1141 	struct optee_driver_data *data = dev->data;
1142 
1143 	if (!strcmp("hvc", conf->method)) {
1144 		data->smc_call = optee_smccc_hvc;
1145 	} else if (!strcmp("smc", conf->method)) {
1146 		data->smc_call = optee_smccc_smc;
1147 	} else {
1148 		LOG_ERR("Invalid smc_call method");
1149 		return -EINVAL;
1150 	}
1151 
1152 	return 0;
1153 }
1154 
optee_check_uid(const struct device * dev)1155 static bool optee_check_uid(const struct device *dev)
1156 {
1157 	struct arm_smccc_res res;
1158 	struct optee_driver_data *data = (struct optee_driver_data *)dev->data;
1159 
1160 	data->smc_call(OPTEE_SMC_CALLS_UID, 0, 0, 0, 0, 0, 0, 0, &res);
1161 
1162 	if (res.a0 == OPTEE_MSG_UID_0 && res.a1 == OPTEE_MSG_UID_1 &&
1163 	    res.a2 == OPTEE_MSG_UID_2 && res.a3 == OPTEE_MSG_UID_3) {
1164 		return true;
1165 	}
1166 
1167 	return false;
1168 }
1169 
optee_get_revision(const struct device * dev)1170 static void optee_get_revision(const struct device *dev)
1171 {
1172 	struct optee_driver_data *data = (struct optee_driver_data *)dev->data;
1173 	struct arm_smccc_res res = { 0 };
1174 
1175 	data->smc_call(OPTEE_SMC_CALL_GET_OS_REVISION, 0, 0, 0, 0, 0, 0, 0, &res);
1176 
1177 	if (res.a2) {
1178 		LOG_INF("OPTEE revision %lu.%lu (%08lx)", res.a0,
1179 			res.a1, res.a2);
1180 	} else {
1181 		LOG_INF("OPTEE revision %lu.%lu", res.a0, res.a1);
1182 	}
1183 }
1184 
optee_exchange_caps(const struct device * dev,unsigned long * sec_caps)1185 static bool optee_exchange_caps(const struct device *dev, unsigned long *sec_caps)
1186 {
1187 	struct optee_driver_data *data = (struct optee_driver_data *)dev->data;
1188 	struct arm_smccc_res res = { 0 };
1189 	unsigned long a1 = 0;
1190 
1191 	if (!IS_ENABLED(CONFIG_SMP) || arch_num_cpus() == 1) {
1192 		a1 |= OPTEE_SMC_NSEC_CAP_UNIPROCESSOR;
1193 	}
1194 
1195 	data->smc_call(OPTEE_SMC_EXCHANGE_CAPABILITIES, a1, 0, 0, 0, 0, 0, 0, &res);
1196 
1197 	if (res.a0 != OPTEE_SMC_RETURN_OK) {
1198 		return false;
1199 	}
1200 
1201 	*sec_caps = res.a1;
1202 	return true;
1203 }
1204 
optee_get_thread_count(const struct device * dev,unsigned long * thread_count)1205 static unsigned long optee_get_thread_count(const struct device *dev, unsigned long *thread_count)
1206 {
1207 	struct optee_driver_data *data = (struct optee_driver_data *)dev->data;
1208 	struct arm_smccc_res res = { 0 };
1209 	unsigned long a1 = 0;
1210 
1211 	data->smc_call(OPTEE_SMC_GET_THREAD_COUNT, a1, 0, 0, 0, 0, 0, 0, &res);
1212 
1213 	if (res.a0 != OPTEE_SMC_RETURN_OK) {
1214 		return false;
1215 	}
1216 
1217 	*thread_count = res.a1;
1218 	return true;
1219 }
1220 
optee_init(const struct device * dev)1221 static int optee_init(const struct device *dev)
1222 {
1223 	struct optee_driver_data *data = dev->data;
1224 	unsigned long thread_count;
1225 
1226 	if (set_optee_method(dev)) {
1227 		return -ENOTSUP;
1228 	}
1229 
1230 	sys_dlist_init(&data->notif);
1231 	k_mutex_init(&data->supp.mutex);
1232 	k_sem_init(&data->supp.reqs_c, 0, 1);
1233 	sys_dlist_init(&data->supp.reqs);
1234 
1235 	if (!optee_check_uid(dev)) {
1236 		LOG_ERR("OPTEE API UID mismatch");
1237 		return -EINVAL;
1238 	}
1239 
1240 	optee_get_revision(dev);
1241 
1242 	if (!optee_exchange_caps(dev, &data->sec_caps)) {
1243 		LOG_ERR("OPTEE capabilities exchange failed\n");
1244 		return -EINVAL;
1245 	}
1246 
1247 	if (!(data->sec_caps & OPTEE_SMC_SEC_CAP_DYNAMIC_SHM)) {
1248 		LOG_ERR("OPTEE does not support dynamic shared memory");
1249 		return -ENOTSUP;
1250 	}
1251 
1252 	if (!optee_get_thread_count(dev, &thread_count)) {
1253 		LOG_ERR("OPTEE unable to get maximum thread count");
1254 		return -ENOTSUP;
1255 	}
1256 
1257 	k_sem_init(&data->call_sem, thread_count, thread_count);
1258 
1259 	return 0;
1260 }
1261 
1262 static DEVICE_API(tee, optee_driver_api) = {
1263 	.get_version = optee_get_version,
1264 	.open_session = optee_open_session,
1265 	.close_session = optee_close_session,
1266 	.cancel = optee_cancel,
1267 	.invoke_func = optee_invoke_func,
1268 	.shm_register = optee_shm_register,
1269 	.shm_unregister = optee_shm_unregister,
1270 	.suppl_recv = optee_suppl_recv,
1271 	.suppl_send = optee_suppl_send,
1272 };
1273 
1274 /*
1275  * Bitmap of the ongoing notificatons, received from OP-TEE. Maximum number is
1276  * CONFIG_OPTEE_MAX_NOTIF. This bitmap is needed to handle case when SEND command
1277  * was received before WAIT command from OP-TEE. In this case WAIT will not create
1278  * locks.
1279  */
1280 #define OPTEE_DT_DEVICE_INIT(inst)					\
1281 	SYS_BITARRAY_DEFINE_STATIC(notif_bitmap_##inst, CONFIG_OPTEE_MAX_NOTIF); \
1282 									\
1283 	static struct optee_driver_config optee_config_##inst = {	\
1284 		.method = DT_INST_PROP(inst, method)			\
1285 	};								\
1286 									\
1287 	static struct optee_driver_data optee_data_##inst = {		\
1288 		.notif_bitmap = &notif_bitmap_##inst			\
1289 	};								\
1290 									\
1291 	DEVICE_DT_INST_DEFINE(inst, optee_init, NULL, &optee_data_##inst, \
1292 			      &optee_config_##inst, POST_KERNEL,	\
1293 			      CONFIG_KERNEL_INIT_PRIORITY_DEVICE,	\
1294 			      &optee_driver_api);			\
1295 
1296 DT_INST_FOREACH_STATUS_OKAY(OPTEE_DT_DEVICE_INIT)
1297