[PATCH 00/19] Introduce a filesystem layer

From: Simon Glass <sjg@chromium.org> U-Boot's filesystems work reasonably well but could be improved: - There is no equivalent of Linux's VFS, meaning that the device type must be provided with filesystem commands like 'ls' and 'load' - There is no caching, nor really anything to hang caching on to, so each access causes the filesystem to be remounted - There is no real 'driver model' access to filesystems, in the sense of opening a file, reading it and then later closing it - It is quite hard to support non-block filesystems, since many functions pass around a struct blk_desc for want of a better structure. As a first step towards improving things, this series provides a simple filesystem uclass, which can be implemented to provide access to filesystems via driver model. Only one filesystem is currently supported: sandbox's hostfs The existing filesystem layer is renamed to 'legacy', to indicate that it is on the way out. New filesystems should try to build on this new series. The rename is only partial, since there is no attempt here to replace the existing filesystem commands. Basic versions of a directory and file are also added. The directory uclass only supports listing directories. The file uclass only supports reading files. There is a small test. From this small start, we can perhaps build on more features. Simon Glass (19): blk: Use hex indices for the device name dm: Rename dev_get_child_count() to dev_read_child_count() sandbox: Update os_open() to return an error code fs: Rename fs.h to fs_legacy.h fs: Rename fs.c to fs_legacy.c fs: Provide a Kconfig option for legacy-filesystem support fs: Provide an SPL Kconfig for legacy-filesystem support fs: Create a common header for legacy and new fs: Create a header file for filesystem-related commands fs: Rename fs_read() to fs_legacy_read() fs: Provide information about non-block filesystems bootstd: Use an enum for hunter numbers fs: Add support for a filesystem fs: Add simple sandbox test fs: Add support for a directory fs: Add a sandbox test for the directory uclass fs: Add a header file for I/O iteration fs: Add support for a file fs: Add a sandbox test for the file uclass MAINTAINERS | 14 + arch/arm/mach-k3/common.c | 2 +- arch/sandbox/cpu/os.c | 33 +- arch/sandbox/dts/test.dts | 13 + board/gdsys/a38x/hre.c | 2 +- board/inversepath/usbarmory/usbarmory.c | 2 +- boot/bootdev-uclass.c | 2 +- boot/bootmeth-uclass.c | 4 +- boot/bootmeth_efi.c | 2 +- boot/bootmeth_extlinux.c | 2 +- boot/bootmeth_pxe.c | 2 +- boot/bootmeth_script.c | 2 +- cmd/addr_find.c | 2 +- cmd/btrfs.c | 2 +- cmd/cat.c | 2 +- cmd/cedit.c | 2 +- cmd/erofs.c | 2 +- cmd/ext2.c | 2 +- cmd/ext4.c | 2 +- cmd/fat.c | 2 +- cmd/fpga.c | 2 +- cmd/fs.c | 2 +- cmd/fs_uuid.c | 3 +- cmd/host.c | 2 +- cmd/mvebu/bubt.c | 8 +- cmd/pstore.c | 2 +- cmd/pxe.c | 2 +- cmd/sqfs.c | 2 +- cmd/sysboot.c | 4 +- cmd/test.c | 2 +- cmd/xxd.c | 4 +- common/board_f.c | 2 +- common/spl/spl_blk_fs.c | 6 +- common/splash_source.c | 4 +- disk/part.c | 3 +- doc/develop/bootstd/overview.rst | 4 +- drivers/adc/stm32-adc.c | 2 +- drivers/block/blk-uclass.c | 2 +- drivers/block/host_dev.c | 4 +- drivers/bootcount/bootcount_fs.c | 7 +- drivers/core/read.c | 2 +- drivers/dfu/dfu_mmc.c | 3 +- drivers/dfu/dfu_scsi.c | 3 +- drivers/fastboot/fb_getvar.c | 2 +- drivers/fpga/zynqpl.c | 10 +- drivers/misc/Kconfig | 2 + drivers/misc/fs_loader.c | 7 +- drivers/mtd/spi/sandbox.c | 2 +- drivers/net/phy/aquantia.c | 6 +- drivers/phy/phy-mtk-tphy.c | 2 +- drivers/remoteproc/ipu_rproc.c | 2 +- drivers/scsi/sandbox_scsi.c | 2 +- drivers/usb/emul/sandbox_flash.c | 2 +- drivers/virtio/virtio-uclass.c | 2 +- drivers/virtio/virtio_sandbox.c | 3 + fs/Kconfig | 40 +++ fs/Makefile | 8 +- fs/dir-uclass.c | 121 +++++++ fs/erofs/erofs_fs.h | 2 +- fs/exfat/io.c | 2 +- fs/fat/fat.c | 2 +- fs/file-uclass.c | 103 ++++++ fs/fs-uclass.c | 122 +++++++ fs/{fs.c => fs_legacy.c} | 12 +- fs/sandbox/hostfs_bootdev.c | 2 +- fs/sandbox/sandboxfs.c | 271 +++++++++++++++- fs/semihostingfs.c | 2 +- fs/squashfs/sqfs.c | 2 +- fs/squashfs/sqfs_filesystem.h | 2 +- include/dir.h | 141 +++++++++ include/dm/read.h | 6 +- include/dm/uclass-id.h | 3 + include/dt-bindings/virtio.h | 1 + include/erofs.h | 3 + include/ext4fs.h | 2 +- include/fat.h | 2 +- include/file.h | 86 +++++ include/fs.h | 404 ++++-------------------- include/fs_cmd.h | 83 +++++ include/fs_common.h | 76 +++++ include/fs_legacy.h | 244 ++++++++++++++ include/iovec.h | 85 +++++ include/os.h | 12 +- include/part.h | 2 + include/squashfs.h | 3 + lib/efi_loader/efi_capsule.c | 2 +- lib/efi_loader/efi_disk.c | 2 +- lib/efi_loader/efi_file.c | 6 +- lib/efi_loader/efi_helper.c | 2 +- lib/efi_loader/efi_load_initrd.c | 2 +- lib/efi_loader/efi_var_file.c | 6 +- test/boot/bootdev.c | 43 +-- test/boot/bootflow.c | 4 +- test/boot/bootstd_common.h | 11 +- test/dm/Makefile | 1 + test/dm/fs.c | 106 +++++++ test/dm/host.c | 2 +- test/dm/rkmtd.c | 2 +- test/image/spl_load_fs.c | 7 +- 99 files changed, 1781 insertions(+), 472 deletions(-) create mode 100644 fs/dir-uclass.c create mode 100644 fs/file-uclass.c create mode 100644 fs/fs-uclass.c rename fs/{fs.c => fs_legacy.c} (98%) create mode 100644 include/dir.h create mode 100644 include/file.h create mode 100644 include/fs_cmd.h create mode 100644 include/fs_common.h create mode 100644 include/fs_legacy.h create mode 100644 include/iovec.h create mode 100644 test/dm/fs.c -- 2.43.0 base-commit: 1c71a3f024de2249cf8264dc0b8fb746fd619cea branch: qemc

From: Simon Glass <sjg@chromium.org> It is confusing to use decimal values in device names. For example, with virtio: => dm tree ... pci 5 [ + ] pci_bridge_drv | |-- pci_0:1.5 virtio 5 [ + ] virtio-pci.m | | `-- virtio-pci.m#5 blk 0 [ + ] virtio-blk | | |-- virtio-blk#5 partition 0 [ + ] blk_partition | | | |-- virtio-blk#5:1 partition 1 [ + ] blk_partition | | | |-- virtio-blk#5:14 partition 2 [ + ] blk_partition | | | |-- virtio-blk#5:15 partition 3 [ + ] blk_partition | | | `-- virtio-blk#5:16 bootdev 2 [ + ] virtio_bootdev | | `-- virtio-blk#5.bootdev pci 6 [ + ] pci_bridge_drv | |-- pci_0:1.6 ... => ls virtio 0:14 ** Invalid partition 20 ** Couldn't find partition virtio 0:14 Fix this by using hex for both the block-device number and the partition. Signed-off-by: Simon Glass <sjg@chromium.org> --- drivers/block/blk-uclass.c | 2 +- drivers/virtio/virtio-uclass.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/block/blk-uclass.c b/drivers/block/blk-uclass.c index f3ac8db9464..f06b2ce3887 100644 --- a/drivers/block/blk-uclass.c +++ b/drivers/block/blk-uclass.c @@ -822,7 +822,7 @@ static int part_create_block_devices(struct udevice *blk_dev) for (count = 0, part = 1; part <= MAX_SEARCH_PARTITIONS; part++) { if (part_get_info(desc, part, &info)) continue; - snprintf(devname, sizeof(devname), "%s:%d", blk_dev->name, + snprintf(devname, sizeof(devname), "%s:%x", blk_dev->name, part); ret = device_bind_driver(blk_dev, "blk_partition", diff --git a/drivers/virtio/virtio-uclass.c b/drivers/virtio/virtio-uclass.c index 1dbc1a56aa2..17ef47df030 100644 --- a/drivers/virtio/virtio-uclass.c +++ b/drivers/virtio/virtio-uclass.c @@ -230,7 +230,7 @@ static int virtio_uclass_post_probe(struct udevice *udev) return 0; } - snprintf(dev_name, sizeof(dev_name), "%s#%d", name, dev_seq(udev)); + snprintf(dev_name, sizeof(dev_name), "%s#%x", name, dev_seq(udev)); str = strdup(dev_name); if (!str) return -ENOMEM; -- 2.43.0

From: Simon Glass <sjg@chromium.org> The existing name is confusing as this function relates to the devicetree rather than the device itself. Rename it to include the word 'read' like other functions in this API. Signed-off-by: Simon Glass <sjg@chromium.org> --- drivers/adc/stm32-adc.c | 2 +- drivers/core/read.c | 2 +- drivers/phy/phy-mtk-tphy.c | 2 +- include/dm/read.h | 6 +++--- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/drivers/adc/stm32-adc.c b/drivers/adc/stm32-adc.c index d50f00f1233..609ed36d7e4 100644 --- a/drivers/adc/stm32-adc.c +++ b/drivers/adc/stm32-adc.c @@ -318,7 +318,7 @@ static int stm32_adc_chan_of_init(struct udevice *dev) int ret; bool legacy = false; - num_channels = dev_get_child_count(dev); + num_channels = dev_read_child_count(dev); /* If no channels have been found, fallback to channels legacy properties. */ if (!num_channels) { legacy = true; diff --git a/drivers/core/read.c b/drivers/core/read.c index 55c19f335ae..08aa3e0981a 100644 --- a/drivers/core/read.c +++ b/drivers/core/read.c @@ -438,7 +438,7 @@ fdt_addr_t dev_read_addr_pci(const struct udevice *dev, fdt_size_t *sizep) return addr; } -int dev_get_child_count(const struct udevice *dev) +int dev_read_child_count(const struct udevice *dev) { return ofnode_get_child_count(dev_ofnode(dev)); } diff --git a/drivers/phy/phy-mtk-tphy.c b/drivers/phy/phy-mtk-tphy.c index 0a45dc58629..7b9d1212655 100644 --- a/drivers/phy/phy-mtk-tphy.c +++ b/drivers/phy/phy-mtk-tphy.c @@ -840,7 +840,7 @@ static int mtk_tphy_probe(struct udevice *dev) ofnode subnode; int index = 0; - tphy->nphys = dev_get_child_count(dev); + tphy->nphys = dev_read_child_count(dev); tphy->phys = devm_kcalloc(dev, tphy->nphys, sizeof(*tphy->phys), GFP_KERNEL); diff --git a/include/dm/read.h b/include/dm/read.h index 894bc698bb4..5ba25b919f9 100644 --- a/include/dm/read.h +++ b/include/dm/read.h @@ -786,12 +786,12 @@ int dev_get_dma_range(const struct udevice *dev, phys_addr_t *cpu, int dev_read_alias_highest_id(const char *stem); /** - * dev_get_child_count() - get the child count of a device + * dev_read_child_count() - get the child count of a device * * @dev: device to use for interation (`struct udevice *`) * Return: the count of child subnode */ -int dev_get_child_count(const struct udevice *dev); +int dev_read_child_count(const struct udevice *dev); /** * dev_read_pci_bus_range - Read PCI bus-range resource @@ -1243,7 +1243,7 @@ static inline int dev_read_alias_highest_id(const char *stem) return fdtdec_get_alias_highest_id(gd->fdt_blob, stem); } -static inline int dev_get_child_count(const struct udevice *dev) +static inline int dev_read_child_count(const struct udevice *dev) { return ofnode_get_child_count(dev_ofnode(dev)); } -- 2.43.0

From: Simon Glass <sjg@chromium.org> It is convenient to be able to report the system error when available. Update os_open() to return it. Signed-off-by: Simon Glass <sjg@chromium.org> --- arch/sandbox/cpu/os.c | 14 +++++++++----- drivers/block/host_dev.c | 4 ++-- drivers/mtd/spi/sandbox.c | 2 +- drivers/scsi/sandbox_scsi.c | 2 +- drivers/usb/emul/sandbox_flash.c | 2 +- include/os.h | 2 +- 6 files changed, 15 insertions(+), 11 deletions(-) diff --git a/arch/sandbox/cpu/os.c b/arch/sandbox/cpu/os.c index f5c9a8aecf2..d1fda05444d 100644 --- a/arch/sandbox/cpu/os.c +++ b/arch/sandbox/cpu/os.c @@ -100,7 +100,7 @@ off_t os_lseek(int fd, off_t offset, int whence) int os_open(const char *pathname, int os_flags) { - int flags; + int flags, ret; switch (os_flags & OS_O_MASK) { case OS_O_RDONLY: @@ -127,7 +127,11 @@ int os_open(const char *pathname, int os_flags) */ flags |= O_CLOEXEC; - return open(pathname, flags, 0644); + ret = open(pathname, flags, 0644); + if (ret == -1) + return -errno; + + return ret; } int os_close(int fd) @@ -172,7 +176,7 @@ int os_write_file(const char *fname, const void *buf, int size) fd = os_open(fname, OS_O_WRONLY | OS_O_CREAT | OS_O_TRUNC); if (fd < 0) { printf("Cannot open file '%s'\n", fname); - return -EIO; + return fd; } if (os_write(fd, buf, size) != size) { printf("Cannot write to file '%s'\n", fname); @@ -206,7 +210,7 @@ int os_read_file(const char *fname, void **bufp, int *sizep) fd = os_open(fname, OS_O_RDONLY); if (fd < 0) { printf("Cannot open file '%s'\n", fname); - return -EIO; + return fd; } size = os_filesize(fd); if (size < 0) { @@ -242,7 +246,7 @@ int os_map_file(const char *pathname, int os_flags, void **bufp, int *sizep) ifd = os_open(pathname, os_flags); if (ifd < 0) { printf("Cannot open file '%s'\n", pathname); - return -EIO; + return ifd; } size = os_filesize(ifd); if (size < 0) { diff --git a/drivers/block/host_dev.c b/drivers/block/host_dev.c index b3ff3cd1fab..504a196e631 100644 --- a/drivers/block/host_dev.c +++ b/drivers/block/host_dev.c @@ -39,11 +39,11 @@ static int host_sb_attach_file(struct udevice *dev, const char *filename) return ret; fd = os_open(filename, OS_O_RDWR); - if (fd == -1) { + if (fd < 0) { printf("Failed to access host backing file '%s', trying read-only\n", filename); fd = os_open(filename, OS_O_RDONLY); - if (fd == -1) { + if (fd < 0) { printf("- still failed\n"); return log_msg_ret("open", -ENOENT); } diff --git a/drivers/mtd/spi/sandbox.c b/drivers/mtd/spi/sandbox.c index e5ebc3479fb..d9afe77e52d 100644 --- a/drivers/mtd/spi/sandbox.c +++ b/drivers/mtd/spi/sandbox.c @@ -171,7 +171,7 @@ static int sandbox_sf_probe(struct udevice *dev) memset(sandbox_sf_0xff, 0xff, sizeof(sandbox_sf_0xff)); sbsf->fd = os_open(pdata->filename, 02); - if (sbsf->fd == -1) { + if (sbsf->fd < 0) { printf("%s: unable to open file '%s'\n", __func__, pdata->filename); ret = -EIO; diff --git a/drivers/scsi/sandbox_scsi.c b/drivers/scsi/sandbox_scsi.c index 544a0247083..3c451313109 100644 --- a/drivers/scsi/sandbox_scsi.c +++ b/drivers/scsi/sandbox_scsi.c @@ -105,7 +105,7 @@ static int sandbox_scsi_probe(struct udevice *dev) if (priv->pathname) { priv->fd = os_open(priv->pathname, OS_O_RDONLY); - if (priv->fd != -1) { + if (priv->fd >= 0) { ret = os_get_filesize(priv->pathname, &info->file_size); if (ret) return log_msg_ret("sz", ret); diff --git a/drivers/usb/emul/sandbox_flash.c b/drivers/usb/emul/sandbox_flash.c index b5176bb30ce..25d968e91c7 100644 --- a/drivers/usb/emul/sandbox_flash.c +++ b/drivers/usb/emul/sandbox_flash.c @@ -342,7 +342,7 @@ static int sandbox_flash_probe(struct udevice *dev) int ret; priv->fd = os_open(plat->pathname, OS_O_RDWR); - if (priv->fd != -1) { + if (priv->fd >= 0) { ret = os_get_filesize(plat->pathname, &info->file_size); if (ret) return log_msg_ret("sz", ret); diff --git a/include/os.h b/include/os.h index ae3ca6d42a2..f4f2667d206 100644 --- a/include/os.h +++ b/include/os.h @@ -71,7 +71,7 @@ off_t os_filesize(int fd); * * @pathname: Pathname of file to open * @flags: Flags, like OS_O_RDONLY, OS_O_RDWR - * Return: file descriptor, or -1 on error + * Return: file descriptor, or -errno on error */ int os_open(const char *pathname, int flags); -- 2.43.0

From: Simon Glass <sjg@chromium.org> A new filesystem interface is coming, so rename the current header to indicate that it is the old one. Signed-off-by: Simon Glass <sjg@chromium.org> --- arch/arm/mach-k3/common.c | 2 +- board/gdsys/a38x/hre.c | 2 +- board/inversepath/usbarmory/usbarmory.c | 2 +- boot/bootdev-uclass.c | 2 +- boot/bootmeth-uclass.c | 2 +- boot/bootmeth_efi.c | 2 +- boot/bootmeth_extlinux.c | 2 +- boot/bootmeth_pxe.c | 2 +- boot/bootmeth_script.c | 2 +- cmd/addr_find.c | 2 +- cmd/btrfs.c | 2 +- cmd/cat.c | 2 +- cmd/cedit.c | 2 +- cmd/erofs.c | 2 +- cmd/ext2.c | 2 +- cmd/ext4.c | 2 +- cmd/fat.c | 2 +- cmd/fpga.c | 2 +- cmd/fs.c | 2 +- cmd/fs_uuid.c | 2 +- cmd/host.c | 2 +- cmd/mvebu/bubt.c | 2 +- cmd/pstore.c | 2 +- cmd/pxe.c | 2 +- cmd/sqfs.c | 2 +- cmd/sysboot.c | 2 +- cmd/test.c | 2 +- cmd/xxd.c | 2 +- common/board_f.c | 2 +- common/spl/spl_blk_fs.c | 2 +- common/splash_source.c | 2 +- drivers/bootcount/bootcount_fs.c | 2 +- drivers/fastboot/fb_getvar.c | 2 +- drivers/fpga/zynqpl.c | 2 +- drivers/misc/fs_loader.c | 2 +- drivers/net/phy/aquantia.c | 2 +- drivers/remoteproc/ipu_rproc.c | 2 +- fs/erofs/erofs_fs.h | 2 +- fs/exfat/io.c | 2 +- fs/fat/fat.c | 2 +- fs/fs.c | 2 +- fs/sandbox/hostfs_bootdev.c | 2 +- fs/sandbox/sandboxfs.c | 2 +- fs/semihostingfs.c | 2 +- fs/squashfs/sqfs.c | 2 +- fs/squashfs/sqfs_filesystem.h | 2 +- include/ext4fs.h | 2 +- include/fat.h | 2 +- include/{fs.h => fs_legacy.h} | 0 lib/efi_loader/efi_capsule.c | 2 +- lib/efi_loader/efi_disk.c | 2 +- lib/efi_loader/efi_file.c | 2 +- lib/efi_loader/efi_helper.c | 2 +- lib/efi_loader/efi_load_initrd.c | 2 +- lib/efi_loader/efi_var_file.c | 2 +- test/dm/host.c | 2 +- test/dm/rkmtd.c | 2 +- test/image/spl_load_fs.c | 2 +- 58 files changed, 57 insertions(+), 57 deletions(-) rename include/{fs.h => fs_legacy.h} (100%) diff --git a/arch/arm/mach-k3/common.c b/arch/arm/mach-k3/common.c index fa8cd93d664..aa53a1c474c 100644 --- a/arch/arm/mach-k3/common.c +++ b/arch/arm/mach-k3/common.c @@ -23,7 +23,7 @@ #include <asm/hardware.h> #include <asm/io.h> #include <fs_loader.h> -#include <fs.h> +#include <fs_legacy.h> #include <efi_loader.h> #include <env.h> #include <elf.h> diff --git a/board/gdsys/a38x/hre.c b/board/gdsys/a38x/hre.c index 06856ea36d3..c23d920849d 100644 --- a/board/gdsys/a38x/hre.c +++ b/board/gdsys/a38x/hre.c @@ -6,7 +6,7 @@ #include <log.h> #include <malloc.h> -#include <fs.h> +#include <fs_legacy.h> #include <i2c.h> #include <mmc.h> #include <tpm-v1.h> diff --git a/board/inversepath/usbarmory/usbarmory.c b/board/inversepath/usbarmory/usbarmory.c index fbed8abcecf..5d8491c2608 100644 --- a/board/inversepath/usbarmory/usbarmory.c +++ b/board/inversepath/usbarmory/usbarmory.c @@ -9,7 +9,7 @@ #include <config.h> #include <command.h> -#include <fs.h> +#include <fs_legacy.h> #include <init.h> #include <asm/global_data.h> #include <asm/io.h> diff --git a/boot/bootdev-uclass.c b/boot/bootdev-uclass.c index 76397a1a990..aaca2f12b5a 100644 --- a/boot/bootdev-uclass.c +++ b/boot/bootdev-uclass.c @@ -11,7 +11,7 @@ #include <bootflow.h> #include <bootmeth.h> #include <bootstd.h> -#include <fs.h> +#include <fs_legacy.h> #include <log.h> #include <malloc.h> #include <part.h> diff --git a/boot/bootmeth-uclass.c b/boot/bootmeth-uclass.c index 5f2e10c879b..f49e9c2a008 100644 --- a/boot/bootmeth-uclass.c +++ b/boot/bootmeth-uclass.c @@ -13,7 +13,7 @@ #include <bootstd.h> #include <dm.h> #include <env_internal.h> -#include <fs.h> +#include <fs_legacy.h> #include <malloc.h> #include <mapmem.h> #include <dm/uclass-internal.h> diff --git a/boot/bootmeth_efi.c b/boot/bootmeth_efi.c index 01cc7ec3bec..703c73c273d 100644 --- a/boot/bootmeth_efi.c +++ b/boot/bootmeth_efi.c @@ -15,7 +15,7 @@ #include <dm.h> #include <efi.h> #include <efi_loader.h> -#include <fs.h> +#include <fs_legacy.h> #include <malloc.h> #include <mapmem.h> #include <mmc.h> diff --git a/boot/bootmeth_extlinux.c b/boot/bootmeth_extlinux.c index 2a268cca9f7..782e5f7ec76 100644 --- a/boot/bootmeth_extlinux.c +++ b/boot/bootmeth_extlinux.c @@ -16,7 +16,7 @@ #include <command.h> #include <dm.h> #include <extlinux.h> -#include <fs.h> +#include <fs_legacy.h> #include <malloc.h> #include <mapmem.h> #include <mmc.h> diff --git a/boot/bootmeth_pxe.c b/boot/bootmeth_pxe.c index 4b5b88bae52..18d8ab446e0 100644 --- a/boot/bootmeth_pxe.c +++ b/boot/bootmeth_pxe.c @@ -14,7 +14,7 @@ #include <command.h> #include <dm.h> #include <extlinux.h> -#include <fs.h> +#include <fs_legacy.h> #include <log.h> #include <malloc.h> #include <mapmem.h> diff --git a/boot/bootmeth_script.c b/boot/bootmeth_script.c index b3a51a35e89..facd0a68d73 100644 --- a/boot/bootmeth_script.c +++ b/boot/bootmeth_script.c @@ -15,7 +15,7 @@ #include <bootstd.h> #include <dm.h> #include <env.h> -#include <fs.h> +#include <fs_legacy.h> #include <image.h> #include <malloc.h> #include <mapmem.h> diff --git a/cmd/addr_find.c b/cmd/addr_find.c index b187337d885..8dcad300ad8 100644 --- a/cmd/addr_find.c +++ b/cmd/addr_find.c @@ -8,7 +8,7 @@ #include <config.h> #include <command.h> #include <env.h> -#include <fs.h> +#include <fs_legacy.h> #include <lmb.h> #include <asm/global_data.h> diff --git a/cmd/btrfs.c b/cmd/btrfs.c index 69d1b1f830d..670aa958245 100644 --- a/cmd/btrfs.c +++ b/cmd/btrfs.c @@ -5,7 +5,7 @@ #include <command.h> #include <btrfs.h> -#include <fs.h> +#include <fs_legacy.h> int do_btrsubvol(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]) { diff --git a/cmd/cat.c b/cmd/cat.c index 24983cb9ca0..6272779b426 100644 --- a/cmd/cat.c +++ b/cmd/cat.c @@ -6,7 +6,7 @@ #include <abuf.h> #include <command.h> -#include <fs.h> +#include <fs_legacy.h> #include <malloc.h> #include <mapmem.h> diff --git a/cmd/cedit.c b/cmd/cedit.c index 9c492d45171..6db5806e851 100644 --- a/cmd/cedit.c +++ b/cmd/cedit.c @@ -11,7 +11,7 @@ #include <command.h> #include <dm.h> #include <expo.h> -#include <fs.h> +#include <fs_legacy.h> #include <malloc.h> #include <mapmem.h> #include <dm/ofnode.h> diff --git a/cmd/erofs.c b/cmd/erofs.c index add80b8b594..f4ff12eadaa 100644 --- a/cmd/erofs.c +++ b/cmd/erofs.c @@ -8,7 +8,7 @@ */ #include <command.h> -#include <fs.h> +#include <fs_legacy.h> #include <erofs.h> static int do_erofs_ls(struct cmd_tbl *cmdtp, int flag, int argc, char * const argv[]) diff --git a/cmd/ext2.c b/cmd/ext2.c index 45c8b353b58..3de098193e7 100644 --- a/cmd/ext2.c +++ b/cmd/ext2.c @@ -20,7 +20,7 @@ * Ext2fs support */ #include <command.h> -#include <fs.h> +#include <fs_legacy.h> static int do_ext2ls(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]) diff --git a/cmd/ext4.c b/cmd/ext4.c index 40d1fe30d5e..02d3f7a174b 100644 --- a/cmd/ext4.c +++ b/cmd/ext4.c @@ -34,7 +34,7 @@ #include <ext4fs.h> #include <linux/stat.h> #include <malloc.h> -#include <fs.h> +#include <fs_legacy.h> #if defined(CONFIG_CMD_USB) && defined(CONFIG_USB_STORAGE) #include <usb.h> diff --git a/cmd/fat.c b/cmd/fat.c index 5b7484dc1af..aa01c36688b 100644 --- a/cmd/fat.c +++ b/cmd/fat.c @@ -10,7 +10,7 @@ #include <command.h> #include <mapmem.h> #include <fat.h> -#include <fs.h> +#include <fs_legacy.h> #include <part.h> #include <asm/cache.h> diff --git a/cmd/fpga.c b/cmd/fpga.c index 93f14098ccb..e6ae3856af8 100644 --- a/cmd/fpga.c +++ b/cmd/fpga.c @@ -10,7 +10,7 @@ #include <command.h> #include <env.h> #include <fpga.h> -#include <fs.h> +#include <fs_legacy.h> #include <gzip.h> #include <image.h> #include <log.h> diff --git a/cmd/fs.c b/cmd/fs.c index 7f1ab8f0fd2..51d587b8b16 100644 --- a/cmd/fs.c +++ b/cmd/fs.c @@ -6,7 +6,7 @@ */ #include <command.h> -#include <fs.h> +#include <fs_legacy.h> static int do_size_wrapper(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]) diff --git a/cmd/fs_uuid.c b/cmd/fs_uuid.c index 5f7770d09ac..6a91c633dcb 100644 --- a/cmd/fs_uuid.c +++ b/cmd/fs_uuid.c @@ -6,7 +6,7 @@ */ #include <command.h> -#include <fs.h> +#include <fs_legacy.h> static int do_fs_uuid_wrapper(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]) diff --git a/cmd/host.c b/cmd/host.c index e03576b4d2d..9832a88a5b0 100644 --- a/cmd/host.c +++ b/cmd/host.c @@ -5,7 +5,7 @@ #include <command.h> #include <dm.h> -#include <fs.h> +#include <fs_legacy.h> #include <part.h> #include <sandbox_host.h> #include <dm/device_compat.h> diff --git a/cmd/mvebu/bubt.c b/cmd/mvebu/bubt.c index 5e4ffc40d72..b64d5a5733c 100644 --- a/cmd/mvebu/bubt.c +++ b/cmd/mvebu/bubt.c @@ -20,7 +20,7 @@ #include <nand.h> #include <scsi.h> #include <usb.h> -#include <fs.h> +#include <fs_legacy.h> #include <mmc.h> #ifdef CONFIG_BLK #include <blk.h> diff --git a/cmd/pstore.c b/cmd/pstore.c index 9795eea2dbc..ab7ac656383 100644 --- a/cmd/pstore.c +++ b/cmd/pstore.c @@ -6,7 +6,7 @@ #include <config.h> #include <command.h> #include <fdtdec.h> -#include <fs.h> +#include <fs_legacy.h> #include <log.h> #include <mapmem.h> #include <memalign.h> diff --git a/cmd/pxe.c b/cmd/pxe.c index 7c9ffd87522..b5f2ff7cb6b 100644 --- a/cmd/pxe.c +++ b/cmd/pxe.c @@ -5,7 +5,7 @@ */ #include <command.h> -#include <fs.h> +#include <fs_legacy.h> #include <net.h> #include <net6.h> #include <malloc.h> diff --git a/cmd/sqfs.c b/cmd/sqfs.c index 107038c4cf2..b10403c4379 100644 --- a/cmd/sqfs.c +++ b/cmd/sqfs.c @@ -8,7 +8,7 @@ */ #include <command.h> -#include <fs.h> +#include <fs_legacy.h> #include <squashfs.h> static int do_sqfs_ls(struct cmd_tbl *cmdtp, int flag, int argc, char * const argv[]) diff --git a/cmd/sysboot.c b/cmd/sysboot.c index 384d5e15e3d..735c90fa42c 100644 --- a/cmd/sysboot.c +++ b/cmd/sysboot.c @@ -2,7 +2,7 @@ #include <command.h> #include <env.h> -#include <fs.h> +#include <fs_legacy.h> #include <pxe_utils.h> #include <vsprintf.h> diff --git a/cmd/test.c b/cmd/test.c index b4c3eabf9f6..cb24479f5b1 100644 --- a/cmd/test.c +++ b/cmd/test.c @@ -5,7 +5,7 @@ */ #include <command.h> -#include <fs.h> +#include <fs_legacy.h> #include <log.h> #include <vsprintf.h> diff --git a/cmd/xxd.c b/cmd/xxd.c index 8ae05f910cb..f1294d763b1 100644 --- a/cmd/xxd.c +++ b/cmd/xxd.c @@ -6,7 +6,7 @@ #include <command.h> #include <display_options.h> -#include <fs.h> +#include <fs_legacy.h> #include <malloc.h> #include <mapmem.h> diff --git a/common/board_f.c b/common/board_f.c index 29af0f1c58c..3a4fb9a42ef 100644 --- a/common/board_f.c +++ b/common/board_f.c @@ -23,7 +23,7 @@ #include <env_internal.h> #include <event.h> #include <fdtdec.h> -#include <fs.h> +#include <fs_legacy.h> #include <hang.h> #include <i2c.h> #include <init.h> diff --git a/common/spl/spl_blk_fs.c b/common/spl/spl_blk_fs.c index bbf90a9741e..aa2a031d169 100644 --- a/common/spl/spl_blk_fs.c +++ b/common/spl/spl_blk_fs.c @@ -8,7 +8,7 @@ #include <spl.h> #include <spl_load.h> #include <image.h> -#include <fs.h> +#include <fs_legacy.h> #include <asm/cache.h> #include <asm/io.h> diff --git a/common/splash_source.c b/common/splash_source.c index 2df78a4f2d7..f6b51aab017 100644 --- a/common/splash_source.c +++ b/common/splash_source.c @@ -9,7 +9,7 @@ #include <command.h> #include <env.h> #include <errno.h> -#include <fs.h> +#include <fs_legacy.h> #include <fdt_support.h> #include <image.h> #include <log.h> diff --git a/drivers/bootcount/bootcount_fs.c b/drivers/bootcount/bootcount_fs.c index 569592d8aad..f8e1478b7b7 100644 --- a/drivers/bootcount/bootcount_fs.c +++ b/drivers/bootcount/bootcount_fs.c @@ -4,7 +4,7 @@ */ #include <bootcount.h> -#include <fs.h> +#include <fs_legacy.h> #include <mapmem.h> #define BC_MAGIC 0xbd diff --git a/drivers/fastboot/fb_getvar.c b/drivers/fastboot/fb_getvar.c index 93cbd598e02..610d359aed3 100644 --- a/drivers/fastboot/fb_getvar.c +++ b/drivers/fastboot/fb_getvar.c @@ -8,7 +8,7 @@ #include <fastboot-internal.h> #include <fb_mmc.h> #include <fb_nand.h> -#include <fs.h> +#include <fs_legacy.h> #include <part.h> #include <version.h> #include <vsprintf.h> diff --git a/drivers/fpga/zynqpl.c b/drivers/fpga/zynqpl.c index 3e86d854a01..0a87eb7917a 100644 --- a/drivers/fpga/zynqpl.c +++ b/drivers/fpga/zynqpl.c @@ -13,7 +13,7 @@ #include <time.h> #include <asm/cache.h> #include <asm/io.h> -#include <fs.h> +#include <fs_legacy.h> #include <zynqpl.h> #include <linux/delay.h> #include <linux/sizes.h> diff --git a/drivers/misc/fs_loader.c b/drivers/misc/fs_loader.c index 66803f4b997..cf253c9864e 100644 --- a/drivers/misc/fs_loader.c +++ b/drivers/misc/fs_loader.c @@ -10,7 +10,7 @@ #include <env.h> #include <errno.h> #include <blk.h> -#include <fs.h> +#include <fs_legacy.h> #include <fs_loader.h> #include <log.h> #include <asm/global_data.h> diff --git a/drivers/net/phy/aquantia.c b/drivers/net/phy/aquantia.c index d2db8d9f792..5af993a6898 100644 --- a/drivers/net/phy/aquantia.c +++ b/drivers/net/phy/aquantia.c @@ -15,7 +15,7 @@ #include <u-boot/crc.h> #include <malloc.h> #include <asm/byteorder.h> -#include <fs.h> +#include <fs_legacy.h> #define AQUNTIA_10G_CTL 0x20 #define AQUNTIA_VENDOR_P1 0xc400 diff --git a/drivers/remoteproc/ipu_rproc.c b/drivers/remoteproc/ipu_rproc.c index 2ca78b550a7..345772b7af2 100644 --- a/drivers/remoteproc/ipu_rproc.c +++ b/drivers/remoteproc/ipu_rproc.c @@ -26,7 +26,7 @@ #include <misc.h> #include <power-domain.h> #include <timer.h> -#include <fs.h> +#include <fs_legacy.h> #include <spl.h> #include <timer.h> #include <reset.h> diff --git a/fs/erofs/erofs_fs.h b/fs/erofs/erofs_fs.h index 5bac4fe1a1d..b8da9abe683 100644 --- a/fs/erofs/erofs_fs.h +++ b/fs/erofs/erofs_fs.h @@ -10,7 +10,7 @@ #define __EROFS_FS_H #include <asm/unaligned.h> -#include <fs.h> +#include <fs_legacy.h> #include <part.h> #include <stdint.h> #include <compiler.h> diff --git a/fs/exfat/io.c b/fs/exfat/io.c index c56f5675987..c4cc778fb39 100644 --- a/fs/exfat/io.c +++ b/fs/exfat/io.c @@ -46,7 +46,7 @@ #include <ublio.h> #endif #else -#include <fs.h> +#include <fs_legacy.h> #include <fs_internal.h> static struct exfat_ctxt { diff --git a/fs/fat/fat.c b/fs/fat/fat.c index e2570e81676..0cbfdf49a32 100644 --- a/fs/fat/fat.c +++ b/fs/fat/fat.c @@ -14,7 +14,7 @@ #include <config.h> #include <exports.h> #include <fat.h> -#include <fs.h> +#include <fs_legacy.h> #include <log.h> #include <asm/byteorder.h> #include <asm/unaligned.h> diff --git a/fs/fs.c b/fs/fs.c index 63ed6436493..5be041e2133 100644 --- a/fs/fs.c +++ b/fs/fs.c @@ -19,7 +19,7 @@ #include <part.h> #include <ext4fs.h> #include <fat.h> -#include <fs.h> +#include <fs_legacy.h> #include <sandboxfs.h> #include <semihostingfs.h> #include <time.h> diff --git a/fs/sandbox/hostfs_bootdev.c b/fs/sandbox/hostfs_bootdev.c index 08dafafcef0..09f8372194c 100644 --- a/fs/sandbox/hostfs_bootdev.c +++ b/fs/sandbox/hostfs_bootdev.c @@ -10,7 +10,7 @@ #include <bootflow.h> #include <bootmeth.h> #include <dm.h> -#include <fs.h> +#include <fs_legacy.h> static int host_get_bootflow(struct udevice *dev, struct bootflow_iter *iter, struct bootflow *bflow) diff --git a/fs/sandbox/sandboxfs.c b/fs/sandbox/sandboxfs.c index 76f1a71f412..bfb30ef47fe 100644 --- a/fs/sandbox/sandboxfs.c +++ b/fs/sandbox/sandboxfs.c @@ -4,7 +4,7 @@ */ #include <stdio.h> -#include <fs.h> +#include <fs_legacy.h> #include <malloc.h> #include <os.h> #include <sandboxfs.h> diff --git a/fs/semihostingfs.c b/fs/semihostingfs.c index 77e39ca407e..939ca290e3b 100644 --- a/fs/semihostingfs.c +++ b/fs/semihostingfs.c @@ -5,7 +5,7 @@ */ #include <stdio.h> -#include <fs.h> +#include <fs_legacy.h> #include <malloc.h> #include <os.h> #include <semihosting.h> diff --git a/fs/squashfs/sqfs.c b/fs/squashfs/sqfs.c index b9314019b1b..182968ac6ce 100644 --- a/fs/squashfs/sqfs.c +++ b/fs/squashfs/sqfs.c @@ -10,7 +10,7 @@ #include <asm/unaligned.h> #include <div64.h> #include <errno.h> -#include <fs.h> +#include <fs_legacy.h> #include <linux/types.h> #include <asm/byteorder.h> #include <linux/compat.h> diff --git a/fs/squashfs/sqfs_filesystem.h b/fs/squashfs/sqfs_filesystem.h index be56498a5e3..32425b0ff29 100644 --- a/fs/squashfs/sqfs_filesystem.h +++ b/fs/squashfs/sqfs_filesystem.h @@ -9,7 +9,7 @@ #define SQFS_FILESYSTEM_H #include <asm/unaligned.h> -#include <fs.h> +#include <fs_legacy.h> #include <part.h> #include <stdint.h> diff --git a/include/ext4fs.h b/include/ext4fs.h index fe3fb301ec8..5822da38545 100644 --- a/include/ext4fs.h +++ b/include/ext4fs.h @@ -27,7 +27,7 @@ #ifndef __EXT4__ #define __EXT4__ #include <ext_common.h> -#include <fs.h> +#include <fs_legacy.h> struct disk_partition; diff --git a/include/fat.h b/include/fat.h index ca97880de12..053c34dd0e2 100644 --- a/include/fat.h +++ b/include/fat.h @@ -9,7 +9,7 @@ #ifndef _FAT_H_ #define _FAT_H_ -#include <fs.h> +#include <fs_legacy.h> #include <asm/byteorder.h> #include <asm/cache.h> diff --git a/include/fs.h b/include/fs_legacy.h similarity index 100% rename from include/fs.h rename to include/fs_legacy.h diff --git a/lib/efi_loader/efi_capsule.c b/lib/efi_loader/efi_capsule.c index 14faf9848e6..9972214b0fa 100644 --- a/lib/efi_loader/efi_capsule.c +++ b/lib/efi_loader/efi_capsule.c @@ -13,7 +13,7 @@ #include <efi_variable.h> #include <env.h> #include <fdtdec.h> -#include <fs.h> +#include <fs_legacy.h> #include <fwu.h> #include <hang.h> #include <malloc.h> diff --git a/lib/efi_loader/efi_disk.c b/lib/efi_loader/efi_disk.c index 47b583cc5e1..83f70bc2157 100644 --- a/lib/efi_loader/efi_disk.c +++ b/lib/efi_loader/efi_disk.c @@ -15,7 +15,7 @@ #include <event.h> #include <efi_driver.h> #include <efi_loader.h> -#include <fs.h> +#include <fs_legacy.h> #include <log.h> #include <part.h> #include <malloc.h> diff --git a/lib/efi_loader/efi_file.c b/lib/efi_loader/efi_file.c index 7d81da8f2d8..65bc99b961b 100644 --- a/lib/efi_loader/efi_file.c +++ b/lib/efi_loader/efi_file.c @@ -12,7 +12,7 @@ #include <log.h> #include <malloc.h> #include <mapmem.h> -#include <fs.h> +#include <fs_legacy.h> #include <part.h> /* GUID for file system information */ diff --git a/lib/efi_loader/efi_helper.c b/lib/efi_loader/efi_helper.c index 9d73200e604..82e0fd7b069 100644 --- a/lib/efi_loader/efi_helper.c +++ b/lib/efi_loader/efi_helper.c @@ -13,7 +13,7 @@ #include <malloc.h> #include <mapmem.h> #include <dm.h> -#include <fs.h> +#include <fs_legacy.h> #include <efi.h> #include <efi_api.h> #include <efi_load_initrd.h> diff --git a/lib/efi_loader/efi_load_initrd.c b/lib/efi_loader/efi_load_initrd.c index b5d58943a80..a6d14eb5f74 100644 --- a/lib/efi_loader/efi_load_initrd.c +++ b/lib/efi_loader/efi_load_initrd.c @@ -8,7 +8,7 @@ #include <efi_loader.h> #include <efi_load_initrd.h> #include <efi_variable.h> -#include <fs.h> +#include <fs_legacy.h> #include <malloc.h> #include <mapmem.h> diff --git a/lib/efi_loader/efi_var_file.c b/lib/efi_loader/efi_var_file.c index ba0bf33ffbd..f3f034dde48 100644 --- a/lib/efi_loader/efi_var_file.c +++ b/lib/efi_loader/efi_var_file.c @@ -8,7 +8,7 @@ #define LOG_CATEGORY LOGC_EFI #include <charset.h> -#include <fs.h> +#include <fs_legacy.h> #include <log.h> #include <malloc.h> #include <mapmem.h> diff --git a/test/dm/host.c b/test/dm/host.c index f577377da6a..a126cc9b3a5 100644 --- a/test/dm/host.c +++ b/test/dm/host.c @@ -6,7 +6,7 @@ #include <blk.h> #include <dm.h> -#include <fs.h> +#include <fs_legacy.h> #include <os.h> #include <sandbox_host.h> #include <asm/test.h> diff --git a/test/dm/rkmtd.c b/test/dm/rkmtd.c index d1ca5d1acac..06e314647e8 100644 --- a/test/dm/rkmtd.c +++ b/test/dm/rkmtd.c @@ -10,7 +10,7 @@ #include <blk.h> #include <dm.h> -#include <fs.h> +#include <fs_legacy.h> #include <rkmtd.h> #include <asm/test.h> #include <dm/device-internal.h> diff --git a/test/image/spl_load_fs.c b/test/image/spl_load_fs.c index 935078bf67b..4663729f58c 100644 --- a/test/image/spl_load_fs.c +++ b/test/image/spl_load_fs.c @@ -7,7 +7,7 @@ #include <ext_common.h> #include <ext4fs.h> #include <fat.h> -#include <fs.h> +#include <fs_legacy.h> #include <memalign.h> #include <spl.h> #include <asm/io.h> -- 2.43.0

From: Simon Glass <sjg@chromium.org> A new filesystem interface is coming, so rename the main fs.c file to indicate that it is the old one. Signed-off-by: Simon Glass <sjg@chromium.org> --- fs/Makefile | 4 ++-- fs/{fs.c => fs_legacy.c} | 0 2 files changed, 2 insertions(+), 2 deletions(-) rename fs/{fs.c => fs_legacy.c} (100%) diff --git a/fs/Makefile b/fs/Makefile index f9f90a2d99c..51a0ad07a15 100644 --- a/fs/Makefile +++ b/fs/Makefile @@ -5,13 +5,13 @@ # Copyright (c) 2012, NVIDIA CORPORATION. All rights reserved. ifdef CONFIG_XPL_BUILD -obj-$(CONFIG_SPL_FS_LOADER) += fs.o +obj-$(CONFIG_SPL_FS_LOADER) += fs_legacy.o obj-$(CONFIG_SPL_FS_FAT) += fat/ obj-$(CONFIG_SPL_FS_EXT4) += ext4/ obj-$(CONFIG_SPL_FS_CBFS) += cbfs/ obj-$(CONFIG_SPL_FS_SQUASHFS) += squashfs/ else -obj-y += fs.o +obj-y += fs_legacy.o obj-$(CONFIG_FS_BTRFS) += btrfs/ obj-$(CONFIG_FS_CBFS) += cbfs/ diff --git a/fs/fs.c b/fs/fs_legacy.c similarity index 100% rename from fs/fs.c rename to fs/fs_legacy.c -- 2.43.0

From: Simon Glass <sjg@chromium.org> There is currently no Kconfig used and the filesystem code is always included in U-Boot proper. Add an option to control this. For now it is always on. Signed-off-by: Simon Glass <sjg@chromium.org> --- fs/Kconfig | 7 +++++++ fs/Makefile | 4 ++-- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/fs/Kconfig b/fs/Kconfig index 3769590d962..de066710901 100644 --- a/fs/Kconfig +++ b/fs/Kconfig @@ -4,6 +4,13 @@ menu "File systems" +config FS_LEGACY + def_bool y + help + Enables legacy support for filesystems. This provides an interface + which can talk to one filesystem at a time, with the filesystem being + re-mounted on each operation. + source "fs/btrfs/Kconfig" source "fs/cbfs/Kconfig" diff --git a/fs/Makefile b/fs/Makefile index 51a0ad07a15..e2de105592f 100644 --- a/fs/Makefile +++ b/fs/Makefile @@ -11,7 +11,7 @@ obj-$(CONFIG_SPL_FS_EXT4) += ext4/ obj-$(CONFIG_SPL_FS_CBFS) += cbfs/ obj-$(CONFIG_SPL_FS_SQUASHFS) += squashfs/ else -obj-y += fs_legacy.o +obj-$(CONFIG_FS_LEGACY) += fs_legacy.o obj-$(CONFIG_FS_BTRFS) += btrfs/ obj-$(CONFIG_FS_CBFS) += cbfs/ @@ -28,4 +28,4 @@ obj-$(CONFIG_CMD_ZFS) += zfs/ obj-$(CONFIG_FS_SQUASHFS) += squashfs/ obj-$(CONFIG_FS_EROFS) += erofs/ endif -obj-y += fs_internal.o +obj-$(CONFIG_FS_LEGACY) += fs_internal.o -- 2.43.0

From: Simon Glass <sjg@chromium.org> Signed-off-by: Simon Glass <sjg@chromium.org> --- drivers/misc/Kconfig | 2 ++ fs/Kconfig | 8 ++++++++ fs/Makefile | 5 ++--- 3 files changed, 12 insertions(+), 3 deletions(-) diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig index e8a2a677129..94567a790f9 100644 --- a/drivers/misc/Kconfig +++ b/drivers/misc/Kconfig @@ -617,6 +617,7 @@ config MPC83XX_SERDES config FS_LOADER bool "Enable loader driver for file system" + select SPL_FS_LEGACY help This is file system generic loader which can be used to load the file image from the storage into target such as memory. @@ -627,6 +628,7 @@ config FS_LOADER config SPL_FS_LOADER bool "Enable loader driver for file system in SPL" depends on SPL + select SPL_FS_LEGACY help This is file system generic loader which can be used to load the file image from the storage into target such as memory. diff --git a/fs/Kconfig b/fs/Kconfig index de066710901..490f9755016 100644 --- a/fs/Kconfig +++ b/fs/Kconfig @@ -11,6 +11,14 @@ config FS_LEGACY which can talk to one filesystem at a time, with the filesystem being re-mounted on each operation. +config SPL_FS_LEGACY + bool + depends on SPL + help + Enables legacy support for filesystems in SPL. This provides an + interface which can talk to one filesystem at a time, with the + filesystem being re-mounted on each operation. + source "fs/btrfs/Kconfig" source "fs/cbfs/Kconfig" diff --git a/fs/Makefile b/fs/Makefile index e2de105592f..02c32aa8287 100644 --- a/fs/Makefile +++ b/fs/Makefile @@ -4,14 +4,14 @@ # Wolfgang Denk, DENX Software Engineering, wd@denx.de. # Copyright (c) 2012, NVIDIA CORPORATION. All rights reserved. +obj-$(CONFIG_$(PHASE_)FS_LEGACY) += fs_legacy.o fs_internal.o + ifdef CONFIG_XPL_BUILD -obj-$(CONFIG_SPL_FS_LOADER) += fs_legacy.o obj-$(CONFIG_SPL_FS_FAT) += fat/ obj-$(CONFIG_SPL_FS_EXT4) += ext4/ obj-$(CONFIG_SPL_FS_CBFS) += cbfs/ obj-$(CONFIG_SPL_FS_SQUASHFS) += squashfs/ else -obj-$(CONFIG_FS_LEGACY) += fs_legacy.o obj-$(CONFIG_FS_BTRFS) += btrfs/ obj-$(CONFIG_FS_CBFS) += cbfs/ @@ -28,4 +28,3 @@ obj-$(CONFIG_CMD_ZFS) += zfs/ obj-$(CONFIG_FS_SQUASHFS) += squashfs/ obj-$(CONFIG_FS_EROFS) += erofs/ endif -obj-$(CONFIG_FS_LEGACY) += fs_internal.o -- 2.43.0

From: Simon Glass <sjg@chromium.org> Some parts of fs_legacy.h are useful for the new fs subsystem. Add a common header and move the filesystem types and some definition into it. Use an enum for the filesystem type, to permit type checking. Signed-off-by: Simon Glass <sjg@chromium.org> --- include/fs_common.h | 72 +++++++++++++++++++++++++++++++++++++++++++++ include/fs_legacy.h | 61 +------------------------------------- 2 files changed, 73 insertions(+), 60 deletions(-) create mode 100644 include/fs_common.h diff --git a/include/fs_common.h b/include/fs_common.h new file mode 100644 index 00000000000..30e8b6737b3 --- /dev/null +++ b/include/fs_common.h @@ -0,0 +1,72 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (c) 2012, NVIDIA CORPORATION. All rights reserved. + */ +#ifndef _FS_COMMON_H +#define _FS_COMMON_H + +#include <rtc.h> + +enum fs_type_t { + FS_TYPE_ANY = 0, + FS_TYPE_FAT, + FS_TYPE_EXT, + FS_TYPE_SANDBOX, + FS_TYPE_UBIFS, + FS_TYPE_BTRFS, + FS_TYPE_SQUASHFS, + FS_TYPE_EROFS, + FS_TYPE_SEMIHOSTING, + FS_TYPE_EXFAT, +}; + +/* + * Directory entry types, matches the subset of DT_x in posix readdir() + * which apply to u-boot. + */ +#define FS_DT_DIR 4 /* directory */ +#define FS_DT_REG 8 /* regular file */ +#define FS_DT_LNK 10 /* symbolic link */ + +#define FS_DIRENT_NAME_LEN CONFIG_IS_ENABLED(FS_EXFAT, (1024), (256)) + +/** + * struct fs_dirent - directory entry + * + * A directory entry, returned by fs_readdir(). Returns information + * about the file/directory at the current directory entry position. + */ +struct fs_dirent { + /** @type: one of FS_DT_x (not a mask) */ + unsigned int type; + /** @size: file size */ + loff_t size; + /** @attr: attribute flags (FS_ATTR_*) */ + u32 attr; + /** @create_time: time of creation */ + struct rtc_time create_time; + /** @access_time: time of last access */ + struct rtc_time access_time; + /** @change_time: time of last modification */ + struct rtc_time change_time; + /** @name: file name */ + char name[FS_DIRENT_NAME_LEN]; +}; + +/** + * struct fs_dir_stream - Structure representing an opened directory + * + * Struct fs_dir_stream should be treated opaque to the user of fs layer. + * The fields @desc and @part are used by the fs layer. + * File system drivers pass additional private fields with the pointers + * to this structure. + * + * @desc: block device descriptor + * @part: partition number + */ +struct fs_dir_stream { + struct blk_desc *desc; + int part; +}; + +#endif diff --git a/include/fs_legacy.h b/include/fs_legacy.h index 5cd9114f33b..1a01fb09aa1 100644 --- a/include/fs_legacy.h +++ b/include/fs_legacy.h @@ -5,22 +5,12 @@ #ifndef _FS_H #define _FS_H +#include <fs_common.h> #include <rtc.h> struct abuf; struct cmd_tbl; -#define FS_TYPE_ANY 0 -#define FS_TYPE_FAT 1 -#define FS_TYPE_EXT 2 -#define FS_TYPE_SANDBOX 3 -#define FS_TYPE_UBIFS 4 -#define FS_TYPE_BTRFS 5 -#define FS_TYPE_SQUASHFS 6 -#define FS_TYPE_EROFS 7 -#define FS_TYPE_SEMIHOSTING 8 -#define FS_TYPE_EXFAT 9 - struct blk_desc; /** @@ -167,55 +157,6 @@ int fs_read(const char *filename, ulong addr, loff_t offset, loff_t len, int fs_write(const char *filename, ulong addr, loff_t offset, loff_t len, loff_t *actwrite); -/* - * Directory entry types, matches the subset of DT_x in posix readdir() - * which apply to u-boot. - */ -#define FS_DT_DIR 4 /* directory */ -#define FS_DT_REG 8 /* regular file */ -#define FS_DT_LNK 10 /* symbolic link */ - -#define FS_DIRENT_NAME_LEN CONFIG_IS_ENABLED(FS_EXFAT, (1024), (256)) - -/** - * struct fs_dirent - directory entry - * - * A directory entry, returned by fs_readdir(). Returns information - * about the file/directory at the current directory entry position. - */ -struct fs_dirent { - /** @type: one of FS_DT_x (not a mask) */ - unsigned int type; - /** @size: file size */ - loff_t size; - /** @attr: attribute flags (FS_ATTR_*) */ - u32 attr; - /** @create_time: time of creation */ - struct rtc_time create_time; - /** @access_time: time of last access */ - struct rtc_time access_time; - /** @change_time: time of last modification */ - struct rtc_time change_time; - /** @name: file name */ - char name[FS_DIRENT_NAME_LEN]; -}; - -/** - * struct fs_dir_stream - Structure representing an opened directory - * - * Struct fs_dir_stream should be treated opaque to the user of fs layer. - * The fields @desc and @part are used by the fs layer. - * File system drivers pass additional private fields with the pointers - * to this structure. - * - * @desc: block device descriptor - * @part: partition number - */ -struct fs_dir_stream { - struct blk_desc *desc; - int part; -}; - /** * fs_opendir - Open a directory * -- 2.43.0

From: Simon Glass <sjg@chromium.org> Most commands access the filesystem through the command-line interface rather than the filesystem API itself. Add a new header file which contains these functions, so we can separate commands from the API. Signed-off-by: Simon Glass <sjg@chromium.org> --- cmd/erofs.c | 2 +- cmd/ext2.c | 2 +- cmd/ext4.c | 2 +- cmd/fat.c | 2 +- cmd/fs.c | 2 +- cmd/fs_uuid.c | 1 + cmd/host.c | 2 +- cmd/pstore.c | 2 +- cmd/sqfs.c | 2 +- cmd/test.c | 2 +- include/erofs.h | 3 ++ include/fs_cmd.h | 83 +++++++++++++++++++++++++++++++++++++++++++++ include/fs_legacy.h | 71 -------------------------------------- include/squashfs.h | 3 ++ 14 files changed, 99 insertions(+), 80 deletions(-) create mode 100644 include/fs_cmd.h diff --git a/cmd/erofs.c b/cmd/erofs.c index f4ff12eadaa..e2479461652 100644 --- a/cmd/erofs.c +++ b/cmd/erofs.c @@ -8,7 +8,7 @@ */ #include <command.h> -#include <fs_legacy.h> +#include <fs_cmd.h> #include <erofs.h> static int do_erofs_ls(struct cmd_tbl *cmdtp, int flag, int argc, char * const argv[]) diff --git a/cmd/ext2.c b/cmd/ext2.c index 3de098193e7..d5150d08001 100644 --- a/cmd/ext2.c +++ b/cmd/ext2.c @@ -20,7 +20,7 @@ * Ext2fs support */ #include <command.h> -#include <fs_legacy.h> +#include <fs_cmd.h> static int do_ext2ls(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]) diff --git a/cmd/ext4.c b/cmd/ext4.c index 02d3f7a174b..bf257c55e06 100644 --- a/cmd/ext4.c +++ b/cmd/ext4.c @@ -34,7 +34,7 @@ #include <ext4fs.h> #include <linux/stat.h> #include <malloc.h> -#include <fs_legacy.h> +#include <fs_cmd.h> #if defined(CONFIG_CMD_USB) && defined(CONFIG_USB_STORAGE) #include <usb.h> diff --git a/cmd/fat.c b/cmd/fat.c index aa01c36688b..e0e08d4a408 100644 --- a/cmd/fat.c +++ b/cmd/fat.c @@ -10,7 +10,7 @@ #include <command.h> #include <mapmem.h> #include <fat.h> -#include <fs_legacy.h> +#include <fs_cmd.h> #include <part.h> #include <asm/cache.h> diff --git a/cmd/fs.c b/cmd/fs.c index 51d587b8b16..7058f17b24f 100644 --- a/cmd/fs.c +++ b/cmd/fs.c @@ -6,7 +6,7 @@ */ #include <command.h> -#include <fs_legacy.h> +#include <fs_cmd.h> static int do_size_wrapper(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]) diff --git a/cmd/fs_uuid.c b/cmd/fs_uuid.c index 6a91c633dcb..3c439a0338c 100644 --- a/cmd/fs_uuid.c +++ b/cmd/fs_uuid.c @@ -6,6 +6,7 @@ */ #include <command.h> +#include <fs_cmd.h> #include <fs_legacy.h> static int do_fs_uuid_wrapper(struct cmd_tbl *cmdtp, int flag, int argc, diff --git a/cmd/host.c b/cmd/host.c index 9832a88a5b0..f037b9b61f9 100644 --- a/cmd/host.c +++ b/cmd/host.c @@ -5,7 +5,7 @@ #include <command.h> #include <dm.h> -#include <fs_legacy.h> +#include <fs_cmd.h> #include <part.h> #include <sandbox_host.h> #include <dm/device_compat.h> diff --git a/cmd/pstore.c b/cmd/pstore.c index ab7ac656383..0eece5bfaf0 100644 --- a/cmd/pstore.c +++ b/cmd/pstore.c @@ -6,7 +6,7 @@ #include <config.h> #include <command.h> #include <fdtdec.h> -#include <fs_legacy.h> +#include <fs_cmd.h> #include <log.h> #include <mapmem.h> #include <memalign.h> diff --git a/cmd/sqfs.c b/cmd/sqfs.c index b10403c4379..463db01714b 100644 --- a/cmd/sqfs.c +++ b/cmd/sqfs.c @@ -8,7 +8,7 @@ */ #include <command.h> -#include <fs_legacy.h> +#include <fs_cmd.h> #include <squashfs.h> static int do_sqfs_ls(struct cmd_tbl *cmdtp, int flag, int argc, char * const argv[]) diff --git a/cmd/test.c b/cmd/test.c index cb24479f5b1..b2e853f379c 100644 --- a/cmd/test.c +++ b/cmd/test.c @@ -5,7 +5,7 @@ */ #include <command.h> -#include <fs_legacy.h> +#include <fs_cmd.h> #include <log.h> #include <vsprintf.h> diff --git a/include/erofs.h b/include/erofs.h index 1fbe82bf72c..26c4d5acefe 100644 --- a/include/erofs.h +++ b/include/erofs.h @@ -2,7 +2,10 @@ #ifndef _EROFS_H_ #define _EROFS_H_ +struct blk_desc; struct disk_partition; +struct fs_dirent; +struct fs_dir_stream; int erofs_opendir(const char *filename, struct fs_dir_stream **dirsp); int erofs_readdir(struct fs_dir_stream *dirs, struct fs_dirent **dentp); diff --git a/include/fs_cmd.h b/include/fs_cmd.h new file mode 100644 index 00000000000..3b58ad516e7 --- /dev/null +++ b/include/fs_cmd.h @@ -0,0 +1,83 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (c) 2012, NVIDIA CORPORATION. All rights reserved. + */ + +#ifndef _FS_CMD_H +#define _FS_CMD_H + +#include <fs_common.h> + +struct cmd_tbl; + +/** + * do_fat_fsload - Run the fatload command + * + * @cmdtp: Command information for fatload + * @flag: Command flags (CMD_FLAG\_...) + * @argc: Number of arguments + * @argv: List of arguments + * Return: result (see enum command_ret_t) + */ +int do_fat_fsload(struct cmd_tbl *cmdtp, int flag, int argc, + char *const argv[]); + +/** + * do_ext2load - Run the ext2load command + * + * @cmdtp: Command information for ext2load + * @flag: Command flags (CMD_FLAG\_...) + * @argc: Number of arguments + * @argv: List of arguments + * Return: result (see enum command_ret_t) + */ +int do_ext2load(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]); + +/* + * Common implementation for various filesystem commands, optionally limited + * to a specific filesystem type via the fstype parameter. + */ +int do_size(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[], + int fstype); +int do_load(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[], + int fstype); +int do_ls(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[], + int fstype); +int file_exists(const char *dev_type, const char *dev_part, const char *file, + int fstype); +int do_save(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[], + int fstype); +int do_rm(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[], + int fstype); +int do_mkdir(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[], + int fstype); +int do_ln(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[], + int fstype); +int do_mv(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[], + int fstype); + +/* + * Determine the UUID of the specified filesystem and print it. Optionally it is + * possible to store the UUID directly in env. + */ +int do_fs_uuid(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[], + int fstype); + +/* + * Determine the type of the specified filesystem and print it. Optionally it is + * possible to store the type directly in env. + */ +int do_fs_type(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]); + +/** + * do_fs_types - List supported filesystems. + * + * @cmdtp: Command information for fstypes + * @flag: Command flags (CMD_FLAG\_...) + * @argc: Number of arguments + * @argv: List of arguments + * Return: result (see enum command_ret_t) + */ +int do_fs_types(struct cmd_tbl *cmdtp, int flag, int argc, char * const argv[]); + +#endif diff --git a/include/fs_legacy.h b/include/fs_legacy.h index 1a01fb09aa1..4a564950b74 100644 --- a/include/fs_legacy.h +++ b/include/fs_legacy.h @@ -9,33 +9,9 @@ #include <rtc.h> struct abuf; -struct cmd_tbl; struct blk_desc; -/** - * do_fat_fsload - Run the fatload command - * - * @cmdtp: Command information for fatload - * @flag: Command flags (CMD_FLAG\_...) - * @argc: Number of arguments - * @argv: List of arguments - * Return: result (see enum command_ret_t) - */ -int do_fat_fsload(struct cmd_tbl *cmdtp, int flag, int argc, - char *const argv[]); - -/** - * do_ext2load - Run the ext2load command - * - * @cmdtp: Command information for ext2load - * @flag: Command flags (CMD_FLAG\_...) - * @argc: Number of arguments - * @argv: List of arguments - * Return: result (see enum command_ret_t) - */ -int do_ext2load(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]); - /* * Tell the fs layer which block device and partition to use for future * commands. This also internally identifies the filesystem that is present @@ -225,53 +201,6 @@ int fs_mkdir(const char *filename); */ int fs_rename(const char *old_path, const char *new_path); -/* - * Common implementation for various filesystem commands, optionally limited - * to a specific filesystem type via the fstype parameter. - */ -int do_size(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[], - int fstype); -int do_load(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[], - int fstype); -int do_ls(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[], - int fstype); -int file_exists(const char *dev_type, const char *dev_part, const char *file, - int fstype); -int do_save(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[], - int fstype); -int do_rm(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[], - int fstype); -int do_mkdir(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[], - int fstype); -int do_ln(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[], - int fstype); -int do_mv(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[], - int fstype); - -/* - * Determine the UUID of the specified filesystem and print it. Optionally it is - * possible to store the UUID directly in env. - */ -int do_fs_uuid(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[], - int fstype); - -/* - * Determine the type of the specified filesystem and print it. Optionally it is - * possible to store the type directly in env. - */ -int do_fs_type(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]); - -/** - * do_fs_types - List supported filesystems. - * - * @cmdtp: Command information for fstypes - * @flag: Command flags (CMD_FLAG\_...) - * @argc: Number of arguments - * @argv: List of arguments - * Return: result (see enum command_ret_t) - */ -int do_fs_types(struct cmd_tbl *cmdtp, int flag, int argc, char * const argv[]); - /** * fs_read_alloc() - Allocate space for a file and read it * diff --git a/include/squashfs.h b/include/squashfs.h index 7489eefa1f2..1e9b6a7a517 100644 --- a/include/squashfs.h +++ b/include/squashfs.h @@ -10,7 +10,10 @@ #ifndef _SQFS_H_ #define _SQFS_H_ +struct blk_desc; struct disk_partition; +struct fs_dirent; +struct fs_dir_stream; int sqfs_opendir(const char *filename, struct fs_dir_stream **dirsp); int sqfs_readdir(struct fs_dir_stream *dirs, struct fs_dirent **dentp); -- 2.43.0

From: Simon Glass <sjg@chromium.org> This existing function does not have any context associated with it. Rename it so that fs_read() can be used for the new FS uclass. Signed-off-by: Simon Glass <sjg@chromium.org> --- boot/bootmeth-uclass.c | 2 +- cmd/mvebu/bubt.c | 6 +++--- cmd/sysboot.c | 2 +- cmd/xxd.c | 2 +- common/spl/spl_blk_fs.c | 4 ++-- common/splash_source.c | 2 +- doc/develop/bootstd/overview.rst | 4 ++-- drivers/bootcount/bootcount_fs.c | 5 +++-- drivers/dfu/dfu_mmc.c | 3 ++- drivers/dfu/dfu_scsi.c | 3 ++- drivers/fpga/zynqpl.c | 8 +++++--- drivers/misc/fs_loader.c | 5 +++-- drivers/net/phy/aquantia.c | 4 ++-- fs/fs_legacy.c | 6 +++--- include/fs_legacy.h | 9 +++++---- lib/efi_loader/efi_file.c | 4 ++-- lib/efi_loader/efi_var_file.c | 4 ++-- test/image/spl_load_fs.c | 5 +++-- 18 files changed, 43 insertions(+), 35 deletions(-) diff --git a/boot/bootmeth-uclass.c b/boot/bootmeth-uclass.c index f49e9c2a008..f0e541c0934 100644 --- a/boot/bootmeth-uclass.c +++ b/boot/bootmeth-uclass.c @@ -421,7 +421,7 @@ int bootmeth_common_read_file(struct udevice *dev, struct bootflow *bflow, if (ret) return log_msg_ret("fs", ret); - ret = fs_read(file_path, addr, 0, 0, &len_read); + ret = fs_legacy_read(file_path, addr, 0, 0, &len_read); if (ret) return ret; *sizep = len_read; diff --git a/cmd/mvebu/bubt.c b/cmd/mvebu/bubt.c index b64d5a5733c..04a48f2a561 100644 --- a/cmd/mvebu/bubt.c +++ b/cmd/mvebu/bubt.c @@ -311,7 +311,7 @@ static size_t mmc_read_file(const char *file_name) } /* Perfrom file read */ - rc = fs_read(file_name, get_load_addr(), 0, 0, &act_read); + rc = fs_legacy_read(file_name, get_load_addr(), 0, 0, &act_read); if (rc) return 0; @@ -448,7 +448,7 @@ static size_t sata_read_file(const char *file_name) } /* Perfrom file read */ - rc = fs_read(file_name, get_load_addr(), 0, 0, &act_read); + rc = fs_legacy_read(file_name, get_load_addr(), 0, 0, &act_read); if (rc) return 0; @@ -624,7 +624,7 @@ static size_t usb_read_file(const char *file_name) } /* Perfrom file read */ - rc = fs_read(file_name, get_load_addr(), 0, 0, &act_read); + rc = fs_legacy_read(file_name, get_load_addr(), 0, 0, &act_read); if (rc) return 0; diff --git a/cmd/sysboot.c b/cmd/sysboot.c index 735c90fa42c..1dad64c9ac5 100644 --- a/cmd/sysboot.c +++ b/cmd/sysboot.c @@ -35,7 +35,7 @@ static int sysboot_read_file(struct pxe_context *ctx, const char *file_path, ret = fs_set_blk_dev(info->ifname, info->dev_part_str, info->fstype); if (ret) return ret; - ret = fs_read(file_path, addr, 0, 0, &len_read); + ret = fs_legacy_read(file_path, addr, 0, 0, &len_read); if (ret) return ret; *sizep = len_read; diff --git a/cmd/xxd.c b/cmd/xxd.c index f1294d763b1..32864d8c906 100644 --- a/cmd/xxd.c +++ b/cmd/xxd.c @@ -59,7 +59,7 @@ static int do_xxd(struct cmd_tbl *cmdtp, int flag, int argc, if (fs_set_blk_dev(ifname, dev, FS_TYPE_ANY)) return CMD_RET_FAILURE; - if (fs_read(file, addr, 0, 0, &file_size)) { + if (fs_legacy_read(file, addr, 0, 0, &file_size)) { log_err("Cannot read file: ifname=%s dev=%s file=%s\n", ifname, dev, file); return CMD_RET_FAILURE; } diff --git a/common/spl/spl_blk_fs.c b/common/spl/spl_blk_fs.c index aa2a031d169..8b458c429a9 100644 --- a/common/spl/spl_blk_fs.c +++ b/common/spl/spl_blk_fs.c @@ -32,8 +32,8 @@ static ulong spl_fit_read(struct spl_load_info *load, ulong file_offset, return ret; } - ret = fs_read(dev->filename, virt_to_phys(buf), file_offset, size, - &actlen); + ret = fs_legacy_read(dev->filename, virt_to_phys(buf), file_offset, + size, &actlen); if (ret < 0) { printf("spl: error reading image %s. Err - %d\n", dev->filename, ret); diff --git a/common/splash_source.c b/common/splash_source.c index f6b51aab017..6bbe705c20e 100644 --- a/common/splash_source.c +++ b/common/splash_source.c @@ -295,7 +295,7 @@ static int splash_load_fs(struct splash_location *location, u32 bmp_load_addr) } splash_select_fs_dev(location); - res = fs_read(splash_file, bmp_load_addr, 0, 0, &actread); + res = fs_legacy_read(splash_file, bmp_load_addr, 0, 0, &actread); out: if (location->ubivol != NULL) diff --git a/doc/develop/bootstd/overview.rst b/doc/develop/bootstd/overview.rst index 7bca043791b..ca76bad7bca 100644 --- a/doc/develop/bootstd/overview.rst +++ b/doc/develop/bootstd/overview.rst @@ -795,8 +795,8 @@ partitions on bootdevs and using bootmeths to find bootflows. How about bootdevs which are not block devices? They are handled by the same methods as above, but with a different implementation. For example, the bootmeth -for PXE boot (over a network) uses `tftp` to read files rather than `fs_read()`. -But other than that it is very similar. +for PXE boot (over a network) uses `tftp` to read files rather than +`fs_legacy_read()`. But other than that it is very similar. Tests diff --git a/drivers/bootcount/bootcount_fs.c b/drivers/bootcount/bootcount_fs.c index f8e1478b7b7..cffe67cbba0 100644 --- a/drivers/bootcount/bootcount_fs.c +++ b/drivers/bootcount/bootcount_fs.c @@ -61,8 +61,9 @@ ulong bootcount_load(void) return 0; } - ret = fs_read(CONFIG_SYS_BOOTCOUNT_FS_NAME, CONFIG_SYS_BOOTCOUNT_ADDR, - 0, sizeof(bootcount_ext_t), &len_read); + ret = fs_legacy_read(CONFIG_SYS_BOOTCOUNT_FS_NAME, + CONFIG_SYS_BOOTCOUNT_ADDR, 0, + sizeof(bootcount_ext_t), &len_read); if (ret != 0 || len_read != sizeof(bootcount_ext_t)) { puts("Error loading bootcount\n"); return 0; diff --git a/drivers/dfu/dfu_mmc.c b/drivers/dfu/dfu_mmc.c index c19eb919388..3814b6c5874 100644 --- a/drivers/dfu/dfu_mmc.c +++ b/drivers/dfu/dfu_mmc.c @@ -128,7 +128,8 @@ static int mmc_file_op(enum dfu_op op, struct dfu_entity *dfu, switch (op) { case DFU_OP_READ: - ret = fs_read(dfu->name, (size_t)buf, offset, *len, &size); + ret = fs_legacy_read(dfu->name, (size_t)buf, offset, *len, + &size); if (ret) { puts("dfu: fs_read error!\n"); return ret; diff --git a/drivers/dfu/dfu_scsi.c b/drivers/dfu/dfu_scsi.c index 9f95194784c..38f9e2e3842 100644 --- a/drivers/dfu/dfu_scsi.c +++ b/drivers/dfu/dfu_scsi.c @@ -107,7 +107,8 @@ static int scsi_file_op(enum dfu_op op, struct dfu_entity *dfu, u64 offset, void switch (op) { case DFU_OP_READ: - ret = fs_read(dfu->name, (size_t)buf, offset, *len, &size); + ret = fs_legacy_read(dfu->name, (size_t)buf, offset, *len, + &size); if (ret) { puts("dfu: fs_read error!\n"); return ret; diff --git a/drivers/fpga/zynqpl.c b/drivers/fpga/zynqpl.c index 0a87eb7917a..763e0718a10 100644 --- a/drivers/fpga/zynqpl.c +++ b/drivers/fpga/zynqpl.c @@ -442,7 +442,7 @@ static int zynq_loadfs(xilinx_desc *desc, const void *buf, size_t bsize, if (fs_set_blk_dev(interface, dev_part, fstype)) return FPGA_FAIL; - if (fs_read(filename, (u32) buf, pos, blocksize, &actread) < 0) + if (fs_legacy_read(filename, (u32)buf, pos, blocksize, &actread) < 0) return FPGA_FAIL; if (zynq_validate_bitstream(desc, buf, bsize, blocksize, &swap, @@ -465,10 +465,12 @@ static int zynq_loadfs(xilinx_desc *desc, const void *buf, size_t bsize, return FPGA_FAIL; if (bsize > blocksize) { - if (fs_read(filename, (u32) buf, pos, blocksize, &actread) < 0) + if (fs_legacy_read(filename, (u32)buf, pos, blocksize, + &actread) < 0) return FPGA_FAIL; } else { - if (fs_read(filename, (u32) buf, pos, bsize, &actread) < 0) + if (fs_legacy_read(filename, (u32)buf, pos, bsize, + &actread) < 0) return FPGA_FAIL; } } while (bsize > blocksize); diff --git a/drivers/misc/fs_loader.c b/drivers/misc/fs_loader.c index cf253c9864e..f52f3b4267e 100644 --- a/drivers/misc/fs_loader.c +++ b/drivers/misc/fs_loader.c @@ -181,8 +181,9 @@ static int fw_get_filesystem_firmware(struct udevice *dev) if (!firmwarep) return -ENOMEM; - ret = fs_read(firmwarep->name, (ulong)map_to_sysmem(firmwarep->data), - firmwarep->offset, firmwarep->size, &actread); + ret = fs_legacy_read(firmwarep->name, + (ulong)map_to_sysmem(firmwarep->data), + firmwarep->offset, firmwarep->size, &actread); if (ret) { debug("Error: %d Failed to read %s from flash %lld != %zu.\n", diff --git a/drivers/net/phy/aquantia.c b/drivers/net/phy/aquantia.c index 5af993a6898..273e16d6b33 100644 --- a/drivers/net/phy/aquantia.c +++ b/drivers/net/phy/aquantia.c @@ -155,8 +155,8 @@ static int aquantia_read_fw(u8 **fw_addr, size_t *fw_length) if (ret < 0) goto cleanup; - ret = fs_read(CONFIG_PHY_AQUANTIA_FW_NAME, (ulong)addr, 0, length, - &read); + ret = fs_legacy_read(CONFIG_PHY_AQUANTIA_FW_NAME, (ulong)addr, 0, + length, &read); if (ret < 0) goto cleanup; diff --git a/fs/fs_legacy.c b/fs/fs_legacy.c index 5be041e2133..5a7a3ae4194 100644 --- a/fs/fs_legacy.c +++ b/fs/fs_legacy.c @@ -638,8 +638,8 @@ static int _fs_read(const char *filename, ulong addr, loff_t offset, loff_t len, return ret; } -int fs_read(const char *filename, ulong addr, loff_t offset, loff_t len, - loff_t *actread) +int fs_legacy_read(const char *filename, ulong addr, loff_t offset, loff_t len, + loff_t *actread) { return _fs_read(filename, addr, offset, len, 0, actread); } @@ -1141,7 +1141,7 @@ int fs_read_alloc(const char *fname, ulong size, uint align, struct abuf *buf) return log_msg_ret("buf", -ENOMEM); buf->size--; - ret = fs_read(fname, abuf_addr(buf), 0, size, &bytes_read); + ret = fs_legacy_read(fname, abuf_addr(buf), 0, size, &bytes_read); if (ret) { abuf_uninit(buf); return log_msg_ret("read", ret); diff --git a/include/fs_legacy.h b/include/fs_legacy.h index 4a564950b74..f1be6fbdc13 100644 --- a/include/fs_legacy.h +++ b/include/fs_legacy.h @@ -53,7 +53,7 @@ int fs_set_blk_dev_with_part(struct blk_desc *desc, int part); * fs_set_blk_dev() or fs_set_dev_with_part(). * * Many file functions implicitly call fs_close(), e.g. fs_closedir(), - * fs_exist(), fs_ln(), fs_ls(), fs_mkdir(), fs_read(), fs_size(), fs_write(), + * fs_exist(), fs_ln(), fs_ls(), fs_mkdir(), fs_legacy_read(), fs_size(), fs_write(), * fs_unlink(), fs_rename(). */ void fs_close(void); @@ -103,7 +103,8 @@ int fs_exists(const char *filename); int fs_size(const char *filename, loff_t *size); /** - * fs_read() - read file from the partition previously set by fs_set_blk_dev() + * fs_legacy_read() - read file from the partition previously set by + * fs_set_blk_dev() * * Note that not all filesystem drivers support either or both of offset != 0 * and len != 0. @@ -115,8 +116,8 @@ int fs_size(const char *filename, loff_t *size); * @actread: returns the actual number of bytes read * Return: 0 if OK with valid @actread, -1 on error conditions */ -int fs_read(const char *filename, ulong addr, loff_t offset, loff_t len, - loff_t *actread); +int fs_legacy_read(const char *filename, ulong addr, loff_t offset, loff_t len, + loff_t *actread); /** * fs_write() - write file to the partition previously set by fs_set_blk_dev() diff --git a/lib/efi_loader/efi_file.c b/lib/efi_loader/efi_file.c index 65bc99b961b..2aa9f191731 100644 --- a/lib/efi_loader/efi_file.c +++ b/lib/efi_loader/efi_file.c @@ -484,8 +484,8 @@ static efi_status_t file_read(struct file_handle *fh, u64 *buffer_size, if (set_blk_dev(fh)) return EFI_DEVICE_ERROR; - if (fs_read(fh->path, map_to_sysmem(buffer), fh->offset, - *buffer_size, &actread)) + if (fs_legacy_read(fh->path, map_to_sysmem(buffer), fh->offset, + *buffer_size, &actread)) return EFI_DEVICE_ERROR; *buffer_size = actread; diff --git a/lib/efi_loader/efi_var_file.c b/lib/efi_loader/efi_var_file.c index f3f034dde48..3c6247dc858 100644 --- a/lib/efi_loader/efi_var_file.c +++ b/lib/efi_loader/efi_var_file.c @@ -170,8 +170,8 @@ efi_status_t efi_var_from_file(void) ret = efi_set_blk_dev_to_system_partition(); if (ret != EFI_SUCCESS) goto error; - r = fs_read(EFI_VAR_FILE_NAME, map_to_sysmem(buf), 0, EFI_VAR_BUF_SIZE, - &len); + r = fs_legacy_read(EFI_VAR_FILE_NAME, map_to_sysmem(buf), 0, + EFI_VAR_BUF_SIZE, &len); if (r || len < sizeof(struct efi_var_file)) { log_err("Failed to load EFI variables\n"); goto error; diff --git a/test/image/spl_load_fs.c b/test/image/spl_load_fs.c index 4663729f58c..ca1a8a9c6c8 100644 --- a/test/image/spl_load_fs.c +++ b/test/image/spl_load_fs.c @@ -282,8 +282,9 @@ static int spl_test_fs(struct unit_test_state *uts, const char *test_name, data_read = malloc_cache_aligned(data_size); ut_assertnonnull(data_read); ut_assertok(fs_set_blk_dev_with_part(dev_desc, 0)); - ut_assertok(fs_read("/" CONFIG_SPL_FS_LOAD_PAYLOAD_NAME, - virt_to_phys(data_read), 0, data_size, &actread)); + ut_assertok(fs_legacy_read("/" CONFIG_SPL_FS_LOAD_PAYLOAD_NAME, + virt_to_phys(data_read), 0, data_size, + &actread)); ut_asserteq(data_size, actread); ut_asserteq_mem(data_write, data_read, data_size); -- 2.43.0

From: Simon Glass <sjg@chromium.org> The existing disk and partition code assumes a block device. Sandbox provides access to host files and does not operate through a block device. This is currently handled with special-case logic. We want to add virtio-fs support, which is also not a block device. It is not easy to have these two co-exist, so add a new type field to struct disk_partition to indicate the type. This is a work-around to deal with the fact that the type needs to be set by blk_get_device_part_str() in such a way that it is visible to fs_readdir() There is a global fs_type in disk/part.c but this is not available in the fs/ code. Signed-off-by: Simon Glass <sjg@chromium.org> --- disk/part.c | 3 ++- fs/fs_legacy.c | 4 ++++ include/part.h | 2 ++ 3 files changed, 8 insertions(+), 1 deletion(-) diff --git a/disk/part.c b/disk/part.c index 303178161c0..bab27ba07d8 100644 --- a/disk/part.c +++ b/disk/part.c @@ -477,7 +477,8 @@ int blk_get_device_part_str(const char *ifname, const char *dev_part_str, if (!strcmp(ifname, "hostfs")) { strcpy((char *)info->type, BOOT_PART_TYPE); strcpy((char *)info->name, "Host filesystem"); - + info->fs_type = IS_ENABLED(CONFIG_SANDBOX) ? FS_TYPE_SANDBOX : + FS_TYPE_SEMIHOSTING; return 0; } #endif diff --git a/fs/fs_legacy.c b/fs/fs_legacy.c index 5a7a3ae4194..82936142c07 100644 --- a/fs/fs_legacy.c +++ b/fs/fs_legacy.c @@ -483,7 +483,11 @@ int fs_set_blk_dev(const char *ifname, const char *dev_part_str, int fstype) if (!fs_dev_desc && !info->null_dev_desc_ok) continue; + if (fs_partition.fs_type && + fs_partition.fs_type != info->fstype) + continue; + log_debug("probe %s\n", info->name); if (!info->probe(fs_dev_desc, &fs_partition)) { fs_type = info->fstype; fs_dev_part = part; diff --git a/include/part.h b/include/part.h index fcb3c13dea4..0fd7c18d6b6 100644 --- a/include/part.h +++ b/include/part.h @@ -7,6 +7,7 @@ #define _PART_H #include <blk.h> +#include <fs_common.h> #include <ide.h> #include <u-boot/uuid.h> #include <linker_lists.h> @@ -84,6 +85,7 @@ struct disk_partition { #ifdef CONFIG_DOS_PARTITION uchar sys_ind; /* partition type */ #endif + enum fs_type_t fs_type; /* type used for hostfs and virtio-fs */ }; /* Accessors for struct disk_partition field ->uuid */ -- 2.43.0

From: Simon Glass <sjg@chromium.org> Add more enum values so we can use these in the tests, instead of adding comments. This makes it easier to adjust tests when new hunters are added. Signed-off-by: Simon Glass <sjg@chromium.org> --- test/boot/bootdev.c | 35 ++++++++++++++++++----------------- test/boot/bootflow.c | 4 ++-- test/boot/bootstd_common.h | 10 ++++++++-- 3 files changed, 28 insertions(+), 21 deletions(-) diff --git a/test/boot/bootdev.c b/test/boot/bootdev.c index 84280caf7b5..cd1d00bfbe0 100644 --- a/test/boot/bootdev.c +++ b/test/boot/bootdev.c @@ -398,7 +398,7 @@ static int bootdev_test_hunter(struct unit_test_state *uts) ut_assert_nextline(" 4 spi_flash sf_bootdev"); ut_assert_nextline(" 5 usb usb_bootdev"); ut_assert_nextline(" 4 virtio virtio_bootdev"); - ut_assert_nextline("(total hunters: 10)"); + ut_assert_nextline("(total hunters: %d)", HUNTER_COUNT); ut_assert_console_end(); ut_assertok(bootdev_hunt("usb1", false)); @@ -406,8 +406,7 @@ static int bootdev_test_hunter(struct unit_test_state *uts) "Bus usb@1: scanning bus usb@1 for devices... 6 USB Device(s) found"); ut_assert_console_end(); - /* USB is 7th in the list, so bit 8 */ - ut_asserteq(BIT(8), std->hunters_used); + ut_asserteq(BIT(HUNTER_USB), std->hunters_used); return 0; } @@ -428,7 +427,7 @@ static int bootdev_test_cmd_hunt(struct unit_test_state *uts) ut_assert_nextline("Prio Used Uclass Hunter"); ut_assert_nextlinen("----"); ut_assert_nextline(" 6 ethernet eth_bootdev"); - ut_assert_skip_to_line("(total hunters: 10)"); + ut_assert_skip_to_line("(total hunters: %d)", HUNTER_COUNT); ut_assert_console_end(); /* Use the MMC hunter and see that it updates */ @@ -436,7 +435,7 @@ static int bootdev_test_cmd_hunt(struct unit_test_state *uts) ut_assertok(run_command("bootdev hunt -l", 0)); ut_assert_skip_to_line(" 5 ide ide_bootdev"); ut_assert_nextline(" 2 * mmc mmc_bootdev"); - ut_assert_skip_to_line("(total hunters: 10)"); + ut_assert_skip_to_line("(total hunters: %d)", HUNTER_COUNT); ut_assert_console_end(); /* Scan all hunters */ @@ -477,10 +476,10 @@ static int bootdev_test_cmd_hunt(struct unit_test_state *uts) ut_assert_nextline(" 4 * spi_flash sf_bootdev"); ut_assert_nextline(" 5 * usb usb_bootdev"); ut_assert_nextline(" 4 * virtio virtio_bootdev"); - ut_assert_nextline("(total hunters: 10)"); + ut_assert_nextline("(total hunters: %d)", HUNTER_COUNT); ut_assert_console_end(); - ut_asserteq(GENMASK(MAX_HUNTER, 0), std->hunters_used); + ut_asserteq(GENMASK(HUNTER_MAX, 0), std->hunters_used); return 0; } @@ -501,7 +500,8 @@ static int bootdev_test_hunt_scan(struct unit_test_state *uts) ut_assertok(bootflow_scan_first(NULL, NULL, &iter, BOOTFLOWIF_SHOW | BOOTFLOWIF_HUNT | BOOTFLOWIF_SKIP_GLOBAL, &bflow)); - ut_asserteq(BIT(MMC_HUNTER) | BIT(1), std->hunters_used); + ut_asserteq(BIT(HUNTER_MMC) | BIT(HUNTER_SIMPLE_BUS), + std->hunters_used); return 0; } @@ -662,8 +662,7 @@ static int bootdev_test_next_label(struct unit_test_state *uts) ut_asserteq_str("scsi.id0lun0.bootdev", dev->name); ut_asserteq(BOOTFLOW_METHF_SINGLE_UCLASS, mflags); - /* SCSI is 7th in the list, so bit 6 */ - ut_asserteq(BIT(MMC_HUNTER) | BIT(6), std->hunters_used); + ut_asserteq(BIT(HUNTER_MMC) | BIT(HUNTER_SCSI), std->hunters_used); ut_assertok(bootdev_next_label(&iter, &dev, &mflags)); ut_assert_console_end(); @@ -672,8 +671,8 @@ static int bootdev_test_next_label(struct unit_test_state *uts) ut_asserteq(BOOTFLOW_METHF_SINGLE_UCLASS | BOOTFLOW_METHF_DHCP_ONLY, mflags); - /* dhcp: Ethernet is first so bit 0 */ - ut_asserteq(BIT(MMC_HUNTER) | BIT(6) | BIT(0), std->hunters_used); + ut_asserteq(BIT(HUNTER_MMC) | BIT(HUNTER_SCSI) | BIT(HUNTER_ETH), + std->hunters_used); ut_assertok(bootdev_next_label(&iter, &dev, &mflags)); ut_assert_console_end(); @@ -682,8 +681,8 @@ static int bootdev_test_next_label(struct unit_test_state *uts) ut_asserteq(BOOTFLOW_METHF_SINGLE_UCLASS | BOOTFLOW_METHF_PXE_ONLY, mflags); - /* pxe: Ethernet is first so bit 0 */ - ut_asserteq(BIT(MMC_HUNTER) | BIT(6) | BIT(0), std->hunters_used); + ut_asserteq(BIT(HUNTER_MMC) | BIT(HUNTER_SCSI) | BIT(HUNTER_ETH), + std->hunters_used); mflags = 123; ut_asserteq(-ENODEV, bootdev_next_label(&iter, &dev, &mflags)); @@ -691,7 +690,8 @@ static int bootdev_test_next_label(struct unit_test_state *uts) ut_assert_console_end(); /* no change */ - ut_asserteq(BIT(MMC_HUNTER) | BIT(6) | BIT(0), std->hunters_used); + ut_asserteq(BIT(HUNTER_MMC) | BIT(HUNTER_SCSI) | BIT(HUNTER_ETH), + std->hunters_used); return 0; } @@ -741,7 +741,8 @@ static int bootdev_test_next_prio(struct unit_test_state *uts) ut_assert_nextline("Hunting with: mmc"); ut_assert_console_end(); - ut_asserteq(BIT(MMC_HUNTER) | BIT(1), std->hunters_used); + ut_asserteq(BIT(HUNTER_MMC) | BIT(HUNTER_SIMPLE_BUS), + std->hunters_used); ut_assertok(bootdev_next_prio(&iter, &dev)); ut_asserteq_str("mmc1.bootdev", dev->name); @@ -772,7 +773,7 @@ static int bootdev_test_next_prio(struct unit_test_state *uts) } while (!ret); ut_asserteq(-ENODEV, ret); ut_assertnull(dev); - ut_asserteq(GENMASK(MAX_HUNTER, 0), std->hunters_used); + ut_asserteq(GENMASK(HUNTER_MAX, 0), std->hunters_used); ut_assert_skip_to_line("Hunting with: ethernet"); ut_assert_console_end(); diff --git a/test/boot/bootflow.c b/test/boot/bootflow.c index 15d2cb535cb..cac5e0b1a35 100644 --- a/test/boot/bootflow.c +++ b/test/boot/bootflow.c @@ -802,7 +802,7 @@ static int bootflow_cmd_hunt_single(struct unit_test_state *uts) ut_assert_console_end(); /* check that the hunter was used */ - ut_asserteq(BIT(MMC_HUNTER) | BIT(1), std->hunters_used); + ut_asserteq(BIT(HUNTER_MMC) | BIT(1), std->hunters_used); return 0; } @@ -824,7 +824,7 @@ static int bootflow_cmd_hunt_label(struct unit_test_state *uts) ut_assertok(run_command("bootflow scan -l mmc", 0)); /* check that the hunter was used */ - ut_asserteq(BIT(MMC_HUNTER) | BIT(1), std->hunters_used); + ut_asserteq(BIT(HUNTER_MMC) | BIT(1), std->hunters_used); /* check that we got the mmc1 bootflow */ ut_assert_nextline("Scanning for bootflows with label 'mmc'"); diff --git a/test/boot/bootstd_common.h b/test/boot/bootstd_common.h index c61698adc02..945515f7da8 100644 --- a/test/boot/bootstd_common.h +++ b/test/boot/bootstd_common.h @@ -20,9 +20,15 @@ #define TEST_VERSION "U-Boot v2022.04-local2" #define TEST_VERNUM 0x00010002 +/* IDs for hunters, which is dependent on their binding order */ enum { - MAX_HUNTER = 9, - MMC_HUNTER = 3, /* ID of MMC hunter */ + HUNTER_ETH = 0, + HUNTER_SIMPLE_BUS, + HUNTER_MMC = 3, + HUNTER_SCSI = 6, + HUNTER_USB = 8, + HUNTER_COUNT = 10, + HUNTER_MAX = HUNTER_COUNT - 1, }; struct unit_test_state; -- 2.43.0

From: Simon Glass <sjg@chromium.org> The existing filesystem support is fairly basic. It supports access to only one filesystem at a time, does not allow caching, does not have an equivalent of Linux's VFS and uses global variables to keep track of which one is in use. As a starting point to improving this, provide a filesystem uclass. For now it only includes operations to mount and unmount. Provide a bootdev so that it is possible to locate bootflows on a filesystem. Signed-off-by: Simon Glass <sjg@chromium.org> --- MAINTAINERS | 6 ++ fs/Kconfig | 8 +++ fs/Makefile | 1 + fs/fs-uclass.c | 113 +++++++++++++++++++++++++++++++++++++ include/dm/uclass-id.h | 1 + include/fs.h | 78 +++++++++++++++++++++++++ test/boot/bootdev.c | 3 + test/boot/bootstd_common.h | 9 +-- 8 files changed, 215 insertions(+), 4 deletions(-) create mode 100644 fs/fs-uclass.c create mode 100644 include/fs.h diff --git a/MAINTAINERS b/MAINTAINERS index b3875718bce..08b57e5306e 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -1182,6 +1182,12 @@ F: net/fastboot_tcp.c F: net/fastboot_udp.c F: test/dm/fastboot.c +FILESYSTEM LAYER +M: Simon Glass <sjg@chromium.org> +S: Maintained +F: fs/fs-uclass.c +F: include/fs.h + FPGA M: Michal Simek <michal.simek@amd.com> S: Maintained diff --git a/fs/Kconfig b/fs/Kconfig index 490f9755016..f7951b483aa 100644 --- a/fs/Kconfig +++ b/fs/Kconfig @@ -4,6 +4,14 @@ menu "File systems" +config FS + bool "Support for filesystems" + default y if SANDBOX || VENDOR_EMULATION || ARCH_QEMU + depends on EXPERT + help + Provides an interface for filesystems, allowing them to be + persistently mounted. Filesystem can contain files and directory. + config FS_LEGACY def_bool y help diff --git a/fs/Makefile b/fs/Makefile index 02c32aa8287..75959d06f12 100644 --- a/fs/Makefile +++ b/fs/Makefile @@ -5,6 +5,7 @@ # Copyright (c) 2012, NVIDIA CORPORATION. All rights reserved. obj-$(CONFIG_$(PHASE_)FS_LEGACY) += fs_legacy.o fs_internal.o +obj-$(CONFIG_$(PHASE_)FS) += fs-uclass.o ifdef CONFIG_XPL_BUILD obj-$(CONFIG_SPL_FS_FAT) += fat/ diff --git a/fs/fs-uclass.c b/fs/fs-uclass.c new file mode 100644 index 00000000000..9e698972df8 --- /dev/null +++ b/fs/fs-uclass.c @@ -0,0 +1,113 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Implementation of a filesystem, e.g. on a partition + * + * Copyright 2025 Simon Glass <sjg@chromium.org> + */ + +#define LOG_DEBUG +#define LOG_CATEGORY UCLASS_FS + +#include <bootdev.h> +#include <bootmeth.h> +#include <dm.h> +#include <fs.h> +#include <dm/device-internal.h> + +int fs_mount(struct udevice *dev) +{ + struct fs_ops *ops = fs_get_ops(dev); + int ret; + + ret = ops->mount(dev); + if (ret) + return log_msg_ret("fsm", ret); + + ret = bootdev_setup_for_dev(dev, "fs_bootdev"); + if (ret) + return log_msg_ret("fss", ret); + + return 0; +} + +int fs_unmount(struct udevice *dev) +{ + struct fs_ops *ops = fs_get_ops(dev); + + return ops->unmount(dev); +} + +static int fs_get_bootflow(struct udevice *dev, struct bootflow_iter *iter, + struct bootflow *bflow) +{ + struct udevice *fsdev = dev_get_parent(dev); + int ret; + + log_debug("get_bootflow fs '%s'\n", fsdev->name); + + ret = bootmeth_check(bflow->method, iter); + if (ret) + return log_msg_ret("check", ret); + + return 0; +} + +static int fs_bootdev_bind(struct udevice *dev) +{ + struct bootdev_uc_plat *ucp = dev_get_uclass_plat(dev); + + /* + * we don't know what priority to give this, so pick something a little + * slow for now + */ + ucp->prio = BOOTDEVP_3_INTERNAL_SLOW; + + return 0; +} + +static int fs_bootdev_hunt(struct bootdev_hunter *info, bool show) +{ + struct udevice *dev; + int ret; + + /* mount all filesystems, which will create bootdevs for each */ + uclass_foreach_dev_probe(UCLASS_FS, dev) { + ret = fs_mount(dev); + if (ret) + log_warning("Failed to mount filesystem '%s'\n", + dev->name); + } + + return 0; +} + +struct bootdev_ops fs_bootdev_ops = { + .get_bootflow = fs_get_bootflow, +}; + +static const struct udevice_id fs_bootdev_ids[] = { + { .compatible = "u-boot,bootdev-fs" }, + { } +}; + +U_BOOT_DRIVER(fs_bootdev) = { + .name = "fs_bootdev", + .id = UCLASS_BOOTDEV, + .ops = &fs_bootdev_ops, + .bind = fs_bootdev_bind, + .of_match = fs_bootdev_ids, +}; + +BOOTDEV_HUNTER(fs_bootdev_hunter) = { + .prio = BOOTDEVP_3_INTERNAL_SLOW, + .uclass = UCLASS_FS, + .hunt = fs_bootdev_hunt, + .drv = DM_DRIVER_REF(fs_bootdev), +}; + +UCLASS_DRIVER(fs) = { + .name = "fs", + .id = UCLASS_FS, + .per_device_auto = sizeof(struct fs_priv), + .per_device_plat_auto = sizeof(struct fs_plat), +}; diff --git a/include/dm/uclass-id.h b/include/dm/uclass-id.h index 4818d9bd272..45e9abfce32 100644 --- a/include/dm/uclass-id.h +++ b/include/dm/uclass-id.h @@ -68,6 +68,7 @@ enum uclass_id { UCLASS_FIRMWARE, /* Firmware */ UCLASS_FPGA, /* FPGA device */ UCLASS_FUZZING_ENGINE, /* Fuzzing engine */ + UCLASS_FS, /* Filesystem */ UCLASS_FS_FIRMWARE_LOADER, /* Generic loader */ UCLASS_FWU_MDATA, /* FWU Metadata Access */ UCLASS_GPIO, /* Bank of general-purpose I/O pins */ diff --git a/include/fs.h b/include/fs.h new file mode 100644 index 00000000000..05a2ac844b8 --- /dev/null +++ b/include/fs.h @@ -0,0 +1,78 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * U-Boot Filesystem layer + * + * Models a filesystem which can be mounted and unmounted. It also allows a + * directory to be looked up. + * + * Copyright 2025 Simon Glass <sjg@chromium.org> + */ + +#ifndef __FS_H +#define __FS_H + +#include <fs_common.h> + +struct udevice; + +enum { + /* Maximum length of the filesystem name */ + FS_MAX_NAME_LEN = 128, +}; + +/** + * struct fs_plat - Filesystem information + * + * @name: Name of the filesystem, or empty if not available + */ +struct fs_plat { + char name[FS_MAX_NAME_LEN]; +}; + +/** + * struct fs_priv - Private information for the FS devices + * + * @mounted: true if mounted + */ +struct fs_priv { + bool mounted; +}; + +struct fs_ops { + /** + * mount() - Mount the filesystem + * + * @dev: Filesystem device + * Return 0 if OK, -EISCONN if already mounted, other -ve on error + */ + int (*mount)(struct udevice *dev); + + /** + * unmount() - Unmount the filesystem + * + * @dev: Filesystem device + * Return 0 if OK, -ENOTCONN if not mounted, other -ve on error + */ + int (*unmount)(struct udevice *dev); +}; + +/* Get access to a filesystem's operations */ +#define fs_get_ops(dev) ((struct fs_ops *)(dev)->driver->ops) + +/** + * fs_mount() - Mount the filesystem + * + * @dev: Filesystem device + * Return 0 if OK, -EISCONN if already mounted, other -ve on error + */ +int fs_mount(struct udevice *dev); + +/** + * fs_unmount() - Unmount the filesystem + * + * @dev: Filesystem device + * Return 0 if OK, -ENOTCONN if not mounted, other -ve on error + */ +int fs_unmount(struct udevice *dev); + +#endif diff --git a/test/boot/bootdev.c b/test/boot/bootdev.c index cd1d00bfbe0..a578af5ccf0 100644 --- a/test/boot/bootdev.c +++ b/test/boot/bootdev.c @@ -390,6 +390,7 @@ static int bootdev_test_hunter(struct unit_test_state *uts) ut_assert_nextlinen("----"); ut_assert_nextline(" 6 ethernet eth_bootdev"); ut_assert_nextline(" 1 simple_bus (none)"); + ut_assert_nextline(" 3 fs fs_bootdev"); ut_assert_nextline(" 5 ide ide_bootdev"); ut_assert_nextline(" 2 mmc mmc_bootdev"); ut_assert_nextline(" 4 nvme nvme_bootdev"); @@ -447,6 +448,7 @@ static int bootdev_test_cmd_hunt(struct unit_test_state *uts) /* This is the extension feature which has no uclass at present */ ut_assert_nextline("Hunting with: simple_bus"); ut_assert_nextline("Found 2 extension board(s)."); + ut_assert_nextline("Hunting with: fs"); ut_assert_nextline("Hunting with: ide"); /* mmc hunter has already been used so should not run again */ @@ -468,6 +470,7 @@ static int bootdev_test_cmd_hunt(struct unit_test_state *uts) ut_assert_nextlinen("----"); ut_assert_nextline(" 6 * ethernet eth_bootdev"); ut_assert_nextline(" 1 * simple_bus (none)"); + ut_assert_nextline(" 3 * fs fs_bootdev"); ut_assert_nextline(" 5 * ide ide_bootdev"); ut_assert_nextline(" 2 * mmc mmc_bootdev"); ut_assert_nextline(" 4 * nvme nvme_bootdev"); diff --git a/test/boot/bootstd_common.h b/test/boot/bootstd_common.h index 945515f7da8..ce049ad8bd1 100644 --- a/test/boot/bootstd_common.h +++ b/test/boot/bootstd_common.h @@ -24,10 +24,11 @@ enum { HUNTER_ETH = 0, HUNTER_SIMPLE_BUS, - HUNTER_MMC = 3, - HUNTER_SCSI = 6, - HUNTER_USB = 8, - HUNTER_COUNT = 10, + HUNTER_FS = 3, + HUNTER_MMC, /* ID of MMC hunter */ + HUNTER_SCSI = 7, /* ID of SCSI hunter */ + HUNTER_USB = 9, /* ID of USB hunter */ + HUNTER_COUNT = 11, HUNTER_MAX = HUNTER_COUNT - 1, }; -- 2.43.0

From: Simon Glass <sjg@chromium.org> Add a simple test of a filesystem on sandbox. Signed-off-by: Simon Glass <sjg@chromium.org> --- MAINTAINERS | 2 ++ arch/sandbox/dts/test.dts | 13 ++++++++ drivers/virtio/virtio_sandbox.c | 3 ++ fs/fs-uclass.c | 4 ++- fs/sandbox/sandboxfs.c | 59 +++++++++++++++++++++++++++++++++ include/dt-bindings/virtio.h | 1 + test/boot/bootdev.c | 5 ++- test/dm/Makefile | 1 + test/dm/fs.c | 28 ++++++++++++++++ 9 files changed, 114 insertions(+), 2 deletions(-) create mode 100644 test/dm/fs.c diff --git a/MAINTAINERS b/MAINTAINERS index 08b57e5306e..14a0e2a9de3 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -1186,7 +1186,9 @@ FILESYSTEM LAYER M: Simon Glass <sjg@chromium.org> S: Maintained F: fs/fs-uclass.c +F: fs/sandbox/sandboxfs.c F: include/fs.h +F: test/dm/fs.c FPGA M: Michal Simek <michal.simek@amd.com> diff --git a/arch/sandbox/dts/test.dts b/arch/sandbox/dts/test.dts index c880cc56818..760153f99a3 100644 --- a/arch/sandbox/dts/test.dts +++ b/arch/sandbox/dts/test.dts @@ -575,6 +575,10 @@ compatible = "denx,u-boot-devres-test"; }; + fs { + compatible = "sandbox,fs"; + }; + another-test { reg = <0 2>; compatible = "denx,u-boot-fdt-test"; @@ -1712,6 +1716,15 @@ }; }; + sandbox-virtio-fs { + compatible = "sandbox,virtio1"; + virtio-type = <VIRTIO_ID_FS>; + + virtio-fs { + compatible = "virtio,fs"; + }; + }; + sandbox_scmi { compatible = "sandbox,scmi-devices"; power-domains = <&pwrdom_scmi 2>; diff --git a/drivers/virtio/virtio_sandbox.c b/drivers/virtio/virtio_sandbox.c index 0f1ebef22e5..857acd672ca 100644 --- a/drivers/virtio/virtio_sandbox.c +++ b/drivers/virtio/virtio_sandbox.c @@ -219,4 +219,7 @@ U_BOOT_DRIVER(virtio_sandbox2) = { .ops = &virtio_sandbox2_ops, .probe = virtio_sandbox_probe, .priv_auto = sizeof(struct virtio_sandbox_priv), +#if CONFIG_IS_ENABLED(OF_REAL) + .bind = dm_scan_fdt_dev, +#endif }; diff --git a/fs/fs-uclass.c b/fs/fs-uclass.c index 9e698972df8..d92b0e24538 100644 --- a/fs/fs-uclass.c +++ b/fs/fs-uclass.c @@ -5,7 +5,6 @@ * Copyright 2025 Simon Glass <sjg@chromium.org> */ -#define LOG_DEBUG #define LOG_CATEGORY UCLASS_FS #include <bootdev.h> @@ -45,6 +44,9 @@ static int fs_get_bootflow(struct udevice *dev, struct bootflow_iter *iter, log_debug("get_bootflow fs '%s'\n", fsdev->name); + /* for now, always fail here as we don't have FS support in bootmeths */ + return -ENOENT; + ret = bootmeth_check(bflow->method, iter); if (ret) return log_msg_ret("check", ret); diff --git a/fs/sandbox/sandboxfs.c b/fs/sandbox/sandboxfs.c index bfb30ef47fe..74c94528cf4 100644 --- a/fs/sandbox/sandboxfs.c +++ b/fs/sandbox/sandboxfs.c @@ -1,14 +1,24 @@ // SPDX-License-Identifier: GPL-2.0+ /* + * Provides access to the host filesystem from sandbox + * * Copyright (c) 2012, Google Inc. */ +#include <dm.h> #include <stdio.h> +#include <fs.h> #include <fs_legacy.h> #include <malloc.h> #include <os.h> #include <sandboxfs.h> +/** + * struct sandbox_fs_priv - Private info about the sandbox filesystem + */ +struct sandbox_fs_priv { +}; + int sandbox_fs_set_blk_dev(struct blk_desc *rbdd, struct disk_partition *info) { /* @@ -142,3 +152,52 @@ int fs_write_sandbox(const char *filename, void *buf, loff_t offset, return ret; } + +static int sandbox_fs_mount(struct udevice *dev) +{ + struct fs_priv *uc_priv = dev_get_uclass_priv(dev); + + if (uc_priv->mounted) + return log_msg_ret("vfi", -EISCONN); + + uc_priv->mounted = true; + + return 0; +} + +static int sandbox_fs_unmount(struct udevice *dev) +{ + struct fs_priv *uc_priv = dev_get_uclass_priv(dev); + + if (!uc_priv->mounted) + return log_msg_ret("vfu", -ENOTCONN); + + uc_priv->mounted = false; + + return 0; +} + +static int sandbox_fs_remove(struct udevice *dev) +{ + return 0; +} + +static const struct fs_ops sandbox_fs_ops = { + .mount = sandbox_fs_mount, + .unmount = sandbox_fs_unmount, +}; + +static const struct udevice_id sandbox_fs_ids[] = { + { .compatible = "sandbox,fs" }, + { } +}; + +U_BOOT_DRIVER(sandbox_fs) = { + .name = "sandbox_fs", + .id = UCLASS_FS, + .of_match = sandbox_fs_ids, + .ops = &sandbox_fs_ops, + .remove = sandbox_fs_remove, + .priv_auto = sizeof(struct sandbox_fs_priv), + .flags = DM_FLAG_ACTIVE_DMA, +}; diff --git a/include/dt-bindings/virtio.h b/include/dt-bindings/virtio.h index 9e3fea14567..8de4a9efcfa 100644 --- a/include/dt-bindings/virtio.h +++ b/include/dt-bindings/virtio.h @@ -15,5 +15,6 @@ #define VIRTIO_ID_BLOCK 2 /* virtio block */ #define VIRTIO_ID_RNG 4 /* virtio rng */ #define VIRTIO_ID_MAX_NUM 27 +#define VIRTIO_ID_FS 26 /* virtio filesystem */ #endif diff --git a/test/boot/bootdev.c b/test/boot/bootdev.c index a578af5ccf0..b1966f7d72c 100644 --- a/test/boot/bootdev.c +++ b/test/boot/bootdev.c @@ -365,7 +365,7 @@ static int bootdev_test_prio(struct unit_test_state *uts) ut_asserteq(0, bootflow_scan_next(&iter, &bflow)); ut_asserteq(-ENODEV, bootflow_scan_next(&iter, &bflow)); - ut_asserteq(8, iter.num_devs); + ut_asserteq(9, iter.num_devs); ut_asserteq_str("hub1.p1.usb_mass_storage.lun0.bootdev", iter.dev_used[0]->name); ut_asserteq_str("mmc2.bootdev", iter.dev_used[1]->name); @@ -754,6 +754,9 @@ static int bootdev_test_next_prio(struct unit_test_state *uts) ut_asserteq_str("mmc0.bootdev", dev->name); ut_assert_console_end(); + ut_assertok(bootdev_next_prio(&iter, &dev)); + ut_assert_nextline("Hunting with: fs"); + ut_assertok(bootdev_next_prio(&iter, &dev)); ut_asserteq_str("spi.bin@0.bootdev", dev->name); ut_assert_skip_to_line("Hunting with: spi_flash"); diff --git a/test/dm/Makefile b/test/dm/Makefile index 7ddd3e78e23..eab78d3ac4a 100644 --- a/test/dm/Makefile +++ b/test/dm/Makefile @@ -39,6 +39,7 @@ obj-$(CONFIG_DM_REBOOT_MODE) += reboot-mode.o obj-$(CONFIG_CLK) += clk.o clk_ccf.o obj-$(CONFIG_CPU) += cpu.o obj-$(CONFIG_CROS_EC) += cros_ec.o +obj-$(CONFIG_FS) += fs.o obj-$(CONFIG_PWM_CROS_EC) += cros_ec_pwm.o obj-$(CONFIG_$(PHASE_)DEVRES) += devres.o obj-$(CONFIG_DMA) += dma.o diff --git a/test/dm/fs.c b/test/dm/fs.c new file mode 100644 index 00000000000..d82d2250c59 --- /dev/null +++ b/test/dm/fs.c @@ -0,0 +1,28 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Tests for the filesystems layer + * + * Copyright 2025 Simon Glass <sjg@chromium.org> + */ + +#include <dm.h> +#include <fs.h> +#include <dm/test.h> +#include <test/ut.h> + +/* Test basic filesystem access */ +static int dm_test_fs_base(struct unit_test_state *uts) +{ + struct udevice *dev; + + ut_assertok(uclass_first_device_err(UCLASS_FS, &dev)); + + ut_assertok(fs_mount(dev)); + ut_asserteq(-EISCONN, fs_mount(dev)); + + ut_assertok(fs_unmount(dev)); + ut_asserteq(-ENOTCONN, fs_unmount(dev)); + + return 0; +} +DM_TEST(dm_test_fs_base, UTF_SCAN_FDT); -- 2.43.0

From: Simon Glass <sjg@chromium.org> Filesystems can have a number of directories within them. U-Boot only worries about directories that have been accessed. Add the concept of a directory, with the filesystem as parent. Note that this is not a hierarchical device structure, so UCLASS_DIR devices always have a UCLASS_FS as the parent. Signed-off-by: Simon Glass <sjg@chromium.org> --- MAINTAINERS | 3 + fs/Kconfig | 8 +++ fs/Makefile | 1 + fs/dir-uclass.c | 111 +++++++++++++++++++++++++++++++++++ fs/fs-uclass.c | 7 +++ include/dir.h | 129 +++++++++++++++++++++++++++++++++++++++++ include/dm/uclass-id.h | 1 + include/fs.h | 21 +++++++ include/fs_common.h | 4 ++ 9 files changed, 285 insertions(+) create mode 100644 fs/dir-uclass.c create mode 100644 include/dir.h diff --git a/MAINTAINERS b/MAINTAINERS index 14a0e2a9de3..6af09911bdd 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -1196,7 +1196,10 @@ S: Maintained T: git https://source.denx.de/u-boot/custodians/u-boot-microblaze.git F: drivers/fpga/ F: cmd/fpga.c +F: fs/dir-uclass.c +F: include/dir.h F: include/fpga.h +F: include/fs.h F: test/dm/fpga.c FLATTENED DEVICE TREE diff --git a/fs/Kconfig b/fs/Kconfig index f7951b483aa..6a3b3d8218e 100644 --- a/fs/Kconfig +++ b/fs/Kconfig @@ -12,6 +12,14 @@ config FS Provides an interface for filesystems, allowing them to be persistently mounted. Filesystem can contain files and directory. +config DIR + bool "Support for directories" + depends on FS + default y if SANDBOX || VENDOR_EMULATION || ARCH_QEMU + help + Provides an interface for directories within filesystems, allowing + them to be listed. + config FS_LEGACY def_bool y help diff --git a/fs/Makefile b/fs/Makefile index 75959d06f12..4e33f312caf 100644 --- a/fs/Makefile +++ b/fs/Makefile @@ -6,6 +6,7 @@ obj-$(CONFIG_$(PHASE_)FS_LEGACY) += fs_legacy.o fs_internal.o obj-$(CONFIG_$(PHASE_)FS) += fs-uclass.o +obj-$(CONFIG_$(PHASE_)DIR) += dir-uclass.o ifdef CONFIG_XPL_BUILD obj-$(CONFIG_SPL_FS_FAT) += fat/ diff --git a/fs/dir-uclass.c b/fs/dir-uclass.c new file mode 100644 index 00000000000..dcbef8dd9ff --- /dev/null +++ b/fs/dir-uclass.c @@ -0,0 +1,111 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Implementation of a directory on a filesystem + * + * Copyright 2025 Simon Glass <sjg@chromium.org> + */ + +#define LOG_CATEGORY UCLASS_DIR + +#include <dm.h> +#include <dir.h> +#include <fs.h> +#include <malloc.h> +#include <dm/device-internal.h> + +int dir_add_probe(struct udevice *fsdev, struct driver *drv, const char *path, + struct udevice **devp) +{ + char dev_name[30], *str, *dup_path; + struct dir_uc_priv *uc_priv; + struct udevice *dev; + int ret; + + snprintf(dev_name, sizeof(dev_name), "%s.dir", fsdev->name); + ret = -ENOMEM; + str = strdup(dev_name); + if (!str) + goto no_dev_name; + dup_path = strdup(path && strcmp("/", path) ? path : ""); + if (!str) + goto no_dev_path; + + ret = device_bind_with_driver_data(fsdev, drv, str, 0 /* data */, + ofnode_null(), &dev); + if (ret) + goto no_bind; + device_set_name_alloced(dev); + + ret = device_probe(dev); + if (ret) + goto no_probe; + uc_priv = dev_get_uclass_priv(dev); + uc_priv->path = dup_path; + + *devp = dev; + + return 0; + +no_probe: + device_unbind(dev); +no_bind: + free(dup_path); +no_dev_path: + free(str); +no_dev_name: + + return ret; +} + +int dir_open(struct udevice *dev, struct fs_dir_stream **strmp) +{ + struct dir_ops *ops = dir_get_ops(dev); + struct fs_dir_stream *strm; + int ret; + + strm = calloc(1, sizeof(struct fs_dir_stream)); + if (!strm) + return log_msg_ret("dom", -ENOMEM); + + strm->dev = dev; + ret = ops->open(dev, strm); + if (ret) { + free(strm); + return log_msg_ret("doo", ret); + } + *strmp = strm; + + return 0; +} + +int dir_read(struct udevice *dev, struct fs_dir_stream *strm, + struct fs_dirent *dent) +{ + struct dir_ops *ops = dir_get_ops(dev); + + log_debug("start %s\n", dev->name); + memset(dent, '\0', sizeof(struct fs_dirent)); + + return ops->read(dev, strm, dent); +} + +int dir_close(struct udevice *dev, struct fs_dir_stream *strm) +{ + struct dir_ops *ops = dir_get_ops(dev); + int ret; + + log_debug("start %s\n", dev->name); + + ret = ops->close(dev, strm); + if (ret) + return log_msg_ret("dcs", ret); + free(strm); + + return 0; +} + +UCLASS_DRIVER(dir) = { + .name = "dir", + .id = UCLASS_DIR, + .per_device_auto = sizeof(struct dir_uc_priv), +}; diff --git a/fs/fs-uclass.c b/fs/fs-uclass.c index d92b0e24538..7311bc72e04 100644 --- a/fs/fs-uclass.c +++ b/fs/fs-uclass.c @@ -13,6 +13,13 @@ #include <fs.h> #include <dm/device-internal.h> +int fs_lookup_dir(struct udevice *dev, const char *path, struct udevice **dirp) +{ + struct fs_ops *ops = fs_get_ops(dev); + + return ops->lookup_dir(dev, path, dirp); +} + int fs_mount(struct udevice *dev) { struct fs_ops *ops = fs_get_ops(dev); diff --git a/include/dir.h b/include/dir.h new file mode 100644 index 00000000000..8e883a6c6b2 --- /dev/null +++ b/include/dir.h @@ -0,0 +1,129 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * U-Boot Filesystem directory + * + * Copyright 2025 Simon Glass <sjg@chromium.org> + */ + +#ifndef __DIR_H +#define __DIR_H + +struct driver; +struct fs_dirent; +struct fs_dir_stream; +struct udevice; + +/** + * enum dir_open_flags_t - Flags to control the open mode of files + * + * @DIR_O_RDONLY: Open the file read-only + * @DIR_O_WRONLY: Open the file write-only, overwriting existing file contents + * @DIR_O_RDWR: Open the file for read/write, allowing the file to be updated + */ +enum dir_open_flags_t { + DIR_O_RDONLY, + DIR_O_WRONLY, + DIR_O_RDWR, +}; + +/** + * struct dir_uc_priv - Uclass information for each directory + * + * @path: Absolute path to directory, "" for root + */ +struct dir_uc_priv { + char *path; +}; + +/** + * struct dir_ops - Operations on directories + */ +struct dir_ops { + /** + * open() - Open a directory for reading + * + * @dev: Directory device (UCLASS_DIR) + * @strm: Stream information to fill in, on success (zeroed on entry) + */ + int (*open)(struct udevice *dev, struct fs_dir_stream *strm); + + /** + * read() - Read a single directory entry + * + * @dev: Directory device (UCLASS_DIR) + * @strm: Directory stream as created by open() + * @dent: Directory entry to fill in (zeroed on entry) + * Return: 0 if OK, -ENOENT if no more entries, other -ve value on error + */ + int (*read)(struct udevice *dev, struct fs_dir_stream *strm, + struct fs_dirent *dent); + + /** + * close() - Stop reading the directory + * + * @dev: Directory device (UCLASS_DIR) + * @strm: Directory stream as created by dir_opendir() + * Return: 0 if OK, -ve on error + */ + int (*close)(struct udevice *dev, struct fs_dir_stream *strm); + + /** + * open_file() - Create a new file device for a file + * + * @dev: Directory device (UCLASS_DIR) + * @leaf: Filename within the directory + * @flags: Open-mode flags to use + * @filp: Returns the UCLASS_FILE device + * Return: 0 if OK, -ve on error + */ + int (*open_file)(struct udevice *dev, const char *leaf, + enum dir_open_flags_t oflags, struct udevice **filp); +}; + +/* Get access to a directory's operations */ +#define dir_get_ops(dev) ((struct dir_ops *)(dev)->driver->ops) + +/** + * dir_open() - Open a directory for reading + * + * @dev: Directory device (UCLASS_DIR) + * @strm: Returns allocated pointer to stream information, on success + */ +int dir_open(struct udevice *dev, struct fs_dir_stream **strmp); + +/** + * dir_read() - Read a single directory entry + * + * @dev: Directory device (UCLASS_DIR) + * @strm: Directory stream as created by open() + * @dent: Directory entry to fill in + * Return: 0 if OK, -ENOENT if no more entries, other -ve value on other + * error + */ +int dir_read(struct udevice *dev, struct fs_dir_stream *strm, + struct fs_dirent *dent); + +/** + * dir_close() - Stop reading the directory + * + * Frees @strm and releases the directory + * + * @dev: Directory device (UCLASS_DIR) + * @strm: Directory stream as created by dir_opendir() + * Return: 0 if OK, -ve on error + */ +int dir_close(struct udevice *dev, struct fs_dir_stream *strm); + +/** + * dir_add_probe() - Add a new directory and probe it + * + * @fsdev: Filesystem containing the directory + * @drv: Driver to use + * @path Absolute path to directory (within the filesystem), or NULL/"/" for + * root + * @devp: Returns the new device, probed ready for use * + */ +int dir_add_probe(struct udevice *fsdev, struct driver *drv, const char *path, + struct udevice **devp); + +#endif diff --git a/include/dm/uclass-id.h b/include/dm/uclass-id.h index 45e9abfce32..247c6322c76 100644 --- a/include/dm/uclass-id.h +++ b/include/dm/uclass-id.h @@ -54,6 +54,7 @@ enum uclass_id { UCLASS_CLK, /* Clock source, e.g. used by peripherals */ UCLASS_CPU, /* CPU, typically part of an SoC */ UCLASS_CROS_EC, /* Chrome OS EC */ + UCLASS_DIR, /* Directory on a filesystem */ UCLASS_DISPLAY, /* Display (e.g. DisplayPort, HDMI) */ UCLASS_DMA, /* Direct Memory Access */ UCLASS_DSA, /* Distributed (Ethernet) Switch Architecture */ diff --git a/include/fs.h b/include/fs.h index 05a2ac844b8..e682ff7fa6a 100644 --- a/include/fs.h +++ b/include/fs.h @@ -54,6 +54,17 @@ struct fs_ops { * Return 0 if OK, -ENOTCONN if not mounted, other -ve on error */ int (*unmount)(struct udevice *dev); + + /** + * lookup_dir() - Look up a directory on a filesystem + * + * @dev: Filesystem device + * @path: Path to look up, empty or "/" for the root + * @dirp: Returns associated directory device, creating if necessary + * Return 0 if OK, -ENOENT, other -ve on error + */ + int (*lookup_dir)(struct udevice *dev, const char *path, + struct udevice **dirp); }; /* Get access to a filesystem's operations */ @@ -75,4 +86,14 @@ int fs_mount(struct udevice *dev); */ int fs_unmount(struct udevice *dev); +/** + * fs_lookup_dir() - Look up a directory on a filesystem + * + * @dev: Filesystem device + * @path: Path to look up, empty or "/" for the root + * @dirp: Returns associated directory device, creating if necessary + * Return 0 if OK, -ENOENT, other -ve on error + */ +int fs_lookup_dir(struct udevice *dev, const char *path, struct udevice **dirp); + #endif diff --git a/include/fs_common.h b/include/fs_common.h index 30e8b6737b3..ac613d0862b 100644 --- a/include/fs_common.h +++ b/include/fs_common.h @@ -61,10 +61,14 @@ struct fs_dirent { * File system drivers pass additional private fields with the pointers * to this structure. * + * @dev: dir device (UCLASS_DIR) * @desc: block device descriptor * @part: partition number */ struct fs_dir_stream { +#ifdef CONFIG_FS + struct udevice *dev; +#endif struct blk_desc *desc; int part; }; -- 2.43.0

From: Simon Glass <sjg@chromium.org> Create a test which looks for a file and a directory in the U-Boot source tree. Signed-off-by: Simon Glass <sjg@chromium.org> --- arch/sandbox/cpu/os.c | 19 +++++++ fs/sandbox/sandboxfs.c | 112 +++++++++++++++++++++++++++++++++++++++++ include/os.h | 10 ++++ test/dm/fs.c | 37 ++++++++++++++ 4 files changed, 178 insertions(+) diff --git a/arch/sandbox/cpu/os.c b/arch/sandbox/cpu/os.c index d1fda05444d..c19f859d4e0 100644 --- a/arch/sandbox/cpu/os.c +++ b/arch/sandbox/cpu/os.c @@ -747,6 +747,25 @@ int os_get_filesize(const char *fname, long long *size) return 0; } +int os_get_filetype(const char *fname) +{ + struct stat buf; + int ret; + + ret = stat(fname, &buf); + if (ret) + return -errno; + + if (buf.st_mode & S_IFREG) + return OS_FILET_REG; + if (buf.st_mode & S_IFDIR) + return OS_FILET_DIR; + if (buf.st_mode & S_IFLNK) + return OS_FILET_LNK; + + return OS_FILET_UNKNOWN; +} + void os_putc(int ch) { os_write(1, &ch, 1); diff --git a/fs/sandbox/sandboxfs.c b/fs/sandbox/sandboxfs.c index 74c94528cf4..4648ac6b55e 100644 --- a/fs/sandbox/sandboxfs.c +++ b/fs/sandbox/sandboxfs.c @@ -5,6 +5,7 @@ * Copyright (c) 2012, Google Inc. */ +#include <dir.h> #include <dm.h> #include <stdio.h> #include <fs.h> @@ -13,10 +14,23 @@ #include <os.h> #include <sandboxfs.h> +/** + * struct sandbox_dir_priv - Private info about sandbox directories + * + * @head: List of directory entries, or NULL if not known + * @ptr: Current position in the list + */ +struct sandbox_dir_priv { + struct os_dirent_node *head, *ptr; +}; + /** * struct sandbox_fs_priv - Private info about the sandbox filesystem + * + * @entries: List of directory entries, or NULL if not scanned yet */ struct sandbox_fs_priv { + struct os_dirent_node *entries; }; int sandbox_fs_set_blk_dev(struct blk_desc *rbdd, struct disk_partition *info) @@ -177,6 +191,103 @@ static int sandbox_fs_unmount(struct udevice *dev) return 0; } +static int sandbox_dir_open(struct udevice *dev, struct fs_dir_stream *strm) +{ + struct sandbox_dir_priv *priv = dev_get_priv(dev); + struct dir_uc_priv *dir_uc_priv = dev_get_uclass_priv(dev); + int ret; + + ret = os_dirent_ls(dir_uc_priv->path, &priv->head); + if (ret) { + log_err("Failed to open directory: %d\n", ret); + return ret; + } + priv->ptr = priv->head; + + return 0; +} + +int sandbox_dir_read(struct udevice *dev, struct fs_dir_stream *strm, + struct fs_dirent *dent) +{ + struct sandbox_dir_priv *dir_priv = dev_get_priv(dev); + struct os_dirent_node *ptr = dir_priv->ptr; + + if (!ptr) + return log_msg_ret("sdr", -ENOENT); + + if (ptr->type == OS_FILET_REG) + dent->type = FS_DT_REG; + else if (ptr->type == OS_FILET_DIR) + dent->type = FS_DT_DIR; + else if (ptr->type == OS_FILET_LNK) + dent->type = FS_DT_LNK; + dent->size = ptr->size; + strlcpy(dent->name, ptr->name, FS_DIRENT_NAME_LEN); + dir_priv->ptr = ptr->next; + + return 0; +} + +static int sandbox_dir_close(struct udevice *dev, struct fs_dir_stream *strm) +{ + struct sandbox_dir_priv *dir_priv = dev_get_priv(dev); + + log_debug("close\n"); + os_dirent_free(dir_priv->head); + dir_priv->ptr = NULL; + + log_debug("close done\n"); + + return 0; +} + +static struct dir_ops sandbox_dir_ops = { + .open = sandbox_dir_open, + .read = sandbox_dir_read, + .close = sandbox_dir_close, +}; + +static const struct udevice_id dir_ids[] = { + { .compatible = "virtio-fs,directory" }, + { } +}; + +U_BOOT_DRIVER(sandbox_dir) = { + .name = "sandbox_dir", + .id = UCLASS_DIR, + .of_match = dir_ids, + .ops = &sandbox_dir_ops, + .priv_auto = sizeof(struct sandbox_dir_priv), + .flags = DM_FLAG_ACTIVE_DMA, +}; + +static int sandbox_fs_lookup_dir(struct udevice *dev, const char *path, + struct udevice **dirp) +{ + struct udevice *dir; + int ftype; + int ret; + + ftype = os_get_filetype(path ?: "/"); + if (ftype < 0) + return ftype; + if (ftype != OS_FILET_DIR) + return log_msg_ret("sld", -ENOTDIR); + + log_debug("looking up path '%s'\n", path); + + ret = dir_add_probe(dev, DM_DRIVER_GET(sandbox_dir), path, &dir); + if (ret) + return log_msg_ret("slD", ret); + + log_debug("added new dir '%s'\n", path); + + *dirp = dir; + + return 0; +} + static int sandbox_fs_remove(struct udevice *dev) { return 0; @@ -185,6 +296,7 @@ static int sandbox_fs_remove(struct udevice *dev) static const struct fs_ops sandbox_fs_ops = { .mount = sandbox_fs_mount, .unmount = sandbox_fs_unmount, + .lookup_dir = sandbox_fs_lookup_dir, }; static const struct udevice_id sandbox_fs_ids[] = { diff --git a/include/os.h b/include/os.h index f4f2667d206..35757fc8bb8 100644 --- a/include/os.h +++ b/include/os.h @@ -319,6 +319,16 @@ const char *os_dirent_get_typename(enum os_dirent_t type); */ int os_get_filesize(const char *fname, long long *size); +/** + * os_get_filetype() - get the type of a file + * + * @fname: Filename to check + * Return: -ve error code if the file does not exist, OS_FILET_REG for a regular + * file, OS_FILET_DIR for a directory, OS_FILET_LNK for a link, or + * OS_FILET_UNKNOWN for some other type of file + */ +int os_get_filetype(const char *fname); + /** * os_putc() - write a character to the controlling OS terminal * diff --git a/test/dm/fs.c b/test/dm/fs.c index d82d2250c59..6e198c8a541 100644 --- a/test/dm/fs.c +++ b/test/dm/fs.c @@ -5,6 +5,7 @@ * Copyright 2025 Simon Glass <sjg@chromium.org> */ +#include <dir.h> #include <dm.h> #include <fs.h> #include <dm/test.h> @@ -26,3 +27,39 @@ static int dm_test_fs_base(struct unit_test_state *uts) return 0; } DM_TEST(dm_test_fs_base, UTF_SCAN_FDT); + +/* Test accessing a directory */ +static int dm_test_fs_dir(struct unit_test_state *uts) +{ + struct udevice *fsdev, *dir; + struct fs_dir_stream *strm; + struct fs_dirent dent; + int found; + + ut_assertok(uclass_first_device_err(UCLASS_FS, &fsdev)); + + ut_assertok(fs_mount(fsdev)); + + ut_assertok(fs_lookup_dir(fsdev, ".", &dir)); + ut_assertnonnull(dir); + ut_asserteq_str("fs.dir", dir->name); + + ut_assertok(dir_open(dir, &strm)); + found = 0; + do { + ut_assertok(dir_read(dir, strm, &dent)); + if (!strcmp("README", dent.name)) { + ut_asserteq(FS_DT_REG, dent.type); + found += 1; + } else if (!strcmp("common", dent.name)) { + ut_asserteq(FS_DT_DIR, dent.type); + found += 1; + } + } while (found < 2); + ut_assertok(dir_close(dir, strm)); + + ut_assertok(fs_unmount(fsdev)); + + return 0; +} +DM_TEST(dm_test_fs_dir, UTF_SCAN_FDT); -- 2.43.0

From: Simon Glass <sjg@chromium.org> Provide a struct iov_iter and some related functions to encapsulate an iterator used when reading and writing files. This will be used with the new 'file' uclass. While it is modelled on Linux, I/O vectors have been omitted for now. These can be added later without updating the interface used by the uclass. Signed-off-by: Simon Glass <sjg@chromium.org> --- MAINTAINERS | 1 + include/iovec.h | 85 +++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 86 insertions(+) create mode 100644 include/iovec.h diff --git a/MAINTAINERS b/MAINTAINERS index 6af09911bdd..9fcff19857d 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -1200,6 +1200,7 @@ F: fs/dir-uclass.c F: include/dir.h F: include/fpga.h F: include/fs.h +F: include/iovec.h F: test/dm/fpga.c FLATTENED DEVICE TREE diff --git a/include/iovec.h b/include/iovec.h new file mode 100644 index 00000000000..f814f80a3da --- /dev/null +++ b/include/iovec.h @@ -0,0 +1,85 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Iterator for I/O, modelled on Linux but significantly simplified + * + * Copyright 2025 Simon Glass <sjg@chromium.org> + */ + +#ifndef __IOVEC_H +#define __IOVEC_H + +#include <linux/types.h> + +/** + * enum iov_type_t - defines the type of this I/O vector + * + * @OIV_BUF: Simple buffer with a size + */ +enum iov_type_t { + OIV_BUF, +}; + +/** + * struct iov_iter - holds an interator for I/O + * + * Do not use this directly. Instead, call copy_to_iter() + * + * Note that this is much simpler than the Linux version, but can be extended + * later as needed. It is introduced so that we can use the desired API for + * read(), etc. It is also commented properly. + * + * @type: Type of the iterator (always OIV_BUF) + * @data_source: true if this iterator produces data, false if it consumes it + * @offset: Current offset within the buffer + * @buf: Contiguous data buffer to use (other things could be added to the + * union later) + * @count: Size of data buffer + */ +struct iov_iter { + enum iov_type_t type; + bool data_source; + ssize_t offset; + union { + void *ubuf; + }; + ssize_t count; +}; + +/** + * iter_iov_ptr() - Get a pointer to the current position + * + * @iter: Iterator to examine + * Return: pointer to the start of the buffer portion to read/write + */ +static inline void *iter_iov_ptr(const struct iov_iter *iter) +{ + return iter->ubuf + iter->offset; +}; + +/** + * iter_iov_avail() - Get the number of bytes available at the current postiion + * + * @iter: iterator to examine + * Return: number of bytes which can be read/written + */ +static inline ssize_t iter_iov_avail(const struct iov_iter *iter) +{ + return iter->count - iter->offset; +}; + +static inline void iter_ubuf(struct iov_iter *iter, bool data_source, void *buf, + size_t count) +{ + *iter = (struct iov_iter) { + .data_source = data_source, + .ubuf = buf, + .count = count, + }; +} + +static inline void iter_advance(struct iov_iter *iter, size_t len) +{ + iter->offset += len; +} + +#endif -- 2.43.0

From: Simon Glass <sjg@chromium.org> Directories can have a number of files within them. U-Boot only needs to create a file object for those that have been opened for read/write. Add the concept of a file, with its directory as parent. Signed-off-by: Simon Glass <sjg@chromium.org> --- MAINTAINERS | 2 + fs/Kconfig | 9 ++++ fs/Makefile | 1 + fs/dir-uclass.c | 10 ++++ fs/file-uclass.c | 103 +++++++++++++++++++++++++++++++++++++++++ include/dir.h | 12 +++++ include/dm/uclass-id.h | 1 + include/file.h | 86 ++++++++++++++++++++++++++++++++++ 8 files changed, 224 insertions(+) create mode 100644 fs/file-uclass.c create mode 100644 include/file.h diff --git a/MAINTAINERS b/MAINTAINERS index 9fcff19857d..e5389aeae45 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -1197,7 +1197,9 @@ T: git https://source.denx.de/u-boot/custodians/u-boot-microblaze.git F: drivers/fpga/ F: cmd/fpga.c F: fs/dir-uclass.c +F: fs/file-uclass.c F: include/dir.h +F: include/file.h F: include/fpga.h F: include/fs.h F: include/iovec.h diff --git a/fs/Kconfig b/fs/Kconfig index 6a3b3d8218e..718172e472e 100644 --- a/fs/Kconfig +++ b/fs/Kconfig @@ -20,6 +20,15 @@ config DIR Provides an interface for directories within filesystems, allowing them to be listed. +config FILE + bool "Support for files" + default y if SANDBOX || VENDOR_EMULATION || ARCH_QEMU + help + Provides an interface for files, allowing them to be opened, read, + written and modified. Files are children of a filesystem device + (UCLASS_FS). Note that a UCLASS_FILE device is only created when it + is opened. + config FS_LEGACY def_bool y help diff --git a/fs/Makefile b/fs/Makefile index 4e33f312caf..d69d6986c41 100644 --- a/fs/Makefile +++ b/fs/Makefile @@ -7,6 +7,7 @@ obj-$(CONFIG_$(PHASE_)FS_LEGACY) += fs_legacy.o fs_internal.o obj-$(CONFIG_$(PHASE_)FS) += fs-uclass.o obj-$(CONFIG_$(PHASE_)DIR) += dir-uclass.o +obj-$(CONFIG_$(PHASE_)FILE) += file-uclass.o ifdef CONFIG_XPL_BUILD obj-$(CONFIG_SPL_FS_FAT) += fat/ diff --git a/fs/dir-uclass.c b/fs/dir-uclass.c index dcbef8dd9ff..f2c3a7c3806 100644 --- a/fs/dir-uclass.c +++ b/fs/dir-uclass.c @@ -104,6 +104,16 @@ int dir_close(struct udevice *dev, struct fs_dir_stream *strm) return 0; } +int dir_open_file(struct udevice *dev, const char *leaf, + enum dir_open_flags_t oflags, struct udevice **filp) +{ + struct dir_ops *ops = dir_get_ops(dev); + + log_debug("start %s\n", dev->name); + + return ops->open_file(dev, leaf, oflags, filp); +} + UCLASS_DRIVER(dir) = { .name = "dir", .id = UCLASS_DIR, diff --git a/fs/file-uclass.c b/fs/file-uclass.c new file mode 100644 index 00000000000..91ced31a94e --- /dev/null +++ b/fs/file-uclass.c @@ -0,0 +1,103 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Implementation of files on a filesystem + * + * Copyright 2025 Simon Glass <sjg@chromium.org> + */ + +#include <dir.h> +#include <dm.h> +#include <file.h> +#include <malloc.h> +#include <dm/device-internal.h> + +int file_add_probe(struct udevice *dir, struct driver *drv, const char *leaf, + size_t size, enum dir_open_flags_t flags, + struct udevice **devp) +{ + char dev_name[30], *str, *dup_leaf; + struct file_uc_priv *uc_priv; + struct udevice *dev; + int ret; + + snprintf(dev_name, sizeof(dev_name), "%s.file.%x", dir->name, + device_get_child_count(dir) + 1); + ret = -ENOMEM; + str = strdup(dev_name); + if (!str) + goto no_dev_name; + dup_leaf = strdup(leaf); + if (!str) + goto no_dev_path; + + ret = device_bind_with_driver_data(dir, drv, str, 0 /* data */, + ofnode_null(), &dev); + if (ret) { + log_debug("bind failed %d\n", ret); + goto no_bind; + } + device_set_name_alloced(dev); + + ret = device_probe(dev); + if (ret) + goto no_probe; + uc_priv = dev_get_uclass_priv(dev); + + uc_priv->leaf = dup_leaf; + uc_priv->size = size; + *devp = dev; + + return 0; + +no_probe: + device_unbind(dir); +no_bind: + free(dup_leaf); +no_dev_path: + free(str); +no_dev_name: + + return ret; +} + +long file_read(struct udevice *dev, void *buf, long len) +{ + struct file_uc_priv *uc_priv = dev_get_uclass_priv(dev); + struct file_ops *ops = file_get_ops(dev); + struct iov_iter iter; + ssize_t ret; + + iter_ubuf(&iter, true, buf, len); + + ret = ops->read_iter(dev, &iter, uc_priv->pos); + if (ret < 0) + return log_msg_ret("fir", ret); + uc_priv->pos += ret; + + return ret; +} + +long file_read_at(struct udevice *dev, void *buf, loff_t offset, long len) +{ + struct file_uc_priv *uc_priv = dev_get_uclass_priv(dev); + struct file_ops *ops = file_get_ops(dev); + struct iov_iter iter; + ssize_t ret; + + if (!len) + len = uc_priv->size - offset; + iter_ubuf(&iter, true, buf, len); + + ret = ops->read_iter(dev, &iter, offset); + if (ret < 0) + return log_msg_ret("fir", ret); + uc_priv->pos = offset + ret; + + return ret; +} + +UCLASS_DRIVER(file) = { + .name = "file", + .id = UCLASS_FILE, + .per_device_auto = sizeof(struct file_uc_priv), +}; diff --git a/include/dir.h b/include/dir.h index 8e883a6c6b2..f948843c6b3 100644 --- a/include/dir.h +++ b/include/dir.h @@ -126,4 +126,16 @@ int dir_close(struct udevice *dev, struct fs_dir_stream *strm); int dir_add_probe(struct udevice *fsdev, struct driver *drv, const char *path, struct udevice **devp); +/** + * dir_open_file() - Create a new file device for a file + * + * @dev: Directory device (UCLASS_DIR) + * @leaf: Filename within the directory + * @flags: Open-mode flags to use + * @filp: Returns the UCLASS_FILE device + * Return: 0 if OK, -ve on error + */ +int dir_open_file(struct udevice *dev, const char *leaf, + enum dir_open_flags_t oflags, struct udevice **filp); + #endif diff --git a/include/dm/uclass-id.h b/include/dm/uclass-id.h index 247c6322c76..c558c95f465 100644 --- a/include/dm/uclass-id.h +++ b/include/dm/uclass-id.h @@ -65,6 +65,7 @@ enum uclass_id { UCLASS_ETH, /* Ethernet device */ UCLASS_ETH_PHY, /* Ethernet PHY device */ UCLASS_EXTCON, /* External Connector Class */ + UCLASS_FILE, /* File on a filesystem */ UCLASS_FFA, /* Arm Firmware Framework for Armv8-A */ UCLASS_FIRMWARE, /* Firmware */ UCLASS_FPGA, /* FPGA device */ diff --git a/include/file.h b/include/file.h new file mode 100644 index 00000000000..d1fdf3c13f1 --- /dev/null +++ b/include/file.h @@ -0,0 +1,86 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Implementation of files on a filesystem + * Copyright 2025 Simon Glass <sjg@chromium.org> + */ + +#ifndef __FILE_H +#define __FILE_H + +#include <dir.h> +#include <iovec.h> + +struct udevice; + +enum { + /* Maximum length of a pathname */ + FILE_MAX_PATH_LEN = 1024, +}; + +/** + * struct file_uc_priv - Uclass information about each file + * + * @leaf: Filename leaf + * @pos: Current file position + * @size: File size + */ +struct file_uc_priv { + const char *leaf; + loff_t pos; + size_t size; +}; + +struct file_ops { + /** + * read_iter() - Read data from a file + * + * Reads from the current file position, which is advanced + * + * @dev: File to read from + * @iter: Interator to receive data + * @pos: File position to read from + * Return: number of bytes read, or -ve error code + */ + ssize_t (*read_iter)(struct udevice *dev, struct iov_iter *iter, + loff_t pos); +}; + +/* Get access to a file's operations */ +#define file_get_ops(dev) ((struct file_ops *)(dev)->driver->ops) + +/** + * file_read() - Read data from a file + * + * Reads from the current file position, which is advanced + * + * @dev: File to read from + * @buf: Buffer to read into + * @len: Number of bytes to read + */ +long file_read(struct udevice *dev, void *buf, long len); + +/** + * read_at() - Read data from a file at a particular position + * + * @dev: File to read from + * @buf: Buffer to read into + * @offset: Offset within the file to start reading + * @len: Number of bytes to read (0 to read as many as possible) + */ +long file_read_at(struct udevice *dev, void *buf, loff_t offset, long len); + +/** + * file_add_probe() - Create a new file device for a file + * + * @dev: Directory device (UCLASS_DIR) + * @leaf: Filename within the directory + * @size: Size of the file in bytes + * @flags: Open-mode flags to use + * @filp: Returns the UCLASS_FILE device + * Return: 0 if OK, -ve on error + */ +int file_add_probe(struct udevice *dir, struct driver *drv, const char *leaf, + size_t size, enum dir_open_flags_t flags, + struct udevice **devp); + +#endif -- 2.43.0

From: Simon Glass <sjg@chromium.org> Create a test which looks for a file reads from it. Signed-off-by: Simon Glass <sjg@chromium.org> --- fs/sandbox/sandboxfs.c | 100 ++++++++++++++++++++++++++++++++++++++++- test/dm/fs.c | 41 +++++++++++++++++ 2 files changed, 140 insertions(+), 1 deletion(-) diff --git a/fs/sandbox/sandboxfs.c b/fs/sandbox/sandboxfs.c index 4648ac6b55e..3d624ab5f7f 100644 --- a/fs/sandbox/sandboxfs.c +++ b/fs/sandbox/sandboxfs.c @@ -7,7 +7,7 @@ #include <dir.h> #include <dm.h> -#include <stdio.h> +#include <file.h> #include <fs.h> #include <fs_legacy.h> #include <malloc.h> @@ -24,6 +24,15 @@ struct sandbox_dir_priv { struct os_dirent_node *head, *ptr; }; +/** + * struct sandbox_dir_priv - Private info about sandbox directories + * + * @fd: File descriptor for the file + */ +struct file_priv { + int fd; +}; + /** * struct sandbox_fs_priv - Private info about the sandbox filesystem * @@ -242,10 +251,99 @@ static int sandbox_dir_close(struct udevice *dev, struct fs_dir_stream *strm) return 0; } +static ssize_t sandbox_read_iter(struct udevice *dev, struct iov_iter *iter, + loff_t pos) +{ + struct file_priv *priv = dev_get_priv(dev); + ssize_t ret; + + log_debug("start dev '%s' len %lx\n", dev->name, iter->count); + ret = os_lseek(priv->fd, pos, OS_SEEK_SET); + if (ret < 0) + return log_msg_ret("vfs", ret); + + ret = os_read(priv->fd, iter_iov_ptr(iter), iter_iov_avail(iter)); + if (ret < 0) + return log_msg_ret("vfr", ret); + iter_advance(iter, ret); + log_debug("read %lx bytes\n", ret); + + return ret; +} + +static struct file_ops sandbox_file_ops = { + .read_iter = sandbox_read_iter, +}; + +static const struct udevice_id file_ids[] = { + { .compatible = "virtio-fs,file" }, + { } +}; + +U_BOOT_DRIVER(sandbox_file) = { + .name = "sandbox_file", + .id = UCLASS_FILE, + .of_match = file_ids, + .ops = &sandbox_file_ops, + .priv_auto = sizeof(struct file_priv), + .flags = DM_FLAG_ACTIVE_DMA, +}; + +static int sandbox_dir_open_file(struct udevice *dir, const char *leaf, + enum dir_open_flags_t oflags, + struct udevice **filp) +{ + struct dir_uc_priv *uc_priv = dev_get_uclass_priv(dir); + char pathname[FILE_MAX_PATH_LEN]; + struct file_priv *priv; + int mode, fd, ftype, ret; + struct udevice *dev; + off_t size; + + snprintf(pathname, sizeof(pathname), "%s/%s", uc_priv->path, leaf); + ftype = os_get_filetype(pathname); + if (ftype < 0) + return log_msg_ret("soF", ftype); + if (ftype != OS_FILET_REG) + return log_msg_ret("sOf", -EINVAL); + + if (oflags == DIR_O_RDONLY) + mode = OS_O_RDONLY; + else if (oflags == DIR_O_WRONLY) + mode = OS_O_WRONLY | OS_O_CREAT; + else if (oflags == DIR_O_RDWR) + mode = OS_O_RDWR; + else + return log_msg_ret("som", -EINVAL); + + ret = os_open(pathname, mode); + if (ret < 0) + return log_msg_ret("sOm", ret); + fd = ret; + + size = os_filesize(fd); + if (size < 0) + return log_msg_ret("sos", ret); + + ret = file_add_probe(dir, DM_DRIVER_GET(sandbox_file), leaf, size, + oflags, &dev); + if (ret) { + os_close(fd); + return log_msg_ret("sof", ret); + } + + priv = dev_get_priv(dev); + priv->fd = fd; + *filp = dev; + + return 0; +} + static struct dir_ops sandbox_dir_ops = { .open = sandbox_dir_open, .read = sandbox_dir_read, .close = sandbox_dir_close, + .open_file = sandbox_dir_open_file, }; static const struct udevice_id dir_ids[] = { diff --git a/test/dm/fs.c b/test/dm/fs.c index 6e198c8a541..e94b7854184 100644 --- a/test/dm/fs.c +++ b/test/dm/fs.c @@ -7,10 +7,13 @@ #include <dir.h> #include <dm.h> +#include <file.h> #include <fs.h> #include <dm/test.h> #include <test/ut.h> +#define READ_SIZE 0x20 + /* Test basic filesystem access */ static int dm_test_fs_base(struct unit_test_state *uts) { @@ -40,6 +43,7 @@ static int dm_test_fs_dir(struct unit_test_state *uts) ut_assertok(fs_mount(fsdev)); + ut_asserteq(-ENOENT, fs_lookup_dir(fsdev, "does-not-exit", &dir)); ut_assertok(fs_lookup_dir(fsdev, ".", &dir)); ut_assertnonnull(dir); ut_asserteq_str("fs.dir", dir->name); @@ -63,3 +67,40 @@ static int dm_test_fs_dir(struct unit_test_state *uts) return 0; } DM_TEST(dm_test_fs_dir, UTF_SCAN_FDT); + +/* Test reading a file */ +static int dm_test_fs_file(struct unit_test_state *uts) +{ + struct udevice *fsdev, *dir, *fil; + struct file_uc_priv *uc_priv; + char buf[READ_SIZE + 1]; + + ut_assertok(uclass_first_device_err(UCLASS_FS, &fsdev)); + + ut_assertok(fs_mount(fsdev)); + + ut_assertok(fs_lookup_dir(fsdev, ".", &dir)); + ut_assertnonnull(dir); + ut_asserteq_str("fs.dir", dir->name); + + /* check the start and end of the README, which perhaps won't change */ + ut_assertok(dir_open_file(dir, "README", DIR_O_RDONLY, &fil)); + ut_assertnonnull(fil); + ut_asserteq_str("fs.dir.file.1", fil->name); + uc_priv = dev_get_uclass_priv(fil); + ut_asserteq_str("README", uc_priv->leaf); + ut_asserteq(0, uc_priv->pos); + ut_assert(uc_priv->size > 0x10000); + + buf[READ_SIZE] = '\0'; + ut_asserteq(READ_SIZE, file_read(fil, buf, READ_SIZE)); + ut_asserteq_str("# SPDX-License-Identifier: GPL-2", buf); + ut_asserteq(0x20, uc_priv->pos); + + ut_asserteq(READ_SIZE, file_read_at(fil, buf, uc_priv->size - 0x20, 0)); + ut_asserteq_str("d the patch submission process.\n", buf); + ut_asserteq(uc_priv->size, uc_priv->pos); + + return 0; +} +DM_TEST(dm_test_fs_file, UTF_SCAN_FDT); -- 2.43.0
participants (1)
-
sjg@u-boot.org