mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
From: Jorge Ramirez-Ortiz <jorge.ramirez@oss.qualcomm.com>
To: jorge.ramirez@oss.qualcomm.com, peterhuewe@gmx.de,
	jarkko@kernel.org, jgg@ziepe.ca, sumit.garg@oss.qualcomm.com
Cc: linux-kernel@vger.kernel.org, linux-integrity@vger.kernel.org
Subject: [PATCH v2 2/2] tpm_ftpm_tee: use the tpm_optee transport core
Date: Tue, 10 Nov 2026 15:19:09 +0100	[thread overview]
Message-ID: <20261110141923.3100770-3-jorge.ramirez@oss.qualcomm.com> (raw)
In-Reply-To: <20261110141923.3100770-1-jorge.ramirez@oss.qualcomm.com>

The firmware-TPM driver and the new discrete-TPM driver share the same
OP-TEE transport, now factored into a common core. Move the firmware-TPM
driver onto it so the transport is not duplicated. The driver keeps its
name, its platform/OF binding and its shutdown behaviour; only the
transport is shared.

Two functional changes come from sharing the core: a command longer than
the caller's buffer is now rejected (it was previously only checked
against the application's maximum), and a failed command submission
returns -EIO instead of the raw error code from the secure world.

Signed-off-by: Jorge Ramirez-Ortiz <jorge.ramirez@oss.qualcomm.com>
---
 drivers/char/tpm/Kconfig        |   1 +
 drivers/char/tpm/tpm_ftpm_tee.c | 295 ++------------------------------
 drivers/char/tpm/tpm_ftpm_tee.h |  35 ----
 drivers/char/tpm/tpm_optee.c    |  11 ++
 drivers/char/tpm/tpm_optee.h    |   1 +
 5 files changed, 31 insertions(+), 312 deletions(-)
 delete mode 100644 drivers/char/tpm/tpm_ftpm_tee.h

diff --git a/drivers/char/tpm/Kconfig b/drivers/char/tpm/Kconfig
index 779154e05204..35aff3003a32 100644
--- a/drivers/char/tpm/Kconfig
+++ b/drivers/char/tpm/Kconfig
@@ -240,6 +240,7 @@ config TCG_VTPM_PROXY
 config TCG_FTPM_TEE
 	tristate "TEE based fTPM Interface"
 	depends on TEE && OPTEE
+	select TCG_OPTEE
 	help
 	  This driver proxies for firmware TPM running in TEE.
 
diff --git a/drivers/char/tpm/tpm_ftpm_tee.c b/drivers/char/tpm/tpm_ftpm_tee.c
index b82490439633..1665e9b584a7 100644
--- a/drivers/char/tpm/tpm_ftpm_tee.c
+++ b/drivers/char/tpm/tpm_ftpm_tee.c
@@ -7,17 +7,22 @@
  *
  * A reference implementation is available here:
  * https://github.com/microsoft/ms-tpm-20-ref/tree/master/Samples/ARM32-FirmwareTPM/optee_ta/fTPM
+ *
+ * The TEE transport is shared with other OP-TEE TPM front-ends and lives in
+ * tpm_optee; this file only carries the fTPM identity and its platform/OF
+ * binding.
  */
 
 #include <linux/acpi.h>
 #include <linux/of.h>
 #include <linux/platform_device.h>
 #include <linux/tee_drv.h>
-#include <linux/tpm.h>
 #include <linux/uuid.h>
 
-#include "tpm.h"
-#include "tpm_ftpm_tee.h"
+#include "tpm_optee.h"
+
+/* The TAF ID implemented in the fTPM TA */
+#define FTPM_OPTEE_TA_SUBMIT_COMMAND	0
 
 /*
  * TA_FTPM_UUID: BC50D971-D4C9-42C4-82CB-343FB7F37896
@@ -26,299 +31,36 @@
  * Defined here in the reference implementation:
  * https://github.com/microsoft/ms-tpm-20-ref/blob/master/Samples/ARM32-FirmwareTPM/optee_ta/fTPM/include/fTPM.h#L42
  */
-static const uuid_t ftpm_ta_uuid =
-	UUID_INIT(0xBC50D971, 0xD4C9, 0x42C4,
-		  0x82, 0xCB, 0x34, 0x3F, 0xB7, 0xF3, 0x78, 0x96);
-
-/**
- * ftpm_tee_tpm_op_send() - send TPM commands through the TEE shared memory
- * and retrieve the response.
- * @chip:	the tpm_chip description as specified in driver/char/tpm/tpm.h
- * @buf:	the buffer to send and to store the response.
- * @bufsiz:	the size of the buffer.
- * @cmd_len:	the number of bytes to send.
- *
- * Return:
- *	In case of success, returns the number of bytes received.
- *	On failure, -errno
- */
-static int ftpm_tee_tpm_op_send(struct tpm_chip *chip, u8 *buf, size_t bufsiz,
-				size_t cmd_len)
-{
-	struct ftpm_tee_private *pvt_data = dev_get_drvdata(chip->dev.parent);
-	size_t resp_len;
-	int rc;
-	u8 *temp_buf;
-	struct tpm_header *resp_header;
-	struct tee_ioctl_invoke_arg transceive_args;
-	struct tee_param command_params[4];
-	struct tee_shm *shm = pvt_data->shm;
-
-	if (cmd_len > MAX_COMMAND_SIZE) {
-		dev_err(&chip->dev,
-			"%s: len=%zd exceeds MAX_COMMAND_SIZE supported by fTPM TA\n",
-			__func__, cmd_len);
-		return -EIO;
-	}
-
-	memset(&transceive_args, 0, sizeof(transceive_args));
-	memset(command_params, 0, sizeof(command_params));
-
-	/* Invoke FTPM_OPTEE_TA_SUBMIT_COMMAND function of fTPM TA */
-	transceive_args = (struct tee_ioctl_invoke_arg) {
-		.func = FTPM_OPTEE_TA_SUBMIT_COMMAND,
-		.session = pvt_data->session,
-		.num_params = 4,
-	};
-
-	/* Fill FTPM_OPTEE_TA_SUBMIT_COMMAND parameters */
-	command_params[0] = (struct tee_param) {
-		.attr = TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INPUT,
-		.u.memref = {
-			.shm = shm,
-			.size = cmd_len,
-			.shm_offs = 0,
-		},
-	};
-
-	temp_buf = tee_shm_get_va(shm, 0);
-	if (IS_ERR(temp_buf)) {
-		dev_err(&chip->dev, "%s: tee_shm_get_va failed for transmit\n",
-			__func__);
-		return PTR_ERR(temp_buf);
-	}
-	memset(temp_buf, 0, (MAX_COMMAND_SIZE + MAX_RESPONSE_SIZE));
-	memcpy(temp_buf, buf, cmd_len);
-
-	command_params[1] = (struct tee_param) {
-		.attr = TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INOUT,
-		.u.memref = {
-			.shm = shm,
-			.size = MAX_RESPONSE_SIZE,
-			.shm_offs = MAX_COMMAND_SIZE,
-		},
-	};
-
-	rc = tee_client_invoke_func(pvt_data->ctx, &transceive_args,
-				    command_params);
-	if ((rc < 0) || (transceive_args.ret != 0)) {
-		dev_err(&chip->dev, "%s: SUBMIT_COMMAND invoke error: 0x%x\n",
-			__func__, transceive_args.ret);
-		return (rc < 0) ? rc : transceive_args.ret;
-	}
-
-	temp_buf = tee_shm_get_va(shm, command_params[1].u.memref.shm_offs);
-	if (IS_ERR(temp_buf)) {
-		dev_err(&chip->dev, "%s: tee_shm_get_va failed for receive\n",
-			__func__);
-		return PTR_ERR(temp_buf);
-	}
-
-	resp_header = (struct tpm_header *)temp_buf;
-	resp_len = be32_to_cpu(resp_header->length);
-
-	/* sanity check resp_len */
-	if (resp_len < TPM_HEADER_SIZE) {
-		dev_err(&chip->dev, "%s: tpm response header too small\n",
-			__func__);
-		return -EIO;
-	}
-	if (resp_len > MAX_RESPONSE_SIZE) {
-		dev_err(&chip->dev,
-			"%s: resp_len=%zd exceeds MAX_RESPONSE_SIZE\n",
-			__func__, resp_len);
-		return -EIO;
-	}
-	if (resp_len > bufsiz) {
-		dev_err(&chip->dev,
-			"%s: resp_len=%zd exceeds bufsiz=%zd\n",
-			__func__, resp_len, bufsiz);
-		return -EIO;
-	}
-
-	memcpy(buf, temp_buf, resp_len);
-
-	return resp_len;
-}
-
-static const struct tpm_class_ops ftpm_tee_tpm_ops = {
-	.flags = TPM_OPS_AUTO_STARTUP,
-	.send = ftpm_tee_tpm_op_send,
+static const struct tpm_optee_config ftpm_tee_config = {
+	.ta_uuid = UUID_INIT(0xBC50D971, 0xD4C9, 0x42C4,
+			     0x82, 0xCB, 0x34, 0x3F, 0xB7, 0xF3, 0x78, 0x96),
+	.login	 = TEE_IOCTL_LOGIN_PUBLIC,
+	.cmd_id	 = FTPM_OPTEE_TA_SUBMIT_COMMAND,
 };
 
-/*
- * Check whether this driver supports the fTPM TA in the TEE instance
- * represented by the params (ver/data) to this function.
- */
-static int ftpm_tee_match(struct tee_ioctl_version_data *ver, const void *data)
-{
-	/*
-	 * Currently this driver only support GP Complaint OPTEE based fTPM TA
-	 */
-	if ((ver->impl_id == TEE_IMPL_ID_OPTEE) &&
-		(ver->gen_caps & TEE_GEN_CAP_GP))
-		return 1;
-	else
-		return 0;
-}
-
-/**
- * ftpm_tee_probe_generic() - initialize the fTPM
- * @dev: the device description.
- *
- * Return:
- *	On success, 0. On failure, -errno.
- */
-static int ftpm_tee_probe_generic(struct device *dev)
-{
-	int rc;
-	struct tpm_chip *chip;
-	struct ftpm_tee_private *pvt_data = NULL;
-	struct tee_ioctl_open_session_arg sess_arg;
-
-	pvt_data = devm_kzalloc(dev, sizeof(struct ftpm_tee_private),
-				GFP_KERNEL);
-	if (!pvt_data)
-		return -ENOMEM;
-
-	dev_set_drvdata(dev, pvt_data);
-
-	/* Open context with TEE driver */
-	pvt_data->ctx = tee_client_open_context(NULL, ftpm_tee_match, NULL,
-						NULL);
-	if (IS_ERR(pvt_data->ctx)) {
-		if (PTR_ERR(pvt_data->ctx) == -ENOENT)
-			return -EPROBE_DEFER;
-		dev_err(dev, "%s: tee_client_open_context failed\n", __func__);
-		return PTR_ERR(pvt_data->ctx);
-	}
-
-	/* Open a session with fTPM TA */
-	memset(&sess_arg, 0, sizeof(sess_arg));
-	export_uuid(sess_arg.uuid, &ftpm_ta_uuid);
-	sess_arg.clnt_login = TEE_IOCTL_LOGIN_PUBLIC;
-	sess_arg.num_params = 0;
-
-	rc = tee_client_open_session(pvt_data->ctx, &sess_arg, NULL);
-	if ((rc < 0) || (sess_arg.ret != 0)) {
-		dev_err(dev, "%s: tee_client_open_session failed, err=%x\n",
-			__func__, sess_arg.ret);
-		rc = -EINVAL;
-		goto out_tee_session;
-	}
-	pvt_data->session = sess_arg.session;
-
-	/* Allocate dynamic shared memory with fTPM TA */
-	pvt_data->shm = tee_shm_alloc_kernel_buf(pvt_data->ctx,
-						 MAX_COMMAND_SIZE +
-						 MAX_RESPONSE_SIZE);
-	if (IS_ERR(pvt_data->shm)) {
-		dev_err(dev, "%s: tee_shm_alloc_kernel_buf failed\n", __func__);
-		rc = -ENOMEM;
-		goto out_shm_alloc;
-	}
-
-	/* Allocate new struct tpm_chip instance */
-	chip = tpm_chip_alloc(dev, &ftpm_tee_tpm_ops);
-	if (IS_ERR(chip)) {
-		dev_err(dev, "%s: tpm_chip_alloc failed\n", __func__);
-		rc = PTR_ERR(chip);
-		goto out_chip_alloc;
-	}
-
-	pvt_data->chip = chip;
-	pvt_data->chip->flags |= TPM_CHIP_FLAG_TPM2 | TPM_CHIP_FLAG_SYNC;
-
-	/* Create a character device for the fTPM */
-	rc = tpm_chip_register(pvt_data->chip);
-	if (rc) {
-		dev_err(dev, "%s: tpm_chip_register failed with rc=%d\n",
-			__func__, rc);
-		goto out_chip;
-	}
-
-	return 0;
-
-out_chip:
-	put_device(&pvt_data->chip->dev);
-out_chip_alloc:
-	tee_shm_free(pvt_data->shm);
-out_shm_alloc:
-	tee_client_close_session(pvt_data->ctx, pvt_data->session);
-out_tee_session:
-	tee_client_close_context(pvt_data->ctx);
-
-	return rc;
-}
-
 static int ftpm_tee_probe(struct tee_client_device *tcdev)
 {
-	struct device *dev = &tcdev->dev;
-
-	return ftpm_tee_probe_generic(dev);
+	return tpm_optee_probe(&tcdev->dev, &ftpm_tee_config);
 }
 
 static int ftpm_plat_tee_probe(struct platform_device *pdev)
 {
-	struct device *dev = &pdev->dev;
-
-	return ftpm_tee_probe_generic(dev);
-}
-
-/**
- * ftpm_tee_remove_generic() - remove the TPM device
- * @dev: the device description.
- *
- * Return:
- *	0 always.
- */
-static void ftpm_tee_remove_generic(struct device *dev)
-{
-	struct ftpm_tee_private *pvt_data = dev_get_drvdata(dev);
-
-	/* Release the chip */
-	tpm_chip_unregister(pvt_data->chip);
-
-	/* frees chip */
-	put_device(&pvt_data->chip->dev);
-
-	/* Free the shared memory pool */
-	tee_shm_free(pvt_data->shm);
-
-	/* close the existing session with fTPM TA*/
-	tee_client_close_session(pvt_data->ctx, pvt_data->session);
-
-	/* close the context with TEE driver */
-	tee_client_close_context(pvt_data->ctx);
-
-	/* memory allocated with devm_kzalloc() is freed automatically */
+	return tpm_optee_probe(&pdev->dev, &ftpm_tee_config);
 }
 
 static void ftpm_tee_remove(struct tee_client_device *tcdev)
 {
-	struct device *dev = &tcdev->dev;
-
-	ftpm_tee_remove_generic(dev);
+	tpm_optee_remove(&tcdev->dev);
 }
 
 static void ftpm_plat_tee_remove(struct platform_device *pdev)
 {
-	struct device *dev = &pdev->dev;
-
-	ftpm_tee_remove_generic(dev);
+	tpm_optee_remove(&pdev->dev);
 }
 
-/**
- * ftpm_plat_tee_shutdown() - shutdown the TPM device
- * @pdev: the platform_device description.
- */
 static void ftpm_plat_tee_shutdown(struct platform_device *pdev)
 {
-	struct ftpm_tee_private *pvt_data = dev_get_drvdata(&pdev->dev);
-
-	tee_shm_free(pvt_data->shm);
-	tee_client_close_session(pvt_data->ctx, pvt_data->session);
-	tee_client_close_context(pvt_data->ctx);
+	tpm_optee_shutdown(&pdev->dev);
 }
 
 static const struct of_device_id of_ftpm_tee_ids[] = {
@@ -343,7 +85,6 @@ static const struct tee_client_device_id optee_ftpm_id_table[] = {
 		   0x82, 0xcb, 0x34, 0x3f, 0xb7, 0xf3, 0x78, 0x96)},
 	{}
 };
-
 MODULE_DEVICE_TABLE(tee, optee_ftpm_id_table);
 
 static struct tee_client_driver ftpm_tee_driver = {
diff --git a/drivers/char/tpm/tpm_ftpm_tee.h b/drivers/char/tpm/tpm_ftpm_tee.h
deleted file mode 100644
index 8d5c3f0d2879..000000000000
--- a/drivers/char/tpm/tpm_ftpm_tee.h
+++ /dev/null
@@ -1,35 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/*
- * Copyright (C) Microsoft Corporation
- */
-
-#ifndef __TPM_FTPM_TEE_H__
-#define __TPM_FTPM_TEE_H__
-
-#include <linux/tee_drv.h>
-#include <linux/tpm.h>
-#include <linux/uuid.h>
-
-/* The TAFs ID implemented in this TA */
-#define FTPM_OPTEE_TA_SUBMIT_COMMAND  (0)
-#define FTPM_OPTEE_TA_EMULATE_PPI     (1)
-
-/* max. buffer size supported by fTPM  */
-#define MAX_COMMAND_SIZE       4096
-#define MAX_RESPONSE_SIZE      4096
-
-/**
- * struct ftpm_tee_private - fTPM's private data
- * @chip:     struct tpm_chip instance registered with tpm framework.
- * @session:  fTPM TA session identifier.
- * @ctx:      TEE context handler.
- * @shm:      Memory pool shared with fTPM TA in TEE.
- */
-struct ftpm_tee_private {
-	struct tpm_chip *chip;
-	u32 session;
-	struct tee_context *ctx;
-	struct tee_shm *shm;
-};
-
-#endif /* __TPM_FTPM_TEE_H__ */
diff --git a/drivers/char/tpm/tpm_optee.c b/drivers/char/tpm/tpm_optee.c
index c251626ae395..e2223242327e 100644
--- a/drivers/char/tpm/tpm_optee.c
+++ b/drivers/char/tpm/tpm_optee.c
@@ -238,5 +238,16 @@ void tpm_optee_remove(struct device *dev)
 }
 EXPORT_SYMBOL_GPL(tpm_optee_remove);
 
+/* Release the TEE resources on shutdown, leaving the chip registered. */
+void tpm_optee_shutdown(struct device *dev)
+{
+	struct tpm_optee_private *pvt_data = dev_get_drvdata(dev);
+
+	tee_shm_free(pvt_data->shm);
+	tee_client_close_session(pvt_data->ctx, pvt_data->session);
+	tee_client_close_context(pvt_data->ctx);
+}
+EXPORT_SYMBOL_GPL(tpm_optee_shutdown);
+
 MODULE_DESCRIPTION("OP-TEE TPM transport core");
 MODULE_LICENSE("GPL");
diff --git a/drivers/char/tpm/tpm_optee.h b/drivers/char/tpm/tpm_optee.h
index 11193b5dc284..a3a2ea2a951d 100644
--- a/drivers/char/tpm/tpm_optee.h
+++ b/drivers/char/tpm/tpm_optee.h
@@ -27,5 +27,6 @@ struct tpm_optee_config {
 
 int tpm_optee_probe(struct device *dev, const struct tpm_optee_config *cfg);
 void tpm_optee_remove(struct device *dev);
+void tpm_optee_shutdown(struct device *dev);
 
 #endif /* __TPM_OPTEE_H__ */
-- 
2.55.0


      parent reply	other threads:[~2026-11-10 14:19 UTC|newest]

Thread overview: 4+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-11-10 14:19 [PATCH v2 0/2] tpm: OP-TEE transport core for discrete and firmware TPMs Jorge Ramirez-Ortiz
2026-11-10 14:19 ` [PATCH v2 1/2] tpm: add OP-TEE transport core and a discrete TPM driver Jorge Ramirez-Ortiz
2026-11-10 15:14   ` Jarkko Sakkinen
2026-11-10 14:19 ` Jorge Ramirez-Ortiz [this message]

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20261110141923.3100770-3-jorge.ramirez@oss.qualcomm.com \
    --to=jorge.ramirez@oss.qualcomm.com \
    --cc=jarkko@kernel.org \
    --cc=jgg@ziepe.ca \
    --cc=linux-integrity@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=peterhuewe@gmx.de \
    --cc=sumit.garg@oss.qualcomm.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
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®