summaryrefslogtreecommitdiff
path: root/drivers/tee/qcomtee/qcomtee_object.h
blob: 5221449be7dbe695b7468443b5a41976222d1932 (plain)
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 */