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

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


The following commit(s) were added to refs/heads/master by this push:
     new 0e7e7c4ee6 rpmb: add virtio rpmb support
0e7e7c4ee6 is described below

commit 0e7e7c4ee6512f527d281ec42d7098da73eee9f5
Author: wanggang26 <[email protected]>
AuthorDate: Wed Aug 30 10:20:22 2023 +0800

    rpmb: add virtio rpmb support
    
    The RPMB partition cannot be accessed via standard block layer, but by a 
set of specific commands: WRITE, READ, GET_WRITE_COUNTER, and PROGRAM_KEY. Such 
a partition provides authenticated and replay protected access, hence suitable 
as a secure storage.
    
    Signed-off-by: wanggang26 <[email protected]>
---
 drivers/virtio/Kconfig       |   4 +
 drivers/virtio/Make.defs     |   5 +
 drivers/virtio/virtio-rpmb.c | 276 +++++++++++++++++++++++++++++++++++++++++++
 drivers/virtio/virtio-rpmb.h | 130 ++++++++++++++++++++
 drivers/virtio/virtio.c      |   9 ++
 5 files changed, 424 insertions(+)

diff --git a/drivers/virtio/Kconfig b/drivers/virtio/Kconfig
index 36fed53416..b70060a6eb 100644
--- a/drivers/virtio/Kconfig
+++ b/drivers/virtio/Kconfig
@@ -59,6 +59,10 @@ config DRIVERS_VIRTIO_RNG
        default n
        select ARCH_HAVE_RNG
 
+config DRIVERS_VIRTIO_RPMB
+       bool "Virtio RPMB support"
+       default n
+
 config DRIVERS_VIRTIO_SERIAL
        bool "Virtio serial support"
        depends on SERIAL
diff --git a/drivers/virtio/Make.defs b/drivers/virtio/Make.defs
index fc7bd8f4a7..d1444e1099 100644
--- a/drivers/virtio/Make.defs
+++ b/drivers/virtio/Make.defs
@@ -48,6 +48,10 @@ ifeq ($(CONFIG_DRIVERS_VIRTIO_RNG),y)
   CSRCS += virtio-rng.c
 endif
 
+ifeq ($(CONFIG_DRIVERS_VIRTIO_RPMB),y)
+  CSRCS += virtio-rpmb.c
+endif
+
 ifeq ($(CONFIG_DRIVERS_VIRTIO_SERIAL),y)
   CSRCS += virtio-serial.c
 endif
@@ -55,6 +59,7 @@ endif
 ifeq ($(CONFIG_DRIVERS_VIRTIO_SOUND),y)
   CSRCS += virtio-snd.c
 endif
+
 # Include build support
 
 DEPPATH += --dep-path virtio
diff --git a/drivers/virtio/virtio-rpmb.c b/drivers/virtio/virtio-rpmb.c
new file mode 100644
index 0000000000..d944875d02
--- /dev/null
+++ b/drivers/virtio/virtio-rpmb.c
@@ -0,0 +1,276 @@
+/****************************************************************************
+ * drivers/virtio/virtio-rpmb.c
+ *
+ * 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 <debug.h>
+#include <errno.h>
+#include <stdio.h>
+
+#include <nuttx/fs/fs.h>
+#include <nuttx/fs/ioctl.h>
+#include <nuttx/semaphore.h>
+#include <nuttx/mmcsd.h>
+#include <nuttx/virtio/virtio.h>
+
+#include "virtio-rpmb.h"
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+#define VIRTIO_RPMB_DEVNAME "/dev/rpmb"
+
+/****************************************************************************
+ * Private Types
+ ****************************************************************************/
+
+struct virtio_rpmb_priv_s
+{
+  /* The virtio device we're associated with */
+
+  FAR struct virtio_device *vdev;
+};
+
+struct virtio_rpmb_cookie_s
+{
+  sem_t  sem;
+  size_t len;
+};
+
+/****************************************************************************
+ * Private Function Prototypes
+ ****************************************************************************/
+
+static int virtio_rpmb_probe(FAR struct virtio_device *vdev);
+static void virtio_rpmb_remove(FAR struct virtio_device *vdev);
+static int virtio_rpmb_ioctl(FAR struct file *, int, unsigned long);
+
+/****************************************************************************
+ * Private Data
+ ****************************************************************************/
+
+static struct virtio_driver g_virtio_rpmb_driver =
+{
+  LIST_INITIAL_VALUE(g_virtio_rpmb_driver.node), /* node */
+  VIRTIO_ID_RPMB,                                /* device id */
+  virtio_rpmb_probe,                             /* probe */
+  virtio_rpmb_remove,                            /* remove */
+};
+
+static const struct file_operations g_virtio_rpmb_ops =
+{
+  NULL,               /* open */
+  NULL,               /* close */
+  NULL,               /* read */
+  NULL,               /* write */
+  NULL,               /* seek */
+  virtio_rpmb_ioctl,  /* ioctl */
+  NULL,               /* mmap */
+  NULL,               /* truncate */
+  NULL,               /* poll */
+#ifndef CONFIG_DISABLE_PSEUDOFS_OPERATIONS
+  NULL,               /* unlink */
+#endif
+};
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+/* virtio_rpmb_done() - virtual queue completion callback */
+
+static void virtio_rpmb_done(FAR struct virtqueue *vq)
+{
+  FAR struct virtio_rpmb_cookie_s *cookie;
+  uint32_t len;
+
+  cookie = virtqueue_get_buffer(vq, &len, NULL);
+  if (cookie != NULL)
+    {
+      /* Assign the return length */
+
+      cookie->len = len;
+
+      /* Read completed, post the sem */
+
+      nxsem_post(&cookie->sem);
+    }
+}
+
+/* This is just a simple helper for processing the virtqueue buf. It will
+ * block until the resp arrives. Returns number of bytes written back
+ * or negative if it failed.
+ */
+
+static int virtio_rpmb_transact(FAR struct virtio_rpmb_priv_s *priv,
+                                FAR struct virtqueue_buf *vb,
+                                int out, int in)
+{
+  FAR struct virtqueue *vq = priv->vdev->vrings_info[0].vq;
+  struct virtio_rpmb_cookie_s cookie;
+  int ret;
+
+  /* Init the cookie */
+
+  cookie.len = 0;
+  nxsem_init(&cookie.sem, 0, 0);
+
+  /* Add the input buffer to the virtqueue, and the cookie as the virtqueue
+   * cookie. (virtqueue_get_buffer() will return cookie).
+   */
+
+  ret = virtqueue_add_buffer(vq, vb, out, in, &cookie);
+  if (ret < 0)
+    {
+      return ret;
+    }
+
+  /* Notify the other side to process the added virtqueue buffer */
+
+  virtqueue_kick(vq);
+
+  /* Wait fot completion */
+
+  nxsem_wait_uninterruptible(&cookie.sem);
+  return cookie.len;
+}
+
+/****************************************************************************
+ * Name: virtio_blk_ioctl
+ ****************************************************************************/
+
+static int virtio_rpmb_ioctl(FAR struct file *filep, int cmd,
+                             unsigned long arg)
+{
+  FAR struct virtio_rpmb_priv_s *priv;
+  FAR struct mmc_ioc_multi_cmd *mioc = (FAR struct mmc_ioc_multi_cmd *)arg;
+  struct virtqueue_buf vb[mioc->num_of_cmds];
+  int ret;
+  int i;
+
+  priv = (FAR struct virtio_rpmb_priv_s *)filep->f_inode->i_private;
+
+  for (i = 0; i < mioc->num_of_cmds; i++)
+    {
+      vb[i].buf = (FAR void *)mioc->cmds[i].data_ptr;
+      vb[i].len = mioc->cmds[i].blocks * mioc->cmds[i].blksz;
+    }
+
+  ret = virtio_rpmb_transact(priv, vb, mioc->num_of_cmds - 1, 1);
+  return ret < 0 ? ret : 0;
+}
+
+static int virtio_rpmb_init(FAR struct virtio_rpmb_priv_s *priv,
+                            FAR struct virtio_device *vdev)
+{
+  FAR const char *vqname[1];
+  vq_callback callback[1];
+  int ret;
+
+  priv->vdev = vdev;
+  vdev->priv = priv;
+
+  /* Initialize the virtio device */
+
+  virtio_set_status(vdev, VIRTIO_CONFIG_STATUS_DRIVER);
+  virtio_set_features(vdev, 0);
+  virtio_set_status(vdev, VIRTIO_CONFIG_FEATURES_OK);
+
+  vqname[0]   = "virtio_rpmb_vq";
+  callback[0] = virtio_rpmb_done;
+  ret = virtio_create_virtqueues(vdev, 0, 1, vqname, callback);
+  if (ret < 0)
+    {
+      vrterr("virtio_device_create_virtqueue failed, ret=%d\n", ret);
+      goto err_with_lock;
+    }
+
+  virtio_set_status(vdev, VIRTIO_CONFIG_STATUS_DRIVER_OK);
+  virtqueue_enable_cb(vdev->vrings_info[0].vq);
+  return OK;
+
+err_with_lock:
+  return ret;
+}
+
+static void virtio_rpmb_uninit(FAR struct virtio_rpmb_priv_s *priv)
+{
+  FAR struct virtio_device *vdev = priv->vdev;
+
+  virtio_reset_device(vdev);
+  virtio_delete_virtqueues(vdev);
+}
+
+static int virtio_rpmb_probe(FAR struct virtio_device *vdev)
+{
+  FAR struct virtio_rpmb_priv_s *priv;
+  int ret;
+
+  /* Alloc the virtio block driver private data */
+
+  priv = kmm_zalloc(sizeof(*priv));
+  if (priv == NULL)
+    {
+      vrterr("No enough memory\n");
+      return -ENOMEM;
+    }
+
+  /* Init the virtio block driver */
+
+  ret = virtio_rpmb_init(priv, vdev);
+  if (ret < 0)
+    {
+      vrterr("virtio_rpmb_init failed, ret=%d\n", ret);
+      goto err_with_priv;
+    }
+
+  ret = register_driver(VIRTIO_RPMB_DEVNAME, &g_virtio_rpmb_ops, 0666,
+                        priv);
+  if (ret < 0)
+    {
+      vrterr("Register NuttX driver failed, ret=%d\n", ret);
+      goto err_with_init;
+    }
+
+  return ret;
+
+err_with_init:
+  virtio_rpmb_uninit(priv);
+err_with_priv:
+  kmm_free(priv);
+  return ret;
+}
+
+static void virtio_rpmb_remove(FAR struct virtio_device *vdev)
+{
+  FAR struct virtio_rpmb_priv_s *priv = vdev->priv;
+
+  unregister_driver(VIRTIO_RPMB_DEVNAME);
+  virtio_rpmb_uninit(priv);
+  kmm_free(priv);
+}
+
+int virtio_register_rpmb_driver(void)
+{
+  return virtio_register_driver(&g_virtio_rpmb_driver);
+}
diff --git a/drivers/virtio/virtio-rpmb.h b/drivers/virtio/virtio-rpmb.h
new file mode 100644
index 0000000000..4cc14f920d
--- /dev/null
+++ b/drivers/virtio/virtio-rpmb.h
@@ -0,0 +1,130 @@
+/****************************************************************************
+ * drivers/virtio/virtio-rpmb.h
+ *
+ * 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_VIRTIO_VIRTIO_RPMB_H
+#define __DRIVERS_VIRTIO_VIRTIO_RPMB_H
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+#include <stdint.h>
+
+#ifdef CONFIG_DRIVERS_VIRTIO_RPMB
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Public Data
+ ****************************************************************************/
+
+#ifdef __cplusplus
+#define EXTERN extern "C"
+extern "C"
+{
+#else
+#define EXTERN extern
+#endif
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+/* RPMB Request Types */
+
+#define VIRTIO_RPMB_REQ_PROGRAM_KEY       0x0001
+#define VIRTIO_RPMB_REQ_GET_WRITE_COUNTER 0x0002
+#define VIRTIO_RPMB_REQ_DATA_WRITE        0x0003
+#define VIRTIO_RPMB_REQ_DATA_READ         0x0004
+#define VIRTIO_RPMB_REQ_RESULT_READ       0x0005
+
+/* RPMB Response Types */
+
+#define VIRTIO_RPMB_RESP_PROGRAM_KEY      0x0100
+#define VIRTIO_RPMB_RESP_GET_COUNTER      0x0200
+#define VIRTIO_RPMB_RESP_DATA_WRITE       0x0300
+#define VIRTIO_RPMB_RESP_DATA_READ        0x0400
+
+/* RPMB Operation Results
+ * VIRTIO_RPMB_RES_OK              : Operation successful
+ * VIRTIO_RPMB_RES_GENERAL_FAILURE : General failure
+ * VIRTIO_RPMB_RES_AUTH_FAILURE    : Mac doesn't match or calculation
+ * failure
+ * VIRTIO_RPMB_RES_COUNT_FAILURE   : Counter doesn't match or counter
+ * increment failure
+ * VIRTIO_RPMB_RES_ADDR_FAILURE    : Address out of range or wrong
+ * address alignment
+ * VIRTIO_RPMB_RES_WRITE_FAILURE   : Data, counter, or result write failure
+ * VIRTIO_RPMB_RES_READ_FAILURE    : Data, counter, or result read failure
+ * VIRTIO_RPMB_RES_NO_AUTH_KEY     : Authentication key not yet programmed
+ * VIRTIO_RPMB_RES_WRITE_COUNTER_EXPIRED:  Counter expired
+ */
+
+#define VIRTIO_RPMB_RES_OK                    0x0000
+#define VIRTIO_RPMB_RES_GENERAL_FAILURE       0x0001
+#define VIRTIO_RPMB_RES_AUTH_FAILURE          0x0002
+#define VIRTIO_RPMB_RES_COUNT_FAILURE         0x0003
+#define VIRTIO_RPMB_RES_ADDR_FAILURE          0x0004
+#define VIRTIO_RPMB_RES_WRITE_FAILURE         0x0005
+#define VIRTIO_RPMB_RES_READ_FAILURE          0x0006
+#define VIRTIO_RPMB_RES_NO_AUTH_KEY           0x0007
+#define VIRTIO_RPMB_RES_WRITE_COUNTER_EXPIRED 0x0080
+
+/****************************************************************************
+ * Public Types
+ ****************************************************************************/
+
+struct virtio_rpmb_config_s
+{
+  uint8_t capacity;
+  uint8_t max_wr_cnt;
+  uint8_t max_rd_cnt;
+};
+
+struct virtio_rpmb_frame
+{
+  uint8_t  stuff[196];
+  uint8_t  key_mac[32];
+  uint8_t  data[256];
+  uint8_t  nonce[16];
+  uint32_t write_counter;
+  uint16_t addr;
+  uint16_t block_count;
+  uint16_t result;
+  uint16_t req_resp;
+};
+
+/****************************************************************************
+ * Public Function Prototypes
+ ****************************************************************************/
+
+int virtio_register_rpmb_driver(void);
+
+#undef EXTERN
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* CONFIG_DRIVERS_VIRTIO_RPMB */
+
+#endif /* __DRIVERS_VIRTIO_VIRTIO_RPMB_H */
diff --git a/drivers/virtio/virtio.c b/drivers/virtio/virtio.c
index 85b218d077..e01a776880 100644
--- a/drivers/virtio/virtio.c
+++ b/drivers/virtio/virtio.c
@@ -33,6 +33,7 @@
 #include "virtio-input.h"
 #include "virtio-net.h"
 #include "virtio-rng.h"
+#include "virtio-rpmb.h"
 #include "virtio-serial.h"
 #include "virtio-snd.h"
 
@@ -176,6 +177,14 @@ void virtio_register_drivers(void)
     }
 #endif
 
+#ifdef CONFIG_DRIVERS_VIRTIO_RPMB
+  ret = virtio_register_rpmb_driver();
+  if (ret < 0)
+    {
+      vrterr("virtio_register_rpmb_driver failed, ret=%d\n", ret);
+    }
+#endif
+
   UNUSED(ret);
 }
 

Reply via email to