mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
* [PATCH v3 0/6] Add TEE based client driver for UEFI Secure Application
@ 2026-10-01 11:02 Harshal Dev
  2026-10-01 11:02 ` [PATCH v3 1/6] tee: qcomtee: Track the object invocation context Harshal Dev
                   ` (5 more replies)
  0 siblings, 6 replies; 12+ messages in thread
From: Harshal Dev @ 2026-10-01 11:02 UTC (permalink / raw)
  To: Jens Wiklander, Sumit Garg, Amirreza Zarrabi, Bjorn Andersson,
	Konrad Dybcio, Dmitry Baryshkov
  Cc: Kuldeep Singh, Basant Kumar, Apurupa Pattapu,
	Arun Kumar Neelakantam, op-tee, linux-kernel, linux-arm-msm,
	Harshal Dev

On Qualcomm SoC based platforms, UEFI stores EFI variables within the
Replay Protected Memory Block (RPMB) located within either the UFS,
eMMC or SPI-NOR storage. The RPMB key which is one-time programmed into
the storage controller to allow authentication of the RPMB frames is
generated by and only available to the Qualcomm Trusted Execution
Environment (QTEE). Thus, only QTEE can prepare the RPMB frames which
will be accepted by the storage controller.

The legacy QSEECOM protocol used for communicating with the QTEE is
deprecated and replaced with the use-case agnostic SMCInvoke protocol
starting with the Qualcomm SM8x50 series. On platforms where the QSEECOM
protocol still works (the QSEECOM driver probes) the driver does not
support a listener interface with QTEE to enable writing of non-volatile
EFI variables (via listener requests to Linux from QTEE) to the RPMB
for UFS and eMMC storage. (Qualcomm Compute platforms with SPI-NOR storage
are an exception to this and work with QSEECOM, see the NOTE below)

Therefore on such platforms, a TEE client driver (which communicates with
QTEE via the SMCInvoke protocol implemented by the QCOMTEE driver
registered with the TEE subsystem) must be used to update such EFI variables
through the RPMB service hosted in the QTEE supplicant user-space daemon
[1] which forwards RPMB packets to the RPMB device.

This series introduces such a uefisecapp TEE client driver for the
aforementioned Qualcomm platforms which installs efi-var operations _if_
the QCOMTEE driver registers support for an object-IPC based uefisecapp
service on the TEE bus during its probe. Only new QTEE firmware versions
available at [2] provide access to the uefisecapp service via the SMCInvoke
protocol.

Thus, QCOMTEE now maintains a static list of always-available object-IPC
based secure services exposed by QTEE. These services are implemented either
within the QTEE kernel or within a pre-loaded Trusted Application (TA)
usually loaded by the bootloader. The uefisecapp TA is an example of a
preloaded TA loaded by UEFI. A static list is required since QTEE does not
yet expose any way to dynamically query and enumerate the services exposed
by it.

To facilitate object-IPC interactions from the kernel-space, this
series also introduces a tee_client_object_invoke_func() to allow
invocation of TEE objects similar to the existing tee_client_invoke_func()
API exported by the TEE subsystem which allows invocation of TEE functions.
Some suporting changes are also introduced to track and handle operations
for TEE contexts opened from the kernel-space in the back-end QCOM-TEE
driver.

Finally and as previously mentioned, access to the object-IPC based uefisecapp
service is restricted on older QTEE firmware versions. A new QTEE firmware
release must be picked up from QArtifactory [2] for all upstream supported
Qualcomm SoCs to enable access to uefisecapp service via the TEE client
driver.

This patch series has been validated on Kodiak RB3Gen2 platform with UFS
storage by attempting to read/write EFI variables via the efivar tool [3]
after mounting the efivarfs filesystem. See [4] for an example.

NOTE: Since Compute platforms do not have a firmware running on their SPI-NOR
storage controller which must be programmed with a RPMB key, QTEE has a
SPI-NOR driver which holds the key, and so the QSEECOM driver can be used
for updating EFI variables on these platforms because QTEE never makes a
listener request to Linux (QTEE doesn't need the Linux SPI-NOR driver).
Such platforms are outlined in the following static list [5].

Merge Strategy:

This patch series could either be taken from the OP-TEE tree or the
QCOM soc tree. I would prefer it to be picked by the OP-TEE tree since
all except the uefisecapp TEE client driver patch in this series make
changes relevant to the TEE subsystem. It would be great if the QCOM soc
tree maintainers can Ack the uefisecapp driver patch.

[1] https://github.com/qualcomm/minkipc
[2] https://shorturl.at/zQU07
[3] https://github.com/rhboot/efivar
[4] https://docs.qualcomm.com/doc/80-70020-27/topic/manage_uefi_environment_variables_using_efivar_tool.html
[5] https://elixir.bootlin.com/linux/v7.3-rc5/source/drivers/firmware/qcom/qcom_scm.c#L2302

Signed-off-by: Harshal Dev <harshal.dev@oss.qualcomm.com>
---
Changes in v3:
- Updated the cover letter and commit messages to highlight the following:
  1. Only QTEE has the ability to prepare RPMB frames since it generates and
     holds the RPMB key.
  2. The QSEECOM protocol is deprecated on new platforms and so this series
     migrates the uefisecapp to SMCInvoke which is a use-case agnostic, transport
     focused and easier to maintain protocol.
- Use single if statement to update both flags and addr/uaddr.
- Remove redundant use of new error variable in qcomtee_get_qtee_feature_list().
- Minor fixes such as concise error prints and use of better error codes.
- Fix a double free in qtee_enumerate_service().
- Re-org the qcomtee_enumerate_services() function to re-use the same oic and
  client_env object.
- Remove depends on !QCOM_QSEECOM_UEFISECAPP from Kconfig since both drivers
  can co-exist even on platforms that support both QSEECOM and SMCInvoke protocols.
- Update the Kconfig description to better help the user understand when to enable
  the TEE based uefisecapp driver.
- Removed qcom_tee_uefisecapp.h file and inline the header in qcom_tee_uefisecapp.c
- Rebased patch series onto the latest linux next tag: next-20260930.
- Link to v2: https://lore.kernel.org/r/20260722-qcom_uefisecapp_migrate_qcomtee-v2-0-b8a8fcbe4211@oss.qualcomm.com

Changes in v2:
- Drop using MSB of the object_id to distingush kernel and user object invoke contexts.
- Introduce enum tee_object_invoke_origin to check the context of object invocation.
- Link to v1: https://lore.kernel.org/r/20260707-qcom_uefisecapp_migrate_qcomtee-v1-0-f659cbd5d04c@oss.qualcomm.com

---
Amirreza Zarrabi (2):
      tee: Add kernel client object invoke helper
      tee: qcomtee: Allow object invokes from kernel clients

Harshal Dev (4):
      tee: qcomtee: Track the object invocation context
      tee: Export uuidv5 generation for TEE backends
      tee: qcomtee: Add support for registering QTEE services on TEE bus
      firmware: qcom: Add support for TEE based EFI-var client driver

 MAINTAINERS                                 |   6 +
 arch/arm64/configs/defconfig                |   1 +
 drivers/firmware/qcom/Kconfig               |  31 ++
 drivers/firmware/qcom/Makefile              |   1 +
 drivers/firmware/qcom/qcom_tee_uefisecapp.c | 636 ++++++++++++++++++++++++++++
 drivers/tee/qcomtee/call.c                  | 206 ++++++++-
 drivers/tee/qcomtee/core.c                  |   9 +-
 drivers/tee/qcomtee/qcomtee.h               |  12 +
 drivers/tee/qcomtee/qcomtee_msg.h           |   1 +
 drivers/tee/qcomtee/qcomtee_object.h        |  16 +-
 drivers/tee/tee_core.c                      |  24 +-
 include/linux/tee_core.h                    |  23 +-
 include/linux/tee_drv.h                     |  18 +-
 13 files changed, 952 insertions(+), 32 deletions(-)
---
base-commit: 6c2cb8b8b843d216ab549b678a0d8831c43153e0
change-id: 20260408-qcom_uefisecapp_migrate_qcomtee-13869d45e014

Best regards,
-- 
Harshal Dev <harshal.dev@oss.qualcomm.com>


^ permalink raw reply	[flat|nested] 12+ messages in thread

* [PATCH v3 1/6] tee: qcomtee: Track the object invocation context
  2026-10-01 11:02 [PATCH v3 0/6] Add TEE based client driver for UEFI Secure Application Harshal Dev
@ 2026-10-01 11:02 ` Harshal Dev
  2026-10-01 12:42   ` Sumit Garg
  2026-10-01 11:02 ` [PATCH v3 2/6] tee: Add kernel client object invoke helper Harshal Dev
                   ` (4 subsequent siblings)
  5 siblings, 1 reply; 12+ messages in thread
From: Harshal Dev @ 2026-10-01 11:02 UTC (permalink / raw)
  To: Jens Wiklander, Sumit Garg, Amirreza Zarrabi, Bjorn Andersson,
	Konrad Dybcio, Dmitry Baryshkov
  Cc: Kuldeep Singh, Basant Kumar, Apurupa Pattapu,
	Arun Kumar Neelakantam, op-tee, linux-kernel, linux-arm-msm,
	Harshal Dev

QCOMTEE needs to distinguish between object invocations arriving from
kernel clients and user-space clients in order to correctly marshal
UBUF parameters and decide whether certain operations should be permitted.

Introduce an enum tee_object_invoke_origin to allow clients to indicate
the context of the TEE object invocation, and add a kernel_ctx flag to the
QCOMTEE context so the TEE back-end can track it.

Signed-off-by: Harshal Dev <harshal.dev@oss.qualcomm.com>
---
 drivers/tee/qcomtee/call.c           | 11 ++++++++---
 drivers/tee/qcomtee/qcomtee_object.h |  8 ++++++--
 drivers/tee/tee_core.c               |  3 ++-
 include/linux/tee_core.h             |  8 +++++++-
 4 files changed, 23 insertions(+), 7 deletions(-)

diff --git a/drivers/tee/qcomtee/call.c b/drivers/tee/qcomtee/call.c
index 4a597eeaf174..a0f2992c0611 100644
--- a/drivers/tee/qcomtee/call.c
+++ b/drivers/tee/qcomtee/call.c
@@ -393,15 +393,20 @@ static int qcomtee_root_object_check(u32 op, struct tee_param *params,
  */
 static int qcomtee_object_invoke(struct tee_context *ctx,
 				 struct tee_ioctl_object_invoke_arg *arg,
-				 struct tee_param *params)
+				 struct tee_param *params,
+				 enum tee_object_invoke_origin origin)
 {
 	struct qcomtee_context_data *ctxdata = ctx->data;
 	struct qcomtee_object *object;
+	bool kernel_ctx = false;
 	int i, ret, result;
 
 	if (qcomtee_params_check(params, arg->num_params))
 		return -EINVAL;
 
+	if (origin == TEE_OBJECT_INVOKE_KERNEL)
+		kernel_ctx = true;
+
 	/* First, handle reserved operations: */
 	if (arg->op == QCOMTEE_MSG_OBJECT_OP_RELEASE) {
 		del_qtee_object(arg->id, ctxdata);
@@ -411,7 +416,7 @@ static int qcomtee_object_invoke(struct tee_context *ctx,
 
 	/* Otherwise, invoke a QTEE object: */
 	struct qcomtee_object_invoke_ctx *oic __free(kfree) =
-		qcomtee_object_invoke_ctx_alloc(ctx);
+		qcomtee_object_invoke_ctx_alloc(ctx, kernel_ctx);
 	if (!oic)
 		return -ENOMEM;
 
@@ -648,7 +653,7 @@ static void qcomtee_get_qtee_feature_list(struct tee_context *ctx, u32 id,
 	int result;
 
 	struct qcomtee_object_invoke_ctx *oic __free(kfree) =
-		qcomtee_object_invoke_ctx_alloc(ctx);
+		qcomtee_object_invoke_ctx_alloc(ctx, true);
 	if (!oic)
 		return;
 
diff --git a/drivers/tee/qcomtee/qcomtee_object.h b/drivers/tee/qcomtee/qcomtee_object.h
index d5de02dcef3b..5f40617361fc 100644
--- a/drivers/tee/qcomtee/qcomtee_object.h
+++ b/drivers/tee/qcomtee/qcomtee_object.h
@@ -147,6 +147,7 @@ static inline int qcomtee_args_len(struct qcomtee_arg *args)
  * struct qcomtee_object_invoke_ctx - QTEE context for object invocation.
  * @ctx: TEE context for this invocation.
  * @flags: flags for the invocation context.
+ * @kernel_ctx: flag that indicates this context is owned by a kernel client.
  * @errno: error code for the invocation.
  * @object: current object invoked in this callback context.
  * @u: array of arguments for the current invocation (+1 for ending arg).
@@ -159,6 +160,7 @@ static inline int qcomtee_args_len(struct qcomtee_arg *args)
 struct qcomtee_object_invoke_ctx {
 	struct tee_context *ctx;
 	unsigned long flags;
+	bool kernel_ctx;
 	int errno;
 
 	struct qcomtee_object *object;
@@ -173,13 +175,15 @@ struct qcomtee_object_invoke_ctx {
 };
 
 static inline struct qcomtee_object_invoke_ctx *
-qcomtee_object_invoke_ctx_alloc(struct tee_context *ctx)
+qcomtee_object_invoke_ctx_alloc(struct tee_context *ctx, bool kernel_ctx)
 {
 	struct qcomtee_object_invoke_ctx *oic;
 
 	oic = kzalloc_obj(*oic);
-	if (oic)
+	if (oic) {
 		oic->ctx = ctx;
+		oic->kernel_ctx = kernel_ctx;
+	}
 	return oic;
 }
 
diff --git a/drivers/tee/tee_core.c b/drivers/tee/tee_core.c
index 1aac50c7c1de..30901390149c 100644
--- a/drivers/tee/tee_core.c
+++ b/drivers/tee/tee_core.c
@@ -701,7 +701,8 @@ static int tee_ioctl_object_invoke(struct tee_context *ctx,
 			goto out;
 	}
 
-	rc = ctx->teedev->desc->ops->object_invoke_func(ctx, &arg, params);
+	rc = ctx->teedev->desc->ops->object_invoke_func(ctx, &arg, params,
+							TEE_OBJECT_INVOKE_USERSPACE);
 	if (rc)
 		goto out;
 
diff --git a/include/linux/tee_core.h b/include/linux/tee_core.h
index f993d5118edd..bcb5418d6fdc 100644
--- a/include/linux/tee_core.h
+++ b/include/linux/tee_core.h
@@ -73,6 +73,11 @@ struct tee_device {
 	struct tee_shm_pool *pool;
 };
 
+enum tee_object_invoke_origin {
+	TEE_OBJECT_INVOKE_USERSPACE,
+	TEE_OBJECT_INVOKE_KERNEL,
+};
+
 /**
  * struct tee_driver_ops - driver operations vtable
  * @get_version:	returns version of driver
@@ -117,7 +122,8 @@ struct tee_driver_ops {
 			   struct tee_param *param);
 	int (*object_invoke_func)(struct tee_context *ctx,
 				  struct tee_ioctl_object_invoke_arg *arg,
-				  struct tee_param *param);
+				  struct tee_param *param,
+				  enum tee_object_invoke_origin origin);
 	int (*cancel_req)(struct tee_context *ctx, u32 cancel_id, u32 session);
 	int (*supp_recv)(struct tee_context *ctx, u32 *func, u32 *num_params,
 			 struct tee_param *param);

-- 
2.34.1


^ permalink raw reply	[flat|nested] 12+ messages in thread

* [PATCH v3 2/6] tee: Add kernel client object invoke helper
  2026-10-01 11:02 [PATCH v3 0/6] Add TEE based client driver for UEFI Secure Application Harshal Dev
  2026-10-01 11:02 ` [PATCH v3 1/6] tee: qcomtee: Track the object invocation context Harshal Dev
@ 2026-10-01 11:02 ` Harshal Dev
  2026-10-01 12:43   ` Sumit Garg
  2026-10-01 11:02 ` [PATCH v3 3/6] tee: qcomtee: Allow object invokes from kernel clients Harshal Dev
                   ` (3 subsequent siblings)
  5 siblings, 1 reply; 12+ messages in thread
From: Harshal Dev @ 2026-10-01 11:02 UTC (permalink / raw)
  To: Jens Wiklander, Sumit Garg, Amirreza Zarrabi, Bjorn Andersson,
	Konrad Dybcio, Dmitry Baryshkov
  Cc: Kuldeep Singh, Basant Kumar, Apurupa Pattapu,
	Arun Kumar Neelakantam, op-tee, linux-kernel, linux-arm-msm,
	Harshal Dev

From: Amirreza Zarrabi <amirreza.zarrabi@oss.qualcomm.com>

Kernel clients can open a TEE context and invoke regular TA commands
through tee_client_invoke_func(). However, there is currently no
equivalent helper for invoking TEE objects.

Add tee_client_object_invoke_func() as a kernel client API for issuing
object invocation requests. The helper checks that the backend provides
object_invoke_func() before forwarding the request by setting the origin
as TEE_OBJECT_INVOKE_KERNEL. This allows TEE backends to support
privileged object-based calls from the kernel-space.

Co-developed-by: Harshal Dev <harshal.dev@oss.qualcomm.com>
Signed-off-by: Harshal Dev <harshal.dev@oss.qualcomm.com>
Signed-off-by: Amirreza Zarrabi <amirreza.zarrabi@oss.qualcomm.com>
---
 drivers/tee/tee_core.c  | 12 ++++++++++++
 include/linux/tee_drv.h | 13 +++++++++++++
 2 files changed, 25 insertions(+)

diff --git a/drivers/tee/tee_core.c b/drivers/tee/tee_core.c
index 30901390149c..a03a3d645dd1 100644
--- a/drivers/tee/tee_core.c
+++ b/drivers/tee/tee_core.c
@@ -1404,6 +1404,18 @@ int tee_client_invoke_func(struct tee_context *ctx,
 }
 EXPORT_SYMBOL_GPL(tee_client_invoke_func);
 
+int tee_client_object_invoke_func(struct tee_context *ctx,
+				  struct tee_ioctl_object_invoke_arg *arg,
+				  struct tee_param *param)
+{
+	if (!ctx->teedev->desc->ops->object_invoke_func)
+		return -EINVAL;
+
+	return ctx->teedev->desc->ops->object_invoke_func(ctx, arg, param,
+							  TEE_OBJECT_INVOKE_KERNEL);
+}
+EXPORT_SYMBOL_GPL(tee_client_object_invoke_func);
+
 int tee_client_cancel_req(struct tee_context *ctx,
 			  struct tee_ioctl_cancel_arg *arg)
 {
diff --git a/include/linux/tee_drv.h b/include/linux/tee_drv.h
index f3c5e106d853..369c87ad0205 100644
--- a/include/linux/tee_drv.h
+++ b/include/linux/tee_drv.h
@@ -283,6 +283,19 @@ int tee_client_invoke_func(struct tee_context *ctx,
 			   struct tee_ioctl_invoke_arg *arg,
 			   struct tee_param *param);
 
+/**
+ * tee_client_object_invoke_func() - Invoke a TEE object from kernel space
+ * @ctx:    TEE Context
+ * @arg:    Invoke arguments, see description of
+ *          struct tee_ioctl_object_invoke_arg
+ * @param:  Parameters for the object invocation
+ *
+ * Return: On success, returns 0; on failure, returns < 0.
+ */
+int tee_client_object_invoke_func(struct tee_context *ctx,
+				  struct tee_ioctl_object_invoke_arg *arg,
+				  struct tee_param *param);
+
 /**
  * tee_client_cancel_req() - Request cancellation of the previous open-session
  * or invoke-command operations in a Trusted Application

-- 
2.34.1


^ permalink raw reply	[flat|nested] 12+ messages in thread

* [PATCH v3 3/6] tee: qcomtee: Allow object invokes from kernel clients
  2026-10-01 11:02 [PATCH v3 0/6] Add TEE based client driver for UEFI Secure Application Harshal Dev
  2026-10-01 11:02 ` [PATCH v3 1/6] tee: qcomtee: Track the object invocation context Harshal Dev
  2026-10-01 11:02 ` [PATCH v3 2/6] tee: Add kernel client object invoke helper Harshal Dev
@ 2026-10-01 11:02 ` Harshal Dev
  2026-10-01 12:47   ` Sumit Garg
  2026-10-01 11:02 ` [PATCH v3 4/6] tee: Export uuidv5 generation for TEE backends Harshal Dev
                   ` (2 subsequent siblings)
  5 siblings, 1 reply; 12+ messages in thread
From: Harshal Dev @ 2026-10-01 11:02 UTC (permalink / raw)
  To: Jens Wiklander, Sumit Garg, Amirreza Zarrabi, Bjorn Andersson,
	Konrad Dybcio, Dmitry Baryshkov
  Cc: Kuldeep Singh, Basant Kumar, Apurupa Pattapu,
	Arun Kumar Neelakantam, op-tee, linux-kernel, linux-arm-msm,
	Harshal Dev

From: Amirreza Zarrabi <amirreza.zarrabi@oss.qualcomm.com>

QCOMTEE currently treats UBUF parameters as userspace addresses and
applies userspace restrictions when invoking the root object. This is
not suitable for object invocation requests issued by kernel clients.

Use the kernel_ctx flag to distinguish kernel client requests from
userspace requests. For kernel contexts, do not mark UBUF parameters as
user addresses, and allow permitted root-object operations to proceed
without applying the userspace-only checks.

This allows in-kernel users of tee_client_object_invoke_func() to issue
object invocation requests through the qcomtee backend.

Co-developed-by: Harshal Dev <harshal.dev@oss.qualcomm.com>
Signed-off-by: Harshal Dev <harshal.dev@oss.qualcomm.com>
Signed-off-by: Amirreza Zarrabi <amirreza.zarrabi@oss.qualcomm.com>
---
 drivers/tee/qcomtee/call.c           | 34 +++++++++++++++++++++++-----------
 drivers/tee/qcomtee/qcomtee_object.h |  5 +++--
 include/linux/tee_drv.h              |  5 ++++-
 3 files changed, 30 insertions(+), 14 deletions(-)

diff --git a/drivers/tee/qcomtee/call.c b/drivers/tee/qcomtee/call.c
index a0f2992c0611..b361d9c04de0 100644
--- a/drivers/tee/qcomtee/call.c
+++ b/drivers/tee/qcomtee/call.c
@@ -202,7 +202,7 @@ int qcomtee_objref_from_arg(struct tee_param *param, struct qcomtee_arg *arg,
  */
 static int qcomtee_params_to_args(struct qcomtee_arg *u,
 				  struct tee_param *params, int num_params,
-				  struct tee_context *ctx)
+				  struct qcomtee_object_invoke_ctx *oic)
 {
 	int i;
 
@@ -210,8 +210,14 @@ static int qcomtee_params_to_args(struct qcomtee_arg *u,
 		switch (params[i].attr) {
 		case TEE_IOCTL_PARAM_ATTR_TYPE_UBUF_INPUT:
 		case TEE_IOCTL_PARAM_ATTR_TYPE_UBUF_OUTPUT:
-			u[i].flags = QCOMTEE_ARG_FLAGS_UADDR;
-			u[i].b.uaddr = params[i].u.ubuf.uaddr;
+			if (oic->kernel_ctx) {
+				u[i].flags = 0;
+				u[i].b.addr = params[i].u.ubuf.addr;
+			} else {
+				u[i].flags = QCOMTEE_ARG_FLAGS_UADDR;
+				u[i].b.uaddr = params[i].u.ubuf.uaddr;
+			}
+
 			u[i].b.size = params[i].u.ubuf.size;
 
 			if (params[i].attr ==
@@ -223,7 +229,7 @@ static int qcomtee_params_to_args(struct qcomtee_arg *u,
 			break;
 		case TEE_IOCTL_PARAM_ATTR_TYPE_OBJREF_INPUT:
 			u[i].type = QCOMTEE_ARG_TYPE_IO;
-			if (qcomtee_objref_to_arg(&u[i], &params[i], ctx))
+			if (qcomtee_objref_to_arg(&u[i], &params[i], oic->ctx))
 				goto out_failed;
 
 			break;
@@ -270,7 +276,7 @@ static int qcomtee_params_to_args(struct qcomtee_arg *u,
  */
 static int qcomtee_params_from_args(struct tee_param *params,
 				    struct qcomtee_arg *u, int num_params,
-				    struct tee_context *ctx)
+				    struct qcomtee_object_invoke_ctx *oic)
 {
 	int i, np;
 
@@ -288,7 +294,8 @@ static int qcomtee_params_from_args(struct tee_param *params,
 			break;
 		case QCOMTEE_ARG_TYPE_OO:
 			/* TEE_IOCTL_PARAM_ATTR_TYPE_OBJREF_OUTPUT */
-			if (qcomtee_objref_from_arg(&params[np], &u[np], ctx))
+			if (qcomtee_objref_from_arg(&params[np], &u[np],
+						    oic->ctx))
 				goto out_failed;
 
 			break;
@@ -304,7 +311,7 @@ static int qcomtee_params_from_args(struct tee_param *params,
 	/* Undo qcomtee_objref_from_arg(). */
 	for (i = 0; i < np; i++) {
 		if (params[i].attr == TEE_IOCTL_PARAM_ATTR_TYPE_OBJREF_OUTPUT)
-			qcomtee_context_del_qtee_object(&params[i], ctx);
+			qcomtee_context_del_qtee_object(&params[i], oic->ctx);
 	}
 
 	/* Release any IO and OO objects not processed. */
@@ -357,7 +364,8 @@ static int qcomtee_params_check(struct tee_param *params, int num_params)
 }
 
 /* Check if an operation on ROOT_QCOMTEE_OBJECT from userspace is permitted. */
-static int qcomtee_root_object_check(u32 op, struct tee_param *params,
+static int qcomtee_root_object_check(struct qcomtee_object_invoke_ctx *oic,
+				     u32 op, struct tee_param *params,
 				     int num_params)
 {
 	/* Some privileged operations recognized by QTEE. */
@@ -366,6 +374,9 @@ static int qcomtee_root_object_check(u32 op, struct tee_param *params,
 	    op == QCOMTEE_ROOT_OP_ADCI_SHUTDOWN)
 		return -EINVAL;
 
+	if (oic->kernel_ctx)
+		return 0;
+
 	/*
 	 * QCOMTEE_ROOT_OP_REG_WITH_CREDENTIALS is to register with QTEE
 	 * by passing a credential object as input OBJREF. TEE_OBJREF_NULL as a
@@ -429,7 +440,8 @@ static int qcomtee_object_invoke(struct tee_context *ctx,
 	/* Get an object to invoke. */
 	if (arg->id == TEE_OBJREF_NULL) {
 		/* Use ROOT if TEE_OBJREF_NULL is invoked. */
-		if (qcomtee_root_object_check(arg->op, params, arg->num_params))
+		if (qcomtee_root_object_check(oic, arg->op, params,
+					      arg->num_params))
 			return -EINVAL;
 
 		object = ROOT_QCOMTEE_OBJECT;
@@ -437,7 +449,7 @@ static int qcomtee_object_invoke(struct tee_context *ctx,
 		return -EINVAL;
 	}
 
-	ret = qcomtee_params_to_args(u, params, arg->num_params, ctx);
+	ret = qcomtee_params_to_args(u, params, arg->num_params, oic);
 	if (ret)
 		goto out;
 
@@ -455,7 +467,7 @@ static int qcomtee_object_invoke(struct tee_context *ctx,
 
 	if (!result) {
 		/* Assume service is UNAVAIL if unable to process the result. */
-		if (qcomtee_params_from_args(params, u, arg->num_params, ctx))
+		if (qcomtee_params_from_args(params, u, arg->num_params, oic))
 			result = QCOMTEE_MSG_ERROR_UNAVAIL;
 	} else {
 		/*
diff --git a/drivers/tee/qcomtee/qcomtee_object.h b/drivers/tee/qcomtee/qcomtee_object.h
index 5f40617361fc..d3740099fae0 100644
--- a/drivers/tee/qcomtee/qcomtee_object.h
+++ b/drivers/tee/qcomtee/qcomtee_object.h
@@ -113,8 +113,9 @@ struct qcomtee_buffer {
  * @b: address and size if the type of argument is a buffer.
  * @o: object instance if the type of argument is an object.
  *
- * &qcomtee_arg.flags only accepts %QCOMTEE_ARG_FLAGS_UADDR for now, which
- * states that &qcomtee_arg.b contains a userspace address in uaddr.
++ * If %QCOMTEE_ARG_FLAGS_UADDR is set in &qcomtee_arg.flags then it implies
++ * that &qcomtee_arg.b contains a userspace address in uaddr.
++ * Otherwise, &qcomtee_arg.b contains a kernel address in addr.
  */
 struct qcomtee_arg {
 	enum qcomtee_arg_type type;
diff --git a/include/linux/tee_drv.h b/include/linux/tee_drv.h
index 369c87ad0205..367208210a32 100644
--- a/include/linux/tee_drv.h
+++ b/include/linux/tee_drv.h
@@ -83,7 +83,10 @@ struct tee_param_memref {
 };
 
 struct tee_param_ubuf {
-	void __user *uaddr;
+	union {
+		void *addr;
+		void __user *uaddr;
+	};
 	size_t size;
 };
 

-- 
2.34.1


^ permalink raw reply	[flat|nested] 12+ messages in thread

* [PATCH v3 4/6] tee: Export uuidv5 generation for TEE backends
  2026-10-01 11:02 [PATCH v3 0/6] Add TEE based client driver for UEFI Secure Application Harshal Dev
                   ` (2 preceding siblings ...)
  2026-10-01 11:02 ` [PATCH v3 3/6] tee: qcomtee: Allow object invokes from kernel clients Harshal Dev
@ 2026-10-01 11:02 ` Harshal Dev
  2026-10-01 12:46   ` Sumit Garg
  2026-10-01 11:02 ` [PATCH v3 5/6] tee: qcomtee: Add support for registering QTEE services on TEE bus Harshal Dev
  2026-10-01 11:02 ` [PATCH v3 6/6] firmware: qcom: Add support for TEE based EFI-var client driver Harshal Dev
  5 siblings, 1 reply; 12+ messages in thread
From: Harshal Dev @ 2026-10-01 11:02 UTC (permalink / raw)
  To: Jens Wiklander, Sumit Garg, Amirreza Zarrabi, Bjorn Andersson,
	Konrad Dybcio, Dmitry Baryshkov
  Cc: Kuldeep Singh, Basant Kumar, Apurupa Pattapu,
	Arun Kumar Neelakantam, op-tee, linux-kernel, linux-arm-msm,
	Harshal Dev

Export the uuidv5() function defined in the TEE core to all TEE backends.
This enables the TEE backend drivers to generate a UUID for identifying
and registering their secure services on the TEE bus.

Signed-off-by: Harshal Dev <harshal.dev@oss.qualcomm.com>
---
 drivers/tee/tee_core.c   |  9 +++++----
 include/linux/tee_core.h | 15 +++++++++++++++
 2 files changed, 20 insertions(+), 4 deletions(-)

diff --git a/drivers/tee/tee_core.c b/drivers/tee/tee_core.c
index a03a3d645dd1..2cfd302d1393 100644
--- a/drivers/tee/tee_core.c
+++ b/drivers/tee/tee_core.c
@@ -135,7 +135,7 @@ static int tee_release(struct inode *inode, struct file *filp)
 }
 
 /**
- * uuid_v5() - Calculate UUIDv5
+ * tee_generate_uuid_v5() - Calculate UUIDv5
  * @uuid: Resulting UUID
  * @ns: Name space ID for UUIDv5 function
  * @name: Name for UUIDv5 function
@@ -146,8 +146,8 @@ static int tee_release(struct inode *inode, struct file *filp)
  * This implements section (for SHA-1):
  * 4.3.  Algorithm for Creating a Name-Based UUID
  */
-static void uuid_v5(uuid_t *uuid, const uuid_t *ns, const void *name,
-		    size_t size)
+void tee_generate_uuid_v5(uuid_t *uuid, const uuid_t *ns, const void *name,
+			  size_t size)
 {
 	unsigned char hash[SHA1_DIGEST_SIZE];
 	struct sha1_ctx ctx;
@@ -163,6 +163,7 @@ static void uuid_v5(uuid_t *uuid, const uuid_t *ns, const void *name,
 	uuid->b[6] = (hash[6] & 0x0F) | 0x50;
 	uuid->b[8] = (hash[8] & 0x3F) | 0x80;
 }
+EXPORT_SYMBOL_GPL(tee_generate_uuid_v5);
 
 int tee_session_calc_client_uuid(uuid_t *uuid, u32 connection_method,
 				 const u8 connection_data[TEE_IOCTL_UUID_LEN])
@@ -228,7 +229,7 @@ int tee_session_calc_client_uuid(uuid_t *uuid, u32 connection_method,
 		goto out_free_name;
 	}
 
-	uuid_v5(uuid, &tee_client_uuid_ns, name, name_len);
+	tee_generate_uuid_v5(uuid, &tee_client_uuid_ns, name, name_len);
 out_free_name:
 	kfree(name);
 
diff --git a/include/linux/tee_core.h b/include/linux/tee_core.h
index bcb5418d6fdc..a3f4f88b8423 100644
--- a/include/linux/tee_core.h
+++ b/include/linux/tee_core.h
@@ -272,6 +272,21 @@ void tee_device_set_dev_groups(struct tee_device *teedev,
 int tee_session_calc_client_uuid(uuid_t *uuid, u32 connection_method,
 				 const u8 connection_data[TEE_IOCTL_UUID_LEN]);
 
+/**
+ * tee_generate_uuid_v5() - Calculate UUIDv5
+ * @uuid: Resulting UUID
+ * @ns: Name space ID for UUIDv5 function
+ * @name: Name for UUIDv5 function
+ * @size: Size of name
+ *
+ * UUIDv5 is specific in RFC 4122.
+ *
+ * This implements section (for SHA-1):
+ * 4.3.  Algorithm for Creating a Name-Based UUID
+ */
+void tee_generate_uuid_v5(uuid_t *uuid, const uuid_t *ns, const void *name,
+			  size_t size);
+
 /**
  * struct tee_shm_pool - shared memory pool
  * @ops:		operations

-- 
2.34.1


^ permalink raw reply	[flat|nested] 12+ messages in thread

* [PATCH v3 5/6] tee: qcomtee: Add support for registering QTEE services on TEE bus
  2026-10-01 11:02 [PATCH v3 0/6] Add TEE based client driver for UEFI Secure Application Harshal Dev
                   ` (3 preceding siblings ...)
  2026-10-01 11:02 ` [PATCH v3 4/6] tee: Export uuidv5 generation for TEE backends Harshal Dev
@ 2026-10-01 11:02 ` Harshal Dev
  2026-10-01 12:57   ` Sumit Garg
  2026-10-01 11:02 ` [PATCH v3 6/6] firmware: qcom: Add support for TEE based EFI-var client driver Harshal Dev
  5 siblings, 1 reply; 12+ messages in thread
From: Harshal Dev @ 2026-10-01 11:02 UTC (permalink / raw)
  To: Jens Wiklander, Sumit Garg, Amirreza Zarrabi, Bjorn Andersson,
	Konrad Dybcio, Dmitry Baryshkov
  Cc: Kuldeep Singh, Basant Kumar, Apurupa Pattapu,
	Arun Kumar Neelakantam, op-tee, linux-kernel, linux-arm-msm,
	Harshal Dev

QTEE exposes certain secure services implemented either within the QTEE
kernel or via pre-loaded Trusted Applications (TAs). Such always-available
services can be readily accessed by TEE client drivers via QTEE's
object-IPC protocol if the service is registered as a device on the TEE
bus.

One such service is the EFI-variables service, implemented by the
uefisecapp TA which enables kernel clients to access EFI variables at
runtime.

Maintain a static list of such always-available secure services and add
support for the QCOMTEE driver to register these services as devices on
the TEE bus during probe.

Signed-off-by: Harshal Dev <harshal.dev@oss.qualcomm.com>
---
 drivers/tee/qcomtee/call.c           | 161 ++++++++++++++++++++++++++++++++++-
 drivers/tee/qcomtee/core.c           |   9 +-
 drivers/tee/qcomtee/qcomtee.h        |  12 +++
 drivers/tee/qcomtee/qcomtee_msg.h    |   1 +
 drivers/tee/qcomtee/qcomtee_object.h |   3 +-
 5 files changed, 179 insertions(+), 7 deletions(-)

diff --git a/drivers/tee/qcomtee/call.c b/drivers/tee/qcomtee/call.c
index b361d9c04de0..8fadb7b13e61 100644
--- a/drivers/tee/qcomtee/call.c
+++ b/drivers/tee/qcomtee/call.c
@@ -675,9 +675,13 @@ static void qcomtee_get_qtee_feature_list(struct tee_context *ctx, u32 id,
 
 	/* Get ''FeatureVersions Service'' object. */
 	service = qcomtee_object_get_service(oic, client_env,
-					     QCOMTEE_FEATURE_VER_UID);
-	if (service == NULL_QCOMTEE_OBJECT)
+					     QCOMTEE_FEATURE_VER_UID,
+					     &result);
+	if (service == NULL_QCOMTEE_OBJECT) {
+		if (result)
+			pr_err("FeatureVersions Service unavailable (%d)\n", result);
 		goto out_failed;
+	}
 
 	/* IB: Feature to query. */
 	u[0].b.addr = &id;
@@ -697,6 +701,156 @@ static void qcomtee_get_qtee_feature_list(struct tee_context *ctx, u32 id,
 	qcomtee_object_put(client_env);
 }
 
+/**
+ * is_qcomtee_service_available() - Check if the QTEE service identified by the UID
+ * is available
+ * @oic: context to use for the current invocation.
+ * @client_env: Client environment object.
+ * @service_name: Name of the QTEE service.
+ * @uid: 32-bit UID of the service.
+ *
+ * Returns true if the service exists and is available.
+ * Returns false if a service is not exposed by QTEE.
+ */
+static bool is_qcomtee_service_available(struct qcomtee_object_invoke_ctx *oic,
+					 struct qcomtee_object *client_env,
+					 const char *service_name, u32 uid)
+{
+	struct qcomtee_object *service;
+	int error = 0;
+	bool ret = false;
+
+	/* Get service object corresponding to the uid. */
+	service = qcomtee_object_get_service(oic, client_env, uid, &error);
+	if (service != NULL_QCOMTEE_OBJECT) {
+		qcomtee_object_put(service);
+		ret = true;
+	}
+
+	/* When we fail to get the service, QTEE provides the reason. */
+	if (error)
+		pr_err("%s is unavailable (%d)\n", service_name, error);
+
+	return ret;
+}
+
+/*
+ * QTEE Service UUID name space identifier
+ *
+ * A random UUID that is allocated as a name space identifier for forming UUID's
+ * representing secure services exposed by QTEE.
+ */
+static const uuid_t qtee_service_uuid_ns = UUID_INIT(0xe1b48857, 0x6154, 0x49f9,
+						     0x93, 0x4e, 0xa2, 0xf2,
+						     0x0a, 0xba, 0x98, 0x42);
+
+static const struct qtee_service qtee_services[] = {
+	{ "qcom.tz.uefisecapp",
+	   QCOMTEE_UEFI_SEC_UID }
+};
+
+static void qtee_release_service(struct device *dev)
+{
+	struct tee_client_device *qtee_service = to_tee_client_device(dev);
+
+	kfree(qtee_service);
+}
+
+/**
+ * qtee_enumerate_service() - Enumerate a given QTEE service and register
+ * it on the TEE bus as a TEE client device
+ * @oic: context to use for the current invocation.
+ * @client_env: Client environment object.
+ * @service_name: Name of the QTEE service to be enumerated.
+ * @uid: 32-bit UID used by QTEE to identify the service.
+ *
+ * Returns 0 on success and < 0 on failure.
+ */
+static int qtee_enumerate_service(struct qcomtee_object_invoke_ctx *oic,
+				  struct qcomtee_object *client_env,
+				  const char *service_name,
+				  const u32 uid)
+{
+	struct tee_client_device *qtee_service;
+	uuid_t service_uuid;
+	int rc;
+
+	if (!is_qcomtee_service_available(oic, client_env, service_name, uid))
+		return -EOPNOTSUPP;
+
+	tee_generate_uuid_v5(&service_uuid, &qtee_service_uuid_ns, service_name,
+			     strlen(service_name));
+
+	qtee_service = kzalloc_obj(*qtee_service);
+	if (!qtee_service)
+		return -ENOMEM;
+
+	qtee_service->dev.bus = &tee_bus_type;
+	qtee_service->dev.release = qtee_release_service;
+	if (dev_set_name(&qtee_service->dev, "qtee-svc-%pUb", &service_uuid)) {
+		kfree(qtee_service);
+		return -ENOMEM;
+	}
+	uuid_copy(&qtee_service->id.uuid, &service_uuid);
+
+	rc = device_register(&qtee_service->dev);
+	if (rc) {
+		pr_err("QTEE service registration failed, err: %d\n", rc);
+		put_device(&qtee_service->dev);
+		return rc;
+	}
+
+	return 0;
+}
+
+/**
+ * qtee_enumerate_services() - Enumerate all the secure services exposed by QTEE
+ * from the static 'qtee_services' list and register them on the TEE bus as
+ * TEE client devices.
+ *
+ * Not all versions of QTEE support a given service. Hence, we try to
+ * enumerate as many services from the 'qtee_services' list as possible.
+ * Not being able to enumerate a service shouldn't cause the driver probe
+ * to fail since none of the services in the list are mandatory for
+ * establishing communication with QTEE.
+ * @ctx: TEE context.
+ */
+static void qtee_enumerate_services(struct tee_context *ctx)
+{
+	u32 idx;
+	struct qcomtee_object *client_env;
+
+	struct qcomtee_object_invoke_ctx *oic __free(kfree) =
+		qcomtee_object_invoke_ctx_alloc(ctx, true);
+	if (!oic)
+		return;
+
+	client_env = qcomtee_object_get_client_env(oic);
+	if (client_env == NULL_QCOMTEE_OBJECT)
+		return;
+
+	for (idx = 0; idx < ARRAY_SIZE(qtee_services); idx++)
+		qtee_enumerate_service(oic, client_env,
+				       qtee_services[idx].name,
+				       qtee_services[idx].uid);
+
+	qcomtee_object_put(client_env);
+}
+
+static int qtee_unregister_service(struct device *dev, void *data)
+{
+	if (!strncmp(dev_name(dev), "qtee-svc", strlen("qtee-svc")))
+		device_unregister(dev);
+
+	return 0;
+}
+
+static void qtee_unregister_services(void)
+{
+	bus_for_each_dev(&tee_bus_type, NULL, NULL,
+			 qtee_unregister_service);
+}
+
 static const struct tee_driver_ops qcomtee_ops = {
 	.get_version = qcomtee_get_version,
 	.open = qcomtee_open,
@@ -778,6 +932,8 @@ static int qcomtee_probe(struct platform_device *pdev)
 		QTEE_VERSION_GET_MINOR(qcomtee->qtee_version),
 		QTEE_VERSION_GET_PATCH(qcomtee->qtee_version));
 
+	qtee_enumerate_services(qcomtee->ctx);
+
 	return 0;
 
 err_dest_wq:
@@ -807,6 +963,7 @@ static void qcomtee_remove(struct platform_device *pdev)
 {
 	struct qcomtee *qcomtee = platform_get_drvdata(pdev);
 
+	qtee_unregister_services();
 	teedev_close_context(qcomtee->ctx);
 	/* Wait for RELEASE operations to be processed for QTEE objects. */
 	tee_device_unregister(qcomtee->teedev);
diff --git a/drivers/tee/qcomtee/core.c b/drivers/tee/qcomtee/core.c
index 60fe3b5776e3..4a523a95bf0e 100644
--- a/drivers/tee/qcomtee/core.c
+++ b/drivers/tee/qcomtee/core.c
@@ -898,19 +898,20 @@ qcomtee_object_get_client_env(struct qcomtee_object_invoke_ctx *oic)
 
 struct qcomtee_object *
 qcomtee_object_get_service(struct qcomtee_object_invoke_ctx *oic,
-			   struct qcomtee_object *client_env, u32 uid)
+			   struct qcomtee_object *client_env, u32 uid,
+			   int *result)
 {
 	struct qcomtee_arg u[3] = { 0 };
-	int ret, result;
+	int ret;
 
 	u[0].b.addr = &uid;
 	u[0].b.size = sizeof(uid);
 	u[0].type = QCOMTEE_ARG_TYPE_IB;
 	u[1].type = QCOMTEE_ARG_TYPE_OO;
 	ret = qcomtee_object_do_invoke(oic, client_env, QCOMTEE_CLIENT_ENV_OPEN,
-				       u, &result);
+				       u, result);
 
-	if (ret || result)
+	if (ret || *result)
 		return NULL_QCOMTEE_OBJECT;
 
 	return u[1].o;
diff --git a/drivers/tee/qcomtee/qcomtee.h b/drivers/tee/qcomtee/qcomtee.h
index f39bf63fd1c2..66d305a46c0a 100644
--- a/drivers/tee/qcomtee/qcomtee.h
+++ b/drivers/tee/qcomtee/qcomtee.h
@@ -17,6 +17,8 @@
 #define QCOMTEE_OBJREF_FLAG_USER	BIT(1)
 #define QCOMTEE_OBJREF_FLAG_MEM		BIT(2)
 
+#define QTEE_UUID_NS_NAME_SIZE	        128
+
 /**
  * struct qcomtee - Main service struct.
  * @teedev: client device.
@@ -39,6 +41,16 @@ struct qcomtee {
 	u32 qtee_version;
 };
 
+/**
+ * struct qtee_service - A secure service exposed by QTEE identified by a 32-bit UID.
+ * @name: Name of the QTEE service.
+ * @uid: 32-bit UID used by QTEE to identify the service.
+ */
+struct qtee_service {
+	const char *name;
+	const u32 uid;
+};
+
 void qcomtee_fetch_async_reqs(struct qcomtee_object_invoke_ctx *oic);
 struct qcomtee_object *qcomtee_idx_erase(struct qcomtee_object_invoke_ctx *oic,
 					 u32 idx);
diff --git a/drivers/tee/qcomtee/qcomtee_msg.h b/drivers/tee/qcomtee/qcomtee_msg.h
index 5d7b21fdd368..9278a361dc70 100644
--- a/drivers/tee/qcomtee/qcomtee_msg.h
+++ b/drivers/tee/qcomtee/qcomtee_msg.h
@@ -105,6 +105,7 @@ union qcomtee_msg_arg {
 #define QTEE_VERSION_GET_MINOR(x) (((x) >> 12) & 0xffU)
 #define QTEE_VERSION_GET_PATCH(x) ((x) >> 0 & 0xfffU)
 
+#define QCOMTEE_UEFI_SEC_UID            413
 /* Response types as returned from qcomtee_object_invoke_ctx_invoke(). */
 
 /* The message contains a callback request. */
diff --git a/drivers/tee/qcomtee/qcomtee_object.h b/drivers/tee/qcomtee/qcomtee_object.h
index d3740099fae0..901ba3565a73 100644
--- a/drivers/tee/qcomtee/qcomtee_object.h
+++ b/drivers/tee/qcomtee/qcomtee_object.h
@@ -317,6 +317,7 @@ qcomtee_object_get_client_env(struct qcomtee_object_invoke_ctx *oic);
 
 struct qcomtee_object *
 qcomtee_object_get_service(struct qcomtee_object_invoke_ctx *oic,
-			   struct qcomtee_object *client_env, u32 uid);
+			   struct qcomtee_object *client_env, u32 uid,
+			   int *result);
 
 #endif /* QCOMTEE_OBJECT_H */

-- 
2.34.1


^ permalink raw reply	[flat|nested] 12+ messages in thread

* [PATCH v3 6/6] firmware: qcom: Add support for TEE based EFI-var client driver
  2026-10-01 11:02 [PATCH v3 0/6] Add TEE based client driver for UEFI Secure Application Harshal Dev
                   ` (4 preceding siblings ...)
  2026-10-01 11:02 ` [PATCH v3 5/6] tee: qcomtee: Add support for registering QTEE services on TEE bus Harshal Dev
@ 2026-10-01 11:02 ` Harshal Dev
  5 siblings, 0 replies; 12+ messages in thread
From: Harshal Dev @ 2026-10-01 11:02 UTC (permalink / raw)
  To: Jens Wiklander, Sumit Garg, Amirreza Zarrabi, Bjorn Andersson,
	Konrad Dybcio, Dmitry Baryshkov
  Cc: Kuldeep Singh, Basant Kumar, Apurupa Pattapu,
	Arun Kumar Neelakantam, op-tee, linux-kernel, linux-arm-msm,
	Harshal Dev

On Qualcomm SoC based platforms, UEFI stores EFI variables within the
Replay Protected Memory Block (RPMB) located within either the UFS,
eMMC or SPI-NOR storage. The RPMB key which is one-time programmed into
the storage controller to allow authentication of the RPMB frames is
generated by and only available to the Qualcomm Trusted Execution
Environment (QTEE).

The legacy QSEECOM protocol used for communicating with the QTEE is
deprecated and replaced with the use-case agnostic SMCInvoke protocol
starting with the Qualcomm SM8x50 series. On platforms where the QSEECOM
still driver probes, it does not support a listener interface with QTEE
to enable writing of non-volatile EFI variables to the RPMB for UFS and
eMMC storage.
Therefore on such platforms, a TEE client driver which communicates with
QTEE via the SMCInvoke protocol implemented by the QCOMTEE driver (and
registered with the TEE subsystem) must be used to update such EFI
variables.

Add support for a TEE based uefisecapp client driver which installs efivar
operations after obtaining an object reference to the uefisecapp service.
This enables the kernel/user-space to access or modify both volatile EFI
variables stored by the Secure Application (in-memory) and non-volatile
ones stored within RPMB.

Signed-off-by: Harshal Dev <harshal.dev@oss.qualcomm.com>
---
 MAINTAINERS                                 |   6 +
 arch/arm64/configs/defconfig                |   1 +
 drivers/firmware/qcom/Kconfig               |  31 ++
 drivers/firmware/qcom/Makefile              |   1 +
 drivers/firmware/qcom/qcom_tee_uefisecapp.c | 636 ++++++++++++++++++++++++++++
 5 files changed, 675 insertions(+)

diff --git a/MAINTAINERS b/MAINTAINERS
index 30c1cdd0fb38..7ccedad8d388 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -22981,6 +22981,12 @@ L:	linux-arm-msm@vger.kernel.org
 S:	Maintained
 F:	drivers/firmware/qcom/qcom_qseecom_uefisecapp.c
 
+QUALCOMM TEE UEFISECAPP DRIVER
+M:	Harshal Dev <harshal.dev@oss.qualcomm.com>
+L:	linux-arm-msm@vger.kernel.org
+S:	Maintained
+F:	drivers/firmware/qcom/qcom_tee_uefisecapp.c
+
 QUALCOMM PINCTRL DRIVERS
 M:	Bartosz Golaszewski <brgl@kernel.org>
 L:	linux-arm-msm@vger.kernel.org
diff --git a/arch/arm64/configs/defconfig b/arch/arm64/configs/defconfig
index fce418fe6ff6..a8525878c679 100644
--- a/arch/arm64/configs/defconfig
+++ b/arch/arm64/configs/defconfig
@@ -277,6 +277,7 @@ CONFIG_IMX_SCU=y
 CONFIG_QCOM_TZMEM_MODE_SHMBRIDGE=y
 CONFIG_QCOM_QSEECOM=y
 CONFIG_QCOM_QSEECOM_UEFISECAPP=y
+CONFIG_QCOM_TEE_UEFISECAPP=m
 CONFIG_EXYNOS_ACPM_PROTOCOL=m
 CONFIG_TEGRA_BPMP=y
 CONFIG_ZYNQMP_FIRMWARE_DEBUG=y
diff --git a/drivers/firmware/qcom/Kconfig b/drivers/firmware/qcom/Kconfig
index 3ad22f8fc3e5..694d98fef4f4 100644
--- a/drivers/firmware/qcom/Kconfig
+++ b/drivers/firmware/qcom/Kconfig
@@ -79,4 +79,35 @@ config QCOM_QSEECOM_UEFISECAPP
 	  Select Y here to provide access to EFI variables on the aforementioned
 	  platforms.
 
+config QCOM_TEE_UEFISECAPP
+	tristate "Qualcomm TEE UEFI Secure App client driver"
+	depends on QCOMTEE
+	depends on EFI
+	help
+	  The QSEECOM protocol used for communicating with the Qualcomm Trusted
+	  Execution Environment (QTEE) is deprecated and replaced with the SMCInvoke
+	  protocol starting with the Qualcomm SM8x50 series. On platforms where the
+	  QSEECOM protocol still works (the QSEECOM driver probes) the driver does
+	  not support a listener interface with QTEE to enable writing of
+	  non-volatile EFI variables (via listener requests to Linux) in the Replay
+	  Protected Memory Block (RPMB) located on UFS/eMMC storage.
+	  Therefore on such platforms, the TEE based uefisecapp client driver
+	  (which communicates with QTEE via the SMCInvoke protocol) must be used
+	  to update such EFI variables through the RPMB service hosted in the QTEE
+	  supplicant user-space daemon (github.com/qualcomm/minkipc) which forwards
+	  RPMB packets to the RPMB device.
+	  NOTE: Qualcomm Compute platforms with SPI-NOR storage are an exception to
+	  this scenario. Since they do not have a firmware running on their SPI-NOR
+	  storage controller which must be programmed with a RPMB key, QTEE has a
+	  SPI-NOR driver which holds the key, and so the QSEECOM driver can be used
+	  for updating EFI variables on these platforms because QTEE never makes a
+	  listener request to Linux (QTEE doesn't need the Linux SPI-NOR driver).
+
+	  This module provides a TEE client driver for uefisecapp, installing efivar
+	  operations to allow the kernel and user-space access to EFI variables.
+
+	  Select m here to provide access to EFI variables on the aforementioned
+	  platforms if your Linux distribution has QTEE supplicant installed and
+	  running.
+
 endmenu
diff --git a/drivers/firmware/qcom/Makefile b/drivers/firmware/qcom/Makefile
index 88ce74d74c3e..237192b74de3 100644
--- a/drivers/firmware/qcom/Makefile
+++ b/drivers/firmware/qcom/Makefile
@@ -9,5 +9,6 @@ CFLAGS_qcom_scm-smc.o := -I$(src)
 obj-$(CONFIG_QCOM_TZMEM)	+= qcom_tzmem.o
 obj-$(CONFIG_QCOM_QSEECOM)	+= qcom_qseecom.o
 obj-$(CONFIG_QCOM_QSEECOM_UEFISECAPP) += qcom_qseecom_uefisecapp.o
+obj-$(CONFIG_QCOM_TEE_UEFISECAPP) += qcom_tee_uefisecapp.o
 obj-$(CONFIG_QCOM_PAS)		+= qcom_pas.o
 obj-$(CONFIG_QCOM_PAS_TEE)	+= qcom_pas_tee.o
diff --git a/drivers/firmware/qcom/qcom_tee_uefisecapp.c b/drivers/firmware/qcom/qcom_tee_uefisecapp.c
new file mode 100644
index 000000000000..71438961cd49
--- /dev/null
+++ b/drivers/firmware/qcom/qcom_tee_uefisecapp.c
@@ -0,0 +1,636 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
+ */
+
+#include <linux/efi.h>
+#include <linux/tee.h>
+#include <linux/tee_drv.h>
+#include <linux/ucs2_string.h>
+
+#define QCOMTEE_OP_CLIENT_ENV_OPEN 0
+#define QCOMTEE_ROOT_OP_REG_WITH_CREDENTIALS 5
+
+/* Each service exposed by QTEE is identified by a 32-bit UID */
+#define QCOMTEE_UEFI_SEC_UID                 413
+
+/* Operations supported by the UEFI Sec App service */
+#define QCOMTEE_UEFI_SEC_OP_GET_VAR 0
+#define QCOMTEE_UEFI_SEC_OP_SET_VAR 1
+#define QCOMTEE_UEFI_SEC_OP_QUERY_VAR_INFO 2
+#define QCOMTEE_UEFI_SEC_OP_GET_NEXT_VAR_NAME 3
+
+/* Error codes returned by the UEFI Sec App service */
+#define QCOMTEE_UEFI_SEC_SUCCESS 0
+#define QCOMTEE_UEFI_SEC_ERROR_INVALID_PARAMETER 10
+#define QCOMTEE_UEFI_SEC_ERROR_UNSUPPORTED 11
+#define QCOMTEE_UEFI_SEC_ERROR_WRITE_PROTECTED 12
+#define QCOMTEE_UEFI_SEC_ERROR_SECURITY_VIOLATION 13
+#define QCOMTEE_UEFI_SEC_ERROR_DEVICE_ERROR 14
+#define QCOMTEE_UEFI_SEC_ERROR_OUT_OF_RESOURCES 15
+#define QCOMTEE_UEFI_SEC_ERROR_VOLUME_CORRUPTED 16
+#define QCOMTEE_UEFI_SEC_ERROR_SIZE_OUT 17
+#define QCOMTEE_UEFI_SEC_ERROR_NOT_FOUND 18
+#define QCOMTEE_UEFI_SEC_ERROR_ALREADY_STARTED 19
+
+/* Operations for objects are 32-bit. QCOMTEE transport uses the upper 16 bits. */
+#define QCOMTEE_MSG_OBJECT_OP_MASK GENMASK(15, 0)
+#define QCOMTEE_MSG_OBJECT_OP_RELEASE (QCOMTEE_MSG_OBJECT_OP_MASK - 0)
+
+/**
+ * struct qcomtee_uefisec_app - An instance of UEFI Secure Application.
+ * @dev: TEE client device on the TEE bus which represents uefisecapp.
+ * @ctx: The context opened with the TEE subsystem by the uefisecapp client.
+ * @uefisec_svc_obj: A TEE object representing the uefisecapp service.
+ * @efivars: EFI variables registered with the EFI subsystem.
+ */
+struct qcomtee_uefisec_app {
+	struct device *dev;
+	struct tee_context *ctx;
+	struct tee_param_objref uefisec_svc_obj;
+	struct efivars efivars;
+};
+
+#define UEFISECAPP_UUID \
+	UUID_INIT(0x01f95dcd, 0x2d7e, 0x58be, \
+		  0xa1, 0x43, 0x81, 0x32, 0xa1, 0x72, 0xdb, 0x7d)
+
+/* Short-hands for these long attribute names */
+#define UBUF_INPUT     TEE_IOCTL_PARAM_ATTR_TYPE_UBUF_INPUT
+#define UBUF_OUTPUT    TEE_IOCTL_PARAM_ATTR_TYPE_UBUF_OUTPUT
+#define OBJREF_INPUT   TEE_IOCTL_PARAM_ATTR_TYPE_OBJREF_INPUT
+#define OBJREF_OUTPUT  TEE_IOCTL_PARAM_ATTR_TYPE_OBJREF_OUTPUT
+
+/* Init instance of 'struct tee_param_objref'. */
+#define SET_TEE_PARAM_OBJREF(param, attri, obj_id, obj_flag) do { \
+		(param).attr = (attri); \
+		(param).u.objref.id = (obj_id); \
+		(param).u.objref.flags = (obj_flag); \
+	} while (0)
+
+/* Init instance of 'struct tee_param_ubuf'. */
+#define SET_TEE_PARAM_UBUF(param, attri, ubuff) do { \
+		(param).attr = (attri); \
+		(param).u.ubuf = (ubuff);  \
+	} while (0)
+
+#define TEE_PARAM_UBUF(x) ((struct tee_param_ubuf){ .addr = &(x), sizeof(x) })
+
+#define SET_INVOKE_ARG(arg, object_id, opp, nparam) do { \
+		(arg).id = (object_id); \
+		(arg).op = (opp); \
+		(arg).num_params = (nparam); \
+	} while (0)
+
+static inline efi_status_t uefisecapp_err_to_efi_status(u32 err)
+{
+	switch (err) {
+	case QCOMTEE_UEFI_SEC_SUCCESS:
+		return EFI_SUCCESS;
+
+	case QCOMTEE_UEFI_SEC_ERROR_INVALID_PARAMETER:
+		return EFI_INVALID_PARAMETER;
+
+	case QCOMTEE_UEFI_SEC_ERROR_UNSUPPORTED:
+		return EFI_UNSUPPORTED;
+
+	case QCOMTEE_UEFI_SEC_ERROR_WRITE_PROTECTED:
+		return EFI_WRITE_PROTECTED;
+
+	case QCOMTEE_UEFI_SEC_ERROR_SECURITY_VIOLATION:
+		return EFI_SECURITY_VIOLATION;
+
+	case QCOMTEE_UEFI_SEC_ERROR_DEVICE_ERROR:
+		return EFI_DEVICE_ERROR;
+
+	case QCOMTEE_UEFI_SEC_ERROR_OUT_OF_RESOURCES:
+		return EFI_OUT_OF_RESOURCES;
+
+	case QCOMTEE_UEFI_SEC_ERROR_SIZE_OUT:
+		return EFI_BUFFER_TOO_SMALL;
+
+	case QCOMTEE_UEFI_SEC_ERROR_NOT_FOUND:
+		return EFI_NOT_FOUND;
+
+	/* No matching on EFI_* list. */
+	case QCOMTEE_UEFI_SEC_ERROR_ALREADY_STARTED: /* EFI_ALREADY_STARTED.  */
+	case QCOMTEE_UEFI_SEC_ERROR_VOLUME_CORRUPTED: /* EFI_VOLUME_CORRUPTED. */
+	default:
+		return EFI_DEVICE_ERROR;
+	}
+}
+
+static struct qcomtee_uefisec_app uefisec_app;
+
+static int qcuefi_get_variable(struct tee_param_ubuf in_variable, efi_guid_t *guid,
+			       struct tee_param_ubuf in_attributes,
+			       struct tee_param_ubuf *data,
+			       u32 *out_attributes, u32 *out_errno)
+{
+	int ret;
+	struct tee_ioctl_object_invoke_arg inv_arg;
+	u64 obj_id = uefisec_app.uefisec_svc_obj.id;
+	u32 nparams = 5;
+	struct tee_param param[nparams];
+
+	struct {
+		efi_guid_t guid;
+		u32 in_data_size;
+	} in_cong = { 0 };
+
+	struct {
+		u32 out_data_size;
+		u32 attributes;
+		u32 errno;
+	} out_cong = { 0 };
+
+	in_cong.guid = *guid;
+	in_cong.in_data_size = data->size;
+
+	memset(&inv_arg, 0, sizeof(inv_arg));
+	memset(&param, 0, sizeof(param));
+
+	SET_INVOKE_ARG(inv_arg, obj_id, QCOMTEE_UEFI_SEC_OP_GET_VAR, nparams);
+	SET_TEE_PARAM_UBUF(param[0], UBUF_INPUT, TEE_PARAM_UBUF(in_cong));
+	SET_TEE_PARAM_UBUF(param[1], UBUF_INPUT, in_variable);
+	SET_TEE_PARAM_UBUF(param[2], UBUF_INPUT, in_attributes);
+	SET_TEE_PARAM_UBUF(param[3], UBUF_OUTPUT, TEE_PARAM_UBUF(out_cong));
+	SET_TEE_PARAM_UBUF(param[4], UBUF_OUTPUT, *data);
+
+	ret = tee_client_object_invoke_func(uefisec_app.ctx, &inv_arg, param);
+	if (ret < 0 || inv_arg.ret != 0) {
+		dev_err(uefisec_app.dev, "QCOMTEE_UEFI_SEC_OP_GET_VAR invoke ret: %d, err: 0x%x\n",
+			ret, inv_arg.ret);
+		return ret ?: inv_arg.ret;
+	}
+
+	data->size = out_cong.out_data_size;
+	*out_attributes = out_cong.attributes;
+	*out_errno = out_cong.errno;
+
+	return ret;
+}
+
+static efi_status_t qcomtee_uefi_get_variable(efi_char16_t *name, efi_guid_t *guid,
+					      u32 *attr, unsigned long *data_size,
+					      void *data)
+{
+	int ret;
+	u32 in_attr, out_attributes, out_errno;
+	struct tee_param_ubuf in_data, in_var, in_attributes;
+
+	if (!name || !guid)
+		return EFI_INVALID_PARAMETER;
+
+	/* 'attr' can be NULL, however an input attribute is always expected
+	 * by UefiSecApp TA
+	 */
+	in_attr = 0;
+	if (attr)
+		in_attr = *attr;
+
+	in_data = (struct tee_param_ubuf){ .addr = data, *data_size };
+	in_var = (struct tee_param_ubuf){ .addr = name,
+					  (ucs2_strlen(name) + 1) * sizeof(*name) };
+	in_attributes = (struct tee_param_ubuf){ .addr = &in_attr, sizeof(u32) };
+
+	/* On SUCCESS, 'data' member of 'in_data' has already been updated. */
+	ret = qcuefi_get_variable(in_var, guid, in_attributes, &in_data,
+				  &out_attributes, &out_errno);
+
+	if (ret)
+		return EFI_DEVICE_ERROR;
+
+	if (!out_errno || out_errno == QCOMTEE_UEFI_SEC_ERROR_SIZE_OUT) {
+		/* If 'attr' is NULL 'out_attributes' is not updated. */
+		if (attr)
+			*attr = out_attributes;
+
+		*data_size = in_data.size;
+	}
+
+	return uefisecapp_err_to_efi_status(out_errno);
+}
+
+static int qcuefi_set_variable(struct tee_param_ubuf in_variable, efi_guid_t *guid,
+			       u32 attributes, struct tee_param_ubuf data,
+			       u32 *out_errno)
+{
+	int ret;
+	struct tee_ioctl_object_invoke_arg inv_arg;
+	u64 obj_id = uefisec_app.uefisec_svc_obj.id;
+	u32 nparams = 4;
+	struct tee_param param[nparams];
+
+	struct {
+		efi_guid_t guid;
+		u32 attributes;
+		u32 in_data_size;
+	} in_cong = { 0 };
+
+	in_cong.guid = *guid;
+	in_cong.attributes = attributes;
+	in_cong.in_data_size = data.size;
+
+	memset(&inv_arg, 0, sizeof(inv_arg));
+	memset(&param, 0, sizeof(param));
+
+	SET_INVOKE_ARG(inv_arg, obj_id, QCOMTEE_UEFI_SEC_OP_SET_VAR, nparams);
+	SET_TEE_PARAM_UBUF(param[0], UBUF_INPUT, TEE_PARAM_UBUF(in_cong));
+	SET_TEE_PARAM_UBUF(param[1], UBUF_INPUT, in_variable);
+	SET_TEE_PARAM_UBUF(param[2], UBUF_INPUT, data);
+	SET_TEE_PARAM_UBUF(param[3], UBUF_OUTPUT, TEE_PARAM_UBUF(*out_errno));
+
+	ret = tee_client_object_invoke_func(uefisec_app.ctx, &inv_arg, param);
+	if (ret < 0 || inv_arg.ret != 0) {
+		dev_err(uefisec_app.dev, "QCOMTEE_UEFI_SEC_OP_SET_VAR invoke ret: %d, err: 0x%x\n",
+			ret, inv_arg.ret);
+		return ret ?: inv_arg.ret;
+	}
+
+	return ret;
+}
+
+static efi_status_t qcomtee_uefi_set_variable(efi_char16_t *name, efi_guid_t *guid,
+					      u32 attr, unsigned long data_size,
+					      void *data)
+{
+	int ret;
+	u32 out_errno;
+	struct tee_param_ubuf in_data, in_var;
+
+	if (!name || !guid)
+		return EFI_INVALID_PARAMETER;
+
+	in_data = (struct tee_param_ubuf){ .addr = data, data_size };
+	in_var = (struct tee_param_ubuf){ .addr = name,
+					  (ucs2_strlen(name) + 1) * sizeof(*name) };
+
+	ret = qcuefi_set_variable(in_var, guid, attr, in_data, &out_errno);
+	if (ret)
+		return EFI_DEVICE_ERROR;
+
+	return uefisecapp_err_to_efi_status(out_errno);
+}
+
+static int qcuefi_get_next_variable(struct tee_param_ubuf in_variable, efi_guid_t *guid,
+				    struct tee_param_ubuf *out_variable,
+				    efi_guid_t *out_vendor_guid, u32 *out_errno)
+{
+	int ret;
+	struct tee_ioctl_object_invoke_arg inv_arg;
+	u64 obj_id = uefisec_app.uefisec_svc_obj.id;
+	u32 nparams = 4;
+	struct tee_param param[nparams];
+
+	struct {
+		efi_guid_t guid;
+		u32 in_data_size;
+	} in_cong = { 0 };
+
+	struct {
+		efi_guid_t guid;
+		u32 out_data_size;
+		u32 errno;
+	} out_cong = { 0 };
+
+	/* Pass size of available buffer */
+	in_cong.in_data_size = out_variable->size;
+	in_cong.guid = *guid;
+
+	memset(&inv_arg, 0, sizeof(inv_arg));
+	memset(&param, 0, sizeof(param));
+
+	SET_INVOKE_ARG(inv_arg, obj_id, QCOMTEE_UEFI_SEC_OP_GET_NEXT_VAR_NAME, nparams);
+	SET_TEE_PARAM_UBUF(param[0], UBUF_INPUT, TEE_PARAM_UBUF(in_cong));
+	SET_TEE_PARAM_UBUF(param[1], UBUF_INPUT, in_variable);
+	SET_TEE_PARAM_UBUF(param[2], UBUF_OUTPUT, TEE_PARAM_UBUF(out_cong));
+	SET_TEE_PARAM_UBUF(param[3], UBUF_OUTPUT, *out_variable);
+
+	ret = tee_client_object_invoke_func(uefisec_app.ctx, &inv_arg, param);
+	if (ret < 0 || inv_arg.ret != 0) {
+		dev_err(uefisec_app.dev, "QCOMTEE_UEFI_SEC_OP_GET_NEXT_VAR_NAME invoke ret: %d, err: 0x%x\n",
+			ret, inv_arg.ret);
+		return ret ?: inv_arg.ret;
+	}
+
+	/* UefiSecApp TA does not touch 'out_variable.size'. Update it here.
+	 * On SUCCESS (!out_errno), 'out_data_size' is length of name in 'out_variable.addr'.
+	 * On failure (out_errno == QCOMTEE_UEFI_SEC_ERROR_SIZE_OUT), 'out_data_size' is
+	 * actual name length.
+	 * Otherwise, it's undefined.
+	 */
+	out_variable->size = out_cong.out_data_size;
+	*out_vendor_guid = out_cong.guid;
+	*out_errno = out_cong.errno;
+
+	return ret;
+}
+
+static efi_status_t qcomtee_uefi_get_next_variable(unsigned long *name_size,
+						   efi_char16_t *name,
+						   efi_guid_t *guid)
+{
+	int ret;
+	u32 out_errno;
+	efi_guid_t out_guid;
+	struct tee_param_ubuf in_var, out_var;
+
+	if (!name_size || !name || !guid)
+		return EFI_INVALID_PARAMETER;
+
+	if (*name_size == 0)
+		return EFI_INVALID_PARAMETER;
+
+	/* For 'in_var', 'name_size' is not necessarily size of 'name';
+	 * could be size of buffer where 'name' has been stored. TA expects a
+	 * NULL-terminated string in 'name' and ignores the size.
+	 * For 'out_var', 'name_size' is size of buffer pointed by 'name'.
+	 */
+	in_var = (struct tee_param_ubuf){ .addr = name, *name_size };
+	out_var = (struct tee_param_ubuf){ .addr = name, *name_size };
+
+	ret = qcuefi_get_next_variable(in_var, guid, &out_var, &out_guid,
+				       &out_errno);
+	if (ret)
+		return EFI_DEVICE_ERROR;
+
+	if (!out_errno)
+		*guid = out_guid;
+
+	if (!out_errno || out_errno == QCOMTEE_UEFI_SEC_ERROR_SIZE_OUT)
+		*name_size = out_var.size;
+
+	/* On SUCCESS, 'name' stores the next variable name. */
+	return uefisecapp_err_to_efi_status(out_errno);
+}
+
+static int qcuefi_query_variable_info(u32 attributes,
+				      u64 *maximum_variable_storage_size,
+				      u64 *remaining_variable_storage_size,
+				      u64 *maximum_variable_size, u32 *out_errno)
+{
+	int ret;
+	struct tee_ioctl_object_invoke_arg inv_arg;
+	u64 obj_id = uefisec_app.uefisec_svc_obj.id;
+	u32 nparams = 2;
+	struct tee_param param[nparams];
+
+	struct {
+		u64 max_var_storage_size;
+		u64 remaining_var_storage_size;
+		u64 maximum_var_size;
+		u32 errno;
+	} out_cong = { 0 };
+
+	memset(&inv_arg, 0, sizeof(inv_arg));
+	memset(&param, 0, sizeof(param));
+
+	SET_INVOKE_ARG(inv_arg, obj_id, QCOMTEE_UEFI_SEC_OP_QUERY_VAR_INFO, nparams);
+	SET_TEE_PARAM_UBUF(param[0], UBUF_INPUT, TEE_PARAM_UBUF(attributes));
+	SET_TEE_PARAM_UBUF(param[1], UBUF_OUTPUT, TEE_PARAM_UBUF(out_cong));
+
+	ret = tee_client_object_invoke_func(uefisec_app.ctx, &inv_arg, param);
+	if (ret < 0 || inv_arg.ret != 0) {
+		dev_err(uefisec_app.dev, "QCOMTEE_UEFI_SEC_OP_QUERY_VAR_INFO invoke ret: %d, err: 0x%x\n",
+			ret, inv_arg.ret);
+		return ret ?: inv_arg.ret;
+	}
+
+	*maximum_variable_storage_size = out_cong.max_var_storage_size;
+	*remaining_variable_storage_size = out_cong.remaining_var_storage_size;
+	*maximum_variable_size = out_cong.maximum_var_size;
+	*out_errno = out_cong.errno;
+
+	return ret;
+}
+
+static efi_status_t qcomtee_uefi_query_variable_info(u32 attr, u64 *storage_space,
+						     u64 *remaining_space,
+						     u64 *max_variable_size)
+{
+	int ret;
+	u32 out_errno;
+	u64 maximum_variable_storage_size;
+	u64 remaining_variable_storage_size;
+	u64 maximum_variable_size;
+
+	if (!storage_space || !remaining_space || !max_variable_size)
+		return EFI_INVALID_PARAMETER;
+
+	ret = qcuefi_query_variable_info(attr,
+					 &maximum_variable_storage_size,
+					 &remaining_variable_storage_size,
+					 &maximum_variable_size,
+					 &out_errno);
+
+	if (ret)
+		return EFI_DEVICE_ERROR;
+
+	if (!out_errno) {
+		*storage_space = maximum_variable_storage_size;
+		*remaining_space = remaining_variable_storage_size;
+		*max_variable_size = maximum_variable_size;
+	}
+
+	return uefisecapp_err_to_efi_status(out_errno);
+}
+
+/**
+ * qcomtee_release_object() - Release an object returned by QTEE.
+ *
+ * Each object returned by QTEE repesents a secure service exposed to the
+ * client. Whenever an secure service is opened, QTEE may allocate resources
+ * on the client's behalf. Therefore, once the client is done accessing the
+ * secure service, the object representing it should be explicitly released
+ * so that QTEE can release the associated resources as well.
+ *
+ * @ctx: TEE context.
+ * @object: The object to release.
+ */
+static void qcomtee_release_object(struct tee_context *ctx,
+				   struct tee_param_objref object)
+{
+	struct tee_ioctl_object_invoke_arg inv_arg;
+
+	memset(&inv_arg, 0, sizeof(inv_arg));
+	SET_INVOKE_ARG(inv_arg, object.id, QCOMTEE_MSG_OBJECT_OP_RELEASE, 0);
+	tee_client_object_invoke_func(ctx, &inv_arg, NULL);
+}
+
+/**
+ * qcomtee_get_uefisec_svc_obj() - Get a UEFI Secure App service object to
+ * begin communication with the service.
+ * @ctx: TEE context.
+ * @client_env_obj: The client environment object returned earlier by QTEE.
+ * @uefisec_svc_obj: The UEFI Secure App service object.
+ *
+ * Returns 0 on success.
+ * Returns < 0 if client environment object invocation failed.
+ * Returns > 0 if client environment invocation was success but UEFI Secure App
+ * service object could not be returned for some other reason (represented by the
+ * returned value)
+ */
+static int qcomtee_get_uefisec_svc_obj(struct tee_context *ctx,
+				       struct tee_param_objref client_env_obj,
+				       struct tee_param_objref *uefisec_svc_obj)
+{
+	int ret;
+	struct tee_ioctl_object_invoke_arg inv_arg;
+	u64 obj_id = client_env_obj.id;
+	u32 nparams = 2;
+	struct tee_param param[nparams];
+	u32 uefisec_uid = QCOMTEE_UEFI_SEC_UID;
+
+	memset(&inv_arg, 0, sizeof(inv_arg));
+	memset(&param, 0, sizeof(param));
+
+	SET_INVOKE_ARG(inv_arg, obj_id, QCOMTEE_OP_CLIENT_ENV_OPEN, nparams);
+	SET_TEE_PARAM_UBUF(param[0], UBUF_INPUT, TEE_PARAM_UBUF(uefisec_uid));
+	SET_TEE_PARAM_OBJREF(param[1], OBJREF_OUTPUT, 0, 0);
+
+	ret = tee_client_object_invoke_func(ctx, &inv_arg, param);
+	if (ret < 0 || inv_arg.ret != 0) {
+		dev_err(uefisec_app.dev, "QCOMTEE_CLIENT_ENV_OPEN invoke ret: %d, err: 0x%x\n",
+			ret, inv_arg.ret);
+		return ret ?: inv_arg.ret;
+	}
+
+	*uefisec_svc_obj = param[1].u.objref;
+	return ret;
+}
+
+/**
+ * qcomtee_get_client_env_obj() - Get a client environment object to begin
+ * object exchange with QTEE.
+ * @ctx: TEE context.
+ * @client_env_obj: The client environment object returned by QTEE.
+ *
+ * Returns 0 on success.
+ * Returns < 0 if root object invocation failed.
+ * Returns > 0 if root object invocation was success but client environment
+ * object could not be returned for some other reason (represented by the
+ * returned value)
+ */
+static int qcomtee_get_client_env_obj(struct tee_context *ctx,
+				      struct tee_param_objref *client_env_obj)
+{
+	int ret;
+	struct tee_ioctl_object_invoke_arg inv_arg;
+	u32 nparams = 2;
+	struct tee_param param[nparams];
+
+	memset(&inv_arg, 0, sizeof(inv_arg));
+	memset(&param, 0, sizeof(param));
+
+	SET_INVOKE_ARG(inv_arg, TEE_OBJREF_NULL,
+		       QCOMTEE_ROOT_OP_REG_WITH_CREDENTIALS, nparams);
+	SET_TEE_PARAM_OBJREF(param[0], OBJREF_INPUT, TEE_OBJREF_NULL, 0);
+	SET_TEE_PARAM_OBJREF(param[1], OBJREF_OUTPUT, 0, 0);
+
+	ret = tee_client_object_invoke_func(ctx, &inv_arg, param);
+	if (ret < 0 || inv_arg.ret != 0) {
+		dev_err(uefisec_app.dev, "QCOMTEE_ROOT_OP_REG_WITH_CREDENTIALS invoke ret: %d, err: 0x%x\n",
+			ret, inv_arg.ret);
+		return ret ?: inv_arg.ret;
+	}
+
+	*client_env_obj = param[1].u.objref;
+	return ret;
+}
+
+static const struct efivar_operations qcom_efivar_ops = {
+	.get_variable = qcomtee_uefi_get_variable,
+	.set_variable = qcomtee_uefi_set_variable,
+	.get_next_variable = qcomtee_uefi_get_next_variable,
+	.query_variable_info = qcomtee_uefi_query_variable_info,
+};
+
+static int qcomtee_ctx_match(struct tee_ioctl_version_data *ver,
+			     const void *data)
+{
+	return (ver->impl_id == TEE_IMPL_ID_QTEE);
+}
+
+static int qcomtee_uefisecapp_probe(struct tee_client_device *tee_dev)
+{
+	int ret, err;
+	struct tee_param_objref client_env_obj;
+	struct tee_param_objref uefisec_svc_obj;
+
+	uefisec_app.dev = &tee_dev->dev;
+	/* Open context with QCOMTEE driver */
+	uefisec_app.ctx = tee_client_open_context(NULL, qcomtee_ctx_match, NULL,
+						  NULL);
+	if (IS_ERR(uefisec_app.ctx))
+		return -ENODEV;
+
+	/* Obtain a reference to client_env object to begin object exchange
+	 * with QTEE
+	 */
+	ret = qcomtee_get_client_env_obj(uefisec_app.ctx, &client_env_obj);
+	if (ret) {
+		err = -EINVAL;
+		goto err_get_client_env;
+	}
+
+	/* Obtain a reference to the uefisec_svc object which provides access to
+	 * the EFI var storage.
+	 */
+	ret = qcomtee_get_uefisec_svc_obj(uefisec_app.ctx, client_env_obj,
+					  &uefisec_svc_obj);
+	if (ret) {
+		err = -EINVAL;
+		goto err_get_uefisec_svc;
+	}
+	uefisec_app.uefisec_svc_obj = uefisec_svc_obj;
+
+	ret = efivars_register(&uefisec_app.efivars, &qcom_efivar_ops);
+	if (ret) {
+		err = ret;
+		goto err_efi_vars_reg;
+	}
+
+	/* We don't need to keep a reference to this object anymore, we only
+	 * needed it to obtain the uefisec_svc object.
+	 */
+	qcomtee_release_object(uefisec_app.ctx, client_env_obj);
+	return 0;
+
+err_efi_vars_reg:
+	qcomtee_release_object(uefisec_app.ctx, uefisec_svc_obj);
+err_get_uefisec_svc:
+	qcomtee_release_object(uefisec_app.ctx, client_env_obj);
+err_get_client_env:
+	tee_client_close_context(uefisec_app.ctx);
+
+	return err;
+}
+
+static void qcomtee_uefisecapp_remove(struct tee_client_device *tee_dev)
+{
+	efivars_unregister(&uefisec_app.efivars);
+	qcomtee_release_object(uefisec_app.ctx, uefisec_app.uefisec_svc_obj);
+	tee_client_close_context(uefisec_app.ctx);
+}
+
+static const struct tee_client_device_id qcomtee_uefisecapp_id_table[] = {
+	{UEFISECAPP_UUID},
+	{}
+};
+MODULE_DEVICE_TABLE(tee, qcomtee_uefisecapp_id_table);
+
+static struct tee_client_driver qcomtee_uefisecapp_driver = {
+	.id_table	= qcomtee_uefisecapp_id_table,
+	.probe		= qcomtee_uefisecapp_probe,
+	.remove		= qcomtee_uefisecapp_remove,
+	.driver		= {
+		.name		= "qcom-tee-uefisecapp",
+	},
+};
+
+module_tee_client_driver(qcomtee_uefisecapp_driver);
+
+MODULE_AUTHOR("Qualcomm");
+MODULE_DESCRIPTION("TEE client driver for Qualcomm TEE UEFI Secure App");
+MODULE_LICENSE("GPL");

-- 
2.34.1


^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [PATCH v3 1/6] tee: qcomtee: Track the object invocation context
  2026-10-01 11:02 ` [PATCH v3 1/6] tee: qcomtee: Track the object invocation context Harshal Dev
@ 2026-10-01 12:42   ` Sumit Garg
  0 siblings, 0 replies; 12+ messages in thread
From: Sumit Garg @ 2026-10-01 12:42 UTC (permalink / raw)
  To: Harshal Dev
  Cc: Jens Wiklander, Amirreza Zarrabi, Bjorn Andersson, Konrad Dybcio,
	Dmitry Baryshkov, Kuldeep Singh, Basant Kumar, Apurupa Pattapu,
	Arun Kumar Neelakantam, op-tee, linux-kernel, linux-arm-msm

On Thu, 01 Oct 2026 at 16:32:33 +0530, Harshal Dev wrote:
>QCOMTEE needs to distinguish between object invocations arriving from
>kernel clients and user-space clients in order to correctly marshal
>UBUF parameters and decide whether certain operations should be permitted.
>
>Introduce an enum tee_object_invoke_origin to allow clients to indicate
>the context of the TEE object invocation, and add a kernel_ctx flag to the
>QCOMTEE context so the TEE back-end can track it.
>
>Signed-off-by: Harshal Dev <harshal.dev@oss.qualcomm.com>
>---
> drivers/tee/qcomtee/call.c           | 11 ++++++++---
> drivers/tee/qcomtee/qcomtee_object.h |  8 ++++++--
> drivers/tee/tee_core.c               |  3 ++-
> include/linux/tee_core.h             |  8 +++++++-
> 4 files changed, 23 insertions(+), 7 deletions(-)

Looks fine to me.

Reviewed-by: Sumit Garg <sumit.garg@oss.qualcomm.com>

-Sumit

>
>diff --git a/drivers/tee/qcomtee/call.c b/drivers/tee/qcomtee/call.c
>index 4a597eeaf174..a0f2992c0611 100644
>--- a/drivers/tee/qcomtee/call.c
>+++ b/drivers/tee/qcomtee/call.c
>@@ -393,15 +393,20 @@ static int qcomtee_root_object_check(u32 op, struct tee_param *params,
>  */
> static int qcomtee_object_invoke(struct tee_context *ctx,
> 				 struct tee_ioctl_object_invoke_arg *arg,
>-				 struct tee_param *params)
>+				 struct tee_param *params,
>+				 enum tee_object_invoke_origin origin)
> {
> 	struct qcomtee_context_data *ctxdata = ctx->data;
> 	struct qcomtee_object *object;
>+	bool kernel_ctx = false;
> 	int i, ret, result;
>
> 	if (qcomtee_params_check(params, arg->num_params))
> 		return -EINVAL;
>
>+	if (origin == TEE_OBJECT_INVOKE_KERNEL)
>+		kernel_ctx = true;
>+
> 	/* First, handle reserved operations: */
> 	if (arg->op == QCOMTEE_MSG_OBJECT_OP_RELEASE) {
> 		del_qtee_object(arg->id, ctxdata);
>@@ -411,7 +416,7 @@ static int qcomtee_object_invoke(struct tee_context *ctx,
>
> 	/* Otherwise, invoke a QTEE object: */
> 	struct qcomtee_object_invoke_ctx *oic __free(kfree) =
>-		qcomtee_object_invoke_ctx_alloc(ctx);
>+		qcomtee_object_invoke_ctx_alloc(ctx, kernel_ctx);
> 	if (!oic)
> 		return -ENOMEM;
>
>@@ -648,7 +653,7 @@ static void qcomtee_get_qtee_feature_list(struct tee_context *ctx, u32 id,
> 	int result;
>
> 	struct qcomtee_object_invoke_ctx *oic __free(kfree) =
>-		qcomtee_object_invoke_ctx_alloc(ctx);
>+		qcomtee_object_invoke_ctx_alloc(ctx, true);
> 	if (!oic)
> 		return;
>
>diff --git a/drivers/tee/qcomtee/qcomtee_object.h b/drivers/tee/qcomtee/qcomtee_object.h
>index d5de02dcef3b..5f40617361fc 100644
>--- a/drivers/tee/qcomtee/qcomtee_object.h
>+++ b/drivers/tee/qcomtee/qcomtee_object.h
>@@ -147,6 +147,7 @@ static inline int qcomtee_args_len(struct qcomtee_arg *args)
>  * struct qcomtee_object_invoke_ctx - QTEE context for object invocation.
>  * @ctx: TEE context for this invocation.
>  * @flags: flags for the invocation context.
>+ * @kernel_ctx: flag that indicates this context is owned by a kernel client.
>  * @errno: error code for the invocation.
>  * @object: current object invoked in this callback context.
>  * @u: array of arguments for the current invocation (+1 for ending arg).
>@@ -159,6 +160,7 @@ static inline int qcomtee_args_len(struct qcomtee_arg *args)
> struct qcomtee_object_invoke_ctx {
> 	struct tee_context *ctx;
> 	unsigned long flags;
>+	bool kernel_ctx;
> 	int errno;
>
> 	struct qcomtee_object *object;
>@@ -173,13 +175,15 @@ struct qcomtee_object_invoke_ctx {
> };
>
> static inline struct qcomtee_object_invoke_ctx *
>-qcomtee_object_invoke_ctx_alloc(struct tee_context *ctx)
>+qcomtee_object_invoke_ctx_alloc(struct tee_context *ctx, bool kernel_ctx)
> {
> 	struct qcomtee_object_invoke_ctx *oic;
>
> 	oic = kzalloc_obj(*oic);
>-	if (oic)
>+	if (oic) {
> 		oic->ctx = ctx;
>+		oic->kernel_ctx = kernel_ctx;
>+	}
> 	return oic;
> }
>
>diff --git a/drivers/tee/tee_core.c b/drivers/tee/tee_core.c
>index 1aac50c7c1de..30901390149c 100644
>--- a/drivers/tee/tee_core.c
>+++ b/drivers/tee/tee_core.c
>@@ -701,7 +701,8 @@ static int tee_ioctl_object_invoke(struct tee_context *ctx,
> 			goto out;
> 	}
>
>-	rc = ctx->teedev->desc->ops->object_invoke_func(ctx, &arg, params);
>+	rc = ctx->teedev->desc->ops->object_invoke_func(ctx, &arg, params,
>+							TEE_OBJECT_INVOKE_USERSPACE);
> 	if (rc)
> 		goto out;
>
>diff --git a/include/linux/tee_core.h b/include/linux/tee_core.h
>index f993d5118edd..bcb5418d6fdc 100644
>--- a/include/linux/tee_core.h
>+++ b/include/linux/tee_core.h
>@@ -73,6 +73,11 @@ struct tee_device {
> 	struct tee_shm_pool *pool;
> };
>
>+enum tee_object_invoke_origin {
>+	TEE_OBJECT_INVOKE_USERSPACE,
>+	TEE_OBJECT_INVOKE_KERNEL,
>+};
>+
> /**
>  * struct tee_driver_ops - driver operations vtable
>  * @get_version:	returns version of driver
>@@ -117,7 +122,8 @@ struct tee_driver_ops {
> 			   struct tee_param *param);
> 	int (*object_invoke_func)(struct tee_context *ctx,
> 				  struct tee_ioctl_object_invoke_arg *arg,
>-				  struct tee_param *param);
>+				  struct tee_param *param,
>+				  enum tee_object_invoke_origin origin);
> 	int (*cancel_req)(struct tee_context *ctx, u32 cancel_id, u32 session);
> 	int (*supp_recv)(struct tee_context *ctx, u32 *func, u32 *num_params,
> 			 struct tee_param *param);
>
>-- 
>2.34.1
>

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [PATCH v3 2/6] tee: Add kernel client object invoke helper
  2026-10-01 11:02 ` [PATCH v3 2/6] tee: Add kernel client object invoke helper Harshal Dev
@ 2026-10-01 12:43   ` Sumit Garg
  0 siblings, 0 replies; 12+ messages in thread
From: Sumit Garg @ 2026-10-01 12:43 UTC (permalink / raw)
  To: Harshal Dev
  Cc: Jens Wiklander, Amirreza Zarrabi, Bjorn Andersson, Konrad Dybcio,
	Dmitry Baryshkov, Kuldeep Singh, Basant Kumar, Apurupa Pattapu,
	Arun Kumar Neelakantam, op-tee, linux-kernel, linux-arm-msm

On Thu, 01 Oct 2026 at 16:32:34 +0530, Harshal Dev wrote:
>From: Amirreza Zarrabi <amirreza.zarrabi@oss.qualcomm.com>
>
>Kernel clients can open a TEE context and invoke regular TA commands
>through tee_client_invoke_func(). However, there is currently no
>equivalent helper for invoking TEE objects.
>
>Add tee_client_object_invoke_func() as a kernel client API for issuing
>object invocation requests. The helper checks that the backend provides
>object_invoke_func() before forwarding the request by setting the origin
>as TEE_OBJECT_INVOKE_KERNEL. This allows TEE backends to support
>privileged object-based calls from the kernel-space.
>
>Co-developed-by: Harshal Dev <harshal.dev@oss.qualcomm.com>
>Signed-off-by: Harshal Dev <harshal.dev@oss.qualcomm.com>
>Signed-off-by: Amirreza Zarrabi <amirreza.zarrabi@oss.qualcomm.com>
>---
> drivers/tee/tee_core.c  | 12 ++++++++++++
> include/linux/tee_drv.h | 13 +++++++++++++
> 2 files changed, 25 insertions(+)

Reviewed-by: Sumit Garg <sumit.garg@oss.qualcomm.com>

-Sumit

>
>diff --git a/drivers/tee/tee_core.c b/drivers/tee/tee_core.c
>index 30901390149c..a03a3d645dd1 100644
>--- a/drivers/tee/tee_core.c
>+++ b/drivers/tee/tee_core.c
>@@ -1404,6 +1404,18 @@ int tee_client_invoke_func(struct tee_context *ctx,
> }
> EXPORT_SYMBOL_GPL(tee_client_invoke_func);
>
>+int tee_client_object_invoke_func(struct tee_context *ctx,
>+				  struct tee_ioctl_object_invoke_arg *arg,
>+				  struct tee_param *param)
>+{
>+	if (!ctx->teedev->desc->ops->object_invoke_func)
>+		return -EINVAL;
>+
>+	return ctx->teedev->desc->ops->object_invoke_func(ctx, arg, param,
>+							  TEE_OBJECT_INVOKE_KERNEL);
>+}
>+EXPORT_SYMBOL_GPL(tee_client_object_invoke_func);
>+
> int tee_client_cancel_req(struct tee_context *ctx,
> 			  struct tee_ioctl_cancel_arg *arg)
> {
>diff --git a/include/linux/tee_drv.h b/include/linux/tee_drv.h
>index f3c5e106d853..369c87ad0205 100644
>--- a/include/linux/tee_drv.h
>+++ b/include/linux/tee_drv.h
>@@ -283,6 +283,19 @@ int tee_client_invoke_func(struct tee_context *ctx,
> 			   struct tee_ioctl_invoke_arg *arg,
> 			   struct tee_param *param);
>
>+/**
>+ * tee_client_object_invoke_func() - Invoke a TEE object from kernel space
>+ * @ctx:    TEE Context
>+ * @arg:    Invoke arguments, see description of
>+ *          struct tee_ioctl_object_invoke_arg
>+ * @param:  Parameters for the object invocation
>+ *
>+ * Return: On success, returns 0; on failure, returns < 0.
>+ */
>+int tee_client_object_invoke_func(struct tee_context *ctx,
>+				  struct tee_ioctl_object_invoke_arg *arg,
>+				  struct tee_param *param);
>+
> /**
>  * tee_client_cancel_req() - Request cancellation of the previous open-session
>  * or invoke-command operations in a Trusted Application
>
>-- 
>2.34.1
>

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [PATCH v3 4/6] tee: Export uuidv5 generation for TEE backends
  2026-10-01 11:02 ` [PATCH v3 4/6] tee: Export uuidv5 generation for TEE backends Harshal Dev
@ 2026-10-01 12:46   ` Sumit Garg
  0 siblings, 0 replies; 12+ messages in thread
From: Sumit Garg @ 2026-10-01 12:46 UTC (permalink / raw)
  To: Harshal Dev
  Cc: Jens Wiklander, Amirreza Zarrabi, Bjorn Andersson, Konrad Dybcio,
	Dmitry Baryshkov, Kuldeep Singh, Basant Kumar, Apurupa Pattapu,
	Arun Kumar Neelakantam, op-tee, linux-kernel, linux-arm-msm

On Thu, 01 Oct 2026 at 16:32:36 +0530, Harshal Dev wrote:
>Export the uuidv5() function defined in the TEE core to all TEE backends.
>This enables the TEE backend drivers to generate a UUID for identifying
>and registering their secure services on the TEE bus.
>
>Signed-off-by: Harshal Dev <harshal.dev@oss.qualcomm.com>
>---
> drivers/tee/tee_core.c   |  9 +++++----
> include/linux/tee_core.h | 15 +++++++++++++++
> 2 files changed, 20 insertions(+), 4 deletions(-)
>

Reviewed-by: Sumit Garg <sumit.garg@oss.qualcomm.com>

-Sumit

>diff --git a/drivers/tee/tee_core.c b/drivers/tee/tee_core.c
>index a03a3d645dd1..2cfd302d1393 100644
>--- a/drivers/tee/tee_core.c
>+++ b/drivers/tee/tee_core.c
>@@ -135,7 +135,7 @@ static int tee_release(struct inode *inode, struct file *filp)
> }
>
> /**
>- * uuid_v5() - Calculate UUIDv5
>+ * tee_generate_uuid_v5() - Calculate UUIDv5
>  * @uuid: Resulting UUID
>  * @ns: Name space ID for UUIDv5 function
>  * @name: Name for UUIDv5 function
>@@ -146,8 +146,8 @@ static int tee_release(struct inode *inode, struct file *filp)
>  * This implements section (for SHA-1):
>  * 4.3.  Algorithm for Creating a Name-Based UUID
>  */
>-static void uuid_v5(uuid_t *uuid, const uuid_t *ns, const void *name,
>-		    size_t size)
>+void tee_generate_uuid_v5(uuid_t *uuid, const uuid_t *ns, const void *name,
>+			  size_t size)
> {
> 	unsigned char hash[SHA1_DIGEST_SIZE];
> 	struct sha1_ctx ctx;
>@@ -163,6 +163,7 @@ static void uuid_v5(uuid_t *uuid, const uuid_t *ns, const void *name,
> 	uuid->b[6] = (hash[6] & 0x0F) | 0x50;
> 	uuid->b[8] = (hash[8] & 0x3F) | 0x80;
> }
>+EXPORT_SYMBOL_GPL(tee_generate_uuid_v5);
>
> int tee_session_calc_client_uuid(uuid_t *uuid, u32 connection_method,
> 				 const u8 connection_data[TEE_IOCTL_UUID_LEN])
>@@ -228,7 +229,7 @@ int tee_session_calc_client_uuid(uuid_t *uuid, u32 connection_method,
> 		goto out_free_name;
> 	}
>
>-	uuid_v5(uuid, &tee_client_uuid_ns, name, name_len);
>+	tee_generate_uuid_v5(uuid, &tee_client_uuid_ns, name, name_len);
> out_free_name:
> 	kfree(name);
>
>diff --git a/include/linux/tee_core.h b/include/linux/tee_core.h
>index bcb5418d6fdc..a3f4f88b8423 100644
>--- a/include/linux/tee_core.h
>+++ b/include/linux/tee_core.h
>@@ -272,6 +272,21 @@ void tee_device_set_dev_groups(struct tee_device *teedev,
> int tee_session_calc_client_uuid(uuid_t *uuid, u32 connection_method,
> 				 const u8 connection_data[TEE_IOCTL_UUID_LEN]);
>
>+/**
>+ * tee_generate_uuid_v5() - Calculate UUIDv5
>+ * @uuid: Resulting UUID
>+ * @ns: Name space ID for UUIDv5 function
>+ * @name: Name for UUIDv5 function
>+ * @size: Size of name
>+ *
>+ * UUIDv5 is specific in RFC 4122.
>+ *
>+ * This implements section (for SHA-1):
>+ * 4.3.  Algorithm for Creating a Name-Based UUID
>+ */
>+void tee_generate_uuid_v5(uuid_t *uuid, const uuid_t *ns, const void *name,
>+			  size_t size);
>+
> /**
>  * struct tee_shm_pool - shared memory pool
>  * @ops:		operations
>
>-- 
>2.34.1
>

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [PATCH v3 3/6] tee: qcomtee: Allow object invokes from kernel clients
  2026-10-01 11:02 ` [PATCH v3 3/6] tee: qcomtee: Allow object invokes from kernel clients Harshal Dev
@ 2026-10-01 12:47   ` Sumit Garg
  0 siblings, 0 replies; 12+ messages in thread
From: Sumit Garg @ 2026-10-01 12:47 UTC (permalink / raw)
  To: Harshal Dev
  Cc: Jens Wiklander, Amirreza Zarrabi, Bjorn Andersson, Konrad Dybcio,
	Dmitry Baryshkov, Kuldeep Singh, Basant Kumar, Apurupa Pattapu,
	Arun Kumar Neelakantam, op-tee, linux-kernel, linux-arm-msm

On Thu, 01 Oct 2026 at 16:32:35 +0530, Harshal Dev wrote:
>From: Amirreza Zarrabi <amirreza.zarrabi@oss.qualcomm.com>
>
>QCOMTEE currently treats UBUF parameters as userspace addresses and
>applies userspace restrictions when invoking the root object. This is
>not suitable for object invocation requests issued by kernel clients.
>
>Use the kernel_ctx flag to distinguish kernel client requests from
>userspace requests. For kernel contexts, do not mark UBUF parameters as
>user addresses, and allow permitted root-object operations to proceed
>without applying the userspace-only checks.
>
>This allows in-kernel users of tee_client_object_invoke_func() to issue
>object invocation requests through the qcomtee backend.
>
>Co-developed-by: Harshal Dev <harshal.dev@oss.qualcomm.com>
>Signed-off-by: Harshal Dev <harshal.dev@oss.qualcomm.com>
>Signed-off-by: Amirreza Zarrabi <amirreza.zarrabi@oss.qualcomm.com>
>---
> drivers/tee/qcomtee/call.c           | 34 +++++++++++++++++++++++-----------
> drivers/tee/qcomtee/qcomtee_object.h |  5 +++--
> include/linux/tee_drv.h              |  5 ++++-
> 3 files changed, 30 insertions(+), 14 deletions(-)

Acked-by: Sumit Garg <sumit.garg@oss.qualcomm.com>

-Sumit

>
>diff --git a/drivers/tee/qcomtee/call.c b/drivers/tee/qcomtee/call.c
>index a0f2992c0611..b361d9c04de0 100644
>--- a/drivers/tee/qcomtee/call.c
>+++ b/drivers/tee/qcomtee/call.c
>@@ -202,7 +202,7 @@ int qcomtee_objref_from_arg(struct tee_param *param, struct qcomtee_arg *arg,
>  */
> static int qcomtee_params_to_args(struct qcomtee_arg *u,
> 				  struct tee_param *params, int num_params,
>-				  struct tee_context *ctx)
>+				  struct qcomtee_object_invoke_ctx *oic)
> {
> 	int i;
>
>@@ -210,8 +210,14 @@ static int qcomtee_params_to_args(struct qcomtee_arg *u,
> 		switch (params[i].attr) {
> 		case TEE_IOCTL_PARAM_ATTR_TYPE_UBUF_INPUT:
> 		case TEE_IOCTL_PARAM_ATTR_TYPE_UBUF_OUTPUT:
>-			u[i].flags = QCOMTEE_ARG_FLAGS_UADDR;
>-			u[i].b.uaddr = params[i].u.ubuf.uaddr;
>+			if (oic->kernel_ctx) {
>+				u[i].flags = 0;
>+				u[i].b.addr = params[i].u.ubuf.addr;
>+			} else {
>+				u[i].flags = QCOMTEE_ARG_FLAGS_UADDR;
>+				u[i].b.uaddr = params[i].u.ubuf.uaddr;
>+			}
>+
> 			u[i].b.size = params[i].u.ubuf.size;
>
> 			if (params[i].attr ==
>@@ -223,7 +229,7 @@ static int qcomtee_params_to_args(struct qcomtee_arg *u,
> 			break;
> 		case TEE_IOCTL_PARAM_ATTR_TYPE_OBJREF_INPUT:
> 			u[i].type = QCOMTEE_ARG_TYPE_IO;
>-			if (qcomtee_objref_to_arg(&u[i], &params[i], ctx))
>+			if (qcomtee_objref_to_arg(&u[i], &params[i], oic->ctx))
> 				goto out_failed;
>
> 			break;
>@@ -270,7 +276,7 @@ static int qcomtee_params_to_args(struct qcomtee_arg *u,
>  */
> static int qcomtee_params_from_args(struct tee_param *params,
> 				    struct qcomtee_arg *u, int num_params,
>-				    struct tee_context *ctx)
>+				    struct qcomtee_object_invoke_ctx *oic)
> {
> 	int i, np;
>
>@@ -288,7 +294,8 @@ static int qcomtee_params_from_args(struct tee_param *params,
> 			break;
> 		case QCOMTEE_ARG_TYPE_OO:
> 			/* TEE_IOCTL_PARAM_ATTR_TYPE_OBJREF_OUTPUT */
>-			if (qcomtee_objref_from_arg(&params[np], &u[np], ctx))
>+			if (qcomtee_objref_from_arg(&params[np], &u[np],
>+						    oic->ctx))
> 				goto out_failed;
>
> 			break;
>@@ -304,7 +311,7 @@ static int qcomtee_params_from_args(struct tee_param *params,
> 	/* Undo qcomtee_objref_from_arg(). */
> 	for (i = 0; i < np; i++) {
> 		if (params[i].attr == TEE_IOCTL_PARAM_ATTR_TYPE_OBJREF_OUTPUT)
>-			qcomtee_context_del_qtee_object(&params[i], ctx);
>+			qcomtee_context_del_qtee_object(&params[i], oic->ctx);
> 	}
>
> 	/* Release any IO and OO objects not processed. */
>@@ -357,7 +364,8 @@ static int qcomtee_params_check(struct tee_param *params, int num_params)
> }
>
> /* Check if an operation on ROOT_QCOMTEE_OBJECT from userspace is permitted. */
>-static int qcomtee_root_object_check(u32 op, struct tee_param *params,
>+static int qcomtee_root_object_check(struct qcomtee_object_invoke_ctx *oic,
>+				     u32 op, struct tee_param *params,
> 				     int num_params)
> {
> 	/* Some privileged operations recognized by QTEE. */
>@@ -366,6 +374,9 @@ static int qcomtee_root_object_check(u32 op, struct tee_param *params,
> 	    op == QCOMTEE_ROOT_OP_ADCI_SHUTDOWN)
> 		return -EINVAL;
>
>+	if (oic->kernel_ctx)
>+		return 0;
>+
> 	/*
> 	 * QCOMTEE_ROOT_OP_REG_WITH_CREDENTIALS is to register with QTEE
> 	 * by passing a credential object as input OBJREF. TEE_OBJREF_NULL as a
>@@ -429,7 +440,8 @@ static int qcomtee_object_invoke(struct tee_context *ctx,
> 	/* Get an object to invoke. */
> 	if (arg->id == TEE_OBJREF_NULL) {
> 		/* Use ROOT if TEE_OBJREF_NULL is invoked. */
>-		if (qcomtee_root_object_check(arg->op, params, arg->num_params))
>+		if (qcomtee_root_object_check(oic, arg->op, params,
>+					      arg->num_params))
> 			return -EINVAL;
>
> 		object = ROOT_QCOMTEE_OBJECT;
>@@ -437,7 +449,7 @@ static int qcomtee_object_invoke(struct tee_context *ctx,
> 		return -EINVAL;
> 	}
>
>-	ret = qcomtee_params_to_args(u, params, arg->num_params, ctx);
>+	ret = qcomtee_params_to_args(u, params, arg->num_params, oic);
> 	if (ret)
> 		goto out;
>
>@@ -455,7 +467,7 @@ static int qcomtee_object_invoke(struct tee_context *ctx,
>
> 	if (!result) {
> 		/* Assume service is UNAVAIL if unable to process the result. */
>-		if (qcomtee_params_from_args(params, u, arg->num_params, ctx))
>+		if (qcomtee_params_from_args(params, u, arg->num_params, oic))
> 			result = QCOMTEE_MSG_ERROR_UNAVAIL;
> 	} else {
> 		/*
>diff --git a/drivers/tee/qcomtee/qcomtee_object.h b/drivers/tee/qcomtee/qcomtee_object.h
>index 5f40617361fc..d3740099fae0 100644
>--- a/drivers/tee/qcomtee/qcomtee_object.h
>+++ b/drivers/tee/qcomtee/qcomtee_object.h
>@@ -113,8 +113,9 @@ struct qcomtee_buffer {
>  * @b: address and size if the type of argument is a buffer.
>  * @o: object instance if the type of argument is an object.
>  *
>- * &qcomtee_arg.flags only accepts %QCOMTEE_ARG_FLAGS_UADDR for now, which
>- * states that &qcomtee_arg.b contains a userspace address in uaddr.
>++ * If %QCOMTEE_ARG_FLAGS_UADDR is set in &qcomtee_arg.flags then it implies
>++ * that &qcomtee_arg.b contains a userspace address in uaddr.
>++ * Otherwise, &qcomtee_arg.b contains a kernel address in addr.
>  */
> struct qcomtee_arg {
> 	enum qcomtee_arg_type type;
>diff --git a/include/linux/tee_drv.h b/include/linux/tee_drv.h
>index 369c87ad0205..367208210a32 100644
>--- a/include/linux/tee_drv.h
>+++ b/include/linux/tee_drv.h
>@@ -83,7 +83,10 @@ struct tee_param_memref {
> };
>
> struct tee_param_ubuf {
>-	void __user *uaddr;
>+	union {
>+		void *addr;
>+		void __user *uaddr;
>+	};
> 	size_t size;
> };
>
>
>-- 
>2.34.1
>

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [PATCH v3 5/6] tee: qcomtee: Add support for registering QTEE services on TEE bus
  2026-10-01 11:02 ` [PATCH v3 5/6] tee: qcomtee: Add support for registering QTEE services on TEE bus Harshal Dev
@ 2026-10-01 12:57   ` Sumit Garg
  0 siblings, 0 replies; 12+ messages in thread
From: Sumit Garg @ 2026-10-01 12:57 UTC (permalink / raw)
  To: Harshal Dev
  Cc: Jens Wiklander, Amirreza Zarrabi, Bjorn Andersson, Konrad Dybcio,
	Dmitry Baryshkov, Kuldeep Singh, Basant Kumar, Apurupa Pattapu,
	Arun Kumar Neelakantam, op-tee, linux-kernel, linux-arm-msm

On Thu, 01 Oct 2026 at 16:32:37 +0530, Harshal Dev wrote:
>QTEE exposes certain secure services implemented either within the QTEE
>kernel or via pre-loaded Trusted Applications (TAs). Such always-available
>services can be readily accessed by TEE client drivers via QTEE's
>object-IPC protocol if the service is registered as a device on the TEE
>bus.
>
>One such service is the EFI-variables service, implemented by the
>uefisecapp TA which enables kernel clients to access EFI variables at
>runtime.
>
>Maintain a static list of such always-available secure services and add
>support for the QCOMTEE driver to register these services as devices on
>the TEE bus during probe.
>
>Signed-off-by: Harshal Dev <harshal.dev@oss.qualcomm.com>
>---
> drivers/tee/qcomtee/call.c           | 161 ++++++++++++++++++++++++++++++++++-
> drivers/tee/qcomtee/core.c           |   9 +-
> drivers/tee/qcomtee/qcomtee.h        |  12 +++
> drivers/tee/qcomtee/qcomtee_msg.h    |   1 +
> drivers/tee/qcomtee/qcomtee_object.h |   3 +-
> 5 files changed, 179 insertions(+), 7 deletions(-)
>
>diff --git a/drivers/tee/qcomtee/call.c b/drivers/tee/qcomtee/call.c
>index b361d9c04de0..8fadb7b13e61 100644
>--- a/drivers/tee/qcomtee/call.c
>+++ b/drivers/tee/qcomtee/call.c
>@@ -675,9 +675,13 @@ static void qcomtee_get_qtee_feature_list(struct tee_context *ctx, u32 id,
>
> 	/* Get ''FeatureVersions Service'' object. */
> 	service = qcomtee_object_get_service(oic, client_env,
>-					     QCOMTEE_FEATURE_VER_UID);
>-	if (service == NULL_QCOMTEE_OBJECT)
>+					     QCOMTEE_FEATURE_VER_UID,
>+					     &result);
>+	if (service == NULL_QCOMTEE_OBJECT) {
>+		if (result)
>+			pr_err("FeatureVersions Service unavailable (%d)\n", result);

Do we really want to error out if a service isn't available? Is it
really the case that every QTEE firmware will implement each service?

> 		goto out_failed;
>+	}
>
> 	/* IB: Feature to query. */
> 	u[0].b.addr = &id;
>@@ -697,6 +701,156 @@ static void qcomtee_get_qtee_feature_list(struct tee_context *ctx, u32 id,
> 	qcomtee_object_put(client_env);
> }
>
>+/**
>+ * is_qcomtee_service_available() - Check if the QTEE service identified by the UID
>+ * is available
>+ * @oic: context to use for the current invocation.
>+ * @client_env: Client environment object.
>+ * @service_name: Name of the QTEE service.
>+ * @uid: 32-bit UID of the service.
>+ *
>+ * Returns true if the service exists and is available.
>+ * Returns false if a service is not exposed by QTEE.
>+ */
>+static bool is_qcomtee_service_available(struct qcomtee_object_invoke_ctx *oic,
>+					 struct qcomtee_object *client_env,
>+					 const char *service_name, u32 uid)
>+{
>+	struct qcomtee_object *service;
>+	int error = 0;
>+	bool ret = false;
>+
>+	/* Get service object corresponding to the uid. */
>+	service = qcomtee_object_get_service(oic, client_env, uid, &error);
>+	if (service != NULL_QCOMTEE_OBJECT) {
>+		qcomtee_object_put(service);
>+		ret = true;
>+	}
>+
>+	/* When we fail to get the service, QTEE provides the reason. */
>+	if (error)
>+		pr_err("%s is unavailable (%d)\n", service_name, error);

Ditto here, rather convert this into a debug message.

>+
>+	return ret;
>+}
>+
>+/*
>+ * QTEE Service UUID name space identifier
>+ *
>+ * A random UUID that is allocated as a name space identifier for forming UUID's
>+ * representing secure services exposed by QTEE.
>+ */
>+static const uuid_t qtee_service_uuid_ns = UUID_INIT(0xe1b48857, 0x6154, 0x49f9,
>+						     0x93, 0x4e, 0xa2, 0xf2,
>+						     0x0a, 0xba, 0x98, 0x42);
>+
>+static const struct qtee_service qtee_services[] = {
>+	{ "qcom.tz.uefisecapp",
>+	   QCOMTEE_UEFI_SEC_UID }
>+};
>+
>+static void qtee_release_service(struct device *dev)
>+{
>+	struct tee_client_device *qtee_service = to_tee_client_device(dev);
>+
>+	kfree(qtee_service);
>+}
>+
>+/**
>+ * qtee_enumerate_service() - Enumerate a given QTEE service and register
>+ * it on the TEE bus as a TEE client device
>+ * @oic: context to use for the current invocation.
>+ * @client_env: Client environment object.
>+ * @service_name: Name of the QTEE service to be enumerated.
>+ * @uid: 32-bit UID used by QTEE to identify the service.
>+ *
>+ * Returns 0 on success and < 0 on failure.
>+ */
>+static int qtee_enumerate_service(struct qcomtee_object_invoke_ctx *oic,
>+				  struct qcomtee_object *client_env,
>+				  const char *service_name,
>+				  const u32 uid)
>+{
>+	struct tee_client_device *qtee_service;
>+	uuid_t service_uuid;
>+	int rc;
>+
>+	if (!is_qcomtee_service_available(oic, client_env, service_name, uid))
>+		return -EOPNOTSUPP;
>+
>+	tee_generate_uuid_v5(&service_uuid, &qtee_service_uuid_ns, service_name,
>+			     strlen(service_name));
>+
>+	qtee_service = kzalloc_obj(*qtee_service);
>+	if (!qtee_service)
>+		return -ENOMEM;
>+
>+	qtee_service->dev.bus = &tee_bus_type;
>+	qtee_service->dev.release = qtee_release_service;
>+	if (dev_set_name(&qtee_service->dev, "qtee-svc-%pUb", &service_uuid)) {
>+		kfree(qtee_service);
>+		return -ENOMEM;
>+	}
>+	uuid_copy(&qtee_service->id.uuid, &service_uuid);
>+
>+	rc = device_register(&qtee_service->dev);
>+	if (rc) {
>+		pr_err("QTEE service registration failed, err: %d\n", rc);
>+		put_device(&qtee_service->dev);
>+		return rc;
>+	}
>+
>+	return 0;
>+}
>+
>+/**
>+ * qtee_enumerate_services() - Enumerate all the secure services exposed by QTEE
>+ * from the static 'qtee_services' list and register them on the TEE bus as
>+ * TEE client devices.
>+ *
>+ * Not all versions of QTEE support a given service. Hence, we try to
>+ * enumerate as many services from the 'qtee_services' list as possible.
>+ * Not being able to enumerate a service shouldn't cause the driver probe
>+ * to fail since none of the services in the list are mandatory for
>+ * establishing communication with QTEE.
>+ * @ctx: TEE context.
>+ */
>+static void qtee_enumerate_services(struct tee_context *ctx)
>+{
>+	u32 idx;
>+	struct qcomtee_object *client_env;
>+
>+	struct qcomtee_object_invoke_ctx *oic __free(kfree) =
>+		qcomtee_object_invoke_ctx_alloc(ctx, true);
>+	if (!oic)
>+		return;
>+
>+	client_env = qcomtee_object_get_client_env(oic);
>+	if (client_env == NULL_QCOMTEE_OBJECT)
>+		return;
>+
>+	for (idx = 0; idx < ARRAY_SIZE(qtee_services); idx++)
>+		qtee_enumerate_service(oic, client_env,
>+				       qtee_services[idx].name,
>+				       qtee_services[idx].uid);
>+
>+	qcomtee_object_put(client_env);
>+}
>+
>+static int qtee_unregister_service(struct device *dev, void *data)
>+{
>+	if (!strncmp(dev_name(dev), "qtee-svc", strlen("qtee-svc")))
>+		device_unregister(dev);
>+
>+	return 0;
>+}
>+
>+static void qtee_unregister_services(void)
>+{
>+	bus_for_each_dev(&tee_bus_type, NULL, NULL,
>+			 qtee_unregister_service);
>+}
>+
> static const struct tee_driver_ops qcomtee_ops = {
> 	.get_version = qcomtee_get_version,
> 	.open = qcomtee_open,
>@@ -778,6 +932,8 @@ static int qcomtee_probe(struct platform_device *pdev)
> 		QTEE_VERSION_GET_MINOR(qcomtee->qtee_version),
> 		QTEE_VERSION_GET_PATCH(qcomtee->qtee_version));
>
>+	qtee_enumerate_services(qcomtee->ctx);

Rather call it qtee_register_services() matching it's counterpart below.

-Sumit

>+
> 	return 0;
>
> err_dest_wq:
>@@ -807,6 +963,7 @@ static void qcomtee_remove(struct platform_device *pdev)
> {
> 	struct qcomtee *qcomtee = platform_get_drvdata(pdev);
>
>+	qtee_unregister_services();
> 	teedev_close_context(qcomtee->ctx);
> 	/* Wait for RELEASE operations to be processed for QTEE objects. */
> 	tee_device_unregister(qcomtee->teedev);
>diff --git a/drivers/tee/qcomtee/core.c b/drivers/tee/qcomtee/core.c
>index 60fe3b5776e3..4a523a95bf0e 100644
>--- a/drivers/tee/qcomtee/core.c
>+++ b/drivers/tee/qcomtee/core.c
>@@ -898,19 +898,20 @@ qcomtee_object_get_client_env(struct qcomtee_object_invoke_ctx *oic)
>
> struct qcomtee_object *
> qcomtee_object_get_service(struct qcomtee_object_invoke_ctx *oic,
>-			   struct qcomtee_object *client_env, u32 uid)
>+			   struct qcomtee_object *client_env, u32 uid,
>+			   int *result)
> {
> 	struct qcomtee_arg u[3] = { 0 };
>-	int ret, result;
>+	int ret;
>
> 	u[0].b.addr = &uid;
> 	u[0].b.size = sizeof(uid);
> 	u[0].type = QCOMTEE_ARG_TYPE_IB;
> 	u[1].type = QCOMTEE_ARG_TYPE_OO;
> 	ret = qcomtee_object_do_invoke(oic, client_env, QCOMTEE_CLIENT_ENV_OPEN,
>-				       u, &result);
>+				       u, result);
>
>-	if (ret || result)
>+	if (ret || *result)
> 		return NULL_QCOMTEE_OBJECT;
>
> 	return u[1].o;
>diff --git a/drivers/tee/qcomtee/qcomtee.h b/drivers/tee/qcomtee/qcomtee.h
>index f39bf63fd1c2..66d305a46c0a 100644
>--- a/drivers/tee/qcomtee/qcomtee.h
>+++ b/drivers/tee/qcomtee/qcomtee.h
>@@ -17,6 +17,8 @@
> #define QCOMTEE_OBJREF_FLAG_USER	BIT(1)
> #define QCOMTEE_OBJREF_FLAG_MEM		BIT(2)
>
>+#define QTEE_UUID_NS_NAME_SIZE	        128
>+
> /**
>  * struct qcomtee - Main service struct.
>  * @teedev: client device.
>@@ -39,6 +41,16 @@ struct qcomtee {
> 	u32 qtee_version;
> };
>
>+/**
>+ * struct qtee_service - A secure service exposed by QTEE identified by a 32-bit UID.
>+ * @name: Name of the QTEE service.
>+ * @uid: 32-bit UID used by QTEE to identify the service.
>+ */
>+struct qtee_service {
>+	const char *name;
>+	const u32 uid;
>+};
>+
> void qcomtee_fetch_async_reqs(struct qcomtee_object_invoke_ctx *oic);
> struct qcomtee_object *qcomtee_idx_erase(struct qcomtee_object_invoke_ctx *oic,
> 					 u32 idx);
>diff --git a/drivers/tee/qcomtee/qcomtee_msg.h b/drivers/tee/qcomtee/qcomtee_msg.h
>index 5d7b21fdd368..9278a361dc70 100644
>--- a/drivers/tee/qcomtee/qcomtee_msg.h
>+++ b/drivers/tee/qcomtee/qcomtee_msg.h
>@@ -105,6 +105,7 @@ union qcomtee_msg_arg {
> #define QTEE_VERSION_GET_MINOR(x) (((x) >> 12) & 0xffU)
> #define QTEE_VERSION_GET_PATCH(x) ((x) >> 0 & 0xfffU)
>
>+#define QCOMTEE_UEFI_SEC_UID            413
> /* Response types as returned from qcomtee_object_invoke_ctx_invoke(). */
>
> /* The message contains a callback request. */
>diff --git a/drivers/tee/qcomtee/qcomtee_object.h b/drivers/tee/qcomtee/qcomtee_object.h
>index d3740099fae0..901ba3565a73 100644
>--- a/drivers/tee/qcomtee/qcomtee_object.h
>+++ b/drivers/tee/qcomtee/qcomtee_object.h
>@@ -317,6 +317,7 @@ qcomtee_object_get_client_env(struct qcomtee_object_invoke_ctx *oic);
>
> struct qcomtee_object *
> qcomtee_object_get_service(struct qcomtee_object_invoke_ctx *oic,
>-			   struct qcomtee_object *client_env, u32 uid);
>+			   struct qcomtee_object *client_env, u32 uid,
>+			   int *result);
>
> #endif /* QCOMTEE_OBJECT_H */
>
>-- 
>2.34.1
>

^ permalink raw reply	[flat|nested] 12+ messages in thread

end of thread, other threads:[~2026-10-01 12:57 UTC | newest]

Thread overview: 12+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-10-01 11:02 [PATCH v3 0/6] Add TEE based client driver for UEFI Secure Application Harshal Dev
2026-10-01 11:02 ` [PATCH v3 1/6] tee: qcomtee: Track the object invocation context Harshal Dev
2026-10-01 12:42   ` Sumit Garg
2026-10-01 11:02 ` [PATCH v3 2/6] tee: Add kernel client object invoke helper Harshal Dev
2026-10-01 12:43   ` Sumit Garg
2026-10-01 11:02 ` [PATCH v3 3/6] tee: qcomtee: Allow object invokes from kernel clients Harshal Dev
2026-10-01 12:47   ` Sumit Garg
2026-10-01 11:02 ` [PATCH v3 4/6] tee: Export uuidv5 generation for TEE backends Harshal Dev
2026-10-01 12:46   ` Sumit Garg
2026-10-01 11:02 ` [PATCH v3 5/6] tee: qcomtee: Add support for registering QTEE services on TEE bus Harshal Dev
2026-10-01 12:57   ` Sumit Garg
2026-10-01 11:02 ` [PATCH v3 6/6] firmware: qcom: Add support for TEE based EFI-var client driver Harshal Dev

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox

all inboxes | Powered by JetHome®