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