All of lore.kernel.org
 help / color / mirror / Atom feed
From: David Lechner <dlechner@baylibre.com>
To: Jorge Ramirez-Ortiz <jorge.ramirez@oss.qualcomm.com>,
	neil.armstrong@linaro.org, trini@konsulko.com,
	jens.wiklander@linaro.org, ilias.apalodimas@linaro.org,
	peng.fan@nxp.com, jh80.chung@samsung.com,
	bhupesh.linux@gmail.com, n-francis@ti.com,
	marek.vasut+renesas@mailbox.org,
	igor.belwon@mentallysanemainliners.org, shawn.lin@rock-chips.com,
	alchark@gmail.com, tuyen.dang.xa@renesas.com,
	yoshihiro.shimoda.uh@renesas.com, padmarao.begari@amd.com,
	jstephan@baylibre.com, hayashi.kunihiko@socionext.com,
	macpaul.lin@mediatek.com, venkyada@qti.qualcomm.com,
	j-mcarthur@ti.com, u-boot@lists.denx.de
Subject: Re: [PATCH v3 2/5] ufs: add RPMB transport over SCSI SECURITY PROTOCOL
Date: Wed, 29 Jul 2026 17:27:30 -0500	[thread overview]
Message-ID: <e0895741-aae1-438a-a7c1-cdad0ca6402e@baylibre.com> (raw)
In-Reply-To: <20260723143852.2287208-3-jorge.ramirez@oss.qualcomm.com>

On 7/23/26 9:38 AM, Jorge Ramirez-Ortiz wrote:
> OP-TEE secure storage (CFG_RPMB_FS) requires RPMB, but on UFS-only
> platforms with no eMMC the OP-TEE RPMB supplicant has no way to reach the
> device's RPMB Well-Known LUN, which UFS exposes through SCSI SECURITY
> PROTOCOL IN/OUT commands rather than an eMMC-style RPMB partition; this
> transport provides that missing path so RPMB-backed secure storage works
> on UFS-based platforms.
> 
> Signed-off-by: Jorge Ramirez-Ortiz <jorge.ramirez@oss.qualcomm.com>
> ---
>  drivers/ufs/Kconfig      |  10 +++
>  drivers/ufs/Makefile     |   1 +
>  drivers/ufs/ufs-rpmb.c   | 173 +++++++++++++++++++++++++++++++++++++++
>  drivers/ufs/ufs-uclass.c |   6 +-
>  drivers/ufs/ufs.h        |   7 ++
>  include/scsi.h           |   2 +
>  include/ufs.h            |   4 +
>  7 files changed, 200 insertions(+), 3 deletions(-)
>  create mode 100644 drivers/ufs/ufs-rpmb.c
> 
> diff --git a/drivers/ufs/Kconfig b/drivers/ufs/Kconfig
> index 49472933de3..99160a0819b 100644
> --- a/drivers/ufs/Kconfig
> +++ b/drivers/ufs/Kconfig
> @@ -92,4 +92,14 @@ config UFS_TI_J721E
>  	  This selects the glue layer driver for Cadence controller
>  	  present on TI's J721E devices.
>  
> +config SUPPORT_UFS_RPMB
> +	bool "Enable UFS RPMB (Replay Protected Memory Block) support"
> +	depends on UFS && OPTEE && !SUPPORT_EMMC_RPMB
> +	help
> +	  Route OP-TEE RPMB requests to the UFS RPMB Well-Known LUN using
> +	  SCSI SECURITY PROTOCOL IN/OUT commands. Required for OP-TEE secure
> +	  storage (CFG_RPMB_FS) on UFS-based platforms that have no eMMC.
> +	  The OP-TEE supplicant handles a single RPMB transport, so this is
> +	  mutually exclusive with the eMMC RPMB supplicant (SUPPORT_EMMC_RPMB).
> +
>  endmenu
> diff --git a/drivers/ufs/Makefile b/drivers/ufs/Makefile
> index e7f3c1d30c4..d60440ca119 100644
> --- a/drivers/ufs/Makefile
> +++ b/drivers/ufs/Makefile
> @@ -13,3 +13,4 @@ obj-$(CONFIG_UFS_RENESAS) += ufs-renesas.o
>  obj-$(CONFIG_UFS_RENESAS_GEN5) += ufs-renesas-rcar-gen5.o
>  obj-$(CONFIG_UFS_ROCKCHIP) += ufs-rockchip.o
>  obj-$(CONFIG_UFS_TI_J721E) += ti-j721e-ufs.o
> +obj-$(CONFIG_SUPPORT_UFS_RPMB) += ufs-rpmb.o
> diff --git a/drivers/ufs/ufs-rpmb.c b/drivers/ufs/ufs-rpmb.c
> new file mode 100644
> index 00000000000..fb4cd42ad75
> --- /dev/null
> +++ b/drivers/ufs/ufs-rpmb.c
> @@ -0,0 +1,173 @@
> +// SPDX-License-Identifier: GPL-2.0+
> +#include <dm.h>
> +#include <log.h>
> +#include <malloc.h>
> +#include <scsi.h>
> +#include <ufs.h>
> +#include <asm/cache.h>
> +#include <linux/errno.h>
> +#include <linux/string.h>
> +#include "ufs.h"
> +
> +#define RPMB_REQ_KEY		1
> +#define RPMB_REQ_WCOUNTER	2
> +#define RPMB_REQ_WRITE_DATA	3
> +#define RPMB_REQ_READ_DATA	4
> +#define RPMB_REQ_STATUS		5
> +
> +#define RPMB_FRAME_SIZE		512
> +#define RPMB_FRAME_REQ_OFFSET	510
> +
> +#define UFS_RPMB_UA_RETRIES	3
> +
> +#define SEC_PROTOCOL_UFS		0xEC
> +#define UFS_RPMB_SEC_PROTOCOL_ID	0x01
> +
> +#define GEOMETRY_DESC_RPMB_RW_SIZE	0x17
> +
> +static u16 rpmb_frame_request(const void *frame)
> +{
> +	const u8 *p = frame;
> +
> +	return ((u16)p[RPMB_FRAME_REQ_OFFSET] << 8) |
> +		p[RPMB_FRAME_REQ_OFFSET + 1];
> +}

I would drop the function and just use get_unaligned_be16()
directly.

> +
> +static int ufs_rpmb_secprot(struct udevice *scsi_dev, unsigned int region,
> +			    u8 opcode, void *buf, unsigned int nframes,
> +			    enum dma_data_direction dir)
> +{
> +	u16 spsp = (region << 8) | UFS_RPMB_SEC_PROTOCOL_ID;
> +	u32 len = nframes * RPMB_FRAME_SIZE;
> +	struct scsi_cmd pccb;
> +	void *dma_buf = buf;
> +	void *bounce = NULL;
> +	int retries;
> +	int ret = 0;
> +
> +	if (!IS_ALIGNED((uintptr_t)buf, ARCH_DMA_MINALIGN)) {
> +		bounce = memalign(ARCH_DMA_MINALIGN,
> +				  ALIGN(len, ARCH_DMA_MINALIGN));
> +		if (!bounce)
> +			return -ENOMEM;
> +		dma_buf = bounce;
> +		if (dir == DMA_TO_DEVICE)
> +			memcpy(bounce, buf, len);
> +	}
> +
> +	memset(&pccb, 0, sizeof(pccb));
> +	pccb.lun = UFS_UPIU_RPMB_WLUN;
> +	pccb.cmd[0] = opcode;
> +	pccb.cmd[1] = SEC_PROTOCOL_UFS;
> +	pccb.cmd[2] = (spsp >> 8) & 0xff;
> +	pccb.cmd[3] = spsp & 0xff;

How about using put_unaligned_be16()?

> +	pccb.cmd[4] = 0;
> +	pccb.cmd[5] = 0;
> +	pccb.cmd[6] = (len >> 24) & 0xff;
> +	pccb.cmd[7] = (len >> 16) & 0xff;
> +	pccb.cmd[8] = (len >> 8) & 0xff;
> +	pccb.cmd[9] = len & 0xff;

And put_unaligned_be32().

> +	pccb.cmd[10] = 0;
> +	pccb.cmd[11] = 0;
> +	pccb.cmdlen = 12;
> +	pccb.pdata = dma_buf;
> +	pccb.datalen = len;
> +	pccb.dma_dir = dir;
> +
> +	for (retries = UFS_RPMB_UA_RETRIES; retries > 0; retries--) {
> +		ret = scsi_exec(scsi_dev, &pccb);
> +		if (!ret)
> +			break;
> +	}
> +
> +	if (bounce) {
> +		if (!ret && dir == DMA_FROM_DEVICE)
> +			memcpy(buf, bounce, len);
> +
> +		free(bounce);
> +	}
> +
> +	return ret;
> +}
> +
> +static int ufs_rpmb_send(struct udevice *scsi_dev, unsigned int region,
> +			 void *frames, unsigned int nframes)
> +{
> +	return ufs_rpmb_secprot(scsi_dev, region, SCSI_SECURITY_PROTOCOL_OUT,
> +				frames, nframes, DMA_TO_DEVICE);
> +}
> +
> +static int ufs_rpmb_recv(struct udevice *scsi_dev, unsigned int region,
> +			 void *frames, unsigned int nframes)
> +{
> +	return ufs_rpmb_secprot(scsi_dev, region, SCSI_SECURITY_PROTOCOL_IN,
> +				frames, nframes, DMA_FROM_DEVICE);
> +}
> +
> +int ufs_rpmb_route_frames(struct udevice *scsi_dev, unsigned int region,
> +			  void *req, unsigned long reqlen, void *rsp,
> +			  unsigned long rsplen)
> +{
> +	unsigned int n_req = reqlen / RPMB_FRAME_SIZE;
> +	unsigned int n_rsp = rsplen / RPMB_FRAME_SIZE;
> +	u16 request;
> +	int ret;
> +
> +	if (!scsi_dev || reqlen % RPMB_FRAME_SIZE ||
> +	    rsplen % RPMB_FRAME_SIZE || !n_req)
> +		return -EINVAL;
> +
> +	request = rpmb_frame_request(req);
> +
> +	switch (request) {
> +	case RPMB_REQ_KEY:
> +	case RPMB_REQ_WRITE_DATA: {
> +		u8 status_frame[RPMB_FRAME_SIZE];
> +
> +		ret = ufs_rpmb_send(scsi_dev, region, req, n_req);
> +		if (ret)
> +			return ret;
> +
> +		memset(status_frame, 0, sizeof(status_frame));
> +		status_frame[RPMB_FRAME_REQ_OFFSET] = RPMB_REQ_STATUS >> 8;
> +		status_frame[RPMB_FRAME_REQ_OFFSET + 1] = RPMB_REQ_STATUS & 0xff;

put_unaligned_be16()

> +		ret = ufs_rpmb_send(scsi_dev, region, status_frame, 1);
> +		if (ret)
> +			return ret;
> +
> +		if (n_rsp < 1)
> +			return -EINVAL;
> +
> +		return ufs_rpmb_recv(scsi_dev, region, rsp, 1);
> +	}
> +	case RPMB_REQ_WCOUNTER:
> +	case RPMB_REQ_READ_DATA:
> +		ret = ufs_rpmb_send(scsi_dev, region, req, 1);
> +		if (ret)
> +			return ret;
> +
> +		if (n_rsp < 1)
> +			return -EINVAL;
> +
> +		return ufs_rpmb_recv(scsi_dev, region, rsp, n_rsp);
> +	default:
> +		debug("ufs-rpmb: unsupported request 0x%x\n", request);
> +		return -EINVAL;
> +	}
> +}
> +

> +static int ufs_rpmb_read_geometry(struct udevice *scsi_dev, u8 *rpmb_rw_size)
> +{
> +	struct ufs_hba *hba = dev_get_uclass_priv(scsi_dev->parent);
> +	u8 desc[QUERY_DESC_GEOMETRY_DEF_SIZE];
> +	int ret;
> +
> +	ret = ufshcd_read_desc_param(hba, QUERY_DESC_IDN_GEOMETRY, 0, 0,
> +				     desc, sizeof(desc));
> +	if (ret)
> +		return ret;
> +
> +	*rpmb_rw_size = desc[GEOMETRY_DESC_RPMB_RW_SIZE];
> +
> +	return 0;
> +}

This function should be defered to the next patch were it is used.
Otherwise we could get compilers complaining during git bisect about
unused static function.


  reply	other threads:[~2026-07-29 22:27 UTC|newest]

Thread overview: 9+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-07-23 14:38 [PATCH v3 0/5] ufs: rpmb: route OP-TEE RPMB secure storage over UFS Jorge Ramirez-Ortiz via U-Boot
2026-07-23 14:38 ` [PATCH v3 1/5] ufs: decode string descriptors as UTF-16 big-endian Jorge Ramirez-Ortiz via U-Boot
2026-07-29 21:51   ` David Lechner
2026-07-23 14:38 ` [PATCH v3 2/5] ufs: add RPMB transport over SCSI SECURITY PROTOCOL Jorge Ramirez-Ortiz via U-Boot
2026-07-29 22:27   ` David Lechner [this message]
2026-07-23 14:38 ` [PATCH v3 3/5] ufs: derive the per-region RPMB CID and size for OP-TEE Jorge Ramirez-Ortiz via U-Boot
2026-07-29 22:40   ` David Lechner
2026-07-23 14:38 ` [PATCH v3 4/5] optee: rename rpmb.c to rpmb_emmc.c Jorge Ramirez-Ortiz via U-Boot
2026-07-23 14:38 ` [PATCH v3 5/5] optee: implement the RPMB subsystem interface for UFS Jorge Ramirez-Ortiz via U-Boot

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=e0895741-aae1-438a-a7c1-cdad0ca6402e@baylibre.com \
    --to=dlechner@baylibre.com \
    --cc=alchark@gmail.com \
    --cc=bhupesh.linux@gmail.com \
    --cc=hayashi.kunihiko@socionext.com \
    --cc=igor.belwon@mentallysanemainliners.org \
    --cc=ilias.apalodimas@linaro.org \
    --cc=j-mcarthur@ti.com \
    --cc=jens.wiklander@linaro.org \
    --cc=jh80.chung@samsung.com \
    --cc=jorge.ramirez@oss.qualcomm.com \
    --cc=jstephan@baylibre.com \
    --cc=macpaul.lin@mediatek.com \
    --cc=marek.vasut+renesas@mailbox.org \
    --cc=n-francis@ti.com \
    --cc=neil.armstrong@linaro.org \
    --cc=padmarao.begari@amd.com \
    --cc=peng.fan@nxp.com \
    --cc=shawn.lin@rock-chips.com \
    --cc=trini@konsulko.com \
    --cc=tuyen.dang.xa@renesas.com \
    --cc=u-boot@lists.denx.de \
    --cc=venkyada@qti.qualcomm.com \
    --cc=yoshihiro.shimoda.uh@renesas.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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.