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/firmware/qcom/qcom_scm.h> 9*d6e29083SAmirreza Zarrabi #include <linux/init.h> 10*d6e29083SAmirreza Zarrabi #include <linux/module.h> 11*d6e29083SAmirreza Zarrabi #include <linux/slab.h> 12*d6e29083SAmirreza Zarrabi #include <linux/uaccess.h> 13*d6e29083SAmirreza Zarrabi #include <linux/xarray.h> 14*d6e29083SAmirreza Zarrabi 15*d6e29083SAmirreza Zarrabi #include "qcomtee.h" 16*d6e29083SAmirreza Zarrabi 17*d6e29083SAmirreza Zarrabi /* QTEE root object. */ 18*d6e29083SAmirreza Zarrabi struct qcomtee_object qcomtee_object_root = { 19*d6e29083SAmirreza Zarrabi .name = "root", 20*d6e29083SAmirreza Zarrabi .object_type = QCOMTEE_OBJECT_TYPE_ROOT, 21*d6e29083SAmirreza Zarrabi .info.qtee_id = QCOMTEE_MSG_OBJECT_ROOT, 22*d6e29083SAmirreza Zarrabi }; 23*d6e29083SAmirreza Zarrabi 24*d6e29083SAmirreza Zarrabi /* Next argument of type @type after index @i. */ 25*d6e29083SAmirreza Zarrabi int qcomtee_next_arg_type(struct qcomtee_arg *u, int i, 26*d6e29083SAmirreza Zarrabi enum qcomtee_arg_type type) 27*d6e29083SAmirreza Zarrabi { 28*d6e29083SAmirreza Zarrabi while (u[i].type != QCOMTEE_ARG_TYPE_INV && u[i].type != type) 29*d6e29083SAmirreza Zarrabi i++; 30*d6e29083SAmirreza Zarrabi return i; 31*d6e29083SAmirreza Zarrabi } 32*d6e29083SAmirreza Zarrabi 33*d6e29083SAmirreza Zarrabi /* 34*d6e29083SAmirreza Zarrabi * QTEE expects IDs with the QCOMTEE_MSG_OBJECT_NS_BIT set for objects 35*d6e29083SAmirreza Zarrabi * of the QCOMTEE_OBJECT_TYPE_CB type. 36*d6e29083SAmirreza Zarrabi */ 37*d6e29083SAmirreza Zarrabi #define QCOMTEE_OBJECT_ID_START (QCOMTEE_MSG_OBJECT_NS_BIT + 1) 38*d6e29083SAmirreza Zarrabi #define QCOMTEE_OBJECT_ID_END (U32_MAX) 39*d6e29083SAmirreza Zarrabi 40*d6e29083SAmirreza Zarrabi #define QCOMTEE_OBJECT_SET(p, type, ...) \ 41*d6e29083SAmirreza Zarrabi __QCOMTEE_OBJECT_SET(p, type, ##__VA_ARGS__, 0UL) 42*d6e29083SAmirreza Zarrabi #define __QCOMTEE_OBJECT_SET(p, type, optr, ...) \ 43*d6e29083SAmirreza Zarrabi do { \ 44*d6e29083SAmirreza Zarrabi (p)->object_type = (type); \ 45*d6e29083SAmirreza Zarrabi (p)->info.qtee_id = (unsigned long)(optr); \ 46*d6e29083SAmirreza Zarrabi } while (0) 47*d6e29083SAmirreza Zarrabi 48*d6e29083SAmirreza Zarrabi static struct qcomtee_object * 49*d6e29083SAmirreza Zarrabi qcomtee_qtee_object_alloc(struct qcomtee_object_invoke_ctx *oic, 50*d6e29083SAmirreza Zarrabi unsigned int object_id) 51*d6e29083SAmirreza Zarrabi { 52*d6e29083SAmirreza Zarrabi struct qcomtee *qcomtee = tee_get_drvdata(oic->ctx->teedev); 53*d6e29083SAmirreza Zarrabi struct qcomtee_object *object; 54*d6e29083SAmirreza Zarrabi 55*d6e29083SAmirreza Zarrabi object = kzalloc(sizeof(*object), GFP_KERNEL); 56*d6e29083SAmirreza Zarrabi if (!object) 57*d6e29083SAmirreza Zarrabi return NULL_QCOMTEE_OBJECT; 58*d6e29083SAmirreza Zarrabi 59*d6e29083SAmirreza Zarrabi /* If failed, "no-name". */ 60*d6e29083SAmirreza Zarrabi object->name = kasprintf(GFP_KERNEL, "qcomtee-%u", object_id); 61*d6e29083SAmirreza Zarrabi QCOMTEE_OBJECT_SET(object, QCOMTEE_OBJECT_TYPE_TEE, object_id); 62*d6e29083SAmirreza Zarrabi kref_init(&object->refcount); 63*d6e29083SAmirreza Zarrabi /* A QTEE object requires a context for async operations. */ 64*d6e29083SAmirreza Zarrabi object->info.qcomtee_async_ctx = qcomtee->ctx; 65*d6e29083SAmirreza Zarrabi teedev_ctx_get(object->info.qcomtee_async_ctx); 66*d6e29083SAmirreza Zarrabi 67*d6e29083SAmirreza Zarrabi return object; 68*d6e29083SAmirreza Zarrabi } 69*d6e29083SAmirreza Zarrabi 70*d6e29083SAmirreza Zarrabi static void qcomtee_qtee_object_free(struct qcomtee_object *object) 71*d6e29083SAmirreza Zarrabi { 72*d6e29083SAmirreza Zarrabi /* See qcomtee_qtee_object_alloc(). */ 73*d6e29083SAmirreza Zarrabi teedev_ctx_put(object->info.qcomtee_async_ctx); 74*d6e29083SAmirreza Zarrabi 75*d6e29083SAmirreza Zarrabi kfree(object->name); 76*d6e29083SAmirreza Zarrabi kfree(object); 77*d6e29083SAmirreza Zarrabi } 78*d6e29083SAmirreza Zarrabi 79*d6e29083SAmirreza Zarrabi static void qcomtee_do_release_qtee_object(struct work_struct *work) 80*d6e29083SAmirreza Zarrabi { 81*d6e29083SAmirreza Zarrabi struct qcomtee_object *object; 82*d6e29083SAmirreza Zarrabi struct qcomtee *qcomtee; 83*d6e29083SAmirreza Zarrabi int ret, result; 84*d6e29083SAmirreza Zarrabi 85*d6e29083SAmirreza Zarrabi /* RELEASE does not require any argument. */ 86*d6e29083SAmirreza Zarrabi struct qcomtee_arg args[] = { { .type = QCOMTEE_ARG_TYPE_INV } }; 87*d6e29083SAmirreza Zarrabi 88*d6e29083SAmirreza Zarrabi object = container_of(work, struct qcomtee_object, work); 89*d6e29083SAmirreza Zarrabi qcomtee = tee_get_drvdata(object->info.qcomtee_async_ctx->teedev); 90*d6e29083SAmirreza Zarrabi /* Get the TEE context used for asynchronous operations. */ 91*d6e29083SAmirreza Zarrabi qcomtee->oic.ctx = object->info.qcomtee_async_ctx; 92*d6e29083SAmirreza Zarrabi 93*d6e29083SAmirreza Zarrabi ret = qcomtee_object_do_invoke_internal(&qcomtee->oic, object, 94*d6e29083SAmirreza Zarrabi QCOMTEE_MSG_OBJECT_OP_RELEASE, 95*d6e29083SAmirreza Zarrabi args, &result); 96*d6e29083SAmirreza Zarrabi 97*d6e29083SAmirreza Zarrabi /* Is it safe to retry the release? */ 98*d6e29083SAmirreza Zarrabi if (ret && ret != -ENODEV) { 99*d6e29083SAmirreza Zarrabi queue_work(qcomtee->wq, &object->work); 100*d6e29083SAmirreza Zarrabi } else { 101*d6e29083SAmirreza Zarrabi if (ret || result) 102*d6e29083SAmirreza Zarrabi pr_err("%s release failed, ret = %d (%x)\n", 103*d6e29083SAmirreza Zarrabi qcomtee_object_name(object), ret, result); 104*d6e29083SAmirreza Zarrabi qcomtee_qtee_object_free(object); 105*d6e29083SAmirreza Zarrabi } 106*d6e29083SAmirreza Zarrabi } 107*d6e29083SAmirreza Zarrabi 108*d6e29083SAmirreza Zarrabi static void qcomtee_release_qtee_object(struct qcomtee_object *object) 109*d6e29083SAmirreza Zarrabi { 110*d6e29083SAmirreza Zarrabi struct qcomtee *qcomtee = 111*d6e29083SAmirreza Zarrabi tee_get_drvdata(object->info.qcomtee_async_ctx->teedev); 112*d6e29083SAmirreza Zarrabi 113*d6e29083SAmirreza Zarrabi INIT_WORK(&object->work, qcomtee_do_release_qtee_object); 114*d6e29083SAmirreza Zarrabi queue_work(qcomtee->wq, &object->work); 115*d6e29083SAmirreza Zarrabi } 116*d6e29083SAmirreza Zarrabi 117*d6e29083SAmirreza Zarrabi static void qcomtee_object_release(struct kref *refcount) 118*d6e29083SAmirreza Zarrabi { 119*d6e29083SAmirreza Zarrabi struct qcomtee_object *object; 120*d6e29083SAmirreza Zarrabi const char *name; 121*d6e29083SAmirreza Zarrabi 122*d6e29083SAmirreza Zarrabi object = container_of(refcount, struct qcomtee_object, refcount); 123*d6e29083SAmirreza Zarrabi 124*d6e29083SAmirreza Zarrabi /* 125*d6e29083SAmirreza Zarrabi * qcomtee_object_get() is called in a RCU read lock. synchronize_rcu() 126*d6e29083SAmirreza Zarrabi * to avoid releasing the object while it is being accessed in 127*d6e29083SAmirreza Zarrabi * qcomtee_object_get(). 128*d6e29083SAmirreza Zarrabi */ 129*d6e29083SAmirreza Zarrabi synchronize_rcu(); 130*d6e29083SAmirreza Zarrabi 131*d6e29083SAmirreza Zarrabi switch (typeof_qcomtee_object(object)) { 132*d6e29083SAmirreza Zarrabi case QCOMTEE_OBJECT_TYPE_TEE: 133*d6e29083SAmirreza Zarrabi qcomtee_release_qtee_object(object); 134*d6e29083SAmirreza Zarrabi 135*d6e29083SAmirreza Zarrabi break; 136*d6e29083SAmirreza Zarrabi case QCOMTEE_OBJECT_TYPE_CB: 137*d6e29083SAmirreza Zarrabi name = object->name; 138*d6e29083SAmirreza Zarrabi 139*d6e29083SAmirreza Zarrabi if (object->ops->release) 140*d6e29083SAmirreza Zarrabi object->ops->release(object); 141*d6e29083SAmirreza Zarrabi 142*d6e29083SAmirreza Zarrabi kfree_const(name); 143*d6e29083SAmirreza Zarrabi 144*d6e29083SAmirreza Zarrabi break; 145*d6e29083SAmirreza Zarrabi case QCOMTEE_OBJECT_TYPE_ROOT: 146*d6e29083SAmirreza Zarrabi case QCOMTEE_OBJECT_TYPE_NULL: 147*d6e29083SAmirreza Zarrabi default: 148*d6e29083SAmirreza Zarrabi break; 149*d6e29083SAmirreza Zarrabi } 150*d6e29083SAmirreza Zarrabi } 151*d6e29083SAmirreza Zarrabi 152*d6e29083SAmirreza Zarrabi /** 153*d6e29083SAmirreza Zarrabi * qcomtee_object_get() - Increase the object's reference count. 154*d6e29083SAmirreza Zarrabi * @object: object to increase the reference count. 155*d6e29083SAmirreza Zarrabi * 156*d6e29083SAmirreza Zarrabi * Context: The caller should hold RCU read lock. 157*d6e29083SAmirreza Zarrabi */ 158*d6e29083SAmirreza Zarrabi int qcomtee_object_get(struct qcomtee_object *object) 159*d6e29083SAmirreza Zarrabi { 160*d6e29083SAmirreza Zarrabi if (object != NULL_QCOMTEE_OBJECT && object != ROOT_QCOMTEE_OBJECT) 161*d6e29083SAmirreza Zarrabi return kref_get_unless_zero(&object->refcount); 162*d6e29083SAmirreza Zarrabi 163*d6e29083SAmirreza Zarrabi return 0; 164*d6e29083SAmirreza Zarrabi } 165*d6e29083SAmirreza Zarrabi 166*d6e29083SAmirreza Zarrabi /** 167*d6e29083SAmirreza Zarrabi * qcomtee_object_put() - Decrease the object's reference count. 168*d6e29083SAmirreza Zarrabi * @object: object to decrease the reference count. 169*d6e29083SAmirreza Zarrabi */ 170*d6e29083SAmirreza Zarrabi void qcomtee_object_put(struct qcomtee_object *object) 171*d6e29083SAmirreza Zarrabi { 172*d6e29083SAmirreza Zarrabi if (object != NULL_QCOMTEE_OBJECT && object != ROOT_QCOMTEE_OBJECT) 173*d6e29083SAmirreza Zarrabi kref_put(&object->refcount, qcomtee_object_release); 174*d6e29083SAmirreza Zarrabi } 175*d6e29083SAmirreza Zarrabi 176*d6e29083SAmirreza Zarrabi static int qcomtee_idx_alloc(struct qcomtee_object_invoke_ctx *oic, u32 *idx, 177*d6e29083SAmirreza Zarrabi struct qcomtee_object *object) 178*d6e29083SAmirreza Zarrabi { 179*d6e29083SAmirreza Zarrabi struct qcomtee *qcomtee = tee_get_drvdata(oic->ctx->teedev); 180*d6e29083SAmirreza Zarrabi 181*d6e29083SAmirreza Zarrabi /* Every ID allocated here has QCOMTEE_MSG_OBJECT_NS_BIT set. */ 182*d6e29083SAmirreza Zarrabi return xa_alloc_cyclic(&qcomtee->xa_local_objects, idx, object, 183*d6e29083SAmirreza Zarrabi XA_LIMIT(QCOMTEE_OBJECT_ID_START, 184*d6e29083SAmirreza Zarrabi QCOMTEE_OBJECT_ID_END), 185*d6e29083SAmirreza Zarrabi &qcomtee->xa_last_id, GFP_KERNEL); 186*d6e29083SAmirreza Zarrabi } 187*d6e29083SAmirreza Zarrabi 188*d6e29083SAmirreza Zarrabi struct qcomtee_object *qcomtee_idx_erase(struct qcomtee_object_invoke_ctx *oic, 189*d6e29083SAmirreza Zarrabi u32 idx) 190*d6e29083SAmirreza Zarrabi { 191*d6e29083SAmirreza Zarrabi struct qcomtee *qcomtee = tee_get_drvdata(oic->ctx->teedev); 192*d6e29083SAmirreza Zarrabi 193*d6e29083SAmirreza Zarrabi if (idx < QCOMTEE_OBJECT_ID_START || idx > QCOMTEE_OBJECT_ID_END) 194*d6e29083SAmirreza Zarrabi return NULL_QCOMTEE_OBJECT; 195*d6e29083SAmirreza Zarrabi 196*d6e29083SAmirreza Zarrabi return xa_erase(&qcomtee->xa_local_objects, idx); 197*d6e29083SAmirreza Zarrabi } 198*d6e29083SAmirreza Zarrabi 199*d6e29083SAmirreza Zarrabi /** 200*d6e29083SAmirreza Zarrabi * qcomtee_object_id_get() - Get an ID for an object to send to QTEE. 201*d6e29083SAmirreza Zarrabi * @oic: context to use for the invocation. 202*d6e29083SAmirreza Zarrabi * @object: object to assign an ID. 203*d6e29083SAmirreza Zarrabi * @object_id: object ID. 204*d6e29083SAmirreza Zarrabi * 205*d6e29083SAmirreza Zarrabi * Called on the path to QTEE to construct the message; see 206*d6e29083SAmirreza Zarrabi * qcomtee_prepare_msg() and qcomtee_update_msg(). 207*d6e29083SAmirreza Zarrabi * 208*d6e29083SAmirreza Zarrabi * Return: On success, returns 0; on failure, returns < 0. 209*d6e29083SAmirreza Zarrabi */ 210*d6e29083SAmirreza Zarrabi static int qcomtee_object_id_get(struct qcomtee_object_invoke_ctx *oic, 211*d6e29083SAmirreza Zarrabi struct qcomtee_object *object, 212*d6e29083SAmirreza Zarrabi unsigned int *object_id) 213*d6e29083SAmirreza Zarrabi { 214*d6e29083SAmirreza Zarrabi u32 idx; 215*d6e29083SAmirreza Zarrabi 216*d6e29083SAmirreza Zarrabi switch (typeof_qcomtee_object(object)) { 217*d6e29083SAmirreza Zarrabi case QCOMTEE_OBJECT_TYPE_CB: 218*d6e29083SAmirreza Zarrabi if (qcomtee_idx_alloc(oic, &idx, object) < 0) 219*d6e29083SAmirreza Zarrabi return -ENOSPC; 220*d6e29083SAmirreza Zarrabi 221*d6e29083SAmirreza Zarrabi *object_id = idx; 222*d6e29083SAmirreza Zarrabi 223*d6e29083SAmirreza Zarrabi break; 224*d6e29083SAmirreza Zarrabi case QCOMTEE_OBJECT_TYPE_ROOT: 225*d6e29083SAmirreza Zarrabi case QCOMTEE_OBJECT_TYPE_TEE: 226*d6e29083SAmirreza Zarrabi *object_id = object->info.qtee_id; 227*d6e29083SAmirreza Zarrabi 228*d6e29083SAmirreza Zarrabi break; 229*d6e29083SAmirreza Zarrabi case QCOMTEE_OBJECT_TYPE_NULL: 230*d6e29083SAmirreza Zarrabi *object_id = QCOMTEE_MSG_OBJECT_NULL; 231*d6e29083SAmirreza Zarrabi 232*d6e29083SAmirreza Zarrabi break; 233*d6e29083SAmirreza Zarrabi } 234*d6e29083SAmirreza Zarrabi 235*d6e29083SAmirreza Zarrabi return 0; 236*d6e29083SAmirreza Zarrabi } 237*d6e29083SAmirreza Zarrabi 238*d6e29083SAmirreza Zarrabi /* Release object ID assigned in qcomtee_object_id_get. */ 239*d6e29083SAmirreza Zarrabi static void qcomtee_object_id_put(struct qcomtee_object_invoke_ctx *oic, 240*d6e29083SAmirreza Zarrabi unsigned int object_id) 241*d6e29083SAmirreza Zarrabi { 242*d6e29083SAmirreza Zarrabi qcomtee_idx_erase(oic, object_id); 243*d6e29083SAmirreza Zarrabi } 244*d6e29083SAmirreza Zarrabi 245*d6e29083SAmirreza Zarrabi /** 246*d6e29083SAmirreza Zarrabi * qcomtee_local_object_get() - Get the object referenced by the ID. 247*d6e29083SAmirreza Zarrabi * @oic: context to use for the invocation. 248*d6e29083SAmirreza Zarrabi * @object_id: object ID. 249*d6e29083SAmirreza Zarrabi * 250*d6e29083SAmirreza Zarrabi * It is called on the path from QTEE. 251*d6e29083SAmirreza Zarrabi * It is called on behalf of QTEE to obtain an instance of an object 252*d6e29083SAmirreza Zarrabi * for a given ID. It increases the object's reference count on success. 253*d6e29083SAmirreza Zarrabi * 254*d6e29083SAmirreza Zarrabi * Return: On error, returns %NULL_QCOMTEE_OBJECT. 255*d6e29083SAmirreza Zarrabi * On success, returns the object. 256*d6e29083SAmirreza Zarrabi */ 257*d6e29083SAmirreza Zarrabi static struct qcomtee_object * 258*d6e29083SAmirreza Zarrabi qcomtee_local_object_get(struct qcomtee_object_invoke_ctx *oic, 259*d6e29083SAmirreza Zarrabi unsigned int object_id) 260*d6e29083SAmirreza Zarrabi { 261*d6e29083SAmirreza Zarrabi struct qcomtee *qcomtee = tee_get_drvdata(oic->ctx->teedev); 262*d6e29083SAmirreza Zarrabi struct qcomtee_object *object; 263*d6e29083SAmirreza Zarrabi 264*d6e29083SAmirreza Zarrabi guard(rcu)(); 265*d6e29083SAmirreza Zarrabi object = xa_load(&qcomtee->xa_local_objects, object_id); 266*d6e29083SAmirreza Zarrabi /* It already checks for %NULL_QCOMTEE_OBJECT. */ 267*d6e29083SAmirreza Zarrabi qcomtee_object_get(object); 268*d6e29083SAmirreza Zarrabi 269*d6e29083SAmirreza Zarrabi return object; 270*d6e29083SAmirreza Zarrabi } 271*d6e29083SAmirreza Zarrabi 272*d6e29083SAmirreza Zarrabi /** 273*d6e29083SAmirreza Zarrabi * qcomtee_object_user_init() - Initialize an object for the user. 274*d6e29083SAmirreza Zarrabi * @object: object to initialize. 275*d6e29083SAmirreza Zarrabi * @ot: type of object as &enum qcomtee_object_type. 276*d6e29083SAmirreza Zarrabi * @ops: instance of callbacks. 277*d6e29083SAmirreza Zarrabi * @fmt: name assigned to the object. 278*d6e29083SAmirreza Zarrabi * 279*d6e29083SAmirreza Zarrabi * Return: On success, returns 0; on failure, returns < 0. 280*d6e29083SAmirreza Zarrabi */ 281*d6e29083SAmirreza Zarrabi int qcomtee_object_user_init(struct qcomtee_object *object, 282*d6e29083SAmirreza Zarrabi enum qcomtee_object_type ot, 283*d6e29083SAmirreza Zarrabi struct qcomtee_object_operations *ops, 284*d6e29083SAmirreza Zarrabi const char *fmt, ...) 285*d6e29083SAmirreza Zarrabi { 286*d6e29083SAmirreza Zarrabi va_list ap; 287*d6e29083SAmirreza Zarrabi int ret; 288*d6e29083SAmirreza Zarrabi 289*d6e29083SAmirreza Zarrabi kref_init(&object->refcount); 290*d6e29083SAmirreza Zarrabi QCOMTEE_OBJECT_SET(object, QCOMTEE_OBJECT_TYPE_NULL); 291*d6e29083SAmirreza Zarrabi 292*d6e29083SAmirreza Zarrabi va_start(ap, fmt); 293*d6e29083SAmirreza Zarrabi switch (ot) { 294*d6e29083SAmirreza Zarrabi case QCOMTEE_OBJECT_TYPE_NULL: 295*d6e29083SAmirreza Zarrabi ret = 0; 296*d6e29083SAmirreza Zarrabi 297*d6e29083SAmirreza Zarrabi break; 298*d6e29083SAmirreza Zarrabi case QCOMTEE_OBJECT_TYPE_CB: 299*d6e29083SAmirreza Zarrabi object->ops = ops; 300*d6e29083SAmirreza Zarrabi if (!object->ops->dispatch) 301*d6e29083SAmirreza Zarrabi return -EINVAL; 302*d6e29083SAmirreza Zarrabi 303*d6e29083SAmirreza Zarrabi /* If failed, "no-name". */ 304*d6e29083SAmirreza Zarrabi object->name = kvasprintf_const(GFP_KERNEL, fmt, ap); 305*d6e29083SAmirreza Zarrabi QCOMTEE_OBJECT_SET(object, QCOMTEE_OBJECT_TYPE_CB); 306*d6e29083SAmirreza Zarrabi 307*d6e29083SAmirreza Zarrabi ret = 0; 308*d6e29083SAmirreza Zarrabi break; 309*d6e29083SAmirreza Zarrabi case QCOMTEE_OBJECT_TYPE_ROOT: 310*d6e29083SAmirreza Zarrabi case QCOMTEE_OBJECT_TYPE_TEE: 311*d6e29083SAmirreza Zarrabi default: 312*d6e29083SAmirreza Zarrabi ret = -EINVAL; 313*d6e29083SAmirreza Zarrabi } 314*d6e29083SAmirreza Zarrabi va_end(ap); 315*d6e29083SAmirreza Zarrabi 316*d6e29083SAmirreza Zarrabi return ret; 317*d6e29083SAmirreza Zarrabi } 318*d6e29083SAmirreza Zarrabi 319*d6e29083SAmirreza Zarrabi /** 320*d6e29083SAmirreza Zarrabi * qcomtee_object_type() - Returns the type of object represented by an ID. 321*d6e29083SAmirreza Zarrabi * @object_id: object ID for the object. 322*d6e29083SAmirreza Zarrabi * 323*d6e29083SAmirreza Zarrabi * Similar to typeof_qcomtee_object(), but instead of receiving an object as 324*d6e29083SAmirreza Zarrabi * an argument, it receives an object ID. It is used internally on the return 325*d6e29083SAmirreza Zarrabi * path from QTEE. 326*d6e29083SAmirreza Zarrabi * 327*d6e29083SAmirreza Zarrabi * Return: Returns the type of object referenced by @object_id. 328*d6e29083SAmirreza Zarrabi */ 329*d6e29083SAmirreza Zarrabi static enum qcomtee_object_type qcomtee_object_type(unsigned int object_id) 330*d6e29083SAmirreza Zarrabi { 331*d6e29083SAmirreza Zarrabi if (object_id == QCOMTEE_MSG_OBJECT_NULL) 332*d6e29083SAmirreza Zarrabi return QCOMTEE_OBJECT_TYPE_NULL; 333*d6e29083SAmirreza Zarrabi 334*d6e29083SAmirreza Zarrabi if (object_id & QCOMTEE_MSG_OBJECT_NS_BIT) 335*d6e29083SAmirreza Zarrabi return QCOMTEE_OBJECT_TYPE_CB; 336*d6e29083SAmirreza Zarrabi 337*d6e29083SAmirreza Zarrabi return QCOMTEE_OBJECT_TYPE_TEE; 338*d6e29083SAmirreza Zarrabi } 339*d6e29083SAmirreza Zarrabi 340*d6e29083SAmirreza Zarrabi /** 341*d6e29083SAmirreza Zarrabi * qcomtee_object_qtee_init() - Initialize an object for QTEE. 342*d6e29083SAmirreza Zarrabi * @oic: context to use for the invocation. 343*d6e29083SAmirreza Zarrabi * @object: object returned. 344*d6e29083SAmirreza Zarrabi * @object_id: object ID received from QTEE. 345*d6e29083SAmirreza Zarrabi * 346*d6e29083SAmirreza Zarrabi * Return: On failure, returns < 0 and sets @object to %NULL_QCOMTEE_OBJECT. 347*d6e29083SAmirreza Zarrabi * On success, returns 0 348*d6e29083SAmirreza Zarrabi */ 349*d6e29083SAmirreza Zarrabi static int qcomtee_object_qtee_init(struct qcomtee_object_invoke_ctx *oic, 350*d6e29083SAmirreza Zarrabi struct qcomtee_object **object, 351*d6e29083SAmirreza Zarrabi unsigned int object_id) 352*d6e29083SAmirreza Zarrabi { 353*d6e29083SAmirreza Zarrabi int ret = 0; 354*d6e29083SAmirreza Zarrabi 355*d6e29083SAmirreza Zarrabi switch (qcomtee_object_type(object_id)) { 356*d6e29083SAmirreza Zarrabi case QCOMTEE_OBJECT_TYPE_NULL: 357*d6e29083SAmirreza Zarrabi *object = NULL_QCOMTEE_OBJECT; 358*d6e29083SAmirreza Zarrabi 359*d6e29083SAmirreza Zarrabi break; 360*d6e29083SAmirreza Zarrabi case QCOMTEE_OBJECT_TYPE_CB: 361*d6e29083SAmirreza Zarrabi *object = qcomtee_local_object_get(oic, object_id); 362*d6e29083SAmirreza Zarrabi if (*object == NULL_QCOMTEE_OBJECT) 363*d6e29083SAmirreza Zarrabi ret = -EINVAL; 364*d6e29083SAmirreza Zarrabi 365*d6e29083SAmirreza Zarrabi break; 366*d6e29083SAmirreza Zarrabi 367*d6e29083SAmirreza Zarrabi default: /* QCOMTEE_OBJECT_TYPE_TEE */ 368*d6e29083SAmirreza Zarrabi *object = qcomtee_qtee_object_alloc(oic, object_id); 369*d6e29083SAmirreza Zarrabi if (*object == NULL_QCOMTEE_OBJECT) 370*d6e29083SAmirreza Zarrabi ret = -ENOMEM; 371*d6e29083SAmirreza Zarrabi 372*d6e29083SAmirreza Zarrabi break; 373*d6e29083SAmirreza Zarrabi } 374*d6e29083SAmirreza Zarrabi 375*d6e29083SAmirreza Zarrabi return ret; 376*d6e29083SAmirreza Zarrabi } 377*d6e29083SAmirreza Zarrabi 378*d6e29083SAmirreza Zarrabi /* 379*d6e29083SAmirreza Zarrabi * ''Marshaling API'' 380*d6e29083SAmirreza Zarrabi * qcomtee_prepare_msg - Prepare the inbound buffer for sending to QTEE 381*d6e29083SAmirreza Zarrabi * qcomtee_update_args - Parse the QTEE response in the inbound buffer 382*d6e29083SAmirreza Zarrabi * qcomtee_prepare_args - Parse the QTEE request from the outbound buffer 383*d6e29083SAmirreza Zarrabi * qcomtee_update_msg - Update the outbound buffer with the response for QTEE 384*d6e29083SAmirreza Zarrabi */ 385*d6e29083SAmirreza Zarrabi 386*d6e29083SAmirreza Zarrabi static int qcomtee_prepare_msg(struct qcomtee_object_invoke_ctx *oic, 387*d6e29083SAmirreza Zarrabi struct qcomtee_object *object, u32 op, 388*d6e29083SAmirreza Zarrabi struct qcomtee_arg *u) 389*d6e29083SAmirreza Zarrabi { 390*d6e29083SAmirreza Zarrabi struct qcomtee_msg_object_invoke *msg; 391*d6e29083SAmirreza Zarrabi unsigned int object_id; 392*d6e29083SAmirreza Zarrabi int i, ib, ob, io, oo; 393*d6e29083SAmirreza Zarrabi size_t offset; 394*d6e29083SAmirreza Zarrabi 395*d6e29083SAmirreza Zarrabi /* Use the input message buffer in 'oic'. */ 396*d6e29083SAmirreza Zarrabi msg = oic->in_msg.addr; 397*d6e29083SAmirreza Zarrabi 398*d6e29083SAmirreza Zarrabi /* Start offset in a message for buffer arguments. */ 399*d6e29083SAmirreza Zarrabi offset = qcomtee_msg_buffer_args(struct qcomtee_msg_object_invoke, 400*d6e29083SAmirreza Zarrabi qcomtee_args_len(u)); 401*d6e29083SAmirreza Zarrabi 402*d6e29083SAmirreza Zarrabi /* Get the ID of the object being invoked. */ 403*d6e29083SAmirreza Zarrabi if (qcomtee_object_id_get(oic, object, &object_id)) 404*d6e29083SAmirreza Zarrabi return -ENOSPC; 405*d6e29083SAmirreza Zarrabi 406*d6e29083SAmirreza Zarrabi ib = 0; 407*d6e29083SAmirreza Zarrabi qcomtee_arg_for_each_input_buffer(i, u) { 408*d6e29083SAmirreza Zarrabi void *msgptr; /* Address of buffer payload: */ 409*d6e29083SAmirreza Zarrabi /* Overflow already checked in qcomtee_msg_buffers_alloc(). */ 410*d6e29083SAmirreza Zarrabi msg->args[ib].b.offset = offset; 411*d6e29083SAmirreza Zarrabi msg->args[ib].b.size = u[i].b.size; 412*d6e29083SAmirreza Zarrabi 413*d6e29083SAmirreza Zarrabi msgptr = qcomtee_msg_offset_to_ptr(msg, offset); 414*d6e29083SAmirreza Zarrabi /* Userspace client or kernel client!? */ 415*d6e29083SAmirreza Zarrabi if (!(u[i].flags & QCOMTEE_ARG_FLAGS_UADDR)) 416*d6e29083SAmirreza Zarrabi memcpy(msgptr, u[i].b.addr, u[i].b.size); 417*d6e29083SAmirreza Zarrabi else if (copy_from_user(msgptr, u[i].b.uaddr, u[i].b.size)) 418*d6e29083SAmirreza Zarrabi return -EINVAL; 419*d6e29083SAmirreza Zarrabi 420*d6e29083SAmirreza Zarrabi offset += qcomtee_msg_offset_align(u[i].b.size); 421*d6e29083SAmirreza Zarrabi ib++; 422*d6e29083SAmirreza Zarrabi } 423*d6e29083SAmirreza Zarrabi 424*d6e29083SAmirreza Zarrabi ob = ib; 425*d6e29083SAmirreza Zarrabi qcomtee_arg_for_each_output_buffer(i, u) { 426*d6e29083SAmirreza Zarrabi /* Overflow already checked in qcomtee_msg_buffers_alloc(). */ 427*d6e29083SAmirreza Zarrabi msg->args[ob].b.offset = offset; 428*d6e29083SAmirreza Zarrabi msg->args[ob].b.size = u[i].b.size; 429*d6e29083SAmirreza Zarrabi 430*d6e29083SAmirreza Zarrabi offset += qcomtee_msg_offset_align(u[i].b.size); 431*d6e29083SAmirreza Zarrabi ob++; 432*d6e29083SAmirreza Zarrabi } 433*d6e29083SAmirreza Zarrabi 434*d6e29083SAmirreza Zarrabi io = ob; 435*d6e29083SAmirreza Zarrabi qcomtee_arg_for_each_input_object(i, u) { 436*d6e29083SAmirreza Zarrabi if (qcomtee_object_id_get(oic, u[i].o, &msg->args[io].o)) { 437*d6e29083SAmirreza Zarrabi qcomtee_object_id_put(oic, object_id); 438*d6e29083SAmirreza Zarrabi for (io--; io >= ob; io--) 439*d6e29083SAmirreza Zarrabi qcomtee_object_id_put(oic, msg->args[io].o); 440*d6e29083SAmirreza Zarrabi 441*d6e29083SAmirreza Zarrabi return -ENOSPC; 442*d6e29083SAmirreza Zarrabi } 443*d6e29083SAmirreza Zarrabi 444*d6e29083SAmirreza Zarrabi io++; 445*d6e29083SAmirreza Zarrabi } 446*d6e29083SAmirreza Zarrabi 447*d6e29083SAmirreza Zarrabi oo = io; 448*d6e29083SAmirreza Zarrabi qcomtee_arg_for_each_output_object(i, u) 449*d6e29083SAmirreza Zarrabi oo++; 450*d6e29083SAmirreza Zarrabi 451*d6e29083SAmirreza Zarrabi /* Set object, operation, and argument counts. */ 452*d6e29083SAmirreza Zarrabi qcomtee_msg_init(msg, object_id, op, ib, ob, io, oo); 453*d6e29083SAmirreza Zarrabi 454*d6e29083SAmirreza Zarrabi return 0; 455*d6e29083SAmirreza Zarrabi } 456*d6e29083SAmirreza Zarrabi 457*d6e29083SAmirreza Zarrabi /** 458*d6e29083SAmirreza Zarrabi * qcomtee_update_args() - Parse the QTEE response in the inbound buffer. 459*d6e29083SAmirreza Zarrabi * @u: array of arguments for the invocation. 460*d6e29083SAmirreza Zarrabi * @oic: context to use for the invocation. 461*d6e29083SAmirreza Zarrabi * 462*d6e29083SAmirreza Zarrabi * @u must be the same as the one used in qcomtee_prepare_msg() when 463*d6e29083SAmirreza Zarrabi * initializing the inbound buffer. 464*d6e29083SAmirreza Zarrabi * 465*d6e29083SAmirreza Zarrabi * On failure, it continues processing the QTEE message. The caller should 466*d6e29083SAmirreza Zarrabi * do the necessary cleanup, including calling qcomtee_object_put() 467*d6e29083SAmirreza Zarrabi * on the output objects. 468*d6e29083SAmirreza Zarrabi * 469*d6e29083SAmirreza Zarrabi * Return: On success, returns 0; on failure, returns < 0. 470*d6e29083SAmirreza Zarrabi */ 471*d6e29083SAmirreza Zarrabi static int qcomtee_update_args(struct qcomtee_arg *u, 472*d6e29083SAmirreza Zarrabi struct qcomtee_object_invoke_ctx *oic) 473*d6e29083SAmirreza Zarrabi { 474*d6e29083SAmirreza Zarrabi struct qcomtee_msg_object_invoke *msg; 475*d6e29083SAmirreza Zarrabi int i, ib, ob, io, oo; 476*d6e29083SAmirreza Zarrabi int ret = 0; 477*d6e29083SAmirreza Zarrabi 478*d6e29083SAmirreza Zarrabi /* Use the input message buffer in 'oic'. */ 479*d6e29083SAmirreza Zarrabi msg = oic->in_msg.addr; 480*d6e29083SAmirreza Zarrabi 481*d6e29083SAmirreza Zarrabi ib = 0; 482*d6e29083SAmirreza Zarrabi qcomtee_arg_for_each_input_buffer(i, u) 483*d6e29083SAmirreza Zarrabi ib++; 484*d6e29083SAmirreza Zarrabi 485*d6e29083SAmirreza Zarrabi ob = ib; 486*d6e29083SAmirreza Zarrabi qcomtee_arg_for_each_output_buffer(i, u) { 487*d6e29083SAmirreza Zarrabi void *msgptr; /* Address of buffer payload: */ 488*d6e29083SAmirreza Zarrabi /* QTEE can override the size to a smaller value. */ 489*d6e29083SAmirreza Zarrabi u[i].b.size = msg->args[ob].b.size; 490*d6e29083SAmirreza Zarrabi 491*d6e29083SAmirreza Zarrabi msgptr = qcomtee_msg_offset_to_ptr(msg, msg->args[ob].b.offset); 492*d6e29083SAmirreza Zarrabi /* Userspace client or kernel client!? */ 493*d6e29083SAmirreza Zarrabi if (!(u[i].flags & QCOMTEE_ARG_FLAGS_UADDR)) 494*d6e29083SAmirreza Zarrabi memcpy(u[i].b.addr, msgptr, u[i].b.size); 495*d6e29083SAmirreza Zarrabi else if (copy_to_user(u[i].b.uaddr, msgptr, u[i].b.size)) 496*d6e29083SAmirreza Zarrabi ret = -EINVAL; 497*d6e29083SAmirreza Zarrabi 498*d6e29083SAmirreza Zarrabi ob++; 499*d6e29083SAmirreza Zarrabi } 500*d6e29083SAmirreza Zarrabi 501*d6e29083SAmirreza Zarrabi io = ob; 502*d6e29083SAmirreza Zarrabi qcomtee_arg_for_each_input_object(i, u) 503*d6e29083SAmirreza Zarrabi io++; 504*d6e29083SAmirreza Zarrabi 505*d6e29083SAmirreza Zarrabi oo = io; 506*d6e29083SAmirreza Zarrabi qcomtee_arg_for_each_output_object(i, u) { 507*d6e29083SAmirreza Zarrabi if (qcomtee_object_qtee_init(oic, &u[i].o, msg->args[oo].o)) 508*d6e29083SAmirreza Zarrabi ret = -EINVAL; 509*d6e29083SAmirreza Zarrabi 510*d6e29083SAmirreza Zarrabi oo++; 511*d6e29083SAmirreza Zarrabi } 512*d6e29083SAmirreza Zarrabi 513*d6e29083SAmirreza Zarrabi return ret; 514*d6e29083SAmirreza Zarrabi } 515*d6e29083SAmirreza Zarrabi 516*d6e29083SAmirreza Zarrabi /** 517*d6e29083SAmirreza Zarrabi * qcomtee_prepare_args() - Parse the QTEE request from the outbound buffer. 518*d6e29083SAmirreza Zarrabi * @oic: context to use for the invocation. 519*d6e29083SAmirreza Zarrabi * 520*d6e29083SAmirreza Zarrabi * It initializes &qcomtee_object_invoke_ctx->u based on the QTEE request in 521*d6e29083SAmirreza Zarrabi * the outbound buffer. It sets %QCOMTEE_ARG_TYPE_INV at the end of the array. 522*d6e29083SAmirreza Zarrabi * 523*d6e29083SAmirreza Zarrabi * On failure, it continues processing the QTEE message. The caller should 524*d6e29083SAmirreza Zarrabi * do the necessary cleanup, including calling qcomtee_object_put() 525*d6e29083SAmirreza Zarrabi * on the input objects. 526*d6e29083SAmirreza Zarrabi * 527*d6e29083SAmirreza Zarrabi * Return: On success, returns 0; on failure, returns < 0. 528*d6e29083SAmirreza Zarrabi */ 529*d6e29083SAmirreza Zarrabi static int qcomtee_prepare_args(struct qcomtee_object_invoke_ctx *oic) 530*d6e29083SAmirreza Zarrabi { 531*d6e29083SAmirreza Zarrabi struct qcomtee_msg_callback *msg; 532*d6e29083SAmirreza Zarrabi int i, ret = 0; 533*d6e29083SAmirreza Zarrabi 534*d6e29083SAmirreza Zarrabi /* Use the output message buffer in 'oic'. */ 535*d6e29083SAmirreza Zarrabi msg = oic->out_msg.addr; 536*d6e29083SAmirreza Zarrabi 537*d6e29083SAmirreza Zarrabi qcomtee_msg_for_each_input_buffer(i, msg) { 538*d6e29083SAmirreza Zarrabi oic->u[i].b.addr = 539*d6e29083SAmirreza Zarrabi qcomtee_msg_offset_to_ptr(msg, msg->args[i].b.offset); 540*d6e29083SAmirreza Zarrabi oic->u[i].b.size = msg->args[i].b.size; 541*d6e29083SAmirreza Zarrabi oic->u[i].type = QCOMTEE_ARG_TYPE_IB; 542*d6e29083SAmirreza Zarrabi } 543*d6e29083SAmirreza Zarrabi 544*d6e29083SAmirreza Zarrabi qcomtee_msg_for_each_output_buffer(i, msg) { 545*d6e29083SAmirreza Zarrabi oic->u[i].b.addr = 546*d6e29083SAmirreza Zarrabi qcomtee_msg_offset_to_ptr(msg, msg->args[i].b.offset); 547*d6e29083SAmirreza Zarrabi oic->u[i].b.size = msg->args[i].b.size; 548*d6e29083SAmirreza Zarrabi oic->u[i].type = QCOMTEE_ARG_TYPE_OB; 549*d6e29083SAmirreza Zarrabi } 550*d6e29083SAmirreza Zarrabi 551*d6e29083SAmirreza Zarrabi qcomtee_msg_for_each_input_object(i, msg) { 552*d6e29083SAmirreza Zarrabi if (qcomtee_object_qtee_init(oic, &oic->u[i].o, msg->args[i].o)) 553*d6e29083SAmirreza Zarrabi ret = -EINVAL; 554*d6e29083SAmirreza Zarrabi 555*d6e29083SAmirreza Zarrabi oic->u[i].type = QCOMTEE_ARG_TYPE_IO; 556*d6e29083SAmirreza Zarrabi } 557*d6e29083SAmirreza Zarrabi 558*d6e29083SAmirreza Zarrabi qcomtee_msg_for_each_output_object(i, msg) 559*d6e29083SAmirreza Zarrabi oic->u[i].type = QCOMTEE_ARG_TYPE_OO; 560*d6e29083SAmirreza Zarrabi 561*d6e29083SAmirreza Zarrabi /* End of Arguments. */ 562*d6e29083SAmirreza Zarrabi oic->u[i].type = QCOMTEE_ARG_TYPE_INV; 563*d6e29083SAmirreza Zarrabi 564*d6e29083SAmirreza Zarrabi return ret; 565*d6e29083SAmirreza Zarrabi } 566*d6e29083SAmirreza Zarrabi 567*d6e29083SAmirreza Zarrabi static int qcomtee_update_msg(struct qcomtee_object_invoke_ctx *oic) 568*d6e29083SAmirreza Zarrabi { 569*d6e29083SAmirreza Zarrabi struct qcomtee_msg_callback *msg; 570*d6e29083SAmirreza Zarrabi int i, ib, ob, io, oo; 571*d6e29083SAmirreza Zarrabi 572*d6e29083SAmirreza Zarrabi /* Use the output message buffer in 'oic'. */ 573*d6e29083SAmirreza Zarrabi msg = oic->out_msg.addr; 574*d6e29083SAmirreza Zarrabi 575*d6e29083SAmirreza Zarrabi ib = 0; 576*d6e29083SAmirreza Zarrabi qcomtee_arg_for_each_input_buffer(i, oic->u) 577*d6e29083SAmirreza Zarrabi ib++; 578*d6e29083SAmirreza Zarrabi 579*d6e29083SAmirreza Zarrabi ob = ib; 580*d6e29083SAmirreza Zarrabi qcomtee_arg_for_each_output_buffer(i, oic->u) { 581*d6e29083SAmirreza Zarrabi /* Only reduce size; never increase it. */ 582*d6e29083SAmirreza Zarrabi if (msg->args[ob].b.size < oic->u[i].b.size) 583*d6e29083SAmirreza Zarrabi return -EINVAL; 584*d6e29083SAmirreza Zarrabi 585*d6e29083SAmirreza Zarrabi msg->args[ob].b.size = oic->u[i].b.size; 586*d6e29083SAmirreza Zarrabi ob++; 587*d6e29083SAmirreza Zarrabi } 588*d6e29083SAmirreza Zarrabi 589*d6e29083SAmirreza Zarrabi io = ob; 590*d6e29083SAmirreza Zarrabi qcomtee_arg_for_each_input_object(i, oic->u) 591*d6e29083SAmirreza Zarrabi io++; 592*d6e29083SAmirreza Zarrabi 593*d6e29083SAmirreza Zarrabi oo = io; 594*d6e29083SAmirreza Zarrabi qcomtee_arg_for_each_output_object(i, oic->u) { 595*d6e29083SAmirreza Zarrabi if (qcomtee_object_id_get(oic, oic->u[i].o, &msg->args[oo].o)) { 596*d6e29083SAmirreza Zarrabi for (oo--; oo >= io; oo--) 597*d6e29083SAmirreza Zarrabi qcomtee_object_id_put(oic, msg->args[oo].o); 598*d6e29083SAmirreza Zarrabi 599*d6e29083SAmirreza Zarrabi return -ENOSPC; 600*d6e29083SAmirreza Zarrabi } 601*d6e29083SAmirreza Zarrabi 602*d6e29083SAmirreza Zarrabi oo++; 603*d6e29083SAmirreza Zarrabi } 604*d6e29083SAmirreza Zarrabi 605*d6e29083SAmirreza Zarrabi return 0; 606*d6e29083SAmirreza Zarrabi } 607*d6e29083SAmirreza Zarrabi 608*d6e29083SAmirreza Zarrabi /* Invoke a callback object. */ 609*d6e29083SAmirreza Zarrabi static void qcomtee_cb_object_invoke(struct qcomtee_object_invoke_ctx *oic, 610*d6e29083SAmirreza Zarrabi struct qcomtee_msg_callback *msg) 611*d6e29083SAmirreza Zarrabi { 612*d6e29083SAmirreza Zarrabi int i, errno; 613*d6e29083SAmirreza Zarrabi u32 op; 614*d6e29083SAmirreza Zarrabi 615*d6e29083SAmirreza Zarrabi /* Get the object being invoked. */ 616*d6e29083SAmirreza Zarrabi unsigned int object_id = msg->cxt; 617*d6e29083SAmirreza Zarrabi struct qcomtee_object *object; 618*d6e29083SAmirreza Zarrabi 619*d6e29083SAmirreza Zarrabi /* QTEE cannot invoke a NULL object or objects it hosts. */ 620*d6e29083SAmirreza Zarrabi if (qcomtee_object_type(object_id) == QCOMTEE_OBJECT_TYPE_NULL || 621*d6e29083SAmirreza Zarrabi qcomtee_object_type(object_id) == QCOMTEE_OBJECT_TYPE_TEE) { 622*d6e29083SAmirreza Zarrabi errno = -EINVAL; 623*d6e29083SAmirreza Zarrabi goto out; 624*d6e29083SAmirreza Zarrabi } 625*d6e29083SAmirreza Zarrabi 626*d6e29083SAmirreza Zarrabi object = qcomtee_local_object_get(oic, object_id); 627*d6e29083SAmirreza Zarrabi if (object == NULL_QCOMTEE_OBJECT) { 628*d6e29083SAmirreza Zarrabi errno = -EINVAL; 629*d6e29083SAmirreza Zarrabi goto out; 630*d6e29083SAmirreza Zarrabi } 631*d6e29083SAmirreza Zarrabi 632*d6e29083SAmirreza Zarrabi oic->object = object; 633*d6e29083SAmirreza Zarrabi 634*d6e29083SAmirreza Zarrabi /* Filter bits used by transport. */ 635*d6e29083SAmirreza Zarrabi op = msg->op & QCOMTEE_MSG_OBJECT_OP_MASK; 636*d6e29083SAmirreza Zarrabi 637*d6e29083SAmirreza Zarrabi switch (op) { 638*d6e29083SAmirreza Zarrabi case QCOMTEE_MSG_OBJECT_OP_RELEASE: 639*d6e29083SAmirreza Zarrabi qcomtee_object_id_put(oic, object_id); 640*d6e29083SAmirreza Zarrabi qcomtee_object_put(object); 641*d6e29083SAmirreza Zarrabi errno = 0; 642*d6e29083SAmirreza Zarrabi 643*d6e29083SAmirreza Zarrabi break; 644*d6e29083SAmirreza Zarrabi case QCOMTEE_MSG_OBJECT_OP_RETAIN: 645*d6e29083SAmirreza Zarrabi qcomtee_object_get(object); 646*d6e29083SAmirreza Zarrabi errno = 0; 647*d6e29083SAmirreza Zarrabi 648*d6e29083SAmirreza Zarrabi break; 649*d6e29083SAmirreza Zarrabi default: 650*d6e29083SAmirreza Zarrabi errno = qcomtee_prepare_args(oic); 651*d6e29083SAmirreza Zarrabi if (errno) { 652*d6e29083SAmirreza Zarrabi /* Release any object that arrived as input. */ 653*d6e29083SAmirreza Zarrabi qcomtee_arg_for_each_input_buffer(i, oic->u) 654*d6e29083SAmirreza Zarrabi qcomtee_object_put(oic->u[i].o); 655*d6e29083SAmirreza Zarrabi 656*d6e29083SAmirreza Zarrabi break; 657*d6e29083SAmirreza Zarrabi } 658*d6e29083SAmirreza Zarrabi 659*d6e29083SAmirreza Zarrabi errno = object->ops->dispatch(oic, object, op, oic->u); 660*d6e29083SAmirreza Zarrabi if (!errno) { 661*d6e29083SAmirreza Zarrabi /* On success, notify at the appropriate time. */ 662*d6e29083SAmirreza Zarrabi oic->flags |= QCOMTEE_OIC_FLAG_NOTIFY; 663*d6e29083SAmirreza Zarrabi } 664*d6e29083SAmirreza Zarrabi } 665*d6e29083SAmirreza Zarrabi 666*d6e29083SAmirreza Zarrabi out: 667*d6e29083SAmirreza Zarrabi 668*d6e29083SAmirreza Zarrabi oic->errno = errno; 669*d6e29083SAmirreza Zarrabi } 670*d6e29083SAmirreza Zarrabi 671*d6e29083SAmirreza Zarrabi static int 672*d6e29083SAmirreza Zarrabi qcomtee_object_invoke_ctx_invoke(struct qcomtee_object_invoke_ctx *oic, 673*d6e29083SAmirreza Zarrabi int *result, u64 *res_type) 674*d6e29083SAmirreza Zarrabi { 675*d6e29083SAmirreza Zarrabi phys_addr_t out_msg_paddr; 676*d6e29083SAmirreza Zarrabi phys_addr_t in_msg_paddr; 677*d6e29083SAmirreza Zarrabi int ret; 678*d6e29083SAmirreza Zarrabi u64 res; 679*d6e29083SAmirreza Zarrabi 680*d6e29083SAmirreza Zarrabi tee_shm_get_pa(oic->out_shm, 0, &out_msg_paddr); 681*d6e29083SAmirreza Zarrabi tee_shm_get_pa(oic->in_shm, 0, &in_msg_paddr); 682*d6e29083SAmirreza Zarrabi if (!(oic->flags & QCOMTEE_OIC_FLAG_BUSY)) 683*d6e29083SAmirreza Zarrabi ret = qcom_scm_qtee_invoke_smc(in_msg_paddr, oic->in_msg.size, 684*d6e29083SAmirreza Zarrabi out_msg_paddr, oic->out_msg.size, 685*d6e29083SAmirreza Zarrabi &res, res_type); 686*d6e29083SAmirreza Zarrabi else 687*d6e29083SAmirreza Zarrabi ret = qcom_scm_qtee_callback_response(out_msg_paddr, 688*d6e29083SAmirreza Zarrabi oic->out_msg.size, 689*d6e29083SAmirreza Zarrabi &res, res_type); 690*d6e29083SAmirreza Zarrabi 691*d6e29083SAmirreza Zarrabi if (ret) 692*d6e29083SAmirreza Zarrabi pr_err("QTEE returned with %d.\n", ret); 693*d6e29083SAmirreza Zarrabi else 694*d6e29083SAmirreza Zarrabi *result = (int)res; 695*d6e29083SAmirreza Zarrabi 696*d6e29083SAmirreza Zarrabi return ret; 697*d6e29083SAmirreza Zarrabi } 698*d6e29083SAmirreza Zarrabi 699*d6e29083SAmirreza Zarrabi /** 700*d6e29083SAmirreza Zarrabi * qcomtee_qtee_objects_put() - Put the callback objects in the argument array. 701*d6e29083SAmirreza Zarrabi * @u: array of arguments. 702*d6e29083SAmirreza Zarrabi * 703*d6e29083SAmirreza Zarrabi * When qcomtee_object_do_invoke_internal() is successfully invoked, 704*d6e29083SAmirreza Zarrabi * QTEE takes ownership of the callback objects. If the invocation fails, 705*d6e29083SAmirreza Zarrabi * qcomtee_object_do_invoke_internal() calls qcomtee_qtee_objects_put() 706*d6e29083SAmirreza Zarrabi * to mimic the release of callback objects by QTEE. 707*d6e29083SAmirreza Zarrabi */ 708*d6e29083SAmirreza Zarrabi static void qcomtee_qtee_objects_put(struct qcomtee_arg *u) 709*d6e29083SAmirreza Zarrabi { 710*d6e29083SAmirreza Zarrabi int i; 711*d6e29083SAmirreza Zarrabi 712*d6e29083SAmirreza Zarrabi qcomtee_arg_for_each_input_object(i, u) { 713*d6e29083SAmirreza Zarrabi if (typeof_qcomtee_object(u[i].o) == QCOMTEE_OBJECT_TYPE_CB) 714*d6e29083SAmirreza Zarrabi qcomtee_object_put(u[i].o); 715*d6e29083SAmirreza Zarrabi } 716*d6e29083SAmirreza Zarrabi } 717*d6e29083SAmirreza Zarrabi 718*d6e29083SAmirreza Zarrabi /** 719*d6e29083SAmirreza Zarrabi * qcomtee_object_do_invoke_internal() - Submit an invocation for an object. 720*d6e29083SAmirreza Zarrabi * @oic: context to use for the current invocation. 721*d6e29083SAmirreza Zarrabi * @object: object being invoked. 722*d6e29083SAmirreza Zarrabi * @op: requested operation on the object. 723*d6e29083SAmirreza Zarrabi * @u: array of arguments for the current invocation. 724*d6e29083SAmirreza Zarrabi * @result: result returned from QTEE. 725*d6e29083SAmirreza Zarrabi * 726*d6e29083SAmirreza Zarrabi * The caller is responsible for keeping track of the refcount for each 727*d6e29083SAmirreza Zarrabi * object, including @object. On return, the caller loses ownership of all 728*d6e29083SAmirreza Zarrabi * input objects of type %QCOMTEE_OBJECT_TYPE_CB. 729*d6e29083SAmirreza Zarrabi * 730*d6e29083SAmirreza Zarrabi * Return: On success, returns 0; on failure, returns < 0. 731*d6e29083SAmirreza Zarrabi */ 732*d6e29083SAmirreza Zarrabi int qcomtee_object_do_invoke_internal(struct qcomtee_object_invoke_ctx *oic, 733*d6e29083SAmirreza Zarrabi struct qcomtee_object *object, u32 op, 734*d6e29083SAmirreza Zarrabi struct qcomtee_arg *u, int *result) 735*d6e29083SAmirreza Zarrabi { 736*d6e29083SAmirreza Zarrabi struct qcomtee_msg_callback *cb_msg; 737*d6e29083SAmirreza Zarrabi struct qcomtee_object *qto; 738*d6e29083SAmirreza Zarrabi int i, ret, errno; 739*d6e29083SAmirreza Zarrabi u64 res_type; 740*d6e29083SAmirreza Zarrabi 741*d6e29083SAmirreza Zarrabi /* Allocate inbound and outbound buffers. */ 742*d6e29083SAmirreza Zarrabi ret = qcomtee_msg_buffers_alloc(oic, u); 743*d6e29083SAmirreza Zarrabi if (ret) { 744*d6e29083SAmirreza Zarrabi qcomtee_qtee_objects_put(u); 745*d6e29083SAmirreza Zarrabi 746*d6e29083SAmirreza Zarrabi return ret; 747*d6e29083SAmirreza Zarrabi } 748*d6e29083SAmirreza Zarrabi 749*d6e29083SAmirreza Zarrabi ret = qcomtee_prepare_msg(oic, object, op, u); 750*d6e29083SAmirreza Zarrabi if (ret) { 751*d6e29083SAmirreza Zarrabi qcomtee_qtee_objects_put(u); 752*d6e29083SAmirreza Zarrabi 753*d6e29083SAmirreza Zarrabi goto out; 754*d6e29083SAmirreza Zarrabi } 755*d6e29083SAmirreza Zarrabi 756*d6e29083SAmirreza Zarrabi /* Use input message buffer in 'oic'. */ 757*d6e29083SAmirreza Zarrabi cb_msg = oic->out_msg.addr; 758*d6e29083SAmirreza Zarrabi 759*d6e29083SAmirreza Zarrabi while (1) { 760*d6e29083SAmirreza Zarrabi if (oic->flags & QCOMTEE_OIC_FLAG_BUSY) { 761*d6e29083SAmirreza Zarrabi errno = oic->errno; 762*d6e29083SAmirreza Zarrabi if (!errno) 763*d6e29083SAmirreza Zarrabi errno = qcomtee_update_msg(oic); 764*d6e29083SAmirreza Zarrabi qcomtee_msg_set_result(cb_msg, errno); 765*d6e29083SAmirreza Zarrabi } 766*d6e29083SAmirreza Zarrabi 767*d6e29083SAmirreza Zarrabi /* Invoke the remote object. */ 768*d6e29083SAmirreza Zarrabi ret = qcomtee_object_invoke_ctx_invoke(oic, result, &res_type); 769*d6e29083SAmirreza Zarrabi /* Return form callback objects result submission: */ 770*d6e29083SAmirreza Zarrabi if (oic->flags & QCOMTEE_OIC_FLAG_BUSY) { 771*d6e29083SAmirreza Zarrabi qto = oic->object; 772*d6e29083SAmirreza Zarrabi if (qto) { 773*d6e29083SAmirreza Zarrabi if (oic->flags & QCOMTEE_OIC_FLAG_NOTIFY) { 774*d6e29083SAmirreza Zarrabi if (qto->ops->notify) 775*d6e29083SAmirreza Zarrabi qto->ops->notify(oic, qto, 776*d6e29083SAmirreza Zarrabi errno || ret); 777*d6e29083SAmirreza Zarrabi } 778*d6e29083SAmirreza Zarrabi 779*d6e29083SAmirreza Zarrabi /* Get is in qcomtee_cb_object_invoke(). */ 780*d6e29083SAmirreza Zarrabi qcomtee_object_put(qto); 781*d6e29083SAmirreza Zarrabi } 782*d6e29083SAmirreza Zarrabi 783*d6e29083SAmirreza Zarrabi oic->object = NULL_QCOMTEE_OBJECT; 784*d6e29083SAmirreza Zarrabi oic->flags &= ~(QCOMTEE_OIC_FLAG_BUSY | 785*d6e29083SAmirreza Zarrabi QCOMTEE_OIC_FLAG_NOTIFY); 786*d6e29083SAmirreza Zarrabi } 787*d6e29083SAmirreza Zarrabi 788*d6e29083SAmirreza Zarrabi if (ret) { 789*d6e29083SAmirreza Zarrabi /* 790*d6e29083SAmirreza Zarrabi * Unable to finished the invocation. 791*d6e29083SAmirreza Zarrabi * If QCOMTEE_OIC_FLAG_SHARED is not set, put 792*d6e29083SAmirreza Zarrabi * QCOMTEE_OBJECT_TYPE_CB input objects. 793*d6e29083SAmirreza Zarrabi */ 794*d6e29083SAmirreza Zarrabi if (!(oic->flags & QCOMTEE_OIC_FLAG_SHARED)) 795*d6e29083SAmirreza Zarrabi qcomtee_qtee_objects_put(u); 796*d6e29083SAmirreza Zarrabi else 797*d6e29083SAmirreza Zarrabi ret = -ENODEV; 798*d6e29083SAmirreza Zarrabi 799*d6e29083SAmirreza Zarrabi goto out; 800*d6e29083SAmirreza Zarrabi 801*d6e29083SAmirreza Zarrabi } else { 802*d6e29083SAmirreza Zarrabi /* 803*d6e29083SAmirreza Zarrabi * QTEE obtained ownership of QCOMTEE_OBJECT_TYPE_CB 804*d6e29083SAmirreza Zarrabi * input objects in 'u'. On further failure, QTEE is 805*d6e29083SAmirreza Zarrabi * responsible for releasing them. 806*d6e29083SAmirreza Zarrabi */ 807*d6e29083SAmirreza Zarrabi oic->flags |= QCOMTEE_OIC_FLAG_SHARED; 808*d6e29083SAmirreza Zarrabi } 809*d6e29083SAmirreza Zarrabi 810*d6e29083SAmirreza Zarrabi /* Is it a callback request? */ 811*d6e29083SAmirreza Zarrabi if (res_type != QCOMTEE_RESULT_INBOUND_REQ_NEEDED) { 812*d6e29083SAmirreza Zarrabi /* 813*d6e29083SAmirreza Zarrabi * Parse results. If failed, assume the service 814*d6e29083SAmirreza Zarrabi * was unavailable (i.e. QCOMTEE_MSG_ERROR_UNAVAIL) 815*d6e29083SAmirreza Zarrabi * and put output objects to initiate cleanup. 816*d6e29083SAmirreza Zarrabi */ 817*d6e29083SAmirreza Zarrabi if (!*result && qcomtee_update_args(u, oic)) { 818*d6e29083SAmirreza Zarrabi *result = QCOMTEE_MSG_ERROR_UNAVAIL; 819*d6e29083SAmirreza Zarrabi qcomtee_arg_for_each_output_object(i, u) 820*d6e29083SAmirreza Zarrabi qcomtee_object_put(u[i].o); 821*d6e29083SAmirreza Zarrabi } 822*d6e29083SAmirreza Zarrabi 823*d6e29083SAmirreza Zarrabi break; 824*d6e29083SAmirreza Zarrabi 825*d6e29083SAmirreza Zarrabi } else { 826*d6e29083SAmirreza Zarrabi oic->flags |= QCOMTEE_OIC_FLAG_BUSY; 827*d6e29083SAmirreza Zarrabi qcomtee_fetch_async_reqs(oic); 828*d6e29083SAmirreza Zarrabi qcomtee_cb_object_invoke(oic, cb_msg); 829*d6e29083SAmirreza Zarrabi } 830*d6e29083SAmirreza Zarrabi } 831*d6e29083SAmirreza Zarrabi 832*d6e29083SAmirreza Zarrabi qcomtee_fetch_async_reqs(oic); 833*d6e29083SAmirreza Zarrabi out: 834*d6e29083SAmirreza Zarrabi qcomtee_msg_buffers_free(oic); 835*d6e29083SAmirreza Zarrabi 836*d6e29083SAmirreza Zarrabi return ret; 837*d6e29083SAmirreza Zarrabi } 838*d6e29083SAmirreza Zarrabi 839*d6e29083SAmirreza Zarrabi int qcomtee_object_do_invoke(struct qcomtee_object_invoke_ctx *oic, 840*d6e29083SAmirreza Zarrabi struct qcomtee_object *object, u32 op, 841*d6e29083SAmirreza Zarrabi struct qcomtee_arg *u, int *result) 842*d6e29083SAmirreza Zarrabi { 843*d6e29083SAmirreza Zarrabi /* User can not set bits used by transport. */ 844*d6e29083SAmirreza Zarrabi if (op & ~QCOMTEE_MSG_OBJECT_OP_MASK) 845*d6e29083SAmirreza Zarrabi return -EINVAL; 846*d6e29083SAmirreza Zarrabi 847*d6e29083SAmirreza Zarrabi /* User can only invoke QTEE hosted objects. */ 848*d6e29083SAmirreza Zarrabi if (typeof_qcomtee_object(object) != QCOMTEE_OBJECT_TYPE_TEE && 849*d6e29083SAmirreza Zarrabi typeof_qcomtee_object(object) != QCOMTEE_OBJECT_TYPE_ROOT) 850*d6e29083SAmirreza Zarrabi return -EINVAL; 851*d6e29083SAmirreza Zarrabi 852*d6e29083SAmirreza Zarrabi /* User cannot directly issue these operations to QTEE. */ 853*d6e29083SAmirreza Zarrabi if (op == QCOMTEE_MSG_OBJECT_OP_RELEASE || 854*d6e29083SAmirreza Zarrabi op == QCOMTEE_MSG_OBJECT_OP_RETAIN) 855*d6e29083SAmirreza Zarrabi return -EINVAL; 856*d6e29083SAmirreza Zarrabi 857*d6e29083SAmirreza Zarrabi return qcomtee_object_do_invoke_internal(oic, object, op, u, result); 858*d6e29083SAmirreza Zarrabi } 859*d6e29083SAmirreza Zarrabi 860*d6e29083SAmirreza Zarrabi /** 861*d6e29083SAmirreza Zarrabi * qcomtee_object_get_client_env() - Get a privileged client env. object. 862*d6e29083SAmirreza Zarrabi * @oic: context to use for the current invocation. 863*d6e29083SAmirreza Zarrabi * 864*d6e29083SAmirreza Zarrabi * The caller should call qcomtee_object_put() on the returned object 865*d6e29083SAmirreza Zarrabi * to release it. 866*d6e29083SAmirreza Zarrabi * 867*d6e29083SAmirreza Zarrabi * Return: On error, returns %NULL_QCOMTEE_OBJECT. 868*d6e29083SAmirreza Zarrabi * On success, returns the object. 869*d6e29083SAmirreza Zarrabi */ 870*d6e29083SAmirreza Zarrabi struct qcomtee_object * 871*d6e29083SAmirreza Zarrabi qcomtee_object_get_client_env(struct qcomtee_object_invoke_ctx *oic) 872*d6e29083SAmirreza Zarrabi { 873*d6e29083SAmirreza Zarrabi struct qcomtee_arg u[3] = { 0 }; 874*d6e29083SAmirreza Zarrabi int ret, result; 875*d6e29083SAmirreza Zarrabi 876*d6e29083SAmirreza Zarrabi u[0].o = NULL_QCOMTEE_OBJECT; 877*d6e29083SAmirreza Zarrabi u[0].type = QCOMTEE_ARG_TYPE_IO; 878*d6e29083SAmirreza Zarrabi u[1].type = QCOMTEE_ARG_TYPE_OO; 879*d6e29083SAmirreza Zarrabi ret = qcomtee_object_do_invoke(oic, ROOT_QCOMTEE_OBJECT, 880*d6e29083SAmirreza Zarrabi QCOMTEE_ROOT_OP_REG_WITH_CREDENTIALS, u, 881*d6e29083SAmirreza Zarrabi &result); 882*d6e29083SAmirreza Zarrabi if (ret || result) 883*d6e29083SAmirreza Zarrabi return NULL_QCOMTEE_OBJECT; 884*d6e29083SAmirreza Zarrabi 885*d6e29083SAmirreza Zarrabi return u[1].o; 886*d6e29083SAmirreza Zarrabi } 887*d6e29083SAmirreza Zarrabi 888*d6e29083SAmirreza Zarrabi struct qcomtee_object * 889*d6e29083SAmirreza Zarrabi qcomtee_object_get_service(struct qcomtee_object_invoke_ctx *oic, 890*d6e29083SAmirreza Zarrabi struct qcomtee_object *client_env, u32 uid) 891*d6e29083SAmirreza Zarrabi { 892*d6e29083SAmirreza Zarrabi struct qcomtee_arg u[3] = { 0 }; 893*d6e29083SAmirreza Zarrabi int ret, result; 894*d6e29083SAmirreza Zarrabi 895*d6e29083SAmirreza Zarrabi u[0].b.addr = &uid; 896*d6e29083SAmirreza Zarrabi u[0].b.size = sizeof(uid); 897*d6e29083SAmirreza Zarrabi u[0].type = QCOMTEE_ARG_TYPE_IB; 898*d6e29083SAmirreza Zarrabi u[1].type = QCOMTEE_ARG_TYPE_OO; 899*d6e29083SAmirreza Zarrabi ret = qcomtee_object_do_invoke(oic, client_env, QCOMTEE_CLIENT_ENV_OPEN, 900*d6e29083SAmirreza Zarrabi u, &result); 901*d6e29083SAmirreza Zarrabi 902*d6e29083SAmirreza Zarrabi if (ret || result) 903*d6e29083SAmirreza Zarrabi return NULL_QCOMTEE_OBJECT; 904*d6e29083SAmirreza Zarrabi 905*d6e29083SAmirreza Zarrabi return u[1].o; 906*d6e29083SAmirreza Zarrabi } 907