| 1 | /* SPDX-License-Identifier: GPL-2.0-only */ |
| 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 | /* Static object IDs recognized by QTEE. */ |
| 57 | #define QCOMTEE_MSG_OBJECT_NULL (0U) |
| 58 | #define QCOMTEE_MSG_OBJECT_ROOT (1U) |
| 59 | |
| 60 | /* Definitions from QTEE as part of the transport protocol. */ |
| 61 | |
| 62 | /* qcomtee_msg_arg is an argument as recognized by QTEE. */ |
| 63 | union qcomtee_msg_arg { |
| 64 | struct { |
| 65 | u32 offset; |
| 66 | u32 size; |
| 67 | } b; |
| 68 | u32 o; |
| 69 | }; |
| 70 | |
| 71 | /* BI and BO payloads in QTEE messages should be at 64-bit boundaries. */ |
| 72 | #define qcomtee_msg_offset_align(o) ALIGN((o), sizeof(u64)) |
| 73 | |
| 74 | /* Operations for objects are 32-bit. Transport uses the upper 16 bits. */ |
| 75 | #define QCOMTEE_MSG_OBJECT_OP_MASK GENMASK(15, 0) |
| 76 | |
| 77 | /* Reserved Operation IDs sent to QTEE: */ |
| 78 | /* QCOMTEE_MSG_OBJECT_OP_RELEASE - Reduces the refcount and releases the object. |
| 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 | /* Subset of operations supported by QTEE root object. */ |
| 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 | /* Subset of operations supported by client_env object. */ |
| 95 | |
| 96 | #define QCOMTEE_CLIENT_ENV_OPEN 0 |
| 97 | |
| 98 | /* List of available QTEE service UIDs and subset of operations. */ |
| 99 | |
| 100 | #define QCOMTEE_FEATURE_VER_UID 2033 |
| 101 | #define QCOMTEE_FEATURE_VER_OP_GET 0 |
| 102 | /* Get QTEE version number. */ |
| 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 | /* Response types as returned from qcomtee_object_invoke_ctx_invoke(). */ |
| 109 | |
| 110 | /* The message contains a callback request. */ |
| 111 | #define QCOMTEE_RESULT_INBOUND_REQ_NEEDED 3 |
| 112 | |
| 113 | /** |
| 114 | * struct qcomtee_msg_object_invoke - Direct object invocation message. |
| 115 | * @ctx: 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 | /* Bit masks for the four 4-bit nibbles holding the counts. */ |
| 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 | /* Offset in the message for the beginning of the buffer argument's contents. */ |
| 165 | #define qcomtee_msg_buffer_args(t, n) \ |
| 166 | qcomtee_msg_offset_align(struct_size_t(t, args, n)) |
| 167 | /* Pointer to the beginning of a buffer argument's content at an offset. */ |
| 168 | #define qcomtee_msg_offset_to_ptr(m, off) ((void *)&((char *)(m))[(off)]) |
| 169 | |
| 170 | /* Some helpers to manage msg.counts. */ |
| 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 | /* Sum of arguments in a message. */ |
| 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 | /* Generic error codes. */ |
| 253 | #define QCOMTEE_MSG_OK 0 /* non-specific success code. */ |
| 254 | #define QCOMTEE_MSG_ERROR 1 /* non-specific error. */ |
| 255 | #define QCOMTEE_MSG_ERROR_INVALID 2 /* unsupported/unrecognized request. */ |
| 256 | #define QCOMTEE_MSG_ERROR_SIZE_IN 3 /* supplied buffer/string too large. */ |
| 257 | #define QCOMTEE_MSG_ERROR_SIZE_OUT 4 /* supplied output buffer too small. */ |
| 258 | #define QCOMTEE_MSG_ERROR_USERBASE 10 /* start of user-defined error range. */ |
| 259 | |
| 260 | /* Transport layer error codes. */ |
| 261 | #define QCOMTEE_MSG_ERROR_DEFUNCT -90 /* object no longer exists. */ |
| 262 | #define QCOMTEE_MSG_ERROR_ABORT -91 /* calling thread must exit. */ |
| 263 | #define QCOMTEE_MSG_ERROR_BADOBJ -92 /* invalid object context. */ |
| 264 | #define QCOMTEE_MSG_ERROR_NOSLOTS -93 /* caller's object table full. */ |
| 265 | #define QCOMTEE_MSG_ERROR_MAXARGS -94 /* too many args. */ |
| 266 | #define QCOMTEE_MSG_ERROR_MAXDATA -95 /* buffers too large. */ |
| 267 | #define QCOMTEE_MSG_ERROR_UNAVAIL -96 /* the request could not be processed. */ |
| 268 | #define QCOMTEE_MSG_ERROR_KMEM -97 /* kernel out of memory. */ |
| 269 | #define QCOMTEE_MSG_ERROR_REMOTE -98 /* local method sent to remote object. */ |
| 270 | #define QCOMTEE_MSG_ERROR_BUSY -99 /* Object is busy. */ |
| 271 | #define QCOMTEE_MSG_ERROR_TIMEOUT -103 /* Call Back Object invocation timed out. */ |
| 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 | /* If err < 0, then it is a transport error. */ |
| 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 | /* If err > 0, then it is user defined error, pass it as is. */ |
| 300 | cb_msg->result = err; |
| 301 | } |
| 302 | } |
| 303 | |
| 304 | #endif /* QCOMTEE_MSG_H */ |
| 305 | |