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 9902f39d92 Add MTD loop driver (use filemtd)
9902f39d92 is described below

commit 9902f39d92e9dbd2ab214bf67f048eb826003fff
Author: Oreh <a.oryshche...@gmail.com>
AuthorDate: Mon Feb 6 16:05:12 2023 +0100

    Add MTD loop driver (use filemtd)
---
 drivers/drivers_initialize.c |   5 +
 drivers/mtd/Kconfig          |   4 +
 drivers/mtd/filemtd.c        | 214 +++++++++++++++++++++++++++++++++++++++++++
 include/nuttx/fs/loopmtd.h   | 107 ++++++++++++++++++++++
 4 files changed, 330 insertions(+)

diff --git a/drivers/drivers_initialize.c b/drivers/drivers_initialize.c
index 9798b2cad2..1fbadea9c3 100644
--- a/drivers/drivers_initialize.c
+++ b/drivers/drivers_initialize.c
@@ -29,6 +29,7 @@
 #include <nuttx/drivers/rpmsgblk.h>
 #include <nuttx/fs/loop.h>
 #include <nuttx/fs/smart.h>
+#include <nuttx/fs/loopmtd.h>
 #include <nuttx/input/uinput.h>
 #include <nuttx/mtd/mtd.h>
 #include <nuttx/net/loopback.h>
@@ -189,4 +190,8 @@ void drivers_initialize(void)
 #ifdef CONFIG_SMART_DEV_LOOP
   smart_loop_register_driver();
 #endif
+
+#ifdef CONFIG_MTD_LOOP
+  mtd_loop_register();
+#endif
 }
diff --git a/drivers/mtd/Kconfig b/drivers/mtd/Kconfig
index dcabd571e3..2015ac9ea3 100644
--- a/drivers/mtd/Kconfig
+++ b/drivers/mtd/Kconfig
@@ -331,6 +331,10 @@ config FILEMTD_ERASESTATE
        hex "Simulated erase state"
        default 0xff
 
+config MTD_LOOP
+       bool "Enable MTD loop device"
+       default n
+
 endif # FILEMTD
 
 config NULLMTD
diff --git a/drivers/mtd/filemtd.c b/drivers/mtd/filemtd.c
index e989ae3d1d..1048461d37 100644
--- a/drivers/mtd/filemtd.c
+++ b/drivers/mtd/filemtd.c
@@ -27,6 +27,7 @@
 #include <sys/param.h>
 #include <sys/types.h>
 #include <sys/stat.h>
+#include <sys/mount.h>
 #include <stdint.h>
 #include <fcntl.h>
 #include <string.h>
@@ -37,6 +38,7 @@
 #include <nuttx/kmalloc.h>
 #include <nuttx/fs/fs.h>
 #include <nuttx/fs/ioctl.h>
+#include <nuttx/fs/loopmtd.h>
 #include <nuttx/mtd/mtd.h>
 
 /****************************************************************************
@@ -118,6 +120,31 @@ static ssize_t file_bytewrite(FAR struct mtd_dev_s *dev, 
off_t offset,
 static int     filemtd_ioctl(FAR struct mtd_dev_s *dev, int cmd,
                  unsigned long arg);
 
+#ifdef CONFIG_MTD_LOOP
+static ssize_t mtd_loop_read(FAR struct file *filep, FAR char *buffer,
+                 size_t buflen);
+static ssize_t mtd_loop_write(FAR struct file *filep,
+                 FAR const char *buffer, size_t buflen);
+static int     mtd_loop_ioctl(FAR struct file *filep, int cmd,
+                 unsigned long arg);
+#endif /* CONFIG_MTD_LOOP */
+
+/****************************************************************************
+ * Private Data
+ ****************************************************************************/
+
+#ifdef CONFIG_MTD_LOOP
+static const struct file_operations g_fops =
+{
+  NULL,                 /* open */
+  NULL,                 /* close */
+  mtd_loop_read,        /* read */
+  mtd_loop_write,       /* write */
+  NULL,                 /* seek */
+  mtd_loop_ioctl,       /* ioctl */
+};
+#endif /* CONFIG_MTD_LOOP */
+
 /****************************************************************************
  * Private Functions
  ****************************************************************************/
@@ -495,6 +522,179 @@ static int filemtd_ioctl(FAR struct mtd_dev_s *dev, int 
cmd,
   return ret;
 }
 
+/****************************************************************************
+ * Name: mtd_loop_setup
+ *
+ * Description: Dynamically setups up a FILEMTD enabled loop device that
+ *              is backed by a file.  The resulting loop device is a
+ *              MTD type block device vs. a generic block device.
+ *
+ ****************************************************************************/
+
+#ifdef CONFIG_MTD_LOOP
+static int mtd_loop_setup(FAR const char *devname, FAR const char *filename,
+                          int sectsize, int erasesize, off_t offset)
+{
+  FAR struct mtd_dev_s *mtd;
+  int ret;
+
+  mtd = filemtd_initialize(filename, offset, sectsize, erasesize);
+  if (mtd == NULL)
+    {
+      return -ENOENT;
+    }
+
+  ret = register_mtddriver(devname, mtd, 0755, NULL);
+  if (ret != OK)
+    {
+      filemtd_teardown(mtd);
+    }
+
+  return ret;
+}
+#endif /* CONFIG_MTD_LOOP */
+
+/****************************************************************************
+ * Name: mtd_loop_teardown
+ *
+ * Description:
+ *   Undo the setup performed by loopmtd_setup
+ *
+ ****************************************************************************/
+
+#ifdef CONFIG_MTD_LOOP
+static int mtd_loop_teardown(FAR const char *devname)
+{
+  FAR struct file_dev_s *dev;
+  FAR struct inode *inode;
+  int ret;
+
+  /* Open the block driver associated with devname so that we can get the
+   * inode reference.
+   */
+
+  ret = open_blockdriver(devname, MS_RDONLY, &inode);
+  if (ret < 0)
+    {
+      ferr("ERROR: Failed to open %s: %d\n", devname, -ret);
+      return ret;
+    }
+
+  /* Inode private data is a reference to the loop device structure */
+
+  dev = (FAR struct file_dev_s *)inode->u.i_mtd;
+
+  /* Validate this is a filemtd backended device */
+
+  if (!filemtd_isfilemtd(&dev->mtd))
+    {
+      ferr("ERROR: Device is not a FILEMTD loop: %s\n", devname);
+      return -EINVAL;
+    }
+
+  close_blockdriver(inode);
+
+  /* Now teardown the filemtd */
+
+  filemtd_teardown(&dev->mtd);
+  unregister_blockdriver(devname);
+  kmm_free(dev);
+
+  return OK;
+}
+#endif /* CONFIG_MTD_LOOP */
+
+/****************************************************************************
+ * Name: mtd_loop_read
+ ****************************************************************************/
+
+#ifdef CONFIG_MTD_LOOP
+static ssize_t mtd_loop_read(FAR struct file *filep, FAR char *buffer,
+                               size_t len)
+{
+  return 0; /* Return EOF */
+}
+#endif /* CONFIG_MTD_LOOP */
+
+/****************************************************************************
+ * Name: mtd_loop_write
+ ****************************************************************************/
+
+#ifdef CONFIG_MTD_LOOP
+static ssize_t mtd_loop_write(FAR struct file *filep,
+                                FAR const char *buffer, size_t len)
+{
+  return len; /* Say that everything was written */
+}
+#endif /* CONFIG_MTD_LOOP */
+
+/****************************************************************************
+ * Name: mtd_loop_ioctl
+ ****************************************************************************/
+
+#ifdef CONFIG_MTD_LOOP
+static int mtd_loop_ioctl(FAR struct file *filep, int cmd,
+                          unsigned long arg)
+{
+  int ret;
+
+  switch (cmd)
+    {
+    /* Command:      LOOPIOC_SETUP
+     * Description:  Setup the loop device
+     * Argument:     A pointer to a read-only instance of struct losetup_s.
+     * Dependencies: The loop device must be enabled (CONFIG_MTD_LOOP=y)
+     */
+
+    case MTD_LOOPIOC_SETUP:
+      {
+        FAR struct mtd_losetup_s *setup =
+          (FAR struct mtd_losetup_s *)((uintptr_t)arg);
+
+        if (setup == NULL)
+          {
+            ret = -EINVAL;
+          }
+        else
+          {
+            ret = mtd_loop_setup(setup->devname, setup->filename,
+                                setup->sectsize, setup->erasesize,
+                                setup->offset);
+          }
+      }
+      break;
+
+    /* Command:      LOOPIOC_TEARDOWN
+     * Description:  Teardown a loop device previously setup via
+     *               LOOPIOC_SETUP
+     * Argument:     A read-able pointer to the path of the device to be
+     *               torn down
+     * Dependencies: The loop device must be enabled (CONFIG_MTD_LOOP=y)
+     */
+
+    case MTD_LOOPIOC_TEARDOWN:
+      {
+        FAR const char *devname = (FAR const char *)((uintptr_t)arg);
+
+        if (devname == NULL)
+          {
+            ret = -EINVAL;
+          }
+        else
+          {
+            ret = mtd_loop_teardown(devname);
+          }
+       }
+       break;
+
+     default:
+       ret = -ENOTTY;
+    }
+
+  return ret;
+}
+#endif /* CONFIG_MTD_LOOP */
+
 /****************************************************************************
  * Public Functions
  ****************************************************************************/
@@ -708,3 +908,17 @@ bool filemtd_isfilemtd(FAR struct mtd_dev_s *dev)
 
   return (priv->mtd.erase == filemtd_erase);
 }
+
+/****************************************************************************
+ * Name: mtd_loop_register_driver
+ *
+ * Description:
+ *   Registers MTD Loop Driver
+ ****************************************************************************/
+
+#ifdef CONFIG_MTD_LOOP
+int mtd_loop_register(void)
+{
+  return register_driver("/dev/loopmtd", &g_fops, 0666, NULL);
+}
+#endif
diff --git a/include/nuttx/fs/loopmtd.h b/include/nuttx/fs/loopmtd.h
new file mode 100644
index 0000000000..eadc41365d
--- /dev/null
+++ b/include/nuttx/fs/loopmtd.h
@@ -0,0 +1,107 @@
+/****************************************************************************
+ * include/nuttx/fs/loopmtd.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 __INCLUDE_NUTTX_FS_LOOPMTD_H
+#define __INCLUDE_NUTTX_FS_LOOPMTD_H
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+
+#include <sys/types.h>
+#include <sys/ioctl.h>
+#include <stdint.h>
+#include <stdbool.h>
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+#ifdef CONFIG_MTD_LOOP
+/* Loop device IOCTL commands */
+
+/* Command:      MTD_LOOPIOC_SETUP
+ * Description:  Setup the loop device
+ * Argument:     A pointer to a read-only instance of struct losetup_s.
+ * Dependencies: The loop device must be enabled (CONFIG_MTD_LOOP=y)
+ */
+
+/* Command:      MTD_LOOPIOC_TEARDOWN
+ * Description:  Teardown a loop device previously setup vis LOOPIOC_SETUP
+ * Argument:     A read-able pointer to the path of the device to be
+ *               torn down
+ * Dependencies: The loop device must be enabled (CONFIG_MTD_LOOP=y)
+ */
+
+#define MTD_LOOPIOC_SETUP     _LOOPIOC(0x0001)
+#define MTD_LOOPIOC_TEARDOWN  _LOOPIOC(0x0002)
+
+#endif
+
+/****************************************************************************
+ * Public Types
+ ****************************************************************************/
+
+#ifdef CONFIG_MTD_LOOP
+/* This is the structure referred to in the argument to the LOOPIOC_SETUP
+ * IOCTL command.
+ */
+
+struct mtd_losetup_s
+{
+  FAR const char *devname;      /* The loop mtd device to be created */
+  FAR const char *filename;     /* The file or character device to use */
+  size_t          erasesize;    /* The erase size to use on the file */
+  size_t          sectsize;     /* The sector / page size of the file */
+  off_t           offset;       /* An offset that may be applied to the device 
*/
+};
+#endif
+
+/****************************************************************************
+ * Public Data
+ ****************************************************************************/
+
+#ifndef __ASSEMBLY__
+
+#ifdef __cplusplus
+#define EXTERN extern "C"
+extern "C"
+{
+#else
+#define EXTERN extern
+#endif
+
+/****************************************************************************
+ * Public Function Prototypes
+ ****************************************************************************/
+
+#ifdef CONFIG_MTD_LOOP
+int mtd_loop_register(void);
+#endif
+
+#undef EXTERN
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __ASSEMBLY__ */
+#endif /* __INCLUDE_NUTTX_FS_LOOPMTD_H */

Reply via email to