[PATCH RFC v2 2/8] tee: optee: define the RPMI control and parcel-reference ABI
Amirreza Zarrabi
amirreza.zarrabi at oss.qualcomm.com
Mon Oct 5 17:39:46 PDT 2026
Define the OP-TEE service protocol carried by RPMI TEE_CALL payloads.
Add operations for version and capability queries, shared-memory
unregistration, asynchronous notification enablement, and yielding-call
start and resume. Use fixed-width little-endian control fields and RPMI
error codes for control responses.
Add a parcel memory-reference layout to the common message parameter
union. Identify shared memory by its parcel ID and nonce, with a 64-bit
byte offset and size, without changing the message parameter size.
Encode NULL references with a zero parcel ID and nonce, leaving parcel
ID zero usable with a nonzero nonce.
Document the wire layouts and ownership rules for matching Linux and
OP-TEE implementations.
Signed-off-by: Amirreza Zarrabi <amirreza.zarrabi at oss.qualcomm.com>
---
drivers/tee/optee/optee_msg.h | 38 +++++--
drivers/tee/optee/optee_rpmi.h | 234 +++++++++++++++++++++++++++++++++++++++++
2 files changed, 264 insertions(+), 8 deletions(-)
diff --git a/drivers/tee/optee/optee_msg.h b/drivers/tee/optee/optee_msg.h
index 6c3043f8da33..028f8cd95fdd 100644
--- a/drivers/tee/optee/optee_msg.h
+++ b/drivers/tee/optee/optee_msg.h
@@ -31,6 +31,9 @@
#define OPTEE_MSG_ATTR_TYPE_FMEM_INPUT OPTEE_MSG_ATTR_TYPE_RMEM_INPUT
#define OPTEE_MSG_ATTR_TYPE_FMEM_OUTPUT OPTEE_MSG_ATTR_TYPE_RMEM_OUTPUT
#define OPTEE_MSG_ATTR_TYPE_FMEM_INOUT OPTEE_MSG_ATTR_TYPE_RMEM_INOUT
+#define OPTEE_MSG_ATTR_TYPE_PMEM_INPUT OPTEE_MSG_ATTR_TYPE_RMEM_INPUT
+#define OPTEE_MSG_ATTR_TYPE_PMEM_OUTPUT OPTEE_MSG_ATTR_TYPE_RMEM_OUTPUT
+#define OPTEE_MSG_ATTR_TYPE_PMEM_INOUT OPTEE_MSG_ATTR_TYPE_RMEM_INOUT
#define OPTEE_MSG_ATTR_TYPE_TMEM_INPUT 0x9
#define OPTEE_MSG_ATTR_TYPE_TMEM_OUTPUT 0xa
#define OPTEE_MSG_ATTR_TYPE_TMEM_INOUT 0xb
@@ -149,6 +152,23 @@ struct optee_msg_param_fmem {
u64 global_id;
};
+/**
+ * struct optee_msg_param_pmem - RPMI parcel memory reference
+ * @offs: full-width byte offset from the parcel's first byte
+ * @size: logical reference size, or required size for a short-buffer response
+ * @parcel_id: firmware-assigned parcel identifier
+ * @nonce: nonzero REE nonce supplied when sharing the parcel
+ *
+ * A zero parcel ID and nonce encode a NULL reference. Its offset must be zero;
+ * its size is preserved. Parcel ID zero remains valid with a nonzero nonce.
+ */
+struct optee_msg_param_pmem {
+ u64 offs;
+ u64 size;
+ u32 parcel_id;
+ u32 nonce;
+};
+
/**
* struct optee_msg_param_value - opaque value parameter
* @a: first opaque value
@@ -166,18 +186,19 @@ struct optee_msg_param_value {
/**
* struct optee_msg_param - parameter used together with struct optee_msg_arg
* @attr: attributes
- * @tmem: parameter by temporary memory reference
- * @rmem: parameter by registered memory reference
- * @fmem: parameter by FF-A registered memory reference
- * @value: parameter by opaque value
- * @octets: parameter by octet string
+ * @u.tmem: parameter by temporary memory reference
+ * @u.rmem: parameter by registered memory reference
+ * @u.fmem: parameter by FF-A registered memory reference
+ * @u.pmem: parameter by RPMI parcel memory reference
+ * @u.value: parameter by opaque value
+ * @u.octets: parameter by octet string
* @u: union holding OP-TEE msg parameter
*
* @attr & OPTEE_MSG_ATTR_TYPE_MASK indicates if tmem, rmem or value is used in
* the union. OPTEE_MSG_ATTR_TYPE_VALUE_* indicates value or octets,
- * OPTEE_MSG_ATTR_TYPE_TMEM_* indicates @tmem and
- * OPTEE_MSG_ATTR_TYPE_RMEM_* or the alias PTEE_MSG_ATTR_TYPE_FMEM_* indicates
- * @rmem or @fmem depending on the conduit.
+ * OPTEE_MSG_ATTR_TYPE_TMEM_* indicates @u.tmem. OPTEE_MSG_ATTR_TYPE_RMEM_*
+ * and its FMEM/PMEM aliases indicate @u.rmem, @u.fmem or @u.pmem depending
+ * on the conduit.
* OPTEE_MSG_ATTR_TYPE_NONE indicates that none of the members are used.
*/
struct optee_msg_param {
@@ -186,6 +207,7 @@ struct optee_msg_param {
struct optee_msg_param_tmem tmem;
struct optee_msg_param_rmem rmem;
struct optee_msg_param_fmem fmem;
+ struct optee_msg_param_pmem pmem;
struct optee_msg_param_value value;
u8 octets[24];
} u;
diff --git a/drivers/tee/optee/optee_rpmi.h b/drivers/tee/optee/optee_rpmi.h
new file mode 100644
index 000000000000..252216aad09b
--- /dev/null
+++ b/drivers/tee/optee/optee_rpmi.h
@@ -0,0 +1,234 @@
+/* SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause) */
+/*
+ * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
+ */
+#ifndef OPTEE_RPMI_H
+#define OPTEE_RPMI_H
+
+#include <linux/bitops.h>
+#include <linux/types.h>
+#include <linux/uuid.h>
+
+/*
+ * OP-TEE service ABI over RPMI TEE_CALL.
+ *
+ * Requests and responses are carried in the TEE_CALL service payload.
+ * Control fields are little-endian. Response status fields contain signed
+ * RPMI error codes, distinct from the outer TEE_CALL status and the GP
+ * command result in optee_msg_arg.ret.
+ */
+#define OPTEE_RPMI_SERVICE_UUID \
+ UUID_INIT(0x486178e0, 0xe7f8, 0x11e3, \
+ 0xbc, 0x5e, 0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b)
+
+#define OPTEE_RPMI_VERSION_MAJOR 1
+#define OPTEE_RPMI_VERSION_MINOR 0
+
+/**
+ * struct optee_rpmi_probe_req - request without operation-specific arguments
+ * @op: GET_API_VERSION, GET_OS_VERSION or EXCHANGE_CAPABILITIES
+ */
+struct optee_rpmi_probe_req {
+ __le32 op;
+} __packed;
+
+/**
+ * struct optee_rpmi_status_resp - response carrying only an RPMI status
+ * @status: signed RPMI error code
+ */
+struct optee_rpmi_status_resp {
+ __le32 status;
+} __packed;
+
+/*
+ * Return the service API version.
+ *
+ * Request: struct optee_rpmi_probe_req
+ * Response: struct optee_rpmi_api_resp
+ */
+#define OPTEE_RPMI_GET_API_VERSION 0
+
+/**
+ * struct optee_rpmi_api_resp - GET_API_VERSION response
+ * @status: signed RPMI error code
+ * @major: incompatible protocol revision
+ * @minor: compatible protocol revision
+ */
+struct optee_rpmi_api_resp {
+ __le32 status;
+ __le32 major;
+ __le32 minor;
+} __packed;
+
+/*
+ * Return the trusted OS revision, not the service API revision.
+ *
+ * Request: struct optee_rpmi_probe_req
+ * Response: struct optee_rpmi_os_resp
+ */
+#define OPTEE_RPMI_GET_OS_VERSION 1
+
+/**
+ * struct optee_rpmi_os_resp - GET_OS_VERSION response
+ * @status: signed RPMI error code
+ * @major: trusted OS major revision
+ * @minor: trusted OS minor revision
+ * @reserved: must be zero
+ * @build_id: trusted OS build identifier, zero if unspecified
+ */
+struct optee_rpmi_os_resp {
+ __le32 status;
+ __le32 major;
+ __le32 minor;
+ __le32 reserved;
+ __le64 build_id;
+} __packed;
+
+/*
+ * Query secure-world capabilities and limits.
+ *
+ * Request: struct optee_rpmi_probe_req
+ * Response: struct optee_rpmi_caps_resp
+ */
+#define OPTEE_RPMI_EXCHANGE_CAPABILITIES 2
+
+/**
+ * struct optee_rpmi_caps_resp - EXCHANGE_CAPABILITIES response
+ * @status: signed RPMI error code
+ * @secure_caps: reserved for future optional features; zero in version 1
+ * @rpc_param_count: nonzero parameter capacity of each RPC argument buffer
+ * @notification_count: nonzero logical key count, including synchronous keys
+ * Keys range from zero through notification_count - 1.
+ *
+ * Version 1 defines no capability bits. Unknown bits are ignored by Linux
+ * for compatibility with future extensions.
+ */
+struct optee_rpmi_caps_resp {
+ __le32 status;
+ __le32 secure_caps;
+ __le32 rpc_param_count;
+ __le32 notification_count;
+} __packed;
+
+/*
+ * Unregister a shared parcel from OP-TEE.
+ *
+ * Request: struct optee_rpmi_unregister_req
+ * Response: struct optee_rpmi_status_resp
+ */
+#define OPTEE_RPMI_UNREGISTER_SHM 3
+
+/**
+ * struct optee_rpmi_unregister_req - retire a shared parcel in OP-TEE
+ * @op: OPTEE_RPMI_UNREGISTER_SHM
+ * @parcel_id: parcel to retire; zero is valid with a nonzero nonce
+ * @nonce: nonzero nonce associated with the parcel
+ *
+ * Success means OP-TEE stopped using the mapping and released its receiver
+ * interest.
+ */
+struct optee_rpmi_unregister_req {
+ __le32 op;
+ __le32 parcel_id;
+ __le32 nonce;
+} __packed;
+
+/*
+ * Enable asynchronous notification delivery.
+ *
+ * Request: struct optee_rpmi_enable_notif_req
+ * Response: struct optee_rpmi_status_resp
+ */
+#define OPTEE_RPMI_ENABLE_ASYNC_NOTIF 4
+
+/**
+ * struct optee_rpmi_enable_notif_req - bind an incoming RPMI doorbell
+ * @op: OPTEE_RPMI_ENABLE_ASYNC_NOTIF
+ * @signal_id: allocated TEE-to-REE signal, not a logical notification key
+ *
+ * Success activates delivery and raises the doorbell for pending work.
+ * Raising the signal requests OPTEE_MSG_CMD_DO_BOTTOM_HALF.
+ * OPTEE_MSG_CMD_STOP_ASYNC_NOTIF stops future doorbell generation, but does
+ * not drain already-raised signals or release the signal ID.
+ */
+struct optee_rpmi_enable_notif_req {
+ __le32 op;
+ __le32 signal_id;
+} __packed;
+
+/*
+ * Start a yielding command using shared command and RPC arguments.
+ *
+ * Request: struct optee_rpmi_call_req
+ * Response: struct optee_rpmi_call_resp
+ */
+#define OPTEE_RPMI_YIELDING_CALL_WITH_ARG 5
+
+#define OPTEE_RPMI_YIELDING_CALL_RETURN_DONE 0
+#define OPTEE_RPMI_YIELDING_CALL_RETURN_RPC_CMD 1
+#define OPTEE_RPMI_YIELDING_CALL_RETURN_INTERRUPT 2
+
+/**
+ * struct optee_rpmi_call_req - start a yielding command
+ * @op: OPTEE_RPMI_YIELDING_CALL_WITH_ARG
+ * @parcel_id: argument parcel identity
+ * @nonce: nonce associated with the parcel
+ * @flags: zero in version 1
+ * @arg_offset: command argument byte offset from the parcel's first byte
+ * @rpc_offset: RPC argument byte offset from the parcel's first byte
+ * @arg_size: command argument extent in bytes
+ * @rpc_size: RPC argument capacity in bytes
+ *
+ * Firmware validates ownership, RW access, alignment and disjoint ranges.
+ * RPMI_ERR_BUSY rejects an initial request without acquiring call ownership.
+ */
+struct optee_rpmi_call_req {
+ __le32 op;
+ __le32 parcel_id;
+ __le32 nonce;
+ __le32 flags;
+ __le64 arg_offset;
+ __le64 rpc_offset;
+ __le32 arg_size;
+ __le32 rpc_size;
+} __packed;
+
+/**
+ * struct optee_rpmi_call_resp - yielding command response
+ * @status: signed RPMI error code, distinct from the command's GP result
+ * @result: OPTEE_RPMI_YIELDING_CALL_RETURN_* value when status is success
+ * @resume_token: zero for DONE, nonzero opaque token for a suspended command
+ *
+ * DONE releases all access to the call's argument and RPC ranges. RPC_CMD
+ * requests RPC command handling; INTERRUPT requests resumption without an
+ * RPC command. Tokens belong to one accepted call, service and caller.
+ */
+struct optee_rpmi_call_resp {
+ __le32 status;
+ __le32 result;
+ __le64 resume_token;
+} __packed;
+
+/*
+ * Resume a suspended yielding command.
+ *
+ * Request: struct optee_rpmi_resume_req
+ * Response: struct optee_rpmi_call_resp
+ */
+#define OPTEE_RPMI_YIELDING_CALL_RESUME 6
+
+/**
+ * struct optee_rpmi_resume_req - resume a suspended command
+ * @op: OPTEE_RPMI_YIELDING_CALL_RESUME
+ * @reserved: must be zero
+ * @resume_token: token from the preceding response for this call
+ *
+ * Resume must not return RPMI_ERR_BUSY.
+ */
+struct optee_rpmi_resume_req {
+ __le32 op;
+ __le32 reserved;
+ __le64 resume_token;
+} __packed;
+
+#endif /* OPTEE_RPMI_H */
--
2.34.1
More information about the linux-riscv
mailing list