| 1 |
|
| 2 | |
| 3 | * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
|
| 4 |
|
| 5 |
|
| 6 | #ifndef QCOMTEE_MSG_H
|
| 7 | #define QCOMTEE_MSG_H
|
| 8 |
|
| 9 | #include <linux/bitfield.h>
|
| 10 |
|
| 11 | |
| 12 | * DOC: ''Qualcomm TEE'' (QTEE) Transport Message
|
| 13 | *
|
| 14 | * There are two buffers shared with QTEE: inbound and outbound buffers.
|
| 15 | * The inbound buffer is used for direct object invocation, and the outbound
|
| 16 | * buffer is used to make a request from QTEE to the kernel; i.e., a callback
|
| 17 | * request.
|
| 18 | *
|
| 19 | * The unused tail of the outbound buffer is also used for sending and
|
| 20 | * receiving asynchronous messages. An asynchronous message is independent of
|
| 21 | * the current object invocation (i.e., contents of the inbound buffer) or
|
| 22 | * callback request (i.e., the head of the outbound buffer); see
|
| 23 | * qcomtee_get_async_buffer(). It is used by endpoints (QTEE or kernel) as an
|
| 24 | * optimization to reduce the number of context switches between the secure and
|
| 25 | * non-secure worlds.
|
| 26 | *
|
| 27 | * For instance, QTEE never sends an explicit callback request to release an
|
| 28 | * object in the kernel. Instead, it sends asynchronous release messages in the
|
| 29 | * outbound buffer when QTEE returns from the previous direct object invocation,
|
| 30 | * or appends asynchronous release messages after the current callback request.
|
| 31 | *
|
| 32 | * QTEE supports two types of arguments in a message: buffer and object
|
| 33 | * arguments. Depending on the direction of data flow, they could be input
|
| 34 | * buffer (IO) to QTEE, output buffer (OB) from QTEE, input object (IO) to QTEE,
|
| 35 | * or output object (OO) from QTEE. Object arguments hold object IDs. Buffer
|
| 36 | * arguments hold (offset, size) pairs into the inbound or outbound buffers.
|
| 37 | *
|
| 38 | * QTEE holds an object table for objects it hosts and exposes to the kernel.
|
| 39 | * An object ID is an index to the object table in QTEE.
|
| 40 | *
|
| 41 | * For the direct object invocation message format in the inbound buffer, see
|
| 42 | * &struct qcomtee_msg_object_invoke. For the callback request message format
|
| 43 | * in the outbound buffer, see &struct qcomtee_msg_callback. For the message
|
| 44 | * format for asynchronous messages in the outbound buffer, see
|
| 45 | * &struct qcomtee_async_msg_hdr.
|
| 46 |
|
| 47 |
|
| 48 | |
| 49 | * define QCOMTEE_MSG_OBJECT_NS_BIT - Non-secure bit
|
| 50 | *
|
| 51 | * Object ID is a globally unique 32-bit number. IDs referencing objects
|
| 52 | * in the kernel should have %QCOMTEE_MSG_OBJECT_NS_BIT set.
|
| 53 |
|
| 54 | #define QCOMTEE_MSG_OBJECT_NS_BIT BIT(31)
|
| 55 |
|
| 56 |
|
| 57 | #define QCOMTEE_MSG_OBJECT_NULL (0U)
|
| 58 | #define QCOMTEE_MSG_OBJECT_ROOT (1U)
|
| 59 |
|
| 60 |
|
| 61 |
|
| 62 |
|
| 63 | union qcomtee_msg_arg {
|
| 64 | struct {
|
| 65 | u32 offset;
|
| 66 | u32 size;
|
| 67 | } b;
|
| 68 | u32 o;
|
| 69 | };
|
| 70 |
|
| 71 |
|
| 72 | #define qcomtee_msg_offset_align(o) ALIGN((o), sizeof(u64))
|
| 73 |
|
| 74 |
|
| 75 | #define QCOMTEE_MSG_OBJECT_OP_MASK GENMASK(15, 0)
|
| 76 |
|
| 77 |
|
| 78 | |
| 79 | * QCOMTEE_MSG_OBJECT_OP_RETAIN - Increases the refcount.
|
| 80 | *
|
| 81 | * These operation IDs are valid for all objects.
|
| 82 |
|
| 83 |
|
| 84 | #define QCOMTEE_MSG_OBJECT_OP_RELEASE (QCOMTEE_MSG_OBJECT_OP_MASK - 0)
|
| 85 | #define QCOMTEE_MSG_OBJECT_OP_RETAIN (QCOMTEE_MSG_OBJECT_OP_MASK - 1)
|
| 86 |
|
| 87 |
|
| 88 |
|
| 89 | #define QCOMTEE_ROOT_OP_REG_WITH_CREDENTIALS 5
|
| 90 | #define QCOMTEE_ROOT_OP_NOTIFY_DOMAIN_CHANGE 4
|
| 91 | #define QCOMTEE_ROOT_OP_ADCI_ACCEPT 8
|
| 92 | #define QCOMTEE_ROOT_OP_ADCI_SHUTDOWN 9
|
| 93 |
|
| 94 |
|
| 95 |
|
| 96 | #define QCOMTEE_CLIENT_ENV_OPEN 0
|
| 97 |
|
| 98 |
|
| 99 |
|
| 100 | #define QCOMTEE_FEATURE_VER_UID 2033
|
| 101 | #define QCOMTEE_FEATURE_VER_OP_GET 0
|
| 102 |
|
| 103 | #define QCOMTEE_FEATURE_VER_OP_GET_QTEE_ID 10
|
| 104 | #define QTEE_VERSION_GET_MAJOR(x) (((x) >> 22) & 0xffU)
|
| 105 | #define QTEE_VERSION_GET_MINOR(x) (((x) >> 12) & 0xffU)
|
| 106 | #define QTEE_VERSION_GET_PATCH(x) ((x) >> 0 & 0xfffU)
|
| 107 |
|
| 108 |
|
| 109 |
|
| 110 |
|
| 111 | #define QCOMTEE_RESULT_INBOUND_REQ_NEEDED 3
|
| 112 |
|
| 113 | |
| 114 | * struct qcomtee_msg_object_invoke - Direct object invocation message.
|
| 115 | * @cxt: object ID hosted in QTEE.
|
| 116 | * @op: operation for the object.
|
| 117 | * @counts: number of different types of arguments in @args.
|
| 118 | * @args: array of arguments.
|
| 119 | *
|
| 120 | * @counts consists of 4 * 4-bit fields. Bits 0 - 3 represent the number of
|
| 121 | * input buffers, bits 4 - 7 represent the number of output buffers,
|
| 122 | * bits 8 - 11 represent the number of input objects, and bits 12 - 15
|
| 123 | * represent the number of output objects. The remaining bits should be zero.
|
| 124 | *
|
| 125 | * 15 12 11 8 7 4 3 0
|
| 126 | * +----------------+----------------+----------------+----------------+
|
| 127 | * | #OO objects | #IO objects | #OB buffers | #IB buffers |
|
| 128 | * +----------------+----------------+----------------+----------------+
|
| 129 | *
|
| 130 | * The maximum number of arguments of each type is defined by
|
| 131 | * %QCOMTEE_ARGS_PER_TYPE.
|
| 132 |
|
| 133 | struct qcomtee_msg_object_invoke {
|
| 134 | u32 cxt;
|
| 135 | u32 op;
|
| 136 | u32 counts;
|
| 137 | union qcomtee_msg_arg args[];
|
| 138 | };
|
| 139 |
|
| 140 |
|
| 141 | #define QCOMTEE_MASK_IB GENMASK(3, 0)
|
| 142 | #define QCOMTEE_MASK_OB GENMASK(7, 4)
|
| 143 | #define QCOMTEE_MASK_IO GENMASK(11, 8)
|
| 144 | #define QCOMTEE_MASK_OO GENMASK(15, 12)
|
| 145 |
|
| 146 | |
| 147 | * struct qcomtee_msg_callback - Callback request message.
|
| 148 | * @result: result of operation @op on the object referenced by @cxt.
|
| 149 | * @cxt: object ID hosted in the kernel.
|
| 150 | * @op: operation for the object.
|
| 151 | * @counts: number of different types of arguments in @args.
|
| 152 | * @args: array of arguments.
|
| 153 | *
|
| 154 | * For details of @counts, see &qcomtee_msg_object_invoke.counts.
|
| 155 |
|
| 156 | struct qcomtee_msg_callback {
|
| 157 | u32 result;
|
| 158 | u32 cxt;
|
| 159 | u32 op;
|
| 160 | u32 counts;
|
| 161 | union qcomtee_msg_arg args[];
|
| 162 | };
|
| 163 |
|
| 164 |
|
| 165 | #define qcomtee_msg_buffer_args(t, n) \
|
| 166 | qcomtee_msg_offset_align(struct_size_t(t, args, n))
|
| 167 |
|
| 168 | #define qcomtee_msg_offset_to_ptr(m, off) ((void *)&((char *)(m))[(off)])
|
| 169 |
|
| 170 |
|
| 171 |
|
| 172 | static inline unsigned int qcomtee_msg_num_ib(u32 counts)
|
| 173 | {
|
| 174 | return FIELD_GET(QCOMTEE_MASK_IB, counts);
|
| 175 | }
|
| 176 |
|
| 177 | static inline unsigned int qcomtee_msg_num_ob(u32 counts)
|
| 178 | {
|
| 179 | return FIELD_GET(QCOMTEE_MASK_OB, counts);
|
| 180 | }
|
| 181 |
|
| 182 | static inline unsigned int qcomtee_msg_num_io(u32 counts)
|
| 183 | {
|
| 184 | return FIELD_GET(QCOMTEE_MASK_IO, counts);
|
| 185 | }
|
| 186 |
|
| 187 | static inline unsigned int qcomtee_msg_num_oo(u32 counts)
|
| 188 | {
|
| 189 | return FIELD_GET(QCOMTEE_MASK_OO, counts);
|
| 190 | }
|
| 191 |
|
| 192 | static inline unsigned int qcomtee_msg_idx_ib(u32 counts)
|
| 193 | {
|
| 194 | return 0;
|
| 195 | }
|
| 196 |
|
| 197 | static inline unsigned int qcomtee_msg_idx_ob(u32 counts)
|
| 198 | {
|
| 199 | return qcomtee_msg_num_ib(counts);
|
| 200 | }
|
| 201 |
|
| 202 | static inline unsigned int qcomtee_msg_idx_io(u32 counts)
|
| 203 | {
|
| 204 | return qcomtee_msg_idx_ob(counts) + qcomtee_msg_num_ob(counts);
|
| 205 | }
|
| 206 |
|
| 207 | static inline unsigned int qcomtee_msg_idx_oo(u32 counts)
|
| 208 | {
|
| 209 | return qcomtee_msg_idx_io(counts) + qcomtee_msg_num_io(counts);
|
| 210 | }
|
| 211 |
|
| 212 | #define qcomtee_msg_for_each(i, first, num) \
|
| 213 | for ((i) = (first); (i) < (first) + (num); (i)++)
|
| 214 |
|
| 215 | #define qcomtee_msg_for_each_input_buffer(i, m) \
|
| 216 | qcomtee_msg_for_each(i, qcomtee_msg_idx_ib((m)->counts), \
|
| 217 | qcomtee_msg_num_ib((m)->counts))
|
| 218 |
|
| 219 | #define qcomtee_msg_for_each_output_buffer(i, m) \
|
| 220 | qcomtee_msg_for_each(i, qcomtee_msg_idx_ob((m)->counts), \
|
| 221 | qcomtee_msg_num_ob((m)->counts))
|
| 222 |
|
| 223 | #define qcomtee_msg_for_each_input_object(i, m) \
|
| 224 | qcomtee_msg_for_each(i, qcomtee_msg_idx_io((m)->counts), \
|
| 225 | qcomtee_msg_num_io((m)->counts))
|
| 226 |
|
| 227 | #define qcomtee_msg_for_each_output_object(i, m) \
|
| 228 | qcomtee_msg_for_each(i, qcomtee_msg_idx_oo((m)->counts), \
|
| 229 | qcomtee_msg_num_oo((m)->counts))
|
| 230 |
|
| 231 |
|
| 232 | #define qcomtee_msg_args(m) \
|
| 233 | (qcomtee_msg_idx_oo((m)->counts) + qcomtee_msg_num_oo((m)->counts))
|
| 234 |
|
| 235 | static inline void qcomtee_msg_init(struct qcomtee_msg_object_invoke *msg,
|
| 236 | u32 cxt, u32 op, int in_buffer,
|
| 237 | int out_buffer, int in_object,
|
| 238 | int out_object)
|
| 239 | {
|
| 240 | u32 counts = 0;
|
| 241 |
|
| 242 | counts |= (in_buffer & 0xfU);
|
| 243 | counts |= ((out_buffer - in_buffer) & 0xfU) << 4;
|
| 244 | counts |= ((in_object - out_buffer) & 0xfU) << 8;
|
| 245 | counts |= ((out_object - in_object) & 0xfU) << 12;
|
| 246 |
|
| 247 | msg->cxt = cxt;
|
| 248 | msg->op = op;
|
| 249 | msg->counts = counts;
|
| 250 | }
|
| 251 |
|
| 252 |
|
| 253 | #define QCOMTEE_MSG_OK 0
|
| 254 | #define QCOMTEE_MSG_ERROR 1
|
| 255 | #define QCOMTEE_MSG_ERROR_INVALID 2
|
| 256 | #define QCOMTEE_MSG_ERROR_SIZE_IN 3
|
| 257 | #define QCOMTEE_MSG_ERROR_SIZE_OUT 4
|
| 258 | #define QCOMTEE_MSG_ERROR_USERBASE 10
|
| 259 |
|
| 260 |
|
| 261 | #define QCOMTEE_MSG_ERROR_DEFUNCT -90
|
| 262 | #define QCOMTEE_MSG_ERROR_ABORT -91
|
| 263 | #define QCOMTEE_MSG_ERROR_BADOBJ -92
|
| 264 | #define QCOMTEE_MSG_ERROR_NOSLOTS -93
|
| 265 | #define QCOMTEE_MSG_ERROR_MAXARGS -94
|
| 266 | #define QCOMTEE_MSG_ERROR_MAXDATA -95
|
| 267 | #define QCOMTEE_MSG_ERROR_UNAVAIL -96
|
| 268 | #define QCOMTEE_MSG_ERROR_KMEM -97
|
| 269 | #define QCOMTEE_MSG_ERROR_REMOTE -98
|
| 270 | #define QCOMTEE_MSG_ERROR_BUSY -99
|
| 271 | #define QCOMTEE_MSG_ERROR_TIMEOUT -103
|
| 272 |
|
| 273 | static inline void qcomtee_msg_set_result(struct qcomtee_msg_callback *cb_msg,
|
| 274 | int err)
|
| 275 | {
|
| 276 | if (!err) {
|
| 277 | cb_msg->result = QCOMTEE_MSG_OK;
|
| 278 | } else if (err < 0) {
|
| 279 |
|
| 280 | switch (err) {
|
| 281 | case -ENOMEM:
|
| 282 | cb_msg->result = QCOMTEE_MSG_ERROR_KMEM;
|
| 283 | break;
|
| 284 | case -ENODEV:
|
| 285 | cb_msg->result = QCOMTEE_MSG_ERROR_DEFUNCT;
|
| 286 | break;
|
| 287 | case -ENOSPC:
|
| 288 | case -EBUSY:
|
| 289 | cb_msg->result = QCOMTEE_MSG_ERROR_BUSY;
|
| 290 | break;
|
| 291 | case -EBADF:
|
| 292 | case -EINVAL:
|
| 293 | cb_msg->result = QCOMTEE_MSG_ERROR_UNAVAIL;
|
| 294 | break;
|
| 295 | default:
|
| 296 | cb_msg->result = QCOMTEE_MSG_ERROR;
|
| 297 | }
|
| 298 | } else {
|
| 299 |
|
| 300 | cb_msg->result = err;
|
| 301 | }
|
| 302 | }
|
| 303 |
|
| 304 | #endif
|