1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316
|
/* SPDX-License-Identifier: GPL-2.0-only */
/*
* Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
*/
#ifndef QCOMTEE_OBJECT_H
#define QCOMTEE_OBJECT_H
#include <linux/completion.h>
#include <linux/kref.h>
#include <linux/slab.h>
#include <linux/workqueue.h>
struct qcomtee_object;
/**
* DOC: Overview
*
* qcomtee_object provides object refcounting, ID allocation for objects hosted
* in the kernel, and necessary message marshaling for Qualcomm TEE (QTEE).
*
* To invoke an object in QTEE, the user calls qcomtee_object_do_invoke()
* while passing an instance of &struct qcomtee_object and the requested
* operation + arguments.
*
* After boot, QTEE provides a static object %ROOT_QCOMTEE_OBJECT (type of
* %QCOMTEE_OBJECT_TYPE_ROOT). The root object is invoked to pass the user's
* credentials and obtain other instances of &struct qcomtee_object (type of
* %QCOMTEE_OBJECT_TYPE_TEE) that represent services and TAs in QTEE;
* see &enum qcomtee_object_type.
*
* The objects received from QTEE are refcounted. So the owner of these objects
* can issue qcomtee_object_get() to increase the refcount and pass objects
* to other clients, or issue qcomtee_object_put() to decrease the refcount
* and release the resources in QTEE.
*
* The kernel can host services accessible to QTEE. A driver should embed
* an instance of &struct qcomtee_object in the struct it wants to export to
* QTEE (this is called a callback object). It issues qcomtee_object_user_init()
* to set the dispatch() operation for the callback object and set its type
* to %QCOMTEE_OBJECT_TYPE_CB.
*
* core.c holds an object table for callback objects. An object ID is assigned
* to each callback object, which is an index to the object table. QTEE uses
* these IDs to reference or invoke callback objects.
*
* If QTEE invokes a callback object in the kernel, the dispatch() operation is
* called in the context of the thread that originally called
* qcomtee_object_do_invoke().
*/
/**
* enum qcomtee_object_type - Object types.
* @QCOMTEE_OBJECT_TYPE_TEE: object hosted on QTEE.
* @QCOMTEE_OBJECT_TYPE_CB: object hosted on kernel.
* @QCOMTEE_OBJECT_TYPE_ROOT: 'primordial' object.
* @QCOMTEE_OBJECT_TYPE_NULL: NULL object.
*
* The primordial object is used for bootstrapping the IPC connection between
* the kernel and QTEE. It is invoked by the kernel when it wants to get a
* 'client env'.
*/
enum qcomtee_object_type {
QCOMTEE_OBJECT_TYPE_TEE,
QCOMTEE_OBJECT_TYPE_CB,
QCOMTEE_OBJECT_TYPE_ROOT,
QCOMTEE_OBJECT_TYPE_NULL,
};
/**
* enum qcomtee_arg_type - Type of QTEE argument.
* @QCOMTEE_ARG_TYPE_INV: invalid type.
* @QCOMTEE_ARG_TYPE_OB: output buffer (OB).
* @QCOMTEE_ARG_TYPE_OO: output object (OO).
* @QCOMTEE_ARG_TYPE_IB: input buffer (IB).
* @QCOMTEE_ARG_TYPE_IO: input object (IO).
*
* Use the invalid type to specify the end of the argument array.
*/
enum qcomtee_arg_type {
QCOMTEE_ARG_TYPE_INV = 0,
QCOMTEE_ARG_TYPE_OB,
QCOMTEE_ARG_TYPE_OO,
QCOMTEE_ARG_TYPE_IB,
QCOMTEE_ARG_TYPE_IO,
QCOMTEE_ARG_TYPE_NR,
};
/**
* define QCOMTEE_ARGS_PER_TYPE - Maximum arguments of a specific type.
*
* The QTEE transport protocol limits the maximum number of arguments of
* a specific type (i.e., IB, OB, IO, and OO).
*/
#define QCOMTEE_ARGS_PER_TYPE 16
/* Maximum arguments that can fit in a QTEE message, ignoring the type. */
#define QCOMTEE_ARGS_MAX (QCOMTEE_ARGS_PER_TYPE * (QCOMTEE_ARG_TYPE_NR - 1))
struct qcomtee_buffer {
union {
void *addr;
void __user *uaddr;
};
size_t size;
};
/**
* struct qcomtee_arg - Argument for QTEE object invocation.
* @type: type of argument as &enum qcomtee_arg_type.
* @flags: extra flags.
* @b: address and size if the type of argument is a buffer.
* @o: object instance if the type of argument is an object.
*
* &qcomtee_arg.flags only accepts %QCOMTEE_ARG_FLAGS_UADDR for now, which
* states that &qcomtee_arg.b contains a userspace address in uaddr.
*/
struct qcomtee_arg {
enum qcomtee_arg_type type;
/* 'b.uaddr' holds a __user address. */
#define QCOMTEE_ARG_FLAGS_UADDR BIT(0)
unsigned int flags;
union {
struct qcomtee_buffer b;
struct qcomtee_object *o;
};
};
static inline int qcomtee_args_len(struct qcomtee_arg *args)
{
int i = 0;
while (args[i].type != QCOMTEE_ARG_TYPE_INV)
i++;
return i;
}
/* Context is busy (callback is in progress). */
#define QCOMTEE_OIC_FLAG_BUSY BIT(1)
/* Context needs to notify the current object. */
#define QCOMTEE_OIC_FLAG_NOTIFY BIT(2)
/* Context has shared state with QTEE. */
#define QCOMTEE_OIC_FLAG_SHARED BIT(3)
/**
* struct qcomtee_object_invoke_ctx - QTEE context for object invocation.
* @ctx: TEE context for this invocation.
* @flags: flags for the invocation context.
* @errno: error code for the invocation.
* @object: current object invoked in this callback context.
* @u: array of arguments for the current invocation (+1 for ending arg).
* @in_msg: inbound buffer shared with QTEE.
* @out_msg: outbound buffer shared with QTEE.
* @in_shm: TEE shm allocated for inbound buffer.
* @out_shm: TEE shm allocated for outbound buffer.
* @data: extra data attached to this context.
*/
struct qcomtee_object_invoke_ctx {
struct tee_context *ctx;
unsigned long flags;
int errno;
struct qcomtee_object *object;
struct qcomtee_arg u[QCOMTEE_ARGS_MAX + 1];
struct qcomtee_buffer in_msg;
struct qcomtee_buffer out_msg;
struct tee_shm *in_shm;
struct tee_shm *out_shm;
void *data;
};
static inline struct qcomtee_object_invoke_ctx *
qcomtee_object_invoke_ctx_alloc(struct tee_context *ctx)
{
struct qcomtee_object_invoke_ctx *oic;
oic = kzalloc(sizeof(*oic), GFP_KERNEL);
if (oic)
oic->ctx = ctx;
return oic;
}
/**
* qcomtee_object_do_invoke() - Submit an invocation for an object.
* @oic: context to use for the current invocation.
* @object: object being invoked.
* @op: requested operation on the object.
* @u: array of arguments for the current invocation.
* @result: result returned from QTEE.
*
* The caller is responsible for keeping track of the refcount for each object,
* including @object. On return, the caller loses ownership of all input
* objects of type %QCOMTEE_OBJECT_TYPE_CB.
*
* @object can be of %QCOMTEE_OBJECT_TYPE_ROOT or %QCOMTEE_OBJECT_TYPE_TEE.
*
* Return: On success, returns 0; on failure, returns < 0.
*/
int qcomtee_object_do_invoke(struct qcomtee_object_invoke_ctx *oic,
struct qcomtee_object *object, u32 op,
struct qcomtee_arg *u, int *result);
/**
* struct qcomtee_object_operations - Callback object operations.
* @release: release the object if QTEE is not using it.
* @dispatch: dispatch the operation requested by QTEE.
* @notify: report the status of any pending response submitted by @dispatch.
*/
struct qcomtee_object_operations {
void (*release)(struct qcomtee_object *object);
int (*dispatch)(struct qcomtee_object_invoke_ctx *oic,
struct qcomtee_object *object, u32 op,
struct qcomtee_arg *args);
void (*notify)(struct qcomtee_object_invoke_ctx *oic,
struct qcomtee_object *object, int err);
};
/**
* struct qcomtee_object - QTEE or kernel object.
* @name: object name.
* @refcount: reference counter.
* @object_type: object type as &enum qcomtee_object_type.
* @info: extra information for the object.
* @ops: callback operations for objects of type %QCOMTEE_OBJECT_TYPE_CB.
* @work: work for async operations on the object.
*
* @work is used for releasing objects of %QCOMTEE_OBJECT_TYPE_TEE type.
*/
struct qcomtee_object {
const char *name;
struct kref refcount;
enum qcomtee_object_type object_type;
struct object_info {
unsigned long qtee_id;
/* TEE context for QTEE object async requests. */
struct tee_context *qcomtee_async_ctx;
} info;
struct qcomtee_object_operations *ops;
struct work_struct work;
};
/* Static instances of qcomtee_object objects. */
#define NULL_QCOMTEE_OBJECT ((struct qcomtee_object *)(0))
extern struct qcomtee_object qcomtee_object_root;
#define ROOT_QCOMTEE_OBJECT (&qcomtee_object_root)
static inline enum qcomtee_object_type
typeof_qcomtee_object(struct qcomtee_object *object)
{
if (object == NULL_QCOMTEE_OBJECT)
return QCOMTEE_OBJECT_TYPE_NULL;
return object->object_type;
}
static inline const char *qcomtee_object_name(struct qcomtee_object *object)
{
if (object == NULL_QCOMTEE_OBJECT)
return "null";
if (!object->name)
return "no-name";
return object->name;
}
/**
* qcomtee_object_user_init() - Initialize an object for the user.
* @object: object to initialize.
* @ot: type of object as &enum qcomtee_object_type.
* @ops: instance of callbacks.
* @fmt: name assigned to the object.
*
* Return: On success, returns 0; on failure, returns < 0.
*/
int qcomtee_object_user_init(struct qcomtee_object *object,
enum qcomtee_object_type ot,
struct qcomtee_object_operations *ops,
const char *fmt, ...) __printf(4, 5);
/* Object release is RCU protected. */
int qcomtee_object_get(struct qcomtee_object *object);
void qcomtee_object_put(struct qcomtee_object *object);
#define qcomtee_arg_for_each(i, args) \
for (i = 0; args[i].type != QCOMTEE_ARG_TYPE_INV; i++)
/* Next argument of type @type after index @i. */
int qcomtee_next_arg_type(struct qcomtee_arg *u, int i,
enum qcomtee_arg_type type);
/* Iterate over argument of given type. */
#define qcomtee_arg_for_each_type(i, args, at) \
for (i = qcomtee_next_arg_type(args, 0, at); \
args[i].type != QCOMTEE_ARG_TYPE_INV; \
i = qcomtee_next_arg_type(args, i + 1, at))
#define qcomtee_arg_for_each_input_buffer(i, args) \
qcomtee_arg_for_each_type(i, args, QCOMTEE_ARG_TYPE_IB)
#define qcomtee_arg_for_each_output_buffer(i, args) \
qcomtee_arg_for_each_type(i, args, QCOMTEE_ARG_TYPE_OB)
#define qcomtee_arg_for_each_input_object(i, args) \
qcomtee_arg_for_each_type(i, args, QCOMTEE_ARG_TYPE_IO)
#define qcomtee_arg_for_each_output_object(i, args) \
qcomtee_arg_for_each_type(i, args, QCOMTEE_ARG_TYPE_OO)
struct qcomtee_object *
qcomtee_object_get_client_env(struct qcomtee_object_invoke_ctx *oic);
struct qcomtee_object *
qcomtee_object_get_service(struct qcomtee_object_invoke_ctx *oic,
struct qcomtee_object *client_env, u32 uid);
#endif /* QCOMTEE_OBJECT_H */
|