optee: refactor driver with internal callbacks
authorJens Wiklander <jens.wiklander@linaro.org>
Thu, 25 Mar 2021 14:08:50 +0000 (15:08 +0100)
committerJens Wiklander <jens.wiklander@linaro.org>
Fri, 15 Oct 2021 09:55:42 +0000 (11:55 +0200)
The OP-TEE driver is refactored with three internal callbacks replacing
direct calls to optee_from_msg_param(), optee_to_msg_param() and
optee_do_call_with_arg().

These functions a central to communicating with OP-TEE in secure world
by using the SMC Calling Convention directly.

This refactoring makes room for using other primitives to communicate
with OP-TEE in secure world while being able to reuse as much as
possible from the present driver.

Reviewed-by: Sumit Garg <sumit.garg@linaro.org>
Signed-off-by: Jens Wiklander <jens.wiklander@linaro.org>
drivers/tee/optee/call.c
drivers/tee/optee/core.c
drivers/tee/optee/optee_private.h
drivers/tee/optee/rpc.c

index 103976df20627a1c67b7376237a3aa4aaa39e737..ddedde45f1ee94e5efc073ea226eeb85937edcee 100644 (file)
@@ -1,6 +1,6 @@
 // SPDX-License-Identifier: GPL-2.0-only
 /*
- * Copyright (c) 2015, Linaro Limited
+ * Copyright (c) 2015-2021, Linaro Limited
  */
 #include <linux/arm-smccc.h>
 #include <linux/device.h>
@@ -118,20 +118,25 @@ static struct optee_session *find_session(struct optee_context_data *ctxdata,
 /**
  * optee_do_call_with_arg() - Do an SMC to OP-TEE in secure world
  * @ctx:       calling context
- * @parg:      physical address of message to pass to secure world
+ * @arg:       shared memory holding the message to pass to secure world
  *
  * Does and SMC to OP-TEE in secure world and handles eventual resulting
  * Remote Procedure Calls (RPC) from OP-TEE.
  *
  * Returns return code from secure world, 0 is OK
  */
-u32 optee_do_call_with_arg(struct tee_context *ctx, phys_addr_t parg)
+int optee_do_call_with_arg(struct tee_context *ctx, struct tee_shm *arg)
 {
        struct optee *optee = tee_get_drvdata(ctx->teedev);
        struct optee_call_waiter w;
        struct optee_rpc_param param = { };
        struct optee_call_ctx call_ctx = { };
-       u32 ret;
+       phys_addr_t parg;
+       int rc;
+
+       rc = tee_shm_get_pa(arg, 0, &parg);
+       if (rc)
+               return rc;
 
        param.a0 = OPTEE_SMC_CALL_WITH_ARG;
        reg_pair_from_64(&param.a1, &param.a2, parg);
@@ -160,7 +165,7 @@ u32 optee_do_call_with_arg(struct tee_context *ctx, phys_addr_t parg)
                        param.a3 = res.a3;
                        optee_handle_rpc(ctx, &param, &call_ctx);
                } else {
-                       ret = res.a0;
+                       rc = res.a0;
                        break;
                }
        }
@@ -172,14 +177,12 @@ u32 optee_do_call_with_arg(struct tee_context *ctx, phys_addr_t parg)
         */
        optee_cq_wait_final(&optee->call_queue, &w);
 
-       return ret;
+       return rc;
 }
 
 static struct tee_shm *get_msg_arg(struct tee_context *ctx, size_t num_params,
-                                  struct optee_msg_arg **msg_arg,
-                                  phys_addr_t *msg_parg)
+                                  struct optee_msg_arg **msg_arg)
 {
-       int rc;
        struct tee_shm *shm;
        struct optee_msg_arg *ma;
 
@@ -190,22 +193,13 @@ static struct tee_shm *get_msg_arg(struct tee_context *ctx, size_t num_params,
 
        ma = tee_shm_get_va(shm, 0);
        if (IS_ERR(ma)) {
-               rc = PTR_ERR(ma);
-               goto out;
+               tee_shm_free(shm);
+               return (void *)ma;
        }
 
-       rc = tee_shm_get_pa(shm, 0, msg_parg);
-       if (rc)
-               goto out;
-
        memset(ma, 0, OPTEE_MSG_GET_ARG_SIZE(num_params));
        ma->num_params = num_params;
        *msg_arg = ma;
-out:
-       if (rc) {
-               tee_shm_free(shm);
-               return ERR_PTR(rc);
-       }
 
        return shm;
 }
@@ -214,16 +208,16 @@ int optee_open_session(struct tee_context *ctx,
                       struct tee_ioctl_open_session_arg *arg,
                       struct tee_param *param)
 {
+       struct optee *optee = tee_get_drvdata(ctx->teedev);
        struct optee_context_data *ctxdata = ctx->data;
        int rc;
        struct tee_shm *shm;
        struct optee_msg_arg *msg_arg;
-       phys_addr_t msg_parg;
        struct optee_session *sess = NULL;
        uuid_t client_uuid;
 
        /* +2 for the meta parameters added below */
-       shm = get_msg_arg(ctx, arg->num_params + 2, &msg_arg, &msg_parg);
+       shm = get_msg_arg(ctx, arg->num_params + 2, &msg_arg);
        if (IS_ERR(shm))
                return PTR_ERR(shm);
 
@@ -247,7 +241,8 @@ int optee_open_session(struct tee_context *ctx,
                goto out;
        export_uuid(msg_arg->params[1].u.octets, &client_uuid);
 
-       rc = optee_to_msg_param(msg_arg->params + 2, arg->num_params, param);
+       rc = optee->ops->to_msg_param(optee, msg_arg->params + 2,
+                                     arg->num_params, param);
        if (rc)
                goto out;
 
@@ -257,7 +252,7 @@ int optee_open_session(struct tee_context *ctx,
                goto out;
        }
 
-       if (optee_do_call_with_arg(ctx, msg_parg)) {
+       if (optee->ops->do_call_with_arg(ctx, shm)) {
                msg_arg->ret = TEEC_ERROR_COMMUNICATION;
                msg_arg->ret_origin = TEEC_ORIGIN_COMMS;
        }
@@ -272,7 +267,8 @@ int optee_open_session(struct tee_context *ctx,
                kfree(sess);
        }
 
-       if (optee_from_msg_param(param, arg->num_params, msg_arg->params + 2)) {
+       if (optee->ops->from_msg_param(optee, param, arg->num_params,
+                                      msg_arg->params + 2)) {
                arg->ret = TEEC_ERROR_COMMUNICATION;
                arg->ret_origin = TEEC_ORIGIN_COMMS;
                /* Close session again to avoid leakage */
@@ -291,16 +287,16 @@ out:
 int optee_close_session_helper(struct tee_context *ctx, u32 session)
 {
        struct tee_shm *shm;
+       struct optee *optee = tee_get_drvdata(ctx->teedev);
        struct optee_msg_arg *msg_arg;
-       phys_addr_t msg_parg;
 
-       shm = get_msg_arg(ctx, 0, &msg_arg, &msg_parg);
+       shm = get_msg_arg(ctx, 0, &msg_arg);
        if (IS_ERR(shm))
                return PTR_ERR(shm);
 
        msg_arg->cmd = OPTEE_MSG_CMD_CLOSE_SESSION;
        msg_arg->session = session;
-       optee_do_call_with_arg(ctx, msg_parg);
+       optee->ops->do_call_with_arg(ctx, shm);
 
        tee_shm_free(shm);
 
@@ -328,10 +324,10 @@ int optee_close_session(struct tee_context *ctx, u32 session)
 int optee_invoke_func(struct tee_context *ctx, struct tee_ioctl_invoke_arg *arg,
                      struct tee_param *param)
 {
+       struct optee *optee = tee_get_drvdata(ctx->teedev);
        struct optee_context_data *ctxdata = ctx->data;
        struct tee_shm *shm;
        struct optee_msg_arg *msg_arg;
-       phys_addr_t msg_parg;
        struct optee_session *sess;
        int rc;
 
@@ -342,7 +338,7 @@ int optee_invoke_func(struct tee_context *ctx, struct tee_ioctl_invoke_arg *arg,
        if (!sess)
                return -EINVAL;
 
-       shm = get_msg_arg(ctx, arg->num_params, &msg_arg, &msg_parg);
+       shm = get_msg_arg(ctx, arg->num_params, &msg_arg);
        if (IS_ERR(shm))
                return PTR_ERR(shm);
        msg_arg->cmd = OPTEE_MSG_CMD_INVOKE_COMMAND;
@@ -350,16 +346,18 @@ int optee_invoke_func(struct tee_context *ctx, struct tee_ioctl_invoke_arg *arg,
        msg_arg->session = arg->session;
        msg_arg->cancel_id = arg->cancel_id;
 
-       rc = optee_to_msg_param(msg_arg->params, arg->num_params, param);
+       rc = optee->ops->to_msg_param(optee, msg_arg->params, arg->num_params,
+                                     param);
        if (rc)
                goto out;
 
-       if (optee_do_call_with_arg(ctx, msg_parg)) {
+       if (optee->ops->do_call_with_arg(ctx, shm)) {
                msg_arg->ret = TEEC_ERROR_COMMUNICATION;
                msg_arg->ret_origin = TEEC_ORIGIN_COMMS;
        }
 
-       if (optee_from_msg_param(param, arg->num_params, msg_arg->params)) {
+       if (optee->ops->from_msg_param(optee, param, arg->num_params,
+                                      msg_arg->params)) {
                msg_arg->ret = TEEC_ERROR_COMMUNICATION;
                msg_arg->ret_origin = TEEC_ORIGIN_COMMS;
        }
@@ -373,10 +371,10 @@ out:
 
 int optee_cancel_req(struct tee_context *ctx, u32 cancel_id, u32 session)
 {
+       struct optee *optee = tee_get_drvdata(ctx->teedev);
        struct optee_context_data *ctxdata = ctx->data;
        struct tee_shm *shm;
        struct optee_msg_arg *msg_arg;
-       phys_addr_t msg_parg;
        struct optee_session *sess;
 
        /* Check that the session is valid */
@@ -386,14 +384,14 @@ int optee_cancel_req(struct tee_context *ctx, u32 cancel_id, u32 session)
        if (!sess)
                return -EINVAL;
 
-       shm = get_msg_arg(ctx, 0, &msg_arg, &msg_parg);
+       shm = get_msg_arg(ctx, 0, &msg_arg);
        if (IS_ERR(shm))
                return PTR_ERR(shm);
 
        msg_arg->cmd = OPTEE_MSG_CMD_CANCEL;
        msg_arg->session = session;
        msg_arg->cancel_id = cancel_id;
-       optee_do_call_with_arg(ctx, msg_parg);
+       optee->ops->do_call_with_arg(ctx, shm);
 
        tee_shm_free(shm);
        return 0;
@@ -622,10 +620,10 @@ int optee_shm_register(struct tee_context *ctx, struct tee_shm *shm,
                       struct page **pages, size_t num_pages,
                       unsigned long start)
 {
-       struct tee_shm *shm_arg = NULL;
+       struct optee *optee = tee_get_drvdata(ctx->teedev);
        struct optee_msg_arg *msg_arg;
+       struct tee_shm *shm_arg;
        u64 *pages_list;
-       phys_addr_t msg_parg;
        int rc;
 
        if (!num_pages)
@@ -639,7 +637,7 @@ int optee_shm_register(struct tee_context *ctx, struct tee_shm *shm,
        if (!pages_list)
                return -ENOMEM;
 
-       shm_arg = get_msg_arg(ctx, 1, &msg_arg, &msg_parg);
+       shm_arg = get_msg_arg(ctx, 1, &msg_arg);
        if (IS_ERR(shm_arg)) {
                rc = PTR_ERR(shm_arg);
                goto out;
@@ -660,7 +658,7 @@ int optee_shm_register(struct tee_context *ctx, struct tee_shm *shm,
        msg_arg->params->u.tmem.buf_ptr = virt_to_phys(pages_list) |
          (tee_shm_get_page_offset(shm) & (OPTEE_MSG_NONCONTIG_PAGE_SIZE - 1));
 
-       if (optee_do_call_with_arg(ctx, msg_parg) ||
+       if (optee->ops->do_call_with_arg(ctx, shm_arg) ||
            msg_arg->ret != TEEC_SUCCESS)
                rc = -EINVAL;
 
@@ -672,12 +670,12 @@ out:
 
 int optee_shm_unregister(struct tee_context *ctx, struct tee_shm *shm)
 {
-       struct tee_shm *shm_arg;
+       struct optee *optee = tee_get_drvdata(ctx->teedev);
        struct optee_msg_arg *msg_arg;
-       phys_addr_t msg_parg;
+       struct tee_shm *shm_arg;
        int rc = 0;
 
-       shm_arg = get_msg_arg(ctx, 1, &msg_arg, &msg_parg);
+       shm_arg = get_msg_arg(ctx, 1, &msg_arg);
        if (IS_ERR(shm_arg))
                return PTR_ERR(shm_arg);
 
@@ -686,7 +684,7 @@ int optee_shm_unregister(struct tee_context *ctx, struct tee_shm *shm)
        msg_arg->params[0].attr = OPTEE_MSG_ATTR_TYPE_RMEM_INPUT;
        msg_arg->params[0].u.rmem.shm_ref = (unsigned long)shm;
 
-       if (optee_do_call_with_arg(ctx, msg_parg) ||
+       if (optee->ops->do_call_with_arg(ctx, shm_arg) ||
            msg_arg->ret != TEEC_SUCCESS)
                rc = -EINVAL;
        tee_shm_free(shm_arg);
index 79f67a79e7b7c45b226ea3c4143af23d4c768030..26492d3115f51bf4d8280d2f2cd7b414f896b443 100644 (file)
@@ -1,6 +1,6 @@
 // SPDX-License-Identifier: GPL-2.0-only
 /*
- * Copyright (c) 2015, Linaro Limited
+ * Copyright (c) 2015-2021, Linaro Limited
  */
 
 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
 
 #define OPTEE_SHM_NUM_PRIV_PAGES       CONFIG_OPTEE_SHM_NUM_PRIV_PAGES
 
+static void from_msg_param_value(struct tee_param *p, u32 attr,
+                                const struct optee_msg_param *mp)
+{
+       p->attr = TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INPUT +
+                 attr - OPTEE_MSG_ATTR_TYPE_VALUE_INPUT;
+       p->u.value.a = mp->u.value.a;
+       p->u.value.b = mp->u.value.b;
+       p->u.value.c = mp->u.value.c;
+}
+
+static int from_msg_param_tmp_mem(struct tee_param *p, u32 attr,
+                                 const struct optee_msg_param *mp)
+{
+       struct tee_shm *shm;
+       phys_addr_t pa;
+       int rc;
+
+       p->attr = TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INPUT +
+                 attr - OPTEE_MSG_ATTR_TYPE_TMEM_INPUT;
+       p->u.memref.size = mp->u.tmem.size;
+       shm = (struct tee_shm *)(unsigned long)mp->u.tmem.shm_ref;
+       if (!shm) {
+               p->u.memref.shm_offs = 0;
+               p->u.memref.shm = NULL;
+               return 0;
+       }
+
+       rc = tee_shm_get_pa(shm, 0, &pa);
+       if (rc)
+               return rc;
+
+       p->u.memref.shm_offs = mp->u.tmem.buf_ptr - pa;
+       p->u.memref.shm = shm;
+
+       /* Check that the memref is covered by the shm object */
+       if (p->u.memref.size) {
+               size_t o = p->u.memref.shm_offs +
+                          p->u.memref.size - 1;
+
+               rc = tee_shm_get_pa(shm, o, NULL);
+               if (rc)
+                       return rc;
+       }
+
+       return 0;
+}
+
+static void from_msg_param_reg_mem(struct tee_param *p, u32 attr,
+                                  const struct optee_msg_param *mp)
+{
+       struct tee_shm *shm;
+
+       p->attr = TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INPUT +
+                 attr - OPTEE_MSG_ATTR_TYPE_RMEM_INPUT;
+       p->u.memref.size = mp->u.rmem.size;
+       shm = (struct tee_shm *)(unsigned long)mp->u.rmem.shm_ref;
+
+       if (shm) {
+               p->u.memref.shm_offs = mp->u.rmem.offs;
+               p->u.memref.shm = shm;
+       } else {
+               p->u.memref.shm_offs = 0;
+               p->u.memref.shm = NULL;
+       }
+}
+
 /**
  * optee_from_msg_param() - convert from OPTEE_MSG parameters to
  *                         struct tee_param
+ * @optee:     main service struct
  * @params:    subsystem internal parameter representation
  * @num_params:        number of elements in the parameter arrays
  * @msg_params:        OPTEE_MSG parameters
  * Returns 0 on success or <0 on failure
  */
-int optee_from_msg_param(struct tee_param *params, size_t num_params,
-                        const struct optee_msg_param *msg_params)
+static int optee_from_msg_param(struct optee *optee, struct tee_param *params,
+                               size_t num_params,
+                               const struct optee_msg_param *msg_params)
 {
        int rc;
        size_t n;
-       struct tee_shm *shm;
-       phys_addr_t pa;
 
        for (n = 0; n < num_params; n++) {
                struct tee_param *p = params + n;
@@ -56,48 +122,19 @@ int optee_from_msg_param(struct tee_param *params, size_t num_params,
                case OPTEE_MSG_ATTR_TYPE_VALUE_INPUT:
                case OPTEE_MSG_ATTR_TYPE_VALUE_OUTPUT:
                case OPTEE_MSG_ATTR_TYPE_VALUE_INOUT:
-                       p->attr = TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INPUT +
-                                 attr - OPTEE_MSG_ATTR_TYPE_VALUE_INPUT;
-                       p->u.value.a = mp->u.value.a;
-                       p->u.value.b = mp->u.value.b;
-                       p->u.value.c = mp->u.value.c;
+                       from_msg_param_value(p, attr, mp);
                        break;
                case OPTEE_MSG_ATTR_TYPE_TMEM_INPUT:
                case OPTEE_MSG_ATTR_TYPE_TMEM_OUTPUT:
                case OPTEE_MSG_ATTR_TYPE_TMEM_INOUT:
-                       p->attr = TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INPUT +
-                                 attr - OPTEE_MSG_ATTR_TYPE_TMEM_INPUT;
-                       p->u.memref.size = mp->u.tmem.size;
-                       shm = (struct tee_shm *)(unsigned long)
-                               mp->u.tmem.shm_ref;
-                       if (!shm) {
-                               p->u.memref.shm_offs = 0;
-                               p->u.memref.shm = NULL;
-                               break;
-                       }
-                       rc = tee_shm_get_pa(shm, 0, &pa);
+                       rc = from_msg_param_tmp_mem(p, attr, mp);
                        if (rc)
                                return rc;
-                       p->u.memref.shm_offs = mp->u.tmem.buf_ptr - pa;
-                       p->u.memref.shm = shm;
                        break;
                case OPTEE_MSG_ATTR_TYPE_RMEM_INPUT:
                case OPTEE_MSG_ATTR_TYPE_RMEM_OUTPUT:
                case OPTEE_MSG_ATTR_TYPE_RMEM_INOUT:
-                       p->attr = TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INPUT +
-                                 attr - OPTEE_MSG_ATTR_TYPE_RMEM_INPUT;
-                       p->u.memref.size = mp->u.rmem.size;
-                       shm = (struct tee_shm *)(unsigned long)
-                               mp->u.rmem.shm_ref;
-
-                       if (!shm) {
-                               p->u.memref.shm_offs = 0;
-                               p->u.memref.shm = NULL;
-                               break;
-                       }
-                       p->u.memref.shm_offs = mp->u.rmem.offs;
-                       p->u.memref.shm = shm;
-
+                       from_msg_param_reg_mem(p, attr, mp);
                        break;
 
                default:
@@ -107,6 +144,16 @@ int optee_from_msg_param(struct tee_param *params, size_t num_params,
        return 0;
 }
 
+static void to_msg_param_value(struct optee_msg_param *mp,
+                              const struct tee_param *p)
+{
+       mp->attr = OPTEE_MSG_ATTR_TYPE_VALUE_INPUT + p->attr -
+                  TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INPUT;
+       mp->u.value.a = p->u.value.a;
+       mp->u.value.b = p->u.value.b;
+       mp->u.value.c = p->u.value.c;
+}
+
 static int to_msg_param_tmp_mem(struct optee_msg_param *mp,
                                const struct tee_param *p)
 {
@@ -149,13 +196,15 @@ static int to_msg_param_reg_mem(struct optee_msg_param *mp,
 
 /**
  * optee_to_msg_param() - convert from struct tee_params to OPTEE_MSG parameters
+ * @optee:     main service struct
  * @msg_params:        OPTEE_MSG parameters
  * @num_params:        number of elements in the parameter arrays
  * @params:    subsystem itnernal parameter representation
  * Returns 0 on success or <0 on failure
  */
-int optee_to_msg_param(struct optee_msg_param *msg_params, size_t num_params,
-                      const struct tee_param *params)
+static int optee_to_msg_param(struct optee *optee,
+                             struct optee_msg_param *msg_params,
+                             size_t num_params, const struct tee_param *params)
 {
        int rc;
        size_t n;
@@ -172,11 +221,7 @@ int optee_to_msg_param(struct optee_msg_param *msg_params, size_t num_params,
                case TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INPUT:
                case TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_OUTPUT:
                case TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INOUT:
-                       mp->attr = OPTEE_MSG_ATTR_TYPE_VALUE_INPUT + p->attr -
-                                  TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INPUT;
-                       mp->u.value.a = p->u.value.a;
-                       mp->u.value.b = p->u.value.b;
-                       mp->u.value.c = p->u.value.c;
+                       to_msg_param_value(mp, p);
                        break;
                case TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INPUT:
                case TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_OUTPUT:
@@ -302,7 +347,7 @@ static void optee_release_supp(struct tee_context *ctx)
        optee_supp_release(&optee->supp);
 }
 
-static const struct tee_driver_ops optee_ops = {
+static const struct tee_driver_ops optee_clnt_ops = {
        .get_version = optee_get_version,
        .open = optee_open,
        .release = optee_release,
@@ -314,9 +359,9 @@ static const struct tee_driver_ops optee_ops = {
        .shm_unregister = optee_shm_unregister,
 };
 
-static const struct tee_desc optee_desc = {
+static const struct tee_desc optee_clnt_desc = {
        .name = DRIVER_NAME "-clnt",
-       .ops = &optee_ops,
+       .ops = &optee_clnt_ops,
        .owner = THIS_MODULE,
 };
 
@@ -337,6 +382,12 @@ static const struct tee_desc optee_supp_desc = {
        .flags = TEE_DESC_PRIVILEGED,
 };
 
+static const struct optee_ops optee_ops = {
+       .do_call_with_arg = optee_do_call_with_arg,
+       .to_msg_param = optee_to_msg_param,
+       .from_msg_param = optee_from_msg_param,
+};
+
 static bool optee_msg_api_uid_is_optee_api(optee_invoke_fn *invoke_fn)
 {
        struct arm_smccc_res res;
@@ -670,10 +721,11 @@ static int optee_probe(struct platform_device *pdev)
                goto err;
        }
 
+       optee->ops = &optee_ops;
        optee->invoke_fn = invoke_fn;
        optee->sec_caps = sec_caps;
 
-       teedev = tee_device_alloc(&optee_desc, NULL, pool, optee);
+       teedev = tee_device_alloc(&optee_clnt_desc, NULL, pool, optee);
        if (IS_ERR(teedev)) {
                rc = PTR_ERR(teedev);
                goto err;
index a55793f9f6eb8ad9d366eee2582fe87e5d55edd2..beca97017996cba522bcd35d4caf6cb743b9bc54 100644 (file)
@@ -1,6 +1,6 @@
 /* SPDX-License-Identifier: GPL-2.0-only */
 /*
- * Copyright (c) 2015, Linaro Limited
+ * Copyright (c) 2015-2021, Linaro Limited
  */
 
 #ifndef OPTEE_PRIVATE_H
@@ -66,9 +66,34 @@ struct optee_supp {
        struct completion reqs_c;
 };
 
+struct optee;
+
+/**
+ * struct optee_ops - OP-TEE driver internal operations
+ * @do_call_with_arg:  enters OP-TEE in secure world
+ * @to_msg_param:      converts from struct tee_param to OPTEE_MSG parameters
+ * @from_msg_param:    converts from OPTEE_MSG parameters to struct tee_param
+ *
+ * These OPs are only supposed to be used internally in the OP-TEE driver
+ * as a way of abstracting the different methogs of entering OP-TEE in
+ * secure world.
+ */
+struct optee_ops {
+       int (*do_call_with_arg)(struct tee_context *ctx,
+                               struct tee_shm *shm_arg);
+       int (*to_msg_param)(struct optee *optee,
+                           struct optee_msg_param *msg_params,
+                           size_t num_params, const struct tee_param *params);
+       int (*from_msg_param)(struct optee *optee, struct tee_param *params,
+                             size_t num_params,
+                             const struct optee_msg_param *msg_params);
+};
+
 /**
  * struct optee - main service struct
  * @supp_teedev:       supplicant device
+ * @ops:               internal callbacks for different ways to reach secure
+ *                     world
  * @teedev:            client device
  * @invoke_fn:         function to issue smc or hvc
  * @call_queue:                queue of threads waiting to call @invoke_fn
@@ -86,6 +111,7 @@ struct optee_supp {
 struct optee {
        struct tee_device *supp_teedev;
        struct tee_device *teedev;
+       const struct optee_ops *ops;
        optee_invoke_fn *invoke_fn;
        struct optee_call_queue call_queue;
        struct optee_wait_queue wait_queue;
@@ -148,7 +174,7 @@ int optee_supp_recv(struct tee_context *ctx, u32 *func, u32 *num_params,
 int optee_supp_send(struct tee_context *ctx, u32 ret, u32 num_params,
                    struct tee_param *param);
 
-u32 optee_do_call_with_arg(struct tee_context *ctx, phys_addr_t parg);
+int optee_do_call_with_arg(struct tee_context *ctx, struct tee_shm *arg);
 int optee_open_session(struct tee_context *ctx,
                       struct tee_ioctl_open_session_arg *arg,
                       struct tee_param *param);
@@ -172,11 +198,6 @@ int optee_shm_register_supp(struct tee_context *ctx, struct tee_shm *shm,
                            unsigned long start);
 int optee_shm_unregister_supp(struct tee_context *ctx, struct tee_shm *shm);
 
-int optee_from_msg_param(struct tee_param *params, size_t num_params,
-                        const struct optee_msg_param *msg_params);
-int optee_to_msg_param(struct optee_msg_param *msg_params, size_t num_params,
-                      const struct tee_param *params);
-
 u64 *optee_allocate_pages_list(size_t num_entries);
 void optee_free_pages_list(void *array, size_t num_entries);
 void optee_fill_pages_list(u64 *dst, struct page **pages, int num_pages,
index efbaff7ad7e59bac2a08c56b6b321953903f7c01..309258d47790f97a7c74fd82c8d52e552fd3af21 100644 (file)
@@ -1,6 +1,6 @@
 // SPDX-License-Identifier: GPL-2.0-only
 /*
- * Copyright (c) 2015-2016, Linaro Limited
+ * Copyright (c) 2015-2021, Linaro Limited
  */
 
 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
@@ -55,6 +55,7 @@ bad:
 static void handle_rpc_func_cmd_i2c_transfer(struct tee_context *ctx,
                                             struct optee_msg_arg *arg)
 {
+       struct optee *optee = tee_get_drvdata(ctx->teedev);
        struct tee_param *params;
        struct i2c_adapter *adapter;
        struct i2c_msg msg = { };
@@ -79,7 +80,8 @@ static void handle_rpc_func_cmd_i2c_transfer(struct tee_context *ctx,
                return;
        }
 
-       if (optee_from_msg_param(params, arg->num_params, arg->params))
+       if (optee->ops->from_msg_param(optee, params, arg->num_params,
+                                      arg->params))
                goto bad;
 
        for (i = 0; i < arg->num_params; i++) {
@@ -122,7 +124,8 @@ static void handle_rpc_func_cmd_i2c_transfer(struct tee_context *ctx,
                arg->ret = TEEC_ERROR_COMMUNICATION;
        } else {
                params[3].u.value.a = msg.len;
-               if (optee_to_msg_param(arg->params, arg->num_params, params))
+               if (optee->ops->to_msg_param(optee, arg->params,
+                                            arg->num_params, params))
                        arg->ret = TEEC_ERROR_BAD_PARAMETERS;
                else
                        arg->ret = TEEC_SUCCESS;
@@ -234,7 +237,7 @@ bad:
        arg->ret = TEEC_ERROR_BAD_PARAMETERS;
 }
 
-static void handle_rpc_supp_cmd(struct tee_context *ctx,
+static void handle_rpc_supp_cmd(struct tee_context *ctx, struct optee *optee,
                                struct optee_msg_arg *arg)
 {
        struct tee_param *params;
@@ -248,14 +251,16 @@ static void handle_rpc_supp_cmd(struct tee_context *ctx,
                return;
        }
 
-       if (optee_from_msg_param(params, arg->num_params, arg->params)) {
+       if (optee->ops->from_msg_param(optee, params, arg->num_params,
+                                      arg->params)) {
                arg->ret = TEEC_ERROR_BAD_PARAMETERS;
                goto out;
        }
 
        arg->ret = optee_supp_thrd_req(ctx, arg->cmd, arg->num_params, params);
 
-       if (optee_to_msg_param(arg->params, arg->num_params, params))
+       if (optee->ops->to_msg_param(optee, arg->params, arg->num_params,
+                                    params))
                arg->ret = TEEC_ERROR_BAD_PARAMETERS;
 out:
        kfree(params);
@@ -480,7 +485,7 @@ static void handle_rpc_func_cmd(struct tee_context *ctx, struct optee *optee,
                handle_rpc_func_cmd_i2c_transfer(ctx, arg);
                break;
        default:
-               handle_rpc_supp_cmd(ctx, arg);
+               handle_rpc_supp_cmd(ctx, optee, arg);
        }
 }