/* 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 */
/* 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 */