/** * optee_supp_thrd_req() - request service from supplicant * @ctx: context doing the request * @func: function requested * @num_params: number of elements in @param array * @param: parameters for function * * Returns result of operation to be passed to secure world
*/
u32 optee_supp_thrd_req(struct tee_context *ctx, u32 func, size_t num_params, struct tee_param *param)
/* * Return in case there is no supplicant available and * non-blocking request.
*/ if (!supp->ctx && ctx->supp_nowait) return TEEC_ERROR_COMMUNICATION;
req = kzalloc(sizeof(*req), GFP_KERNEL); if (!req) return TEEC_ERROR_OUT_OF_MEMORY;
/* Insert the request in the request list */
mutex_lock(&supp->mutex);
list_add_tail(&req->link, &supp->reqs);
req->in_queue = true;
mutex_unlock(&supp->mutex);
/* Tell an eventual waiter there's a new request */
complete(&supp->reqs_c);
/* * Wait for supplicant to process and return result, once we've * returned from wait_for_completion(&req->c) successfully we have * exclusive access again. Allow the wait to be killable such that * the wait doesn't turn into an indefinite state if the supplicant * gets hung for some reason.
*/ if (wait_for_completion_killable(&req->c)) {
mutex_lock(&supp->mutex); if (req->in_queue) {
list_del(&req->link);
req->in_queue = false;
}
mutex_unlock(&supp->mutex);
req->ret = TEEC_ERROR_COMMUNICATION;
}
ret = req->ret;
kfree(req);
return ret;
}
staticstruct optee_supp_req *supp_pop_entry(struct optee_supp *supp, int num_params, int *id)
{ struct optee_supp_req *req;
if (supp->req_id != -1) { /* * Supplicant should not mix synchronous and asnynchronous * requests.
*/ return ERR_PTR(-EINVAL);
}
/* * If there's memrefs we need to decrease those as they where * increased earlier and we'll even refuse to accept any below.
*/ for (n = 0; n < num_params; n++) if (tee_param_is_memref(params + n) && params[n].u.memref.shm)
tee_shm_put(params[n].u.memref.shm);
/* * We only expect parameters as TEE_IOCTL_PARAM_ATTR_TYPE_NONE with * or without the TEE_IOCTL_PARAM_ATTR_META bit set.
*/ for (n = 0; n < num_params; n++) if (params[n].attr &&
params[n].attr != TEE_IOCTL_PARAM_ATTR_META) return -EINVAL;
/* At most we'll need one meta parameter so no need to check for more */ if (params->attr == TEE_IOCTL_PARAM_ATTR_META)
*num_meta = 1; else
*num_meta = 0;
return 0;
}
/** * optee_supp_recv() - receive request for supplicant * @ctx: context receiving the request * @func: requested function in supplicant * @num_params: number of elements allocated in @param, updated with number * used elements * @param: space for parameters for @func * * Returns 0 on success or <0 on failure
*/ int optee_supp_recv(struct tee_context *ctx, u32 *func, u32 *num_params, struct tee_param *param)
{ struct tee_device *teedev = ctx->teedev; struct optee *optee = tee_get_drvdata(teedev); struct optee_supp *supp = &optee->supp; struct optee_supp_req *req = NULL; int id;
size_t num_meta; int rc;
rc = supp_check_recv_params(*num_params, param, &num_meta); if (rc) return rc;
if (req) { if (IS_ERR(req)) return PTR_ERR(req); break;
}
/* * If we didn't get a request we'll block in * wait_for_completion() to avoid needless spinning. * * This is where supplicant will be hanging most of * the time, let's make this interruptable so we * can easily restart supplicant if needed.
*/ if (wait_for_completion_interruptible(&supp->reqs_c)) return -ERESTARTSYS;
}
if (num_meta) { /* * tee-supplicant support meta parameters -> requsts can be * processed asynchronously.
*/
param->attr = TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INOUT |
TEE_IOCTL_PARAM_ATTR_META;
param->u.value.a = id;
param->u.value.b = 0;
param->u.value.c = 0;
} else {
mutex_lock(&supp->mutex);
supp->req_id = id;
mutex_unlock(&supp->mutex);
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.