1d6e29083SAmirreza Zarrabi // SPDX-License-Identifier: GPL-2.0-only 2d6e29083SAmirreza Zarrabi /* 3d6e29083SAmirreza Zarrabi * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. 4d6e29083SAmirreza Zarrabi */ 5d6e29083SAmirreza Zarrabi 6d6e29083SAmirreza Zarrabi #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 7d6e29083SAmirreza Zarrabi 8d6e29083SAmirreza Zarrabi #include <linux/slab.h> 9d6e29083SAmirreza Zarrabi #include <linux/tee.h> 10d6e29083SAmirreza Zarrabi #include <linux/platform_device.h> 11d6e29083SAmirreza Zarrabi #include <linux/xarray.h> 12d6e29083SAmirreza Zarrabi 13d6e29083SAmirreza Zarrabi #include "qcomtee.h" 14d6e29083SAmirreza Zarrabi 15d6e29083SAmirreza Zarrabi static int find_qtee_object(struct qcomtee_object **object, unsigned long id, 16d6e29083SAmirreza Zarrabi struct qcomtee_context_data *ctxdata) 17d6e29083SAmirreza Zarrabi { 18d6e29083SAmirreza Zarrabi int err = 0; 19d6e29083SAmirreza Zarrabi 20d6e29083SAmirreza Zarrabi guard(rcu)(); 21d6e29083SAmirreza Zarrabi /* Object release is RCU protected. */ 22d6e29083SAmirreza Zarrabi *object = idr_find(&ctxdata->qtee_objects_idr, id); 23d6e29083SAmirreza Zarrabi if (!qcomtee_object_get(*object)) 24d6e29083SAmirreza Zarrabi err = -EINVAL; 25d6e29083SAmirreza Zarrabi 26d6e29083SAmirreza Zarrabi return err; 27d6e29083SAmirreza Zarrabi } 28d6e29083SAmirreza Zarrabi 29d6e29083SAmirreza Zarrabi static void del_qtee_object(unsigned long id, 30d6e29083SAmirreza Zarrabi struct qcomtee_context_data *ctxdata) 31d6e29083SAmirreza Zarrabi { 32d6e29083SAmirreza Zarrabi struct qcomtee_object *object; 33d6e29083SAmirreza Zarrabi 34d6e29083SAmirreza Zarrabi scoped_guard(mutex, &ctxdata->qtee_lock) 35d6e29083SAmirreza Zarrabi object = idr_remove(&ctxdata->qtee_objects_idr, id); 36d6e29083SAmirreza Zarrabi 37d6e29083SAmirreza Zarrabi qcomtee_object_put(object); 38d6e29083SAmirreza Zarrabi } 39d6e29083SAmirreza Zarrabi 40d6e29083SAmirreza Zarrabi /** 41d6e29083SAmirreza Zarrabi * qcomtee_context_add_qtee_object() - Add a QTEE object to the context. 42d6e29083SAmirreza Zarrabi * @param: TEE parameter representing @object. 43d6e29083SAmirreza Zarrabi * @object: QTEE object. 44d6e29083SAmirreza Zarrabi * @ctx: context to add the object. 45d6e29083SAmirreza Zarrabi * 46d6e29083SAmirreza Zarrabi * It assumes @object is %QCOMTEE_OBJECT_TYPE_TEE and the caller has already 47d6e29083SAmirreza Zarrabi * issued qcomtee_object_get() for @object. 48d6e29083SAmirreza Zarrabi * 49d6e29083SAmirreza Zarrabi * Return: On success, returns 0; on failure, returns < 0. 50d6e29083SAmirreza Zarrabi */ 51d6e29083SAmirreza Zarrabi int qcomtee_context_add_qtee_object(struct tee_param *param, 52d6e29083SAmirreza Zarrabi struct qcomtee_object *object, 53d6e29083SAmirreza Zarrabi struct tee_context *ctx) 54d6e29083SAmirreza Zarrabi { 55d6e29083SAmirreza Zarrabi int ret; 56d6e29083SAmirreza Zarrabi struct qcomtee_context_data *ctxdata = ctx->data; 57d6e29083SAmirreza Zarrabi 58d6e29083SAmirreza Zarrabi scoped_guard(mutex, &ctxdata->qtee_lock) 59d6e29083SAmirreza Zarrabi ret = idr_alloc(&ctxdata->qtee_objects_idr, object, 0, 0, 60d6e29083SAmirreza Zarrabi GFP_KERNEL); 61d6e29083SAmirreza Zarrabi if (ret < 0) 62d6e29083SAmirreza Zarrabi return ret; 63d6e29083SAmirreza Zarrabi 64d6e29083SAmirreza Zarrabi param->u.objref.id = ret; 65d6e29083SAmirreza Zarrabi /* QTEE Object: QCOMTEE_OBJREF_FLAG_TEE set. */ 66d6e29083SAmirreza Zarrabi param->u.objref.flags = QCOMTEE_OBJREF_FLAG_TEE; 67d6e29083SAmirreza Zarrabi 68d6e29083SAmirreza Zarrabi return 0; 69d6e29083SAmirreza Zarrabi } 70d6e29083SAmirreza Zarrabi 71d6e29083SAmirreza Zarrabi /* Retrieve the QTEE object added with qcomtee_context_add_qtee_object(). */ 72d6e29083SAmirreza Zarrabi int qcomtee_context_find_qtee_object(struct qcomtee_object **object, 73d6e29083SAmirreza Zarrabi struct tee_param *param, 74d6e29083SAmirreza Zarrabi struct tee_context *ctx) 75d6e29083SAmirreza Zarrabi { 76d6e29083SAmirreza Zarrabi struct qcomtee_context_data *ctxdata = ctx->data; 77d6e29083SAmirreza Zarrabi 78d6e29083SAmirreza Zarrabi return find_qtee_object(object, param->u.objref.id, ctxdata); 79d6e29083SAmirreza Zarrabi } 80d6e29083SAmirreza Zarrabi 81d6e29083SAmirreza Zarrabi /** 82d6e29083SAmirreza Zarrabi * qcomtee_context_del_qtee_object() - Delete a QTEE object from the context. 83d6e29083SAmirreza Zarrabi * @param: TEE parameter representing @object. 84d6e29083SAmirreza Zarrabi * @ctx: context for deleting the object. 85d6e29083SAmirreza Zarrabi * 86d6e29083SAmirreza Zarrabi * The @param has been initialized by qcomtee_context_add_qtee_object(). 87d6e29083SAmirreza Zarrabi */ 88d6e29083SAmirreza Zarrabi void qcomtee_context_del_qtee_object(struct tee_param *param, 89d6e29083SAmirreza Zarrabi struct tee_context *ctx) 90d6e29083SAmirreza Zarrabi { 91d6e29083SAmirreza Zarrabi struct qcomtee_context_data *ctxdata = ctx->data; 92d6e29083SAmirreza Zarrabi /* 'qtee_objects_idr' stores QTEE objects only. */ 93d6e29083SAmirreza Zarrabi if (param->u.objref.flags & QCOMTEE_OBJREF_FLAG_TEE) 94d6e29083SAmirreza Zarrabi del_qtee_object(param->u.objref.id, ctxdata); 95d6e29083SAmirreza Zarrabi } 96d6e29083SAmirreza Zarrabi 97d6e29083SAmirreza Zarrabi /** 98d6e29083SAmirreza Zarrabi * qcomtee_objref_to_arg() - Convert OBJREF parameter to QTEE argument. 99d6e29083SAmirreza Zarrabi * @arg: QTEE argument. 100d6e29083SAmirreza Zarrabi * @param: TEE parameter. 101d6e29083SAmirreza Zarrabi * @ctx: context in which the conversion should happen. 102d6e29083SAmirreza Zarrabi * 103d6e29083SAmirreza Zarrabi * It assumes @param is an OBJREF. 104d6e29083SAmirreza Zarrabi * It does not set @arg.type; the caller should initialize it to a correct 105d6e29083SAmirreza Zarrabi * &enum qcomtee_arg_type value. It gets the object's refcount in @arg; 106d6e29083SAmirreza Zarrabi * the caller should manage to put it afterward. 107d6e29083SAmirreza Zarrabi * 108d6e29083SAmirreza Zarrabi * Return: On success, returns 0; on failure, returns < 0. 109d6e29083SAmirreza Zarrabi */ 110d6e29083SAmirreza Zarrabi int qcomtee_objref_to_arg(struct qcomtee_arg *arg, struct tee_param *param, 111d6e29083SAmirreza Zarrabi struct tee_context *ctx) 112d6e29083SAmirreza Zarrabi { 113d6e29083SAmirreza Zarrabi int err = -EINVAL; 114d6e29083SAmirreza Zarrabi 115d6e29083SAmirreza Zarrabi arg->o = NULL_QCOMTEE_OBJECT; 116d6e29083SAmirreza Zarrabi /* param is a NULL object: */ 117d6e29083SAmirreza Zarrabi if (param->u.objref.id == TEE_OBJREF_NULL) 118d6e29083SAmirreza Zarrabi return 0; 119d6e29083SAmirreza Zarrabi 120d6e29083SAmirreza Zarrabi /* param is a callback object: */ 121d6e29083SAmirreza Zarrabi if (param->u.objref.flags & QCOMTEE_OBJREF_FLAG_USER) 122d6e29083SAmirreza Zarrabi err = qcomtee_user_param_to_object(&arg->o, param, ctx); 123d6e29083SAmirreza Zarrabi /* param is a QTEE object: */ 124d6e29083SAmirreza Zarrabi else if (param->u.objref.flags & QCOMTEE_OBJREF_FLAG_TEE) 125d6e29083SAmirreza Zarrabi err = qcomtee_context_find_qtee_object(&arg->o, param, ctx); 126*87ab676dSAmirreza Zarrabi /* param is a memory object: */ 127*87ab676dSAmirreza Zarrabi else if (param->u.objref.flags & QCOMTEE_OBJREF_FLAG_MEM) 128*87ab676dSAmirreza Zarrabi err = qcomtee_memobj_param_to_object(&arg->o, param, ctx); 129d6e29083SAmirreza Zarrabi 130d6e29083SAmirreza Zarrabi /* 131d6e29083SAmirreza Zarrabi * For callback objects, call qcomtee_object_get() to keep a temporary 132d6e29083SAmirreza Zarrabi * copy for the driver, as these objects are released asynchronously 133d6e29083SAmirreza Zarrabi * and may disappear even before returning from QTEE. 134d6e29083SAmirreza Zarrabi * 135d6e29083SAmirreza Zarrabi * - For direct object invocations, the matching put is called in 136d6e29083SAmirreza Zarrabi * qcomtee_object_invoke() when parsing the QTEE response. 137d6e29083SAmirreza Zarrabi * - For callback responses, put is called in qcomtee_user_object_notify() 138d6e29083SAmirreza Zarrabi * after QTEE has received its copies. 139d6e29083SAmirreza Zarrabi */ 140d6e29083SAmirreza Zarrabi 141d6e29083SAmirreza Zarrabi if (!err && (typeof_qcomtee_object(arg->o) == QCOMTEE_OBJECT_TYPE_CB)) 142d6e29083SAmirreza Zarrabi qcomtee_object_get(arg->o); 143d6e29083SAmirreza Zarrabi 144d6e29083SAmirreza Zarrabi return err; 145d6e29083SAmirreza Zarrabi } 146d6e29083SAmirreza Zarrabi 147d6e29083SAmirreza Zarrabi /** 148d6e29083SAmirreza Zarrabi * qcomtee_objref_from_arg() - Convert QTEE argument to OBJREF param. 149d6e29083SAmirreza Zarrabi * @param: TEE parameter. 150d6e29083SAmirreza Zarrabi * @arg: QTEE argument. 151d6e29083SAmirreza Zarrabi * @ctx: context in which the conversion should happen. 152d6e29083SAmirreza Zarrabi * 153d6e29083SAmirreza Zarrabi * It assumes @arg is of %QCOMTEE_ARG_TYPE_IO or %QCOMTEE_ARG_TYPE_OO. 154d6e29083SAmirreza Zarrabi * It does not set @param.attr; the caller should initialize it to a 155d6e29083SAmirreza Zarrabi * correct type. 156d6e29083SAmirreza Zarrabi * 157d6e29083SAmirreza Zarrabi * Return: On success, returns 0; on failure, returns < 0. 158d6e29083SAmirreza Zarrabi */ 159d6e29083SAmirreza Zarrabi int qcomtee_objref_from_arg(struct tee_param *param, struct qcomtee_arg *arg, 160d6e29083SAmirreza Zarrabi struct tee_context *ctx) 161d6e29083SAmirreza Zarrabi { 162d6e29083SAmirreza Zarrabi struct qcomtee_object *object = arg->o; 163d6e29083SAmirreza Zarrabi 164d6e29083SAmirreza Zarrabi switch (typeof_qcomtee_object(object)) { 165d6e29083SAmirreza Zarrabi case QCOMTEE_OBJECT_TYPE_NULL: 166d6e29083SAmirreza Zarrabi param->u.objref.id = TEE_OBJREF_NULL; 167d6e29083SAmirreza Zarrabi 168d6e29083SAmirreza Zarrabi return 0; 169d6e29083SAmirreza Zarrabi case QCOMTEE_OBJECT_TYPE_CB: 170d6e29083SAmirreza Zarrabi /* object is a callback object: */ 171d6e29083SAmirreza Zarrabi if (is_qcomtee_user_object(object)) 172d6e29083SAmirreza Zarrabi return qcomtee_user_param_from_object(param, object, 173d6e29083SAmirreza Zarrabi ctx); 174*87ab676dSAmirreza Zarrabi /* object is a memory object: */ 175*87ab676dSAmirreza Zarrabi else if (is_qcomtee_memobj_object(object)) 176*87ab676dSAmirreza Zarrabi return qcomtee_memobj_param_from_object(param, object, 177*87ab676dSAmirreza Zarrabi ctx); 178d6e29083SAmirreza Zarrabi 179d6e29083SAmirreza Zarrabi break; 180d6e29083SAmirreza Zarrabi case QCOMTEE_OBJECT_TYPE_TEE: 181d6e29083SAmirreza Zarrabi return qcomtee_context_add_qtee_object(param, object, ctx); 182d6e29083SAmirreza Zarrabi 183d6e29083SAmirreza Zarrabi case QCOMTEE_OBJECT_TYPE_ROOT: 184d6e29083SAmirreza Zarrabi default: 185d6e29083SAmirreza Zarrabi break; 186d6e29083SAmirreza Zarrabi } 187d6e29083SAmirreza Zarrabi 188d6e29083SAmirreza Zarrabi return -EINVAL; 189d6e29083SAmirreza Zarrabi } 190d6e29083SAmirreza Zarrabi 191d6e29083SAmirreza Zarrabi /** 192d6e29083SAmirreza Zarrabi * qcomtee_params_to_args() - Convert TEE parameters to QTEE arguments. 193d6e29083SAmirreza Zarrabi * @u: QTEE arguments. 194d6e29083SAmirreza Zarrabi * @params: TEE parameters. 195d6e29083SAmirreza Zarrabi * @num_params: number of elements in the parameter array. 196d6e29083SAmirreza Zarrabi * @ctx: context in which the conversion should happen. 197d6e29083SAmirreza Zarrabi * 198d6e29083SAmirreza Zarrabi * It assumes @u has at least @num_params + 1 entries and has been initialized 199d6e29083SAmirreza Zarrabi * with %QCOMTEE_ARG_TYPE_INV as &struct qcomtee_arg.type. 200d6e29083SAmirreza Zarrabi * 201d6e29083SAmirreza Zarrabi * Return: On success, returns 0; on failure, returns < 0. 202d6e29083SAmirreza Zarrabi */ 203d6e29083SAmirreza Zarrabi static int qcomtee_params_to_args(struct qcomtee_arg *u, 204d6e29083SAmirreza Zarrabi struct tee_param *params, int num_params, 205d6e29083SAmirreza Zarrabi struct tee_context *ctx) 206d6e29083SAmirreza Zarrabi { 207d6e29083SAmirreza Zarrabi int i; 208d6e29083SAmirreza Zarrabi 209d6e29083SAmirreza Zarrabi for (i = 0; i < num_params; i++) { 210d6e29083SAmirreza Zarrabi switch (params[i].attr) { 211d6e29083SAmirreza Zarrabi case TEE_IOCTL_PARAM_ATTR_TYPE_UBUF_INPUT: 212d6e29083SAmirreza Zarrabi case TEE_IOCTL_PARAM_ATTR_TYPE_UBUF_OUTPUT: 213d6e29083SAmirreza Zarrabi u[i].flags = QCOMTEE_ARG_FLAGS_UADDR; 214d6e29083SAmirreza Zarrabi u[i].b.uaddr = params[i].u.ubuf.uaddr; 215d6e29083SAmirreza Zarrabi u[i].b.size = params[i].u.ubuf.size; 216d6e29083SAmirreza Zarrabi 217d6e29083SAmirreza Zarrabi if (params[i].attr == 218d6e29083SAmirreza Zarrabi TEE_IOCTL_PARAM_ATTR_TYPE_UBUF_INPUT) 219d6e29083SAmirreza Zarrabi u[i].type = QCOMTEE_ARG_TYPE_IB; 220d6e29083SAmirreza Zarrabi else /* TEE_IOCTL_PARAM_ATTR_TYPE_UBUF_OUTPUT */ 221d6e29083SAmirreza Zarrabi u[i].type = QCOMTEE_ARG_TYPE_OB; 222d6e29083SAmirreza Zarrabi 223d6e29083SAmirreza Zarrabi break; 224d6e29083SAmirreza Zarrabi case TEE_IOCTL_PARAM_ATTR_TYPE_OBJREF_INPUT: 225d6e29083SAmirreza Zarrabi u[i].type = QCOMTEE_ARG_TYPE_IO; 226d6e29083SAmirreza Zarrabi if (qcomtee_objref_to_arg(&u[i], ¶ms[i], ctx)) 227d6e29083SAmirreza Zarrabi goto out_failed; 228d6e29083SAmirreza Zarrabi 229d6e29083SAmirreza Zarrabi break; 230d6e29083SAmirreza Zarrabi case TEE_IOCTL_PARAM_ATTR_TYPE_OBJREF_OUTPUT: 231d6e29083SAmirreza Zarrabi u[i].type = QCOMTEE_ARG_TYPE_OO; 232d6e29083SAmirreza Zarrabi u[i].o = NULL_QCOMTEE_OBJECT; 233d6e29083SAmirreza Zarrabi break; 234d6e29083SAmirreza Zarrabi default: 235d6e29083SAmirreza Zarrabi goto out_failed; 236d6e29083SAmirreza Zarrabi } 237d6e29083SAmirreza Zarrabi } 238d6e29083SAmirreza Zarrabi 239d6e29083SAmirreza Zarrabi return 0; 240d6e29083SAmirreza Zarrabi 241d6e29083SAmirreza Zarrabi out_failed: 242d6e29083SAmirreza Zarrabi /* Undo qcomtee_objref_to_arg(). */ 243d6e29083SAmirreza Zarrabi for (i--; i >= 0; i--) { 244d6e29083SAmirreza Zarrabi if (u[i].type != QCOMTEE_ARG_TYPE_IO) 245d6e29083SAmirreza Zarrabi continue; 246d6e29083SAmirreza Zarrabi 247d6e29083SAmirreza Zarrabi qcomtee_user_object_set_notify(u[i].o, false); 248d6e29083SAmirreza Zarrabi /* See docs for qcomtee_objref_to_arg() for double put. */ 249d6e29083SAmirreza Zarrabi if (typeof_qcomtee_object(u[i].o) == QCOMTEE_OBJECT_TYPE_CB) 250d6e29083SAmirreza Zarrabi qcomtee_object_put(u[i].o); 251d6e29083SAmirreza Zarrabi 252d6e29083SAmirreza Zarrabi qcomtee_object_put(u[i].o); 253d6e29083SAmirreza Zarrabi } 254d6e29083SAmirreza Zarrabi 255d6e29083SAmirreza Zarrabi return -EINVAL; 256d6e29083SAmirreza Zarrabi } 257d6e29083SAmirreza Zarrabi 258d6e29083SAmirreza Zarrabi /** 259d6e29083SAmirreza Zarrabi * qcomtee_params_from_args() - Convert QTEE arguments to TEE parameters. 260d6e29083SAmirreza Zarrabi * @params: TEE parameters. 261d6e29083SAmirreza Zarrabi * @u: QTEE arguments. 262d6e29083SAmirreza Zarrabi * @num_params: number of elements in the parameter array. 263d6e29083SAmirreza Zarrabi * @ctx: context in which the conversion should happen. 264d6e29083SAmirreza Zarrabi * 265d6e29083SAmirreza Zarrabi * @u should have already been initialized by qcomtee_params_to_args(). 266d6e29083SAmirreza Zarrabi * This also represents the end of a QTEE invocation that started with 267d6e29083SAmirreza Zarrabi * qcomtee_params_to_args() by releasing %QCOMTEE_ARG_TYPE_IO objects. 268d6e29083SAmirreza Zarrabi * 269d6e29083SAmirreza Zarrabi * Return: On success, returns 0; on failure, returns < 0. 270d6e29083SAmirreza Zarrabi */ 271d6e29083SAmirreza Zarrabi static int qcomtee_params_from_args(struct tee_param *params, 272d6e29083SAmirreza Zarrabi struct qcomtee_arg *u, int num_params, 273d6e29083SAmirreza Zarrabi struct tee_context *ctx) 274d6e29083SAmirreza Zarrabi { 275d6e29083SAmirreza Zarrabi int i, np; 276d6e29083SAmirreza Zarrabi 277d6e29083SAmirreza Zarrabi qcomtee_arg_for_each(np, u) { 278d6e29083SAmirreza Zarrabi switch (u[np].type) { 279d6e29083SAmirreza Zarrabi case QCOMTEE_ARG_TYPE_OB: 280d6e29083SAmirreza Zarrabi /* TEE_IOCTL_PARAM_ATTR_TYPE_UBUF_OUTPUT */ 281d6e29083SAmirreza Zarrabi params[np].u.ubuf.size = u[np].b.size; 282d6e29083SAmirreza Zarrabi 283d6e29083SAmirreza Zarrabi break; 284d6e29083SAmirreza Zarrabi case QCOMTEE_ARG_TYPE_IO: 285d6e29083SAmirreza Zarrabi /* IEE_IOCTL_PARAM_ATTR_TYPE_OBJREF_INPUT */ 286d6e29083SAmirreza Zarrabi qcomtee_object_put(u[np].o); 287d6e29083SAmirreza Zarrabi 288d6e29083SAmirreza Zarrabi break; 289d6e29083SAmirreza Zarrabi case QCOMTEE_ARG_TYPE_OO: 290d6e29083SAmirreza Zarrabi /* TEE_IOCTL_PARAM_ATTR_TYPE_OBJREF_OUTPUT */ 291d6e29083SAmirreza Zarrabi if (qcomtee_objref_from_arg(¶ms[np], &u[np], ctx)) 292d6e29083SAmirreza Zarrabi goto out_failed; 293d6e29083SAmirreza Zarrabi 294d6e29083SAmirreza Zarrabi break; 295d6e29083SAmirreza Zarrabi case QCOMTEE_ARG_TYPE_IB: 296d6e29083SAmirreza Zarrabi default: 297d6e29083SAmirreza Zarrabi break; 298d6e29083SAmirreza Zarrabi } 299d6e29083SAmirreza Zarrabi } 300d6e29083SAmirreza Zarrabi 301d6e29083SAmirreza Zarrabi return 0; 302d6e29083SAmirreza Zarrabi 303d6e29083SAmirreza Zarrabi out_failed: 304d6e29083SAmirreza Zarrabi /* Undo qcomtee_objref_from_arg(). */ 305d6e29083SAmirreza Zarrabi for (i = 0; i < np; i++) { 306d6e29083SAmirreza Zarrabi if (params[i].attr == TEE_IOCTL_PARAM_ATTR_TYPE_OBJREF_OUTPUT) 307d6e29083SAmirreza Zarrabi qcomtee_context_del_qtee_object(¶ms[i], ctx); 308d6e29083SAmirreza Zarrabi } 309d6e29083SAmirreza Zarrabi 310d6e29083SAmirreza Zarrabi /* Release any IO and OO objects not processed. */ 311d6e29083SAmirreza Zarrabi for (; u[i].type && i < num_params; i++) { 312d6e29083SAmirreza Zarrabi if (u[i].type == QCOMTEE_ARG_TYPE_OO || 313d6e29083SAmirreza Zarrabi u[i].type == QCOMTEE_ARG_TYPE_IO) 314d6e29083SAmirreza Zarrabi qcomtee_object_put(u[i].o); 315d6e29083SAmirreza Zarrabi } 316d6e29083SAmirreza Zarrabi 317d6e29083SAmirreza Zarrabi return -EINVAL; 318d6e29083SAmirreza Zarrabi } 319d6e29083SAmirreza Zarrabi 320d6e29083SAmirreza Zarrabi /* TEE Device Ops. */ 321d6e29083SAmirreza Zarrabi 322d6e29083SAmirreza Zarrabi static int qcomtee_params_check(struct tee_param *params, int num_params) 323d6e29083SAmirreza Zarrabi { 324d6e29083SAmirreza Zarrabi int io = 0, oo = 0, ib = 0, ob = 0; 325d6e29083SAmirreza Zarrabi int i; 326d6e29083SAmirreza Zarrabi 327d6e29083SAmirreza Zarrabi /* QTEE can accept 64 arguments. */ 328d6e29083SAmirreza Zarrabi if (num_params > QCOMTEE_ARGS_MAX) 329d6e29083SAmirreza Zarrabi return -EINVAL; 330d6e29083SAmirreza Zarrabi 331d6e29083SAmirreza Zarrabi /* Supported parameter types. */ 332d6e29083SAmirreza Zarrabi for (i = 0; i < num_params; i++) { 333d6e29083SAmirreza Zarrabi switch (params[i].attr) { 334d6e29083SAmirreza Zarrabi case TEE_IOCTL_PARAM_ATTR_TYPE_UBUF_INPUT: 335d6e29083SAmirreza Zarrabi ib++; 336d6e29083SAmirreza Zarrabi break; 337d6e29083SAmirreza Zarrabi case TEE_IOCTL_PARAM_ATTR_TYPE_UBUF_OUTPUT: 338d6e29083SAmirreza Zarrabi ob++; 339d6e29083SAmirreza Zarrabi break; 340d6e29083SAmirreza Zarrabi case TEE_IOCTL_PARAM_ATTR_TYPE_OBJREF_INPUT: 341d6e29083SAmirreza Zarrabi io++; 342d6e29083SAmirreza Zarrabi break; 343d6e29083SAmirreza Zarrabi case TEE_IOCTL_PARAM_ATTR_TYPE_OBJREF_OUTPUT: 344d6e29083SAmirreza Zarrabi oo++; 345d6e29083SAmirreza Zarrabi break; 346d6e29083SAmirreza Zarrabi default: 347d6e29083SAmirreza Zarrabi return -EINVAL; 348d6e29083SAmirreza Zarrabi } 349d6e29083SAmirreza Zarrabi } 350d6e29083SAmirreza Zarrabi 351d6e29083SAmirreza Zarrabi /* QTEE can accept 16 arguments of each supported types. */ 352d6e29083SAmirreza Zarrabi if (io > QCOMTEE_ARGS_PER_TYPE || oo > QCOMTEE_ARGS_PER_TYPE || 353d6e29083SAmirreza Zarrabi ib > QCOMTEE_ARGS_PER_TYPE || ob > QCOMTEE_ARGS_PER_TYPE) 354d6e29083SAmirreza Zarrabi return -EINVAL; 355d6e29083SAmirreza Zarrabi 356d6e29083SAmirreza Zarrabi return 0; 357d6e29083SAmirreza Zarrabi } 358d6e29083SAmirreza Zarrabi 359d6e29083SAmirreza Zarrabi /* Check if an operation on ROOT_QCOMTEE_OBJECT from userspace is permitted. */ 360d6e29083SAmirreza Zarrabi static int qcomtee_root_object_check(u32 op, struct tee_param *params, 361d6e29083SAmirreza Zarrabi int num_params) 362d6e29083SAmirreza Zarrabi { 363d6e29083SAmirreza Zarrabi /* Some privileged operations recognized by QTEE. */ 364d6e29083SAmirreza Zarrabi if (op == QCOMTEE_ROOT_OP_NOTIFY_DOMAIN_CHANGE || 365d6e29083SAmirreza Zarrabi op == QCOMTEE_ROOT_OP_ADCI_ACCEPT || 366d6e29083SAmirreza Zarrabi op == QCOMTEE_ROOT_OP_ADCI_SHUTDOWN) 367d6e29083SAmirreza Zarrabi return -EINVAL; 368d6e29083SAmirreza Zarrabi 369d6e29083SAmirreza Zarrabi /* 370d6e29083SAmirreza Zarrabi * QCOMTEE_ROOT_OP_REG_WITH_CREDENTIALS is to register with QTEE 371d6e29083SAmirreza Zarrabi * by passing a credential object as input OBJREF. TEE_OBJREF_NULL as a 372d6e29083SAmirreza Zarrabi * credential object represents a privileged client for QTEE and 373d6e29083SAmirreza Zarrabi * is used by the kernel only. 374d6e29083SAmirreza Zarrabi */ 375d6e29083SAmirreza Zarrabi if (op == QCOMTEE_ROOT_OP_REG_WITH_CREDENTIALS && num_params == 2) { 376d6e29083SAmirreza Zarrabi if (params[0].attr == TEE_IOCTL_PARAM_ATTR_TYPE_OBJREF_INPUT && 377d6e29083SAmirreza Zarrabi params[1].attr == TEE_IOCTL_PARAM_ATTR_TYPE_OBJREF_OUTPUT) { 378d6e29083SAmirreza Zarrabi if (params[0].u.objref.id == TEE_OBJREF_NULL) 379d6e29083SAmirreza Zarrabi return -EINVAL; 380d6e29083SAmirreza Zarrabi } 381d6e29083SAmirreza Zarrabi } 382d6e29083SAmirreza Zarrabi 383d6e29083SAmirreza Zarrabi return 0; 384d6e29083SAmirreza Zarrabi } 385d6e29083SAmirreza Zarrabi 386d6e29083SAmirreza Zarrabi /** 387d6e29083SAmirreza Zarrabi * qcomtee_object_invoke() - Invoke a QTEE object. 388d6e29083SAmirreza Zarrabi * @ctx: TEE context. 389d6e29083SAmirreza Zarrabi * @arg: ioctl arguments. 390d6e29083SAmirreza Zarrabi * @params: parameters for the object. 391d6e29083SAmirreza Zarrabi * 392d6e29083SAmirreza Zarrabi * Return: On success, returns 0; on failure, returns < 0. 393d6e29083SAmirreza Zarrabi */ 394d6e29083SAmirreza Zarrabi static int qcomtee_object_invoke(struct tee_context *ctx, 395d6e29083SAmirreza Zarrabi struct tee_ioctl_object_invoke_arg *arg, 396d6e29083SAmirreza Zarrabi struct tee_param *params) 397d6e29083SAmirreza Zarrabi { 398d6e29083SAmirreza Zarrabi struct qcomtee_object_invoke_ctx *oic __free(kfree) = NULL; 399d6e29083SAmirreza Zarrabi struct qcomtee_context_data *ctxdata = ctx->data; 400d6e29083SAmirreza Zarrabi struct qcomtee_arg *u __free(kfree) = NULL; 401d6e29083SAmirreza Zarrabi struct qcomtee_object *object; 402d6e29083SAmirreza Zarrabi int i, ret, result; 403d6e29083SAmirreza Zarrabi 404d6e29083SAmirreza Zarrabi if (qcomtee_params_check(params, arg->num_params)) 405d6e29083SAmirreza Zarrabi return -EINVAL; 406d6e29083SAmirreza Zarrabi 407d6e29083SAmirreza Zarrabi /* First, handle reserved operations: */ 408d6e29083SAmirreza Zarrabi if (arg->op == QCOMTEE_MSG_OBJECT_OP_RELEASE) { 409d6e29083SAmirreza Zarrabi del_qtee_object(arg->id, ctxdata); 410d6e29083SAmirreza Zarrabi 411d6e29083SAmirreza Zarrabi return 0; 412d6e29083SAmirreza Zarrabi } 413d6e29083SAmirreza Zarrabi 414d6e29083SAmirreza Zarrabi /* Otherwise, invoke a QTEE object: */ 415d6e29083SAmirreza Zarrabi oic = qcomtee_object_invoke_ctx_alloc(ctx); 416d6e29083SAmirreza Zarrabi if (!oic) 417d6e29083SAmirreza Zarrabi return -ENOMEM; 418d6e29083SAmirreza Zarrabi 419d6e29083SAmirreza Zarrabi /* +1 for ending QCOMTEE_ARG_TYPE_INV. */ 420d6e29083SAmirreza Zarrabi u = kcalloc(arg->num_params + 1, sizeof(*u), GFP_KERNEL); 421d6e29083SAmirreza Zarrabi if (!u) 422d6e29083SAmirreza Zarrabi return -ENOMEM; 423d6e29083SAmirreza Zarrabi 424d6e29083SAmirreza Zarrabi /* Get an object to invoke. */ 425d6e29083SAmirreza Zarrabi if (arg->id == TEE_OBJREF_NULL) { 426d6e29083SAmirreza Zarrabi /* Use ROOT if TEE_OBJREF_NULL is invoked. */ 427d6e29083SAmirreza Zarrabi if (qcomtee_root_object_check(arg->op, params, arg->num_params)) 428d6e29083SAmirreza Zarrabi return -EINVAL; 429d6e29083SAmirreza Zarrabi 430d6e29083SAmirreza Zarrabi object = ROOT_QCOMTEE_OBJECT; 431d6e29083SAmirreza Zarrabi } else if (find_qtee_object(&object, arg->id, ctxdata)) { 432d6e29083SAmirreza Zarrabi return -EINVAL; 433d6e29083SAmirreza Zarrabi } 434d6e29083SAmirreza Zarrabi 435d6e29083SAmirreza Zarrabi ret = qcomtee_params_to_args(u, params, arg->num_params, ctx); 436d6e29083SAmirreza Zarrabi if (ret) 437d6e29083SAmirreza Zarrabi goto out; 438d6e29083SAmirreza Zarrabi 439d6e29083SAmirreza Zarrabi ret = qcomtee_object_do_invoke(oic, object, arg->op, u, &result); 440d6e29083SAmirreza Zarrabi if (ret) { 441d6e29083SAmirreza Zarrabi qcomtee_arg_for_each_input_object(i, u) { 442d6e29083SAmirreza Zarrabi qcomtee_user_object_set_notify(u[i].o, false); 443d6e29083SAmirreza Zarrabi qcomtee_object_put(u[i].o); 444d6e29083SAmirreza Zarrabi } 445d6e29083SAmirreza Zarrabi 446d6e29083SAmirreza Zarrabi goto out; 447d6e29083SAmirreza Zarrabi } 448d6e29083SAmirreza Zarrabi 449d6e29083SAmirreza Zarrabi /* Prase QTEE response and put driver's object copies: */ 450d6e29083SAmirreza Zarrabi 451d6e29083SAmirreza Zarrabi if (!result) { 452d6e29083SAmirreza Zarrabi /* Assume service is UNAVAIL if unable to process the result. */ 453d6e29083SAmirreza Zarrabi if (qcomtee_params_from_args(params, u, arg->num_params, ctx)) 454d6e29083SAmirreza Zarrabi result = QCOMTEE_MSG_ERROR_UNAVAIL; 455d6e29083SAmirreza Zarrabi } else { 456d6e29083SAmirreza Zarrabi /* 457d6e29083SAmirreza Zarrabi * qcomtee_params_to_args() gets a copy of IO for the driver to 458d6e29083SAmirreza Zarrabi * make sure they do not get released while in the middle of 459d6e29083SAmirreza Zarrabi * invocation. On success (!result), qcomtee_params_from_args() 460d6e29083SAmirreza Zarrabi * puts them; Otherwise, put them here. 461d6e29083SAmirreza Zarrabi */ 462d6e29083SAmirreza Zarrabi qcomtee_arg_for_each_input_object(i, u) 463d6e29083SAmirreza Zarrabi qcomtee_object_put(u[i].o); 464d6e29083SAmirreza Zarrabi } 465d6e29083SAmirreza Zarrabi 466d6e29083SAmirreza Zarrabi arg->ret = result; 467d6e29083SAmirreza Zarrabi out: 468d6e29083SAmirreza Zarrabi qcomtee_object_put(object); 469d6e29083SAmirreza Zarrabi 470d6e29083SAmirreza Zarrabi return ret; 471d6e29083SAmirreza Zarrabi } 472d6e29083SAmirreza Zarrabi 473d6e29083SAmirreza Zarrabi /** 474d6e29083SAmirreza Zarrabi * qcomtee_supp_recv() - Wait for a request for the supplicant. 475d6e29083SAmirreza Zarrabi * @ctx: TEE context. 476d6e29083SAmirreza Zarrabi * @op: requested operation on the object. 477d6e29083SAmirreza Zarrabi * @num_params: number of elements in the parameter array. 478d6e29083SAmirreza Zarrabi * @params: parameters for @op. 479d6e29083SAmirreza Zarrabi * 480d6e29083SAmirreza Zarrabi * The first parameter is a meta %TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INOUT. 481d6e29083SAmirreza Zarrabi * On input, it provides a user buffer. This buffer is used for parameters of 482d6e29083SAmirreza Zarrabi * type %TEE_IOCTL_PARAM_ATTR_TYPE_UBUF_INPUT in qcomtee_cb_params_from_args(). 483d6e29083SAmirreza Zarrabi * On output, the object ID and request ID are stored in the meta parameter. 484d6e29083SAmirreza Zarrabi * 485d6e29083SAmirreza Zarrabi * @num_params is updated to the number of parameters that actually exist 486d6e29083SAmirreza Zarrabi * in @params on return. 487d6e29083SAmirreza Zarrabi * 488d6e29083SAmirreza Zarrabi * Return: On success, returns 0; on failure, returns < 0. 489d6e29083SAmirreza Zarrabi */ 490d6e29083SAmirreza Zarrabi static int qcomtee_supp_recv(struct tee_context *ctx, u32 *op, u32 *num_params, 491d6e29083SAmirreza Zarrabi struct tee_param *params) 492d6e29083SAmirreza Zarrabi { 493d6e29083SAmirreza Zarrabi struct qcomtee_user_object_request_data data; 494d6e29083SAmirreza Zarrabi void __user *uaddr; 495d6e29083SAmirreza Zarrabi size_t ubuf_size; 496d6e29083SAmirreza Zarrabi int i, ret; 497d6e29083SAmirreza Zarrabi 498d6e29083SAmirreza Zarrabi if (!*num_params) 499d6e29083SAmirreza Zarrabi return -EINVAL; 500d6e29083SAmirreza Zarrabi 501d6e29083SAmirreza Zarrabi /* First parameter should be an INOUT + meta parameter. */ 502d6e29083SAmirreza Zarrabi if (params->attr != 503d6e29083SAmirreza Zarrabi (TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INOUT | TEE_IOCTL_PARAM_ATTR_META)) 504d6e29083SAmirreza Zarrabi return -EINVAL; 505d6e29083SAmirreza Zarrabi 506d6e29083SAmirreza Zarrabi /* Other parameters are none. */ 507d6e29083SAmirreza Zarrabi for (i = 1; i < *num_params; i++) 508d6e29083SAmirreza Zarrabi if (params[i].attr) 509d6e29083SAmirreza Zarrabi return -EINVAL; 510d6e29083SAmirreza Zarrabi 511d6e29083SAmirreza Zarrabi if (!IS_ALIGNED(params->u.value.a, 8)) 512d6e29083SAmirreza Zarrabi return -EINVAL; 513d6e29083SAmirreza Zarrabi 514d6e29083SAmirreza Zarrabi /* User buffer and size from meta parameter. */ 515d6e29083SAmirreza Zarrabi uaddr = u64_to_user_ptr(params->u.value.a); 516d6e29083SAmirreza Zarrabi ubuf_size = params->u.value.b; 517d6e29083SAmirreza Zarrabi /* Process TEE parameters. +/-1 to ignore the meta parameter. */ 518d6e29083SAmirreza Zarrabi ret = qcomtee_user_object_select(ctx, params + 1, *num_params - 1, 519d6e29083SAmirreza Zarrabi uaddr, ubuf_size, &data); 520d6e29083SAmirreza Zarrabi if (ret) 521d6e29083SAmirreza Zarrabi return ret; 522d6e29083SAmirreza Zarrabi 523d6e29083SAmirreza Zarrabi params->u.value.a = data.object_id; 524d6e29083SAmirreza Zarrabi params->u.value.b = data.id; 525d6e29083SAmirreza Zarrabi params->u.value.c = 0; 526d6e29083SAmirreza Zarrabi *op = data.op; 527d6e29083SAmirreza Zarrabi *num_params = data.np + 1; 528d6e29083SAmirreza Zarrabi 529d6e29083SAmirreza Zarrabi return 0; 530d6e29083SAmirreza Zarrabi } 531d6e29083SAmirreza Zarrabi 532d6e29083SAmirreza Zarrabi /** 533d6e29083SAmirreza Zarrabi * qcomtee_supp_send() - Submit a response for a request. 534d6e29083SAmirreza Zarrabi * @ctx: TEE context. 535d6e29083SAmirreza Zarrabi * @errno: return value for the request. 536d6e29083SAmirreza Zarrabi * @num_params: number of elements in the parameter array. 537d6e29083SAmirreza Zarrabi * @params: returned parameters. 538d6e29083SAmirreza Zarrabi * 539d6e29083SAmirreza Zarrabi * The first parameter is a meta %TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_OUTPUT. 540d6e29083SAmirreza Zarrabi * It specifies the request ID this response belongs to. 541d6e29083SAmirreza Zarrabi * 542d6e29083SAmirreza Zarrabi * Return: On success, returns 0; on failure, returns < 0. 543d6e29083SAmirreza Zarrabi */ 544d6e29083SAmirreza Zarrabi static int qcomtee_supp_send(struct tee_context *ctx, u32 errno, u32 num_params, 545d6e29083SAmirreza Zarrabi struct tee_param *params) 546d6e29083SAmirreza Zarrabi { 547d6e29083SAmirreza Zarrabi int req_id; 548d6e29083SAmirreza Zarrabi 549d6e29083SAmirreza Zarrabi if (!num_params) 550d6e29083SAmirreza Zarrabi return -EINVAL; 551d6e29083SAmirreza Zarrabi 552d6e29083SAmirreza Zarrabi /* First parameter should be an OUTPUT + meta parameter. */ 553d6e29083SAmirreza Zarrabi if (params->attr != (TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_OUTPUT | 554d6e29083SAmirreza Zarrabi TEE_IOCTL_PARAM_ATTR_META)) 555d6e29083SAmirreza Zarrabi return -EINVAL; 556d6e29083SAmirreza Zarrabi 557d6e29083SAmirreza Zarrabi req_id = params->u.value.a; 558d6e29083SAmirreza Zarrabi /* Process TEE parameters. +/-1 to ignore the meta parameter. */ 559d6e29083SAmirreza Zarrabi return qcomtee_user_object_submit(ctx, params + 1, num_params - 1, 560d6e29083SAmirreza Zarrabi req_id, errno); 561d6e29083SAmirreza Zarrabi } 562d6e29083SAmirreza Zarrabi 563d6e29083SAmirreza Zarrabi static int qcomtee_open(struct tee_context *ctx) 564d6e29083SAmirreza Zarrabi { 565d6e29083SAmirreza Zarrabi struct qcomtee_context_data *ctxdata __free(kfree) = NULL; 566d6e29083SAmirreza Zarrabi 567d6e29083SAmirreza Zarrabi ctxdata = kzalloc(sizeof(*ctxdata), GFP_KERNEL); 568d6e29083SAmirreza Zarrabi if (!ctxdata) 569d6e29083SAmirreza Zarrabi return -ENOMEM; 570d6e29083SAmirreza Zarrabi 571d6e29083SAmirreza Zarrabi /* 572d6e29083SAmirreza Zarrabi * In the QTEE driver, the same context is used to refcount resources 573d6e29083SAmirreza Zarrabi * shared by QTEE. For example, teedev_ctx_get() is called for any 574d6e29083SAmirreza Zarrabi * instance of callback objects (see qcomtee_user_param_to_object()). 575d6e29083SAmirreza Zarrabi * 576d6e29083SAmirreza Zarrabi * Maintain a copy of teedev for QTEE as it serves as a direct user of 577d6e29083SAmirreza Zarrabi * this context. The teedev will be released in the context's release(). 578d6e29083SAmirreza Zarrabi * 579d6e29083SAmirreza Zarrabi * tee_device_unregister() will remain blocked until all contexts 580d6e29083SAmirreza Zarrabi * are released. This includes contexts owned by the user, which are 581d6e29083SAmirreza Zarrabi * closed by teedev_close_context(), as well as those owned by QTEE 582d6e29083SAmirreza Zarrabi * closed by teedev_ctx_put() in object's release(). 583d6e29083SAmirreza Zarrabi */ 584d6e29083SAmirreza Zarrabi if (!tee_device_get(ctx->teedev)) 585d6e29083SAmirreza Zarrabi return -EINVAL; 586d6e29083SAmirreza Zarrabi 587d6e29083SAmirreza Zarrabi idr_init(&ctxdata->qtee_objects_idr); 588d6e29083SAmirreza Zarrabi mutex_init(&ctxdata->qtee_lock); 589d6e29083SAmirreza Zarrabi idr_init(&ctxdata->reqs_idr); 590d6e29083SAmirreza Zarrabi INIT_LIST_HEAD(&ctxdata->reqs_list); 591d6e29083SAmirreza Zarrabi mutex_init(&ctxdata->reqs_lock); 592d6e29083SAmirreza Zarrabi init_completion(&ctxdata->req_c); 593d6e29083SAmirreza Zarrabi 594d6e29083SAmirreza Zarrabi ctx->data = no_free_ptr(ctxdata); 595d6e29083SAmirreza Zarrabi 596d6e29083SAmirreza Zarrabi return 0; 597d6e29083SAmirreza Zarrabi } 598d6e29083SAmirreza Zarrabi 599d6e29083SAmirreza Zarrabi /* Gets called when the user closes the device */ 600d6e29083SAmirreza Zarrabi static void qcomtee_close_context(struct tee_context *ctx) 601d6e29083SAmirreza Zarrabi { 602d6e29083SAmirreza Zarrabi struct qcomtee_context_data *ctxdata = ctx->data; 603d6e29083SAmirreza Zarrabi struct qcomtee_object *object; 604d6e29083SAmirreza Zarrabi int id; 605d6e29083SAmirreza Zarrabi 606d6e29083SAmirreza Zarrabi /* Process QUEUED or PROCESSING requests. */ 607d6e29083SAmirreza Zarrabi qcomtee_requests_destroy(ctxdata); 608d6e29083SAmirreza Zarrabi /* Release QTEE objects. */ 609d6e29083SAmirreza Zarrabi idr_for_each_entry(&ctxdata->qtee_objects_idr, object, id) 610d6e29083SAmirreza Zarrabi qcomtee_object_put(object); 611d6e29083SAmirreza Zarrabi } 612d6e29083SAmirreza Zarrabi 613d6e29083SAmirreza Zarrabi /* Gets called when the final reference to the context goes away. */ 614d6e29083SAmirreza Zarrabi static void qcomtee_release(struct tee_context *ctx) 615d6e29083SAmirreza Zarrabi { 616d6e29083SAmirreza Zarrabi struct qcomtee_context_data *ctxdata = ctx->data; 617d6e29083SAmirreza Zarrabi 618d6e29083SAmirreza Zarrabi idr_destroy(&ctxdata->qtee_objects_idr); 619d6e29083SAmirreza Zarrabi idr_destroy(&ctxdata->reqs_idr); 620d6e29083SAmirreza Zarrabi kfree(ctxdata); 621d6e29083SAmirreza Zarrabi 622d6e29083SAmirreza Zarrabi /* There is nothing shared in this context with QTEE. */ 623d6e29083SAmirreza Zarrabi tee_device_put(ctx->teedev); 624d6e29083SAmirreza Zarrabi } 625d6e29083SAmirreza Zarrabi 626d6e29083SAmirreza Zarrabi static void qcomtee_get_version(struct tee_device *teedev, 627d6e29083SAmirreza Zarrabi struct tee_ioctl_version_data *vers) 628d6e29083SAmirreza Zarrabi { 629d6e29083SAmirreza Zarrabi struct tee_ioctl_version_data v = { 630d6e29083SAmirreza Zarrabi .impl_id = TEE_IMPL_ID_QTEE, 631d6e29083SAmirreza Zarrabi .gen_caps = TEE_GEN_CAP_OBJREF, 632d6e29083SAmirreza Zarrabi }; 633d6e29083SAmirreza Zarrabi 634d6e29083SAmirreza Zarrabi *vers = v; 635d6e29083SAmirreza Zarrabi } 636d6e29083SAmirreza Zarrabi 637d6e29083SAmirreza Zarrabi /** 638d6e29083SAmirreza Zarrabi * qcomtee_get_qtee_feature_list() - Query QTEE features versions. 639d6e29083SAmirreza Zarrabi * @ctx: TEE context. 640d6e29083SAmirreza Zarrabi * @id: ID of the feature to query. 641d6e29083SAmirreza Zarrabi * @version: version of the feature. 642d6e29083SAmirreza Zarrabi * 643d6e29083SAmirreza Zarrabi * Used to query the verion of features supported by QTEE. 644d6e29083SAmirreza Zarrabi */ 645d6e29083SAmirreza Zarrabi static void qcomtee_get_qtee_feature_list(struct tee_context *ctx, u32 id, 646d6e29083SAmirreza Zarrabi u32 *version) 647d6e29083SAmirreza Zarrabi { 648d6e29083SAmirreza Zarrabi struct qcomtee_object_invoke_ctx *oic __free(kfree); 649d6e29083SAmirreza Zarrabi struct qcomtee_object *client_env, *service; 650d6e29083SAmirreza Zarrabi struct qcomtee_arg u[3] = { 0 }; 651d6e29083SAmirreza Zarrabi int result; 652d6e29083SAmirreza Zarrabi 653d6e29083SAmirreza Zarrabi oic = qcomtee_object_invoke_ctx_alloc(ctx); 654d6e29083SAmirreza Zarrabi if (!oic) 655d6e29083SAmirreza Zarrabi return; 656d6e29083SAmirreza Zarrabi 657d6e29083SAmirreza Zarrabi client_env = qcomtee_object_get_client_env(oic); 658d6e29083SAmirreza Zarrabi if (client_env == NULL_QCOMTEE_OBJECT) 659d6e29083SAmirreza Zarrabi return; 660d6e29083SAmirreza Zarrabi 661d6e29083SAmirreza Zarrabi /* Get ''FeatureVersions Service'' object. */ 662d6e29083SAmirreza Zarrabi service = qcomtee_object_get_service(oic, client_env, 663d6e29083SAmirreza Zarrabi QCOMTEE_FEATURE_VER_UID); 664d6e29083SAmirreza Zarrabi if (service == NULL_QCOMTEE_OBJECT) 665d6e29083SAmirreza Zarrabi goto out_failed; 666d6e29083SAmirreza Zarrabi 667d6e29083SAmirreza Zarrabi /* IB: Feature to query. */ 668d6e29083SAmirreza Zarrabi u[0].b.addr = &id; 669d6e29083SAmirreza Zarrabi u[0].b.size = sizeof(id); 670d6e29083SAmirreza Zarrabi u[0].type = QCOMTEE_ARG_TYPE_IB; 671d6e29083SAmirreza Zarrabi 672d6e29083SAmirreza Zarrabi /* OB: Version returned. */ 673d6e29083SAmirreza Zarrabi u[1].b.addr = version; 674d6e29083SAmirreza Zarrabi u[1].b.size = sizeof(*version); 675d6e29083SAmirreza Zarrabi u[1].type = QCOMTEE_ARG_TYPE_OB; 676d6e29083SAmirreza Zarrabi 677d6e29083SAmirreza Zarrabi qcomtee_object_do_invoke(oic, service, QCOMTEE_FEATURE_VER_OP_GET, u, 678d6e29083SAmirreza Zarrabi &result); 679d6e29083SAmirreza Zarrabi 680d6e29083SAmirreza Zarrabi out_failed: 681d6e29083SAmirreza Zarrabi qcomtee_object_put(service); 682d6e29083SAmirreza Zarrabi qcomtee_object_put(client_env); 683d6e29083SAmirreza Zarrabi } 684d6e29083SAmirreza Zarrabi 685d6e29083SAmirreza Zarrabi static const struct tee_driver_ops qcomtee_ops = { 686d6e29083SAmirreza Zarrabi .get_version = qcomtee_get_version, 687d6e29083SAmirreza Zarrabi .open = qcomtee_open, 688d6e29083SAmirreza Zarrabi .close_context = qcomtee_close_context, 689d6e29083SAmirreza Zarrabi .release = qcomtee_release, 690d6e29083SAmirreza Zarrabi .object_invoke_func = qcomtee_object_invoke, 691d6e29083SAmirreza Zarrabi .supp_recv = qcomtee_supp_recv, 692d6e29083SAmirreza Zarrabi .supp_send = qcomtee_supp_send, 693d6e29083SAmirreza Zarrabi }; 694d6e29083SAmirreza Zarrabi 695d6e29083SAmirreza Zarrabi static const struct tee_desc qcomtee_desc = { 696d6e29083SAmirreza Zarrabi .name = "qcomtee", 697d6e29083SAmirreza Zarrabi .ops = &qcomtee_ops, 698d6e29083SAmirreza Zarrabi .owner = THIS_MODULE, 699d6e29083SAmirreza Zarrabi }; 700d6e29083SAmirreza Zarrabi 701d6e29083SAmirreza Zarrabi static int qcomtee_probe(struct platform_device *pdev) 702d6e29083SAmirreza Zarrabi { 703d6e29083SAmirreza Zarrabi struct workqueue_struct *async_wq; 704d6e29083SAmirreza Zarrabi struct tee_device *teedev; 705d6e29083SAmirreza Zarrabi struct tee_shm_pool *pool; 706d6e29083SAmirreza Zarrabi struct tee_context *ctx; 707d6e29083SAmirreza Zarrabi struct qcomtee *qcomtee; 708d6e29083SAmirreza Zarrabi int err; 709d6e29083SAmirreza Zarrabi 710d6e29083SAmirreza Zarrabi qcomtee = kzalloc(sizeof(*qcomtee), GFP_KERNEL); 711d6e29083SAmirreza Zarrabi if (!qcomtee) 712d6e29083SAmirreza Zarrabi return -ENOMEM; 713d6e29083SAmirreza Zarrabi 714d6e29083SAmirreza Zarrabi pool = qcomtee_shm_pool_alloc(); 715d6e29083SAmirreza Zarrabi if (IS_ERR(pool)) { 716d6e29083SAmirreza Zarrabi err = PTR_ERR(pool); 717d6e29083SAmirreza Zarrabi 718d6e29083SAmirreza Zarrabi goto err_free_qcomtee; 719d6e29083SAmirreza Zarrabi } 720d6e29083SAmirreza Zarrabi 721d6e29083SAmirreza Zarrabi teedev = tee_device_alloc(&qcomtee_desc, NULL, pool, qcomtee); 722d6e29083SAmirreza Zarrabi if (IS_ERR(teedev)) { 723d6e29083SAmirreza Zarrabi err = PTR_ERR(teedev); 724d6e29083SAmirreza Zarrabi 725d6e29083SAmirreza Zarrabi goto err_pool_destroy; 726d6e29083SAmirreza Zarrabi } 727d6e29083SAmirreza Zarrabi 728d6e29083SAmirreza Zarrabi qcomtee->teedev = teedev; 729d6e29083SAmirreza Zarrabi qcomtee->pool = pool; 730d6e29083SAmirreza Zarrabi err = tee_device_register(qcomtee->teedev); 731d6e29083SAmirreza Zarrabi if (err) 732d6e29083SAmirreza Zarrabi goto err_unreg_teedev; 733d6e29083SAmirreza Zarrabi 734d6e29083SAmirreza Zarrabi platform_set_drvdata(pdev, qcomtee); 735d6e29083SAmirreza Zarrabi /* Start async wq. */ 736d6e29083SAmirreza Zarrabi async_wq = alloc_ordered_workqueue("qcomtee_wq", 0); 737d6e29083SAmirreza Zarrabi if (!async_wq) { 738d6e29083SAmirreza Zarrabi err = -ENOMEM; 739d6e29083SAmirreza Zarrabi 740d6e29083SAmirreza Zarrabi goto err_unreg_teedev; 741d6e29083SAmirreza Zarrabi } 742d6e29083SAmirreza Zarrabi 743d6e29083SAmirreza Zarrabi qcomtee->wq = async_wq; 744d6e29083SAmirreza Zarrabi /* Driver context used for async operations of teedev. */ 745d6e29083SAmirreza Zarrabi ctx = teedev_open(qcomtee->teedev); 746d6e29083SAmirreza Zarrabi if (IS_ERR(ctx)) { 747d6e29083SAmirreza Zarrabi err = PTR_ERR(ctx); 748d6e29083SAmirreza Zarrabi 749d6e29083SAmirreza Zarrabi goto err_dest_wq; 750d6e29083SAmirreza Zarrabi } 751d6e29083SAmirreza Zarrabi 752d6e29083SAmirreza Zarrabi qcomtee->ctx = ctx; 753d6e29083SAmirreza Zarrabi /* Init Object table. */ 754d6e29083SAmirreza Zarrabi qcomtee->xa_last_id = 0; 755d6e29083SAmirreza Zarrabi xa_init_flags(&qcomtee->xa_local_objects, XA_FLAGS_ALLOC); 756d6e29083SAmirreza Zarrabi /* Get QTEE verion. */ 757d6e29083SAmirreza Zarrabi qcomtee_get_qtee_feature_list(qcomtee->ctx, 758d6e29083SAmirreza Zarrabi QCOMTEE_FEATURE_VER_OP_GET_QTEE_ID, 759d6e29083SAmirreza Zarrabi &qcomtee->qtee_version); 760d6e29083SAmirreza Zarrabi 761d6e29083SAmirreza Zarrabi pr_info("QTEE version %u.%u.%u\n", 762d6e29083SAmirreza Zarrabi QTEE_VERSION_GET_MAJOR(qcomtee->qtee_version), 763d6e29083SAmirreza Zarrabi QTEE_VERSION_GET_MINOR(qcomtee->qtee_version), 764d6e29083SAmirreza Zarrabi QTEE_VERSION_GET_PATCH(qcomtee->qtee_version)); 765d6e29083SAmirreza Zarrabi 766d6e29083SAmirreza Zarrabi return 0; 767d6e29083SAmirreza Zarrabi 768d6e29083SAmirreza Zarrabi err_dest_wq: 769d6e29083SAmirreza Zarrabi destroy_workqueue(qcomtee->wq); 770d6e29083SAmirreza Zarrabi err_unreg_teedev: 771d6e29083SAmirreza Zarrabi tee_device_unregister(qcomtee->teedev); 772d6e29083SAmirreza Zarrabi err_pool_destroy: 773d6e29083SAmirreza Zarrabi tee_shm_pool_free(pool); 774d6e29083SAmirreza Zarrabi err_free_qcomtee: 775d6e29083SAmirreza Zarrabi kfree(qcomtee); 776d6e29083SAmirreza Zarrabi 777d6e29083SAmirreza Zarrabi return err; 778d6e29083SAmirreza Zarrabi } 779d6e29083SAmirreza Zarrabi 780d6e29083SAmirreza Zarrabi /** 781d6e29083SAmirreza Zarrabi * qcomtee_remove() - Device Removal Routine. 782d6e29083SAmirreza Zarrabi * @pdev: platform device information struct. 783d6e29083SAmirreza Zarrabi * 784d6e29083SAmirreza Zarrabi * It is called by the platform subsystem to alert the driver that it should 785d6e29083SAmirreza Zarrabi * release the device. 786d6e29083SAmirreza Zarrabi * 787d6e29083SAmirreza Zarrabi * QTEE does not provide an API to inform it about a callback object going away. 788d6e29083SAmirreza Zarrabi * However, when releasing QTEE objects, any callback object sent to QTEE 789d6e29083SAmirreza Zarrabi * previously would be released by QTEE as part of the object release. 790d6e29083SAmirreza Zarrabi */ 791d6e29083SAmirreza Zarrabi static void qcomtee_remove(struct platform_device *pdev) 792d6e29083SAmirreza Zarrabi { 793d6e29083SAmirreza Zarrabi struct qcomtee *qcomtee = platform_get_drvdata(pdev); 794d6e29083SAmirreza Zarrabi 795d6e29083SAmirreza Zarrabi teedev_close_context(qcomtee->ctx); 796d6e29083SAmirreza Zarrabi /* Wait for RELEASE operations to be processed for QTEE objects. */ 797d6e29083SAmirreza Zarrabi tee_device_unregister(qcomtee->teedev); 798d6e29083SAmirreza Zarrabi destroy_workqueue(qcomtee->wq); 799d6e29083SAmirreza Zarrabi tee_shm_pool_free(qcomtee->pool); 800d6e29083SAmirreza Zarrabi kfree(qcomtee); 801d6e29083SAmirreza Zarrabi } 802d6e29083SAmirreza Zarrabi 803d6e29083SAmirreza Zarrabi static const struct platform_device_id qcomtee_ids[] = { { "qcomtee", 0 }, {} }; 804d6e29083SAmirreza Zarrabi MODULE_DEVICE_TABLE(platform, qcomtee_ids); 805d6e29083SAmirreza Zarrabi 806d6e29083SAmirreza Zarrabi static struct platform_driver qcomtee_platform_driver = { 807d6e29083SAmirreza Zarrabi .probe = qcomtee_probe, 808d6e29083SAmirreza Zarrabi .remove = qcomtee_remove, 809d6e29083SAmirreza Zarrabi .driver = { 810d6e29083SAmirreza Zarrabi .name = "qcomtee", 811d6e29083SAmirreza Zarrabi }, 812d6e29083SAmirreza Zarrabi .id_table = qcomtee_ids, 813d6e29083SAmirreza Zarrabi }; 814d6e29083SAmirreza Zarrabi 815d6e29083SAmirreza Zarrabi module_platform_driver(qcomtee_platform_driver); 816d6e29083SAmirreza Zarrabi 817d6e29083SAmirreza Zarrabi MODULE_AUTHOR("Qualcomm"); 818d6e29083SAmirreza Zarrabi MODULE_DESCRIPTION("QTEE driver"); 819d6e29083SAmirreza Zarrabi MODULE_VERSION("1.0"); 820d6e29083SAmirreza Zarrabi MODULE_LICENSE("GPL"); 821