This is an automated email from the ASF dual-hosted git repository.

xiaoxiang781216 pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/nuttx.git

commit a50305b9cfd0e4f41efca3dfa51a33c369f0568b
Author: Bowen Wang <[email protected]>
AuthorDate: Sat Oct 24 19:53:50 2026 +0800

    drivers/vhost: add vhost-rpmb backend
    
    Add the device side of virtio-rpmb. The driver reads the path of a local
    block device holding the RPMB partition from the device config space
    (struct vhost_rpmb_config_s), opens it, publishes the partition's
    capacity and reliable-write count read from the eMMC EXT_CSD back into
    the virtio config space, and on a dedicated kernel thread forwards each
    request chain as MMC_IOC_MULTI_CMD: request frames are written with
    CMD25 and the response frame is read back with CMD18.
    
    This lets a core without access to the eMMC controller relay RPMB frames
    to the core that owns it.
    
    Signed-off-by: anpeiyun <[email protected]>
---
 drivers/vhost/CMakeLists.txt       |   4 +
 drivers/vhost/Kconfig              |  24 ++
 drivers/vhost/Make.defs            |   4 +
 drivers/vhost/vhost-rpmb.c         | 453 +++++++++++++++++++++++++++++++++++++
 drivers/vhost/vhost-rpmb.h         |  63 ++++++
 drivers/vhost/vhost.c              |   9 +
 include/nuttx/virtio/virtio-rpmb.h |  24 ++
 7 files changed, 581 insertions(+)

diff --git a/drivers/vhost/CMakeLists.txt b/drivers/vhost/CMakeLists.txt
index cbd65288fcb..faad9b1f999 100644
--- a/drivers/vhost/CMakeLists.txt
+++ b/drivers/vhost/CMakeLists.txt
@@ -33,6 +33,10 @@ if(CONFIG_DRIVERS_VHOST_I2C)
   list(APPEND SRCS vhost-i2c.c)
 endif()
 
+if(CONFIG_DRIVERS_VHOST_RPMB)
+  list(APPEND SRCS vhost-rpmb.c)
+endif()
+
 if(CONFIG_DRIVERS_VHOST_RNG)
   list(APPEND SRCS vhost-rng.c)
 endif()
diff --git a/drivers/vhost/Kconfig b/drivers/vhost/Kconfig
index 341cb32bf81..db7a8caa659 100644
--- a/drivers/vhost/Kconfig
+++ b/drivers/vhost/Kconfig
@@ -74,3 +74,27 @@ config DRIVERS_VHOST_CAN
                Enable the vhost CAN backend.  It bridges a VirtIO CAN device
                (device ID 36) to a local SocketCAN interface, forwarding frames
                between the peer's tx/rx/control virtqueues and the local bus.
+
+config DRIVERS_VHOST_RPMB
+       bool "Virtual Host RPMB Device Support"
+       default n
+       select DRIVERS_VHOST
+       ---help---
+               Enable the vhost (device-side) RPMB backend.  It bridges a 
VirtIO
+               RPMB device (device ID 22) to the RPMB partition of a local 
eMMC,
+               forwarding the peer's RPMB frames as MMC_IOC_MULTI_CMD requests.
+               The local block device is named by a path in the device config
+               space, and the capacity and reliable-write count read from its
+               EXT_CSD are published back through the config space.
+
+if DRIVERS_VHOST_RPMB
+
+config DRIVERS_VHOST_RPMB_PRIORITY
+       int "vhost rpmb thread priority"
+       default 224
+
+config DRIVERS_VHOST_RPMB_STACKSIZE
+       int "vhost rpmb stack size"
+       default DEFAULT_TASK_STACKSIZE
+
+endif
diff --git a/drivers/vhost/Make.defs b/drivers/vhost/Make.defs
index 65908111c3c..3f810163021 100644
--- a/drivers/vhost/Make.defs
+++ b/drivers/vhost/Make.defs
@@ -34,6 +34,10 @@ ifeq ($(CONFIG_DRIVERS_VHOST_I2C),y)
   CSRCS += vhost-i2c.c
 endif
 
+ifeq ($(CONFIG_DRIVERS_VHOST_RPMB),y)
+  CSRCS += vhost-rpmb.c
+endif
+
 ifeq ($(CONFIG_DRIVERS_VHOST_RNG),y)
   CSRCS += vhost-rng.c
 endif
diff --git a/drivers/vhost/vhost-rpmb.c b/drivers/vhost/vhost-rpmb.c
new file mode 100644
index 00000000000..76bbfc15602
--- /dev/null
+++ b/drivers/vhost/vhost-rpmb.c
@@ -0,0 +1,453 @@
+/****************************************************************************
+ * drivers/vhost/vhost-rpmb.c
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.  The
+ * ASF licenses this file to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the
+ * License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ****************************************************************************/
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/debug.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <arpa/inet.h>
+
+#include <nuttx/fs/fs.h>
+#include <nuttx/fs/ioctl.h>
+#include <nuttx/kmalloc.h>
+#include <nuttx/kthread.h>
+#include <nuttx/mmcsd.h>
+#include <nuttx/semaphore.h>
+#include <nuttx/vhost/vhost.h>
+#include <nuttx/virtio/virtio-rpmb.h>
+
+#include "vhost-rpmb.h"
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+/* MMC_* command opcodes */
+
+#define VHOST_RPMB_MMC_SEND_EXT_CSD         8
+#define VHOST_RPMB_MMC_READ_MULTIPLE_BLOCK  18
+#define VHOST_RPMB_MMC_WRITE_MULTIPLE_BLOCK 25
+
+/* MMC command flags */
+
+#define VHOST_RPMB_MMC_RSP_PRESENT          (1 << 0)
+#define VHOST_RPMB_MMC_RSP_CRC              (1 << 2)
+#define VHOST_RPMB_MMC_RSP_OPCODE           (1 << 4)
+#define VHOST_RPMB_MMC_CMD_ADTC             (1 << 5)
+#define VHOST_RPMB_MMC_RSP_R1               (VHOST_RPMB_MMC_RSP_PRESENT | \
+                                             VHOST_RPMB_MMC_RSP_CRC | \
+                                             VHOST_RPMB_MMC_RSP_OPCODE)
+
+/* CMD23 reliable write flag */
+
+#define VHOST_RPMB_MMC_CMD23_ARG_REL_WR     (1 << 31)
+
+/* Maximum number of commands in a multi-command request */
+
+#define VHOST_RPMB_MMC_IOC_MAX_CMDS         3
+
+/* RPMB frame size */
+
+#define VHOST_RPMB_FRAME_SIZE               512
+
+/****************************************************************************
+ * Private Types
+ ****************************************************************************/
+
+struct vhost_rpmb_priv_s
+{
+  FAR struct vhost_device *hdev;   /* Virtio device */
+  sem_t                    semrx;  /* Wake up the worker thread */
+  pid_t                    pid;    /* Worker thread PID */
+  struct file              bdev;   /* eMMC RPMB partition */
+  char                     path[VIRTIO_RPMB_PATH_SIZE];
+};
+
+/****************************************************************************
+ * Private Function Prototypes
+ ****************************************************************************/
+
+/* Vhost driver callbacks */
+
+static int  vhost_rpmb_probe(FAR struct vhost_device *hdev);
+static void vhost_rpmb_remove(FAR struct vhost_device *hdev);
+
+/****************************************************************************
+ * Private Data
+ ****************************************************************************/
+
+static struct vhost_driver g_vhost_rpmb_driver =
+{
+  LIST_INITIAL_VALUE(g_vhost_rpmb_driver.node), /* node */
+  VIRTIO_ID_RPMB,                               /* device id */
+  vhost_rpmb_probe,                             /* probe */
+  vhost_rpmb_remove,                            /* remove */
+};
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: vhost_rpmb_set_mmc_io_cmd
+ *
+ * Description:
+ *   Set the per-request fields of one command.
+ *
+ ****************************************************************************/
+
+static void vhost_rpmb_set_mmc_ioc_cmd(FAR struct mmc_ioc_cmd *cmd,
+                                       uint32_t opcode, int write_flag,
+                                       FAR void *data, unsigned int len)
+{
+  cmd->blksz      = VHOST_RPMB_FRAME_SIZE;
+  cmd->blocks     = len / VHOST_RPMB_FRAME_SIZE;
+  cmd->flags      = VHOST_RPMB_MMC_RSP_R1 | VHOST_RPMB_MMC_CMD_ADTC;
+  cmd->opcode     = opcode;
+  cmd->write_flag = write_flag;
+  mmc_ioc_cmd_set_data(*cmd, data);
+}
+
+/****************************************************************************
+ * Name: vhost_rpmb_update_config
+ *
+ * Description:
+ *   Read EXT_CSD from the eMMC and publish capacity/max_wr_cnt in
+ *   the virtio config space, so the TEE can query them without relaying a
+ *   raw eMMC command through the virtqueue.
+ *
+ ****************************************************************************/
+
+static int vhost_rpmb_update_config(FAR struct vhost_device *hdev,
+                                    FAR struct file *bdev)
+{
+  struct virtio_rpmb_config_s cfg;
+  struct mmc_ioc_cmd cmd;
+  uint8_t ext_csd[VHOST_RPMB_FRAME_SIZE];
+  int ret;
+
+  memset(&cmd, 0, sizeof(cmd));
+  memset(ext_csd, 0, sizeof(ext_csd));
+  vhost_rpmb_set_mmc_ioc_cmd(&cmd, VHOST_RPMB_MMC_SEND_EXT_CSD, 0,
+                             ext_csd, sizeof(ext_csd));
+
+  ret = file_ioctl(bdev, MMC_IOC_CMD, (unsigned long)&cmd);
+  if (ret < 0)
+    {
+      vhosterr("MMC_SEND_EXT_CSD failed, ret=%d\n", ret);
+      return ret;
+    }
+
+  cfg.capacity   = ext_csd[VIRTIO_RPMB_EXT_CSD_RPMB_SIZE];
+  cfg.max_wr_cnt = ext_csd[VIRTIO_RPMB_EXT_CSD_REL_WR_SEC_C];
+  cfg.max_rd_cnt = 0;
+
+  vhost_write_config(hdev, 0, &cfg, sizeof(cfg));
+  return OK;
+}
+
+/****************************************************************************
+ * Name: vhost_rpmb_handler
+ *
+ * Description:
+ *   Process a single RPMB request from the virtqueue. Build an
+ *   mmc_ioc_multi_cmd from the descriptor chain buffers and forward it to
+ *   the eMMC RPMB device. The SDHCI driver writes response data directly
+ *   into the in buffers (shared memory).
+ *
+ *   Returns the number of bytes written into the response (in) buffers,
+ *   or a negative errno on failure.
+ *
+ ****************************************************************************/
+
+static ssize_t vhost_rpmb_handler(FAR struct vhost_rpmb_priv_s *priv,
+                                  FAR struct virtqueue_buf *vb,
+                                  size_t vbcnt)
+{
+  uint8_t mcmd_buf[sizeof(struct mmc_ioc_multi_cmd) +
+                   VHOST_RPMB_MMC_IOC_MAX_CMDS * sizeof(struct mmc_ioc_cmd)];
+  FAR struct mmc_ioc_multi_cmd *mcmd;
+  size_t out_cnt;
+  ssize_t ret;
+  size_t i;
+
+  /* vb[] is in descriptor chain order: request frames first, response
+   * frame last. A chain without both is malformed.
+   */
+
+  if (vbcnt < 2 || vbcnt > VHOST_RPMB_MMC_IOC_MAX_CMDS)
+    {
+      vhosterr("Malformed request, vbcnt=%zu\n", vbcnt);
+      return -EINVAL;
+    }
+
+  out_cnt = vbcnt - 1;
+
+  memset(mcmd_buf, 0, sizeof(mcmd_buf));
+  mcmd = (FAR struct mmc_ioc_multi_cmd *)mcmd_buf;
+  mcmd->num_of_cmds = vbcnt;
+
+  /* Each out buffer -> CMD25 (write to eMMC RPMB partition) */
+
+  for (i = 0; i < out_cnt; i++)
+    {
+      FAR struct mmc_ioc_cmd *cmd = &mcmd->cmds[i];
+      FAR struct virtio_rpmb_frame *frm = vb[i].buf;
+      uint16_t msg_type;
+      int rel_wr = 0;
+
+      /* Check if this is a reliable write (DATA_WRITE or PROGRAM_KEY) */
+
+      if (vb[i].len >= sizeof(struct virtio_rpmb_frame))
+        {
+          msg_type = betoh16(frm->req_resp);
+          if (msg_type == VIRTIO_RPMB_REQ_DATA_WRITE ||
+              msg_type == VIRTIO_RPMB_REQ_PROGRAM_KEY)
+            {
+              rel_wr = VHOST_RPMB_MMC_CMD23_ARG_REL_WR;
+            }
+        }
+
+      vhost_rpmb_set_mmc_ioc_cmd(cmd, VHOST_RPMB_MMC_WRITE_MULTIPLE_BLOCK,
+                                 1 | rel_wr, vb[i].buf, vb[i].len);
+    }
+
+  /* Each in buffer -> CMD18 (read from eMMC RPMB partition) */
+
+  for (; i < vbcnt; i++)
+    {
+      FAR struct mmc_ioc_cmd *cmd = &mcmd->cmds[i];
+
+      vhost_rpmb_set_mmc_ioc_cmd(cmd, VHOST_RPMB_MMC_READ_MULTIPLE_BLOCK,
+                                 0, vb[i].buf, vb[i].len);
+    }
+
+  ret = file_ioctl(&priv->bdev, MMC_IOC_MULTI_CMD, (unsigned long)mcmd);
+  if (ret < 0)
+    {
+      vhosterr("MMC_IOC_MULTI_CMD failed, ret=%zd\n", ret);
+      return ret;
+    }
+
+  /* Return the total length of the response (in) buffers written back */
+
+  for (i = out_cnt; i < vbcnt; i++)
+    {
+      ret += vb[i].len;
+    }
+
+  return ret;
+}
+
+/****************************************************************************
+ * Name: vhost_rpmb_work
+ ****************************************************************************/
+
+static void vhost_rpmb_work(FAR struct vhost_rpmb_priv_s *priv)
+{
+  FAR struct virtqueue *vq;
+  struct virtqueue_buf vb[VHOST_RPMB_MMC_IOC_MAX_CMDS];
+  size_t vbcnt;
+  ssize_t ret;
+  int head;
+
+  vq = priv->hdev->vrings_info[0].vq;
+  for (; ; )
+    {
+      head = vhost_get_vq_buffers(vq, vb, VHOST_RPMB_MMC_IOC_MAX_CMDS,
+                                  &vbcnt);
+      if (head < 0)
+        {
+          break;
+        }
+
+      ret = vhost_rpmb_handler(priv, vb, vbcnt);
+      if (ret < 0)
+        {
+          vhosterr("handler failed, ret=%zd\n", ret);
+          ret = VHOST_RPMB_FRAME_SIZE;
+        }
+
+      virtqueue_add_consumed_buffer(vq, head, ret);
+    }
+
+  virtqueue_kick(vq);
+}
+
+/****************************************************************************
+ * Name: vhost_rpmb_thread
+ ****************************************************************************/
+
+static int vhost_rpmb_thread(int argc, FAR char *argv[])
+{
+  FAR struct vhost_rpmb_priv_s *priv =
+    (FAR struct vhost_rpmb_priv_s *)((uintptr_t)strtoul(argv[1], NULL, 16));
+
+  for (; ; )
+    {
+      nxsem_wait_uninterruptible(&priv->semrx);
+      vhost_rpmb_work(priv);
+    }
+
+  return 0;
+}
+
+/****************************************************************************
+ * Name: vhost_rpmb_callback
+ ****************************************************************************/
+
+static void vhost_rpmb_callback(FAR struct virtqueue *vq)
+{
+  FAR struct vhost_rpmb_priv_s *priv = vq->vq_dev->priv;
+  int semcount;
+
+  nxsem_get_value(&priv->semrx, &semcount);
+  while (semcount++ < 1)
+    {
+      nxsem_post(&priv->semrx);
+    }
+}
+
+/****************************************************************************
+ * Name: vhost_rpmb_probe
+ ****************************************************************************/
+
+static int vhost_rpmb_probe(FAR struct vhost_device *hdev)
+{
+  FAR struct vhost_rpmb_priv_s *priv;
+  FAR const char *vqname[1];
+  vq_callback callback[1];
+  FAR char *argv[2];
+  char arg0[32];
+  int ret;
+
+  /* Alloc the vhost rpmb driver private data */
+
+  priv = kmm_zalloc(sizeof(*priv));
+  if (priv == NULL)
+    {
+      vhosterr("No enough memory\n");
+      return -ENOMEM;
+    }
+
+  /* Init the vhost rpmb driver */
+
+  priv->hdev = hdev;
+  hdev->priv = priv;
+  nxsem_init(&priv->semrx, 0, 0);
+
+  /* Read the device path from virtio config space */
+
+  vhost_read_config_member(hdev, struct vhost_rpmb_config_s,
+                           path, &priv->path);
+  ret = file_open(&priv->bdev, priv->path, O_RDWR | O_CLOEXEC);
+  if (ret < 0)
+    {
+      vhosterr("ERROR: Failed to open %s, ret=%d\n", priv->path, ret);
+      goto err_init;
+    }
+
+  /* Read EXT_CSD and update virtio config space with accurate values */
+
+  ret = vhost_rpmb_update_config(hdev, &priv->bdev);
+  if (ret < 0)
+    {
+      vhosterr("ERROR: Failed to update RPMB config, ret=%d\n", ret);
+      goto err_bdev;
+    }
+
+  /* Create the virtqueue */
+
+  vqname[0]   = "vhost_rpmb";
+  callback[0] = vhost_rpmb_callback;
+  ret = vhost_create_virtqueues(hdev, 0, 1, vqname, callback, NULL);
+  if (ret < 0)
+    {
+      vhosterr("vhost_create_virtqueues failed, ret=%d\n", ret);
+      goto err_vq;
+    }
+
+  /* Start the worker thread */
+
+  snprintf(arg0, sizeof(arg0), "%p", priv);
+  argv[0] = arg0;
+  argv[1] = NULL;
+
+  priv->pid = kthread_create("vhost-rpmb",
+                             CONFIG_DRIVERS_VHOST_RPMB_PRIORITY,
+                             CONFIG_DRIVERS_VHOST_RPMB_STACKSIZE,
+                             vhost_rpmb_thread, argv);
+  if (priv->pid < 0)
+    {
+      vhosterr("vhost rpmb thread create failed %d\n", priv->pid);
+      ret = priv->pid;
+      goto err_thread;
+    }
+
+  virtqueue_enable_cb(hdev->vrings_info[0].vq);
+  return OK;
+
+err_thread:
+  vhost_delete_virtqueues(hdev);
+err_vq:
+err_bdev:
+  file_close(&priv->bdev);
+  nxsem_destroy(&priv->semrx);
+err_init:
+  kmm_free(priv);
+  return ret;
+}
+
+/****************************************************************************
+ * Name: vhost_rpmb_remove
+ ****************************************************************************/
+
+static void vhost_rpmb_remove(FAR struct vhost_device *hdev)
+{
+  FAR struct vhost_rpmb_priv_s *priv = hdev->priv;
+
+  virtqueue_disable_cb(hdev->vrings_info[0].vq);
+  kthread_delete(priv->pid);
+  vhost_delete_virtqueues(hdev);
+  file_close(&priv->bdev);
+  nxsem_destroy(&priv->semrx);
+  kmm_free(priv);
+}
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: vhost_register_rpmb_driver
+ ****************************************************************************/
+
+int vhost_register_rpmb_driver(void)
+{
+  return vhost_register_driver(&g_vhost_rpmb_driver);
+}
diff --git a/drivers/vhost/vhost-rpmb.h b/drivers/vhost/vhost-rpmb.h
new file mode 100644
index 00000000000..8b99487e217
--- /dev/null
+++ b/drivers/vhost/vhost-rpmb.h
@@ -0,0 +1,63 @@
+/****************************************************************************
+ * drivers/vhost/vhost-rpmb.h
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.  The
+ * ASF licenses this file to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the
+ * License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ****************************************************************************/
+
+#ifndef __DRIVERS_VHOST_VHOST_RPMB_H
+#define __DRIVERS_VHOST_VHOST_RPMB_H
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+
+#ifdef CONFIG_DRIVERS_VHOST_RPMB
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Public Data
+ ****************************************************************************/
+
+#ifdef __cplusplus
+#define EXTERN extern "C"
+extern "C"
+{
+#else
+#define EXTERN extern
+#endif
+
+/****************************************************************************
+ * Public Function Prototypes
+ ****************************************************************************/
+
+int vhost_register_rpmb_driver(void);
+
+#undef EXTERN
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* CONFIG_DRIVERS_VHOST_RPMB */
+
+#endif /* __DRIVERS_VHOST_VHOST_RPMB_H */
diff --git a/drivers/vhost/vhost.c b/drivers/vhost/vhost.c
index 0c177ff1df3..1441707910b 100644
--- a/drivers/vhost/vhost.c
+++ b/drivers/vhost/vhost.c
@@ -38,6 +38,7 @@
 #include "vhost-can.h"
 #include "vhost-i2c.h"
 #include "vhost-rng.h"
+#include "vhost-rpmb.h"
 #include "vhost-rpmsg.h"
 
 /****************************************************************************
@@ -537,6 +538,14 @@ void vhost_register_drivers(void)
     }
 #endif
 
+#ifdef CONFIG_DRIVERS_VHOST_RPMB
+  ret = vhost_register_rpmb_driver();
+  if (ret < 0)
+    {
+      vhosterr("vhost_register_rpmb_driver failed, ret=%d\n", ret);
+    }
+#endif
+
 #ifdef CONFIG_DRIVERS_VHOST_RNG
   ret = vhost_register_rng_driver();
   if (ret < 0)
diff --git a/include/nuttx/virtio/virtio-rpmb.h 
b/include/nuttx/virtio/virtio-rpmb.h
index 4b2f416a1dc..19f63b39810 100644
--- a/include/nuttx/virtio/virtio-rpmb.h
+++ b/include/nuttx/virtio/virtio-rpmb.h
@@ -75,6 +75,18 @@
 #define VIRTIO_RPMB_RES_NO_AUTH_KEY           0x0007
 #define VIRTIO_RPMB_RES_WRITE_COUNTER_EXPIRED 0x0080
 
+/* Max length of the local RPMB block device path in the device config
+ * space (a device-side private extension; the spec defines none).
+ */
+
+#define VIRTIO_RPMB_PATH_SIZE                 32
+
+/* RPMB EXT_CSD (eMMC standard command 8) layout */
+
+#define VIRTIO_RPMB_EXT_CSD_SIZE              512
+#define VIRTIO_RPMB_EXT_CSD_RPMB_SIZE         168
+#define VIRTIO_RPMB_EXT_CSD_REL_WR_SEC_C      222
+
 /****************************************************************************
  * Public Types
  ****************************************************************************/
@@ -88,6 +100,18 @@ begin_packed_struct struct virtio_rpmb_config_s
   uint8_t max_rd_cnt;
 } end_packed_struct;
 
+/* Device-side private config space: extends virtio_rpmb_config_s with the
+ * path of the local block device holding the RPMB partition.  The device
+ * side publishes capacity/max_wr_cnt back through virtio_rpmb_config_s
+ * after reading them from the eMMC EXT_CSD.
+ */
+
+begin_packed_struct struct vhost_rpmb_config_s
+{
+  struct virtio_rpmb_config_s config;
+  char                        path[VIRTIO_RPMB_PATH_SIZE];
+} end_packed_struct;
+
 /* RPMB frame (virtio spec 5.12.6.1, 512 bytes) */
 
 begin_packed_struct struct virtio_rpmb_frame

Reply via email to