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);
}