Orange Pi5 kernel

Deprecated Linux kernel 5.10.110 for OrangePi 5/5B/5+ boards

3 Commits   0 Branches   0 Tags
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   1) // SPDX-License-Identifier: GPL-2.0-only
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   3)  * Copyright (c) 2015, Linaro Limited
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   4)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   5) #include <linux/device.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   6) #include <linux/slab.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   7) #include <linux/uaccess.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   8) #include "optee_private.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   9) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  10) struct optee_supp_req {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  11) 	struct list_head link;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  12) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  13) 	bool in_queue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  14) 	u32 func;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  15) 	u32 ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  16) 	size_t num_params;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  17) 	struct tee_param *param;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  18) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  19) 	struct completion c;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  20) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  21) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  22) void optee_supp_init(struct optee_supp *supp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  23) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  24) 	memset(supp, 0, sizeof(*supp));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  25) 	mutex_init(&supp->mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  26) 	init_completion(&supp->reqs_c);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  27) 	idr_init(&supp->idr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  28) 	INIT_LIST_HEAD(&supp->reqs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  29) 	supp->req_id = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  30) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  31) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  32) void optee_supp_uninit(struct optee_supp *supp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  33) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  34) 	mutex_destroy(&supp->mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  35) 	idr_destroy(&supp->idr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  36) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  37) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  38) void optee_supp_release(struct optee_supp *supp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  39) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  40) 	int id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  41) 	struct optee_supp_req *req;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  42) 	struct optee_supp_req *req_tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  43) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  44) 	mutex_lock(&supp->mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  45) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  46) 	/* Abort all request retrieved by supplicant */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  47) 	idr_for_each_entry(&supp->idr, req, id) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  48) 		idr_remove(&supp->idr, id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  49) 		req->ret = TEEC_ERROR_COMMUNICATION;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  50) 		complete(&req->c);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  51) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  52) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  53) 	/* Abort all queued requests */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  54) 	list_for_each_entry_safe(req, req_tmp, &supp->reqs, link) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  55) 		list_del(&req->link);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  56) 		req->in_queue = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  57) 		req->ret = TEEC_ERROR_COMMUNICATION;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  58) 		complete(&req->c);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  59) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  60) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  61) 	supp->ctx = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  62) 	supp->req_id = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  63) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  64) 	mutex_unlock(&supp->mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  65) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  66) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  67) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  68)  * optee_supp_thrd_req() - request service from supplicant
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  69)  * @ctx:	context doing the request
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  70)  * @func:	function requested
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  71)  * @num_params:	number of elements in @param array
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  72)  * @param:	parameters for function
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  73)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  74)  * Returns result of operation to be passed to secure world
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  75)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  76) u32 optee_supp_thrd_req(struct tee_context *ctx, u32 func, size_t num_params,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  77) 			struct tee_param *param)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  78) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  79) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  80) 	struct optee *optee = tee_get_drvdata(ctx->teedev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  81) 	struct optee_supp *supp = &optee->supp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  82) 	struct optee_supp_req *req;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  83) 	bool interruptable;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  84) 	u32 ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  85) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  86) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  87) 	 * Return in case there is no supplicant available and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  88) 	 * non-blocking request.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  89) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  90) 	if (!supp->ctx && ctx->supp_nowait)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  91) 		return TEEC_ERROR_COMMUNICATION;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  92) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  93) 	req = kzalloc(sizeof(*req), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  94) 	if (!req)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  95) 		return TEEC_ERROR_OUT_OF_MEMORY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  96) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  97) 	init_completion(&req->c);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  98) 	req->func = func;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  99) 	req->num_params = num_params;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) 	req->param = param;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) 	/* Insert the request in the request list */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) 	mutex_lock(&supp->mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) 	list_add_tail(&req->link, &supp->reqs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) 	req->in_queue = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) 	mutex_unlock(&supp->mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) 	/* Tell an eventual waiter there's a new request */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) 	complete(&supp->reqs_c);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) 	 * Wait for supplicant to process and return result, once we've
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) 	 * returned from wait_for_completion(&req->c) successfully we have
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) 	 * exclusive access again.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) 	while (wait_for_completion_interruptible(&req->c)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) 		mutex_lock(&supp->mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) 		interruptable = !supp->ctx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) 		if (interruptable) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) 			/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) 			 * There's no supplicant available and since the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) 			 * supp->mutex currently is held none can
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) 			 * become available until the mutex released
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) 			 * again.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) 			 *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) 			 * Interrupting an RPC to supplicant is only
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) 			 * allowed as a way of slightly improving the user
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) 			 * experience in case the supplicant hasn't been
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) 			 * started yet. During normal operation the supplicant
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) 			 * will serve all requests in a timely manner and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) 			 * interrupting then wouldn't make sense.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) 			 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) 			if (req->in_queue) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) 				list_del(&req->link);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) 				req->in_queue = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) 			}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) 		mutex_unlock(&supp->mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) 		if (interruptable) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) 			req->ret = TEEC_ERROR_COMMUNICATION;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) 	ret = req->ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) 	kfree(req);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) 	return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) static struct optee_supp_req  *supp_pop_entry(struct optee_supp *supp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) 					      int num_params, int *id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) 	struct optee_supp_req *req;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) 	if (supp->req_id != -1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) 		/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) 		 * Supplicant should not mix synchronous and asnynchronous
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) 		 * requests.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) 		 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) 		return ERR_PTR(-EINVAL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) 	if (list_empty(&supp->reqs))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) 		return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) 	req = list_first_entry(&supp->reqs, struct optee_supp_req, link);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) 	if (num_params < req->num_params) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) 		/* Not enough room for parameters */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) 		return ERR_PTR(-EINVAL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) 	*id = idr_alloc(&supp->idr, req, 1, 0, GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) 	if (*id < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) 		return ERR_PTR(-ENOMEM);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) 	list_del(&req->link);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) 	req->in_queue = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) 	return req;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) static int supp_check_recv_params(size_t num_params, struct tee_param *params,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) 				  size_t *num_meta)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) 	size_t n;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) 	if (!num_params)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) 		return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) 	 * If there's memrefs we need to decrease those as they where
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) 	 * increased earlier and we'll even refuse to accept any below.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) 	for (n = 0; n < num_params; n++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) 		if (tee_param_is_memref(params + n) && params[n].u.memref.shm)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) 			tee_shm_put(params[n].u.memref.shm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) 	 * We only expect parameters as TEE_IOCTL_PARAM_ATTR_TYPE_NONE with
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) 	 * or without the TEE_IOCTL_PARAM_ATTR_META bit set.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) 	for (n = 0; n < num_params; n++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) 		if (params[n].attr &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) 		    params[n].attr != TEE_IOCTL_PARAM_ATTR_META)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) 			return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) 	/* At most we'll need one meta parameter so no need to check for more */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) 	if (params->attr == TEE_IOCTL_PARAM_ATTR_META)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) 		*num_meta = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) 	else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) 		*num_meta = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220)  * optee_supp_recv() - receive request for supplicant
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221)  * @ctx:	context receiving the request
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222)  * @func:	requested function in supplicant
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223)  * @num_params:	number of elements allocated in @param, updated with number
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224)  *		used elements
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225)  * @param:	space for parameters for @func
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227)  * Returns 0 on success or <0 on failure
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) int optee_supp_recv(struct tee_context *ctx, u32 *func, u32 *num_params,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) 		    struct tee_param *param)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) 	struct tee_device *teedev = ctx->teedev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) 	struct optee *optee = tee_get_drvdata(teedev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) 	struct optee_supp *supp = &optee->supp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) 	struct optee_supp_req *req = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) 	int id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) 	size_t num_meta;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) 	int rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) 	rc = supp_check_recv_params(*num_params, param, &num_meta);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) 	if (rc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) 		return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) 	while (true) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) 		mutex_lock(&supp->mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) 		req = supp_pop_entry(supp, *num_params - num_meta, &id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) 		mutex_unlock(&supp->mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) 		if (req) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) 			if (IS_ERR(req))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) 				return PTR_ERR(req);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) 		/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) 		 * If we didn't get a request we'll block in
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) 		 * wait_for_completion() to avoid needless spinning.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) 		 *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) 		 * This is where supplicant will be hanging most of
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) 		 * the time, let's make this interruptable so we
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) 		 * can easily restart supplicant if needed.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) 		 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) 		if (wait_for_completion_interruptible(&supp->reqs_c))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) 			return -ERESTARTSYS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) 	if (num_meta) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) 		/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) 		 * tee-supplicant support meta parameters -> requsts can be
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) 		 * processed asynchronously.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) 		 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) 		param->attr = TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INOUT |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) 			      TEE_IOCTL_PARAM_ATTR_META;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) 		param->u.value.a = id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) 		param->u.value.b = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) 		param->u.value.c = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) 	} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) 		mutex_lock(&supp->mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) 		supp->req_id = id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) 		mutex_unlock(&supp->mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) 	*func = req->func;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) 	*num_params = req->num_params + num_meta;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) 	memcpy(param + num_meta, req->param,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) 	       sizeof(struct tee_param) * req->num_params);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) static struct optee_supp_req *supp_pop_req(struct optee_supp *supp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) 					   size_t num_params,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) 					   struct tee_param *param,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) 					   size_t *num_meta)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) 	struct optee_supp_req *req;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) 	int id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) 	size_t nm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) 	const u32 attr = TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INOUT |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) 			 TEE_IOCTL_PARAM_ATTR_META;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) 	if (!num_params)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) 		return ERR_PTR(-EINVAL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) 	if (supp->req_id == -1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) 		if (param->attr != attr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) 			return ERR_PTR(-EINVAL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) 		id = param->u.value.a;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) 		nm = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) 	} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) 		id = supp->req_id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) 		nm = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) 	req = idr_find(&supp->idr, id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) 	if (!req)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) 		return ERR_PTR(-ENOENT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) 	if ((num_params - nm) != req->num_params)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) 		return ERR_PTR(-EINVAL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) 	idr_remove(&supp->idr, id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) 	supp->req_id = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) 	*num_meta = nm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) 	return req;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330)  * optee_supp_send() - send result of request from supplicant
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331)  * @ctx:	context sending result
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332)  * @ret:	return value of request
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333)  * @num_params:	number of parameters returned
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334)  * @param:	returned parameters
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336)  * Returns 0 on success or <0 on failure.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) int optee_supp_send(struct tee_context *ctx, u32 ret, u32 num_params,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) 		    struct tee_param *param)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) 	struct tee_device *teedev = ctx->teedev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) 	struct optee *optee = tee_get_drvdata(teedev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) 	struct optee_supp *supp = &optee->supp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) 	struct optee_supp_req *req;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) 	size_t n;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) 	size_t num_meta;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) 	mutex_lock(&supp->mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) 	req = supp_pop_req(supp, num_params, param, &num_meta);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) 	mutex_unlock(&supp->mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) 	if (IS_ERR(req)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) 		/* Something is wrong, let supplicant restart. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) 		return PTR_ERR(req);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) 	/* Update out and in/out parameters */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) 	for (n = 0; n < req->num_params; n++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) 		struct tee_param *p = req->param + n;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) 		switch (p->attr & TEE_IOCTL_PARAM_ATTR_TYPE_MASK) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) 		case TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_OUTPUT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) 		case TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INOUT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) 			p->u.value.a = param[n + num_meta].u.value.a;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) 			p->u.value.b = param[n + num_meta].u.value.b;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) 			p->u.value.c = param[n + num_meta].u.value.c;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) 		case TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_OUTPUT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) 		case TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INOUT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) 			p->u.memref.size = param[n + num_meta].u.memref.size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) 		default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) 	req->ret = ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) 	/* Let the requesting thread continue */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) 	complete(&req->c);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) }