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 */