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