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
|
/* SPDX-License-Identifier: GPL-2.0-only */
/*
* Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
*/
#ifndef QCOMTEE_MSG_H
#define QCOMTEE_MSG_H
#include <linux/bitfield.h>
/**
* DOC: ''Qualcomm TEE'' (QTEE) Transport Message
*
* There are two buffers shared with QTEE: inbound and outbound buffers.
* The inbound buffer is used for direct object invocation, and the outbound
* buffer is used to make a request from QTEE to the kernel; i.e., a callback
* request.
*
* The unused tail of the outbound buffer is also used for sending and
* receiving asynchronous messages. An asynchronous message is independent of
* the current object invocation (i.e., contents of the inbound buffer) or
* callback request (i.e., the head of the outbound buffer); see
* qcomtee_get_async_buffer(). It is used by endpoints (QTEE or kernel) as an
* optimization to reduce the number of context switches between the secure and
* non-secure worlds.
*
* For instance, QTEE never sends an explicit callback request to release an
* object in the kernel. Instead, it sends asynchronous release messages in the
* outbound buffer when QTEE returns from the previous direct object invocation,
* or appends asynchronous release messages after the current callback request.
*
* QTEE supports two types of arguments in a message: buffer and object
* arguments. Depending on the direction of data flow, they could be input
* buffer (IO) to QTEE, output buffer (OB) from QTEE, input object (IO) to QTEE,
* or output object (OO) from QTEE. Object arguments hold object IDs. Buffer
* arguments hold (offset, size) pairs into the inbound or outbound buffers.
*
* QTEE holds an object table for objects it hosts and exposes to the kernel.
* An object ID is an index to the object table in QTEE.
*
* For the direct object invocation message format in the inbound buffer, see
* &struct qcomtee_msg_object_invoke. For the callback request message format
* in the outbound buffer, see &struct qcomtee_msg_callback. For the message
* format for asynchronous messages in the outbound buffer, see
* &struct qcomtee_async_msg_hdr.
*/
/**
* define QCOMTEE_MSG_OBJECT_NS_BIT - Non-secure bit
*
* Object ID is a globally unique 32-bit number. IDs referencing objects
* in the kernel should have %QCOMTEE_MSG_OBJECT_NS_BIT set.
*/
#define QCOMTEE_MSG_OBJECT_NS_BIT BIT(31)
/* Static object IDs recognized by QTEE. */
#define QCOMTEE_MSG_OBJECT_NULL (0U)
#define QCOMTEE_MSG_OBJECT_ROOT (1U)
/* Definitions from QTEE as part of the transport protocol. */
/* qcomtee_msg_arg is an argument as recognized by QTEE. */
union qcomtee_msg_arg {
struct {
u32 offset;
u32 size;
} b;
u32 o;
};
/* BI and BO payloads in QTEE messages should be at 64-bit boundaries. */
#define qcomtee_msg_offset_align(o) ALIGN((o), sizeof(u64))
/* Operations for objects are 32-bit. Transport uses the upper 16 bits. */
#define QCOMTEE_MSG_OBJECT_OP_MASK GENMASK(15, 0)
/* Reserved Operation IDs sent to QTEE: */
/* QCOMTEE_MSG_OBJECT_OP_RELEASE - Reduces the refcount and releases the object.
* QCOMTEE_MSG_OBJECT_OP_RETAIN - Increases the refcount.
*
* These operation IDs are valid for all objects.
*/
#define QCOMTEE_MSG_OBJECT_OP_RELEASE (QCOMTEE_MSG_OBJECT_OP_MASK - 0)
#define QCOMTEE_MSG_OBJECT_OP_RETAIN (QCOMTEE_MSG_OBJECT_OP_MASK - 1)
/* Subset of operations supported by QTEE root object. */
#define QCOMTEE_ROOT_OP_REG_WITH_CREDENTIALS 5
#define QCOMTEE_ROOT_OP_NOTIFY_DOMAIN_CHANGE 4
#define QCOMTEE_ROOT_OP_ADCI_ACCEPT 8
#define QCOMTEE_ROOT_OP_ADCI_SHUTDOWN 9
/* Subset of operations supported by client_env object. */
#define QCOMTEE_CLIENT_ENV_OPEN 0
/* List of available QTEE service UIDs and subset of operations. */
#define QCOMTEE_FEATURE_VER_UID 2033
#define QCOMTEE_FEATURE_VER_OP_GET 0
/* Get QTEE version number. */
#define QCOMTEE_FEATURE_VER_OP_GET_QTEE_ID 10
#define QTEE_VERSION_GET_MAJOR(x) (((x) >> 22) & 0xffU)
#define QTEE_VERSION_GET_MINOR(x) (((x) >> 12) & 0xffU)
#define QTEE_VERSION_GET_PATCH(x) ((x) >> 0 & 0xfffU)
/* Response types as returned from qcomtee_object_invoke_ctx_invoke(). */
/* The message contains a callback request. */
#define QCOMTEE_RESULT_INBOUND_REQ_NEEDED 3
/**
* struct qcomtee_msg_object_invoke - Direct object invocation message.
* @ctx: object ID hosted in QTEE.
* @op: operation for the object.
* @counts: number of different types of arguments in @args.
* @args: array of arguments.
*
* @counts consists of 4 * 4-bit fields. Bits 0 - 3 represent the number of
* input buffers, bits 4 - 7 represent the number of output buffers,
* bits 8 - 11 represent the number of input objects, and bits 12 - 15
* represent the number of output objects. The remaining bits should be zero.
*
* 15 12 11 8 7 4 3 0
* +----------------+----------------+----------------+----------------+
* | #OO objects | #IO objects | #OB buffers | #IB buffers |
* +----------------+----------------+----------------+----------------+
*
* The maximum number of arguments of each type is defined by
* %QCOMTEE_ARGS_PER_TYPE.
*/
struct qcomtee_msg_object_invoke {
u32 cxt;
u32 op;
u32 counts;
union qcomtee_msg_arg args[];
};
/* Bit masks for the four 4-bit nibbles holding the counts. */
#define QCOMTEE_MASK_IB GENMASK(3, 0)
#define QCOMTEE_MASK_OB GENMASK(7, 4)
#define QCOMTEE_MASK_IO GENMASK(11, 8)
#define QCOMTEE_MASK_OO GENMASK(15, 12)
/**
* struct qcomtee_msg_callback - Callback request message.
* @result: result of operation @op on the object referenced by @cxt.
* @cxt: object ID hosted in the kernel.
* @op: operation for the object.
* @counts: number of different types of arguments in @args.
* @args: array of arguments.
*
* For details of @counts, see &qcomtee_msg_object_invoke.counts.
*/
struct qcomtee_msg_callback {
u32 result;
u32 cxt;
u32 op;
u32 counts;
union qcomtee_msg_arg args[];
};
/* Offset in the message for the beginning of the buffer argument's contents. */
#define qcomtee_msg_buffer_args(t, n) \
qcomtee_msg_offset_align(struct_size_t(t, args, n))
/* Pointer to the beginning of a buffer argument's content at an offset. */
#define qcomtee_msg_offset_to_ptr(m, off) ((void *)&((char *)(m))[(off)])
/* Some helpers to manage msg.counts. */
static inline unsigned int qcomtee_msg_num_ib(u32 counts)
{
return FIELD_GET(QCOMTEE_MASK_IB, counts);
}
static inline unsigned int qcomtee_msg_num_ob(u32 counts)
{
return FIELD_GET(QCOMTEE_MASK_OB, counts);
}
static inline unsigned int qcomtee_msg_num_io(u32 counts)
{
return FIELD_GET(QCOMTEE_MASK_IO, counts);
}
static inline unsigned int qcomtee_msg_num_oo(u32 counts)
{
return FIELD_GET(QCOMTEE_MASK_OO, counts);
}
static inline unsigned int qcomtee_msg_idx_ib(u32 counts)
{
return 0;
}
static inline unsigned int qcomtee_msg_idx_ob(u32 counts)
{
return qcomtee_msg_num_ib(counts);
}
static inline unsigned int qcomtee_msg_idx_io(u32 counts)
{
return qcomtee_msg_idx_ob(counts) + qcomtee_msg_num_ob(counts);
}
static inline unsigned int qcomtee_msg_idx_oo(u32 counts)
{
return qcomtee_msg_idx_io(counts) + qcomtee_msg_num_io(counts);
}
#define qcomtee_msg_for_each(i, first, num) \
for ((i) = (first); (i) < (first) + (num); (i)++)
#define qcomtee_msg_for_each_input_buffer(i, m) \
qcomtee_msg_for_each(i, qcomtee_msg_idx_ib((m)->counts), \
qcomtee_msg_num_ib((m)->counts))
#define qcomtee_msg_for_each_output_buffer(i, m) \
qcomtee_msg_for_each(i, qcomtee_msg_idx_ob((m)->counts), \
qcomtee_msg_num_ob((m)->counts))
#define qcomtee_msg_for_each_input_object(i, m) \
qcomtee_msg_for_each(i, qcomtee_msg_idx_io((m)->counts), \
qcomtee_msg_num_io((m)->counts))
#define qcomtee_msg_for_each_output_object(i, m) \
qcomtee_msg_for_each(i, qcomtee_msg_idx_oo((m)->counts), \
qcomtee_msg_num_oo((m)->counts))
/* Sum of arguments in a message. */
#define qcomtee_msg_args(m) \
(qcomtee_msg_idx_oo((m)->counts) + qcomtee_msg_num_oo((m)->counts))
static inline void qcomtee_msg_init(struct qcomtee_msg_object_invoke *msg,
u32 cxt, u32 op, int in_buffer,
int out_buffer, int in_object,
int out_object)
{
u32 counts = 0;
counts |= (in_buffer & 0xfU);
counts |= ((out_buffer - in_buffer) & 0xfU) << 4;
counts |= ((in_object - out_buffer) & 0xfU) << 8;
counts |= ((out_object - in_object) & 0xfU) << 12;
msg->cxt = cxt;
msg->op = op;
msg->counts = counts;
}
/* Generic error codes. */
#define QCOMTEE_MSG_OK 0 /* non-specific success code. */
#define QCOMTEE_MSG_ERROR 1 /* non-specific error. */
#define QCOMTEE_MSG_ERROR_INVALID 2 /* unsupported/unrecognized request. */
#define QCOMTEE_MSG_ERROR_SIZE_IN 3 /* supplied buffer/string too large. */
#define QCOMTEE_MSG_ERROR_SIZE_OUT 4 /* supplied output buffer too small. */
#define QCOMTEE_MSG_ERROR_USERBASE 10 /* start of user-defined error range. */
/* Transport layer error codes. */
#define QCOMTEE_MSG_ERROR_DEFUNCT -90 /* object no longer exists. */
#define QCOMTEE_MSG_ERROR_ABORT -91 /* calling thread must exit. */
#define QCOMTEE_MSG_ERROR_BADOBJ -92 /* invalid object context. */
#define QCOMTEE_MSG_ERROR_NOSLOTS -93 /* caller's object table full. */
#define QCOMTEE_MSG_ERROR_MAXARGS -94 /* too many args. */
#define QCOMTEE_MSG_ERROR_MAXDATA -95 /* buffers too large. */
#define QCOMTEE_MSG_ERROR_UNAVAIL -96 /* the request could not be processed. */
#define QCOMTEE_MSG_ERROR_KMEM -97 /* kernel out of memory. */
#define QCOMTEE_MSG_ERROR_REMOTE -98 /* local method sent to remote object. */
#define QCOMTEE_MSG_ERROR_BUSY -99 /* Object is busy. */
#define QCOMTEE_MSG_ERROR_TIMEOUT -103 /* Call Back Object invocation timed out. */
static inline void qcomtee_msg_set_result(struct qcomtee_msg_callback *cb_msg,
int err)
{
if (!err) {
cb_msg->result = QCOMTEE_MSG_OK;
} else if (err < 0) {
/* If err < 0, then it is a transport error. */
switch (err) {
case -ENOMEM:
cb_msg->result = QCOMTEE_MSG_ERROR_KMEM;
break;
case -ENODEV:
cb_msg->result = QCOMTEE_MSG_ERROR_DEFUNCT;
break;
case -ENOSPC:
case -EBUSY:
cb_msg->result = QCOMTEE_MSG_ERROR_BUSY;
break;
case -EBADF:
case -EINVAL:
cb_msg->result = QCOMTEE_MSG_ERROR_UNAVAIL;
break;
default:
cb_msg->result = QCOMTEE_MSG_ERROR;
}
} else {
/* If err > 0, then it is user defined error, pass it as is. */
cb_msg->result = err;
}
}
#endif /* QCOMTEE_MSG_H */
|