From: Jorge Ramirez-Ortiz <jorge.ramirez@oss.qualcomm.com>
To: jorge.ramirez@oss.qualcomm.com, dlechner@baylibre.com,
trini@konsulko.com, jens.wiklander@linaro.org,
ilias.apalodimas@linaro.org, peng.fan@nxp.com,
jh80.chung@samsung.com, tanmay.kathpalia@altera.com,
neil.armstrong@linaro.org, bhupesh.linux@gmail.com,
n-francis@ti.com, xypron.glpk@gmx.de, s-vadapalli@ti.com,
michal.simek@amd.com, jbx6244@gmail.com,
marek.vasut+renesas@mailbox.org, sumit.garg@oss.qualcomm.com,
jens.wiklander@oss.qualcomm.com
Cc: u-boot@lists.u-boot-project.org
Subject: [PATCH v5 6/6] optee: implement the RPMB subsystem interface for UFS
Date: Fri, 18 Sep 2026 22:06:38 +0200 [thread overview]
Message-ID: <20260918200641.2286077-7-jorge.ramirez@oss.qualcomm.com> (raw)
In-Reply-To: <20260918200641.2286077-1-jorge.ramirez@oss.qualcomm.com>
The legacy RPMB supplicant assumes an eMMC device and derives the key
from an eMMC-shaped device ID, so it can never reproduce the key Linux
derives for a UFS device. Secure storage on UFS-only platforms instead
needs the transport-agnostic RPMB subsystem interface, through which the
normal world describes the real RPMB device to OP-TEE.
Add a UFS backend for it so OP-TEE derives a key matching Linux and can
use RPMB secure storage on UFS. eMMC keeps using the legacy interface.
Signed-off-by: Jorge Ramirez-Ortiz <jorge.ramirez@oss.qualcomm.com>
---
drivers/tee/optee/Makefile | 1 +
drivers/tee/optee/optee_msg_supplicant.h | 8 ++
drivers/tee/optee/optee_private.h | 41 +++++++
drivers/tee/optee/rpmb_ufs.c | 141 +++++++++++++++++++++++
drivers/tee/optee/supplicant.c | 9 ++
drivers/ufs/Kconfig | 8 ++
6 files changed, 208 insertions(+)
create mode 100644 drivers/tee/optee/rpmb_ufs.c
diff --git a/drivers/tee/optee/Makefile b/drivers/tee/optee/Makefile
index d0c7f8dfb12..f2af10999a9 100644
--- a/drivers/tee/optee/Makefile
+++ b/drivers/tee/optee/Makefile
@@ -4,3 +4,4 @@ obj-$(CONFIG_OPTEE) += core.o
obj-y += supplicant.o
obj-$(CONFIG_DM_I2C) += i2c.o
obj-$(CONFIG_SUPPORT_EMMC_RPMB) += rpmb_emmc.o
+obj-$(CONFIG_SUPPORT_UFS_RPMB) += rpmb_ufs.o
diff --git a/drivers/tee/optee/optee_msg_supplicant.h b/drivers/tee/optee/optee_msg_supplicant.h
index 963cfd47824..b720d5d7b3f 100644
--- a/drivers/tee/optee/optee_msg_supplicant.h
+++ b/drivers/tee/optee/optee_msg_supplicant.h
@@ -152,6 +152,14 @@
*/
#define OPTEE_MSG_RPC_CMD_I2C_TRANSFER 21
+#define OPTEE_MSG_RPC_CMD_RPMB_PROBE_RESET 22
+#define OPTEE_MSG_RPC_CMD_RPMB_PROBE_NEXT 23
+#define OPTEE_MSG_RPC_CMD_RPMB_FRAMES 24
+
+#define OPTEE_RPC_SHM_TYPE_APPL 0
+
+#define OPTEE_RPC_RPMB_UFS 1
+
/*
* Was OPTEE_MSG_RPC_CMD_SQL_FS, which isn't supported any longer
*/
diff --git a/drivers/tee/optee/optee_private.h b/drivers/tee/optee/optee_private.h
index 1f07a27ee4b..2888257aefe 100644
--- a/drivers/tee/optee/optee_private.h
+++ b/drivers/tee/optee/optee_private.h
@@ -9,6 +9,17 @@
#include <tee.h>
#include <log.h>
+#ifdef CONFIG_SUPPORT_UFS_RPMB
+/**
+ * struct optee_private - OP-TEE driver private data
+ * @rpmb_next_region: next UFS RPMB region to report on PROBE_NEXT
+ * @rpmb_cur_region: UFS RPMB region selected by the last PROBE_NEXT
+ */
+struct optee_private {
+ unsigned int rpmb_next_region;
+ unsigned int rpmb_cur_region;
+};
+#else
/**
* struct optee_private - OP-TEE driver private data
* @rpmb_mmc: mmc device for the RPMB partition
@@ -22,6 +33,7 @@ struct optee_private {
int rpmb_dev_id;
int rpmb_original_part;
};
+#endif
struct optee_msg_arg;
@@ -60,6 +72,35 @@ static inline void optee_suppl_rpmb_release(struct udevice *dev)
}
#endif
+#ifdef CONFIG_SUPPORT_UFS_RPMB
+void optee_suppl_cmd_rpmb_probe_reset(struct udevice *dev,
+ struct optee_msg_arg *arg);
+
+void optee_suppl_cmd_rpmb_probe_next(struct udevice *dev,
+ struct optee_msg_arg *arg);
+
+void optee_suppl_cmd_rpmb_frames(struct udevice *dev,
+ struct optee_msg_arg *arg);
+#else
+static inline void optee_suppl_cmd_rpmb_probe_reset(struct udevice *dev,
+ struct optee_msg_arg *arg)
+{
+ arg->ret = TEE_ERROR_NOT_IMPLEMENTED;
+}
+
+static inline void optee_suppl_cmd_rpmb_probe_next(struct udevice *dev,
+ struct optee_msg_arg *arg)
+{
+ arg->ret = TEE_ERROR_NOT_IMPLEMENTED;
+}
+
+static inline void optee_suppl_cmd_rpmb_frames(struct udevice *dev,
+ struct optee_msg_arg *arg)
+{
+ arg->ret = TEE_ERROR_NOT_IMPLEMENTED;
+}
+#endif
+
#ifdef CONFIG_DM_I2C
/**
* optee_suppl_cmd_i2c_transfer() - route I2C requests to an I2C chip
diff --git a/drivers/tee/optee/rpmb_ufs.c b/drivers/tee/optee/rpmb_ufs.c
new file mode 100644
index 00000000000..3e54a1a37d7
--- /dev/null
+++ b/drivers/tee/optee/rpmb_ufs.c
@@ -0,0 +1,141 @@
+// SPDX-License-Identifier: GPL-2.0+
+
+#include <dm.h>
+#include <tee.h>
+#include <ufs.h>
+
+#include "optee_msg.h"
+#include "optee_msg_supplicant.h"
+#include "optee_private.h"
+
+static int optee_rpmb_get_dev(struct udevice **scsi_devp)
+{
+ struct udevice *ufs_dev, *scsi_dev;
+ int ret;
+
+ ret = uclass_get_device(UCLASS_UFS, CONFIG_UFS_RPMB_CONTROLLER,
+ &ufs_dev);
+ if (ret)
+ return ret;
+
+ ret = device_get_child(ufs_dev, 0, &scsi_dev);
+ if (ret)
+ return ret;
+
+ *scsi_devp = scsi_dev;
+
+ return 0;
+}
+
+void optee_suppl_cmd_rpmb_probe_reset(struct udevice *dev,
+ struct optee_msg_arg *arg)
+{
+ struct optee_private *priv = dev_get_priv(dev);
+
+ if (arg->num_params != 1 ||
+ arg->params[0].attr != OPTEE_MSG_ATTR_TYPE_VALUE_OUTPUT) {
+ arg->ret = TEE_ERROR_BAD_PARAMETERS;
+ return;
+ }
+
+ priv->rpmb_next_region = 0;
+ priv->rpmb_cur_region = 0;
+
+ arg->params[0].u.value.a = OPTEE_RPC_SHM_TYPE_APPL;
+ arg->ret = TEE_SUCCESS;
+}
+
+void optee_suppl_cmd_rpmb_probe_next(struct udevice *dev,
+ struct optee_msg_arg *arg)
+{
+ struct optee_private *priv = dev_get_priv(dev);
+ struct udevice *scsi_dev;
+ struct tee_shm *cid_shm;
+ u8 size_mult = 0;
+ u8 rel_wr = 0;
+ void *cid_buf;
+ ulong cid_size;
+ int ret;
+
+ if (arg->num_params != 2 ||
+ arg->params[0].attr != OPTEE_MSG_ATTR_TYPE_VALUE_OUTPUT ||
+ arg->params[1].attr != OPTEE_MSG_ATTR_TYPE_RMEM_OUTPUT) {
+ arg->ret = TEE_ERROR_BAD_PARAMETERS;
+ return;
+ }
+
+ cid_shm = (struct tee_shm *)(ulong)arg->params[1].u.rmem.shm_ref;
+ cid_buf = (u8 *)cid_shm->addr + arg->params[1].u.rmem.offs;
+ cid_size = arg->params[1].u.rmem.size;
+ if (cid_size < UFS_RPMB_CID_SIZE) {
+ arg->ret = TEE_ERROR_SHORT_BUFFER;
+ return;
+ }
+
+ if (optee_rpmb_get_dev(&scsi_dev)) {
+ arg->ret = TEE_ERROR_ITEM_NOT_FOUND;
+ return;
+ }
+
+ while (priv->rpmb_next_region < UFS_RPMB_NUM_REGIONS) {
+ unsigned int region = priv->rpmb_next_region++;
+
+ ret = ufs_rpmb_get_region_info(scsi_dev, region, &size_mult,
+ &rel_wr, cid_buf);
+ if (ret < 0) {
+ arg->ret = TEE_ERROR_GENERIC;
+ return;
+ }
+ if (!ret)
+ continue;
+
+ priv->rpmb_cur_region = region;
+ arg->params[0].u.value.a = OPTEE_RPC_RPMB_UFS;
+ arg->params[0].u.value.b = size_mult;
+ arg->params[0].u.value.c = rel_wr;
+ arg->params[1].u.rmem.size = UFS_RPMB_CID_SIZE;
+ arg->ret = TEE_SUCCESS;
+ return;
+ }
+
+ arg->ret = TEE_ERROR_ITEM_NOT_FOUND;
+}
+
+void optee_suppl_cmd_rpmb_frames(struct udevice *dev,
+ struct optee_msg_arg *arg)
+{
+ struct optee_private *priv = dev_get_priv(dev);
+ struct tee_shm *req_shm;
+ struct tee_shm *rsp_shm;
+ struct udevice *scsi_dev;
+ void *req_buf;
+ void *rsp_buf;
+ ulong req_size;
+ ulong rsp_size;
+
+ if (arg->num_params != 2 ||
+ arg->params[0].attr != OPTEE_MSG_ATTR_TYPE_RMEM_INPUT ||
+ arg->params[1].attr != OPTEE_MSG_ATTR_TYPE_RMEM_OUTPUT) {
+ arg->ret = TEE_ERROR_BAD_PARAMETERS;
+ return;
+ }
+
+ if (optee_rpmb_get_dev(&scsi_dev)) {
+ arg->ret = TEE_ERROR_ITEM_NOT_FOUND;
+ return;
+ }
+
+ req_shm = (struct tee_shm *)(ulong)arg->params[0].u.rmem.shm_ref;
+ req_buf = (u8 *)req_shm->addr + arg->params[0].u.rmem.offs;
+ req_size = arg->params[0].u.rmem.size;
+
+ rsp_shm = (struct tee_shm *)(ulong)arg->params[1].u.rmem.shm_ref;
+ rsp_buf = (u8 *)rsp_shm->addr + arg->params[1].u.rmem.offs;
+ rsp_size = arg->params[1].u.rmem.size;
+
+ if (ufs_rpmb_route_frames(scsi_dev, priv->rpmb_cur_region, req_buf,
+ req_size, rsp_buf, rsp_size))
+ arg->ret = TEE_ERROR_BAD_PARAMETERS;
+ else
+ arg->ret = TEE_SUCCESS;
+}
diff --git a/drivers/tee/optee/supplicant.c b/drivers/tee/optee/supplicant.c
index 8a426f53ba8..50b780037fb 100644
--- a/drivers/tee/optee/supplicant.c
+++ b/drivers/tee/optee/supplicant.c
@@ -89,6 +89,15 @@ void optee_suppl_cmd(struct udevice *dev, struct tee_shm *shm_arg,
case OPTEE_MSG_RPC_CMD_RPMB:
optee_suppl_cmd_rpmb(dev, arg);
break;
+ case OPTEE_MSG_RPC_CMD_RPMB_PROBE_RESET:
+ optee_suppl_cmd_rpmb_probe_reset(dev, arg);
+ break;
+ case OPTEE_MSG_RPC_CMD_RPMB_PROBE_NEXT:
+ optee_suppl_cmd_rpmb_probe_next(dev, arg);
+ break;
+ case OPTEE_MSG_RPC_CMD_RPMB_FRAMES:
+ optee_suppl_cmd_rpmb_frames(dev, arg);
+ break;
case OPTEE_MSG_RPC_CMD_I2C_TRANSFER:
optee_suppl_cmd_i2c_transfer(arg);
break;
diff --git a/drivers/ufs/Kconfig b/drivers/ufs/Kconfig
index 648b58b46e4..f174ca0841d 100644
--- a/drivers/ufs/Kconfig
+++ b/drivers/ufs/Kconfig
@@ -105,4 +105,12 @@ config SUPPORT_UFS_RPMB
single RPMB transport, so this is mutually exclusive with the eMMC
RPMB supplicant (SUPPORT_EMMC_RPMB).
+config UFS_RPMB_CONTROLLER
+ int "UFS controller index used for RPMB"
+ depends on SUPPORT_UFS_RPMB
+ default 0
+ help
+ Index of the RPMB-owning UFS controller in the UCLASS_UFS device
+ list. Leave at 0 unless the board has more than one UFS controller.
+
endmenu
--
2.54.0
next prev parent reply other threads:[~2026-09-18 20:07 UTC|newest]
Thread overview: 24+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-09-18 20:06 [PATCH v5 0/6] ufs: rpmb: route OP-TEE RPMB secure storage over UFS Jorge Ramirez-Ortiz
2026-09-18 20:06 ` [PATCH v5 1/6] ufs: decode string descriptors as UTF-16 big-endian Jorge Ramirez-Ortiz
2026-10-14 12:20 ` neil.armstrong
2026-09-18 20:06 ` [PATCH v5 2/6] ufs: surface sense data from ufs_scsi_exec() Jorge Ramirez-Ortiz
2026-10-02 11:16 ` Ilias Apalodimas
2026-10-13 17:48 ` Jorge Ramirez
2026-10-13 17:51 ` Tom Rini
2026-10-14 12:19 ` neil.armstrong
2026-10-14 12:20 ` neil.armstrong
2026-09-18 20:06 ` [PATCH v5 3/6] ufs: add RPMB transport over SCSI SECURITY PROTOCOL Jorge Ramirez-Ortiz
2026-09-29 3:29 ` Stanley Jhu
2026-10-14 12:22 ` neil.armstrong
2026-09-18 20:06 ` [PATCH v5 4/6] ufs: derive the per-region RPMB CID and size for OP-TEE Jorge Ramirez-Ortiz
2026-09-18 20:06 ` [PATCH v5 5/6] optee: rename rpmb.c to rpmb_emmc.c Jorge Ramirez-Ortiz
2026-10-02 11:14 ` Ilias Apalodimas
2026-09-18 20:06 ` Jorge Ramirez-Ortiz [this message]
2026-10-02 11:14 ` [PATCH v5 6/6] optee: implement the RPMB subsystem interface for UFS Ilias Apalodimas
2026-09-18 20:15 ` [PATCH v5 0/6] ufs: rpmb: route OP-TEE RPMB secure storage over UFS Jorge Ramirez
2026-09-24 17:50 ` Macpaul Lin (林智斌)
2026-09-25 9:59 ` Ilias Apalodimas
2026-09-26 20:41 ` Jorge Ramirez
2026-09-26 21:08 ` Jorge Ramirez
2026-09-28 7:32 ` Jens Wiklander
2026-09-28 10:02 ` Ilias Apalodimas
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=20260918200641.2286077-7-jorge.ramirez@oss.qualcomm.com \
--to=jorge.ramirez@oss.qualcomm.com \
--cc=bhupesh.linux@gmail.com \
--cc=dlechner@baylibre.com \
--cc=ilias.apalodimas@linaro.org \
--cc=jbx6244@gmail.com \
--cc=jens.wiklander@linaro.org \
--cc=jens.wiklander@oss.qualcomm.com \
--cc=jh80.chung@samsung.com \
--cc=marek.vasut+renesas@mailbox.org \
--cc=michal.simek@amd.com \
--cc=n-francis@ti.com \
--cc=neil.armstrong@linaro.org \
--cc=peng.fan@nxp.com \
--cc=s-vadapalli@ti.com \
--cc=sumit.garg@oss.qualcomm.com \
--cc=tanmay.kathpalia@altera.com \
--cc=trini@konsulko.com \
--cc=u-boot@lists.u-boot-project.org \
--cc=xypron.glpk@gmx.de \
/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