[Concept,10/34] vfs: cmd: Add fs command with mount and umount subcommands

Message ID 20260403140523.1998228-11-sjg@u-boot.org
State New
Headers
Series Add a virtual filesystem (VFS) layer to U-Boot |

Commit Message

Simon Glass April 3, 2026, 2:04 p.m. UTC
  From: Simon Glass <sjg@chromium.org>

Add a new 'fs' command for VFS operations:
- fs mount [<dev> <path>] - list or create mounts
- fs umount <path>        - unmount a filesystem

Signed-off-by: Simon Glass <sjg@chromium.org>
---

 cmd/Kconfig  |  8 +++++
 cmd/Makefile |  1 +
 cmd/vfs.c    | 96 ++++++++++++++++++++++++++++++++++++++++++++++++++++
 test/dm/fs.c | 27 +++++++++++++++
 4 files changed, 132 insertions(+)
 create mode 100644 cmd/vfs.c
  

Patch

diff --git a/cmd/Kconfig b/cmd/Kconfig
index 95ccb9fca1a..60ebb56de00 100644
--- a/cmd/Kconfig
+++ b/cmd/Kconfig
@@ -2987,6 +2987,14 @@  config CMD_FS_LEGACY
 	  include load, save, ls, size, mkdir, rm, ln, mv, fstype and
 	  fstypes.
 
+config CMD_VFS
+	bool "fs - virtual filesystem commands"
+	depends on VFS
+	default y if SANDBOX
+	help
+	  Provides the 'fs' command with mount, umount and ls subcommands
+	  for the virtual filesystem layer.
+
 config CMD_FS_UUID
 	bool "fsuuid command"
 	default y if SANDBOX
diff --git a/cmd/Makefile b/cmd/Makefile
index 4d1b3eab90c..412a3096d0e 100644
--- a/cmd/Makefile
+++ b/cmd/Makefile
@@ -94,6 +94,7 @@  obj-$(CONFIG_CMD_FPGA) += fpga.o
 obj-$(CONFIG_CMD_LUKS) += luks.o
 obj-$(CONFIG_CMD_FPGAD) += fpgad.o
 obj-$(CONFIG_CMD_FS_LEGACY) += fs_legacy.o
+obj-$(CONFIG_CMD_VFS) += vfs.o
 obj-$(CONFIG_CMD_FUSE) += fuse.o
 obj-$(CONFIG_CMD_FWU_METADATA) += fwu_mdata.o
 obj-$(CONFIG_CMD_GETTIME) += gettime.o
diff --git a/cmd/vfs.c b/cmd/vfs.c
new file mode 100644
index 00000000000..23b8cabdcdb
--- /dev/null
+++ b/cmd/vfs.c
@@ -0,0 +1,96 @@ 
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * VFS commands - 'fs mount', 'fs umount'
+ *
+ * Provides a new 'fs' command with subcommands for the virtual filesystem
+ * layer, co-existing with the legacy filesystem commands in cmd/fs.c.
+ *
+ * Copyright 2026 Simon Glass <sjg@chromium.org>
+ */
+
+#include <command.h>
+#include <dm.h>
+#include <fs.h>
+#include <vfs.h>
+#include <dm/uclass.h>
+
+static int fs_mount_handler(int argc, char *const argv[])
+{
+	struct udevice *vfs, *fsdev, *dir;
+	int ret;
+
+	vfs = vfs_root();
+	if (!vfs)
+		return -ENXIO;
+
+	if (argc < 2) {
+		vfs_print_mounts();
+		return 0;
+	}
+
+	if (argc < 3)
+		return -EINVAL;
+
+	ret = uclass_get_device_by_name(UCLASS_FS, argv[1], &fsdev);
+	if (ret)
+		return ret;
+
+	ret = vfs_resolve(vfs, argv[2], &dir);
+	if (ret)
+		return ret;
+
+	return vfs_mount(vfs, dir, fsdev);
+}
+
+static int do_fs_mount(struct cmd_tbl *cmdtp, int flag, int argc,
+		       char *const argv[])
+{
+	int ret;
+
+	if (argc == 2)
+		return CMD_RET_USAGE;
+
+	ret = fs_mount_handler(argc, argv);
+	if (ret) {
+		printf("fs mount failed: %dE\n", ret);
+		return CMD_RET_FAILURE;
+	}
+
+	return CMD_RET_SUCCESS;
+}
+
+static int fs_umount_handler(const char *path)
+{
+	struct udevice *vfs;
+
+	vfs = vfs_root();
+	if (!vfs)
+		return -ENXIO;
+
+	return vfs_umount_path(vfs, path);
+}
+
+static int do_fs_umount(struct cmd_tbl *cmdtp, int flag, int argc,
+			char *const argv[])
+{
+	int ret;
+
+	if (argc < 2)
+		return CMD_RET_USAGE;
+
+	ret = fs_umount_handler(argv[1]);
+	if (ret) {
+		printf("fs umount failed: %dE\n", ret);
+		return CMD_RET_FAILURE;
+	}
+
+	return CMD_RET_SUCCESS;
+}
+
+U_BOOT_LONGHELP(fs,
+	"mount [<dev> <mountpoint>] - list or create mounts\n"
+	"fs umount <mountpoint>         - unmount a filesystem");
+
+U_BOOT_CMD_WITH_SUBCMDS(fs, "Filesystem operations", fs_help_text,
+	U_BOOT_SUBCMD_MKENT(mount, 3, 1, do_fs_mount),
+	U_BOOT_SUBCMD_MKENT(umount, 2, 1, do_fs_umount));
diff --git a/test/dm/fs.c b/test/dm/fs.c
index f31a11e90cb..f71ad361bcd 100644
--- a/test/dm/fs.c
+++ b/test/dm/fs.c
@@ -247,4 +247,31 @@  static int dm_test_vfs_mount(struct unit_test_state *uts)
 	return 0;
 }
 DM_TEST(dm_test_vfs_mount, UTF_SCAN_FDT);
+
+/* Test the VFS layer using the 'fs' command */
+static int dm_test_vfs_cmd(struct unit_test_state *uts)
+{
+	ut_assertok(vfs_init());
+
+	/* Mount the sandbox FS at /host */
+	ut_assertok(run_command("fs mount hostfs /host", 0));
+	ut_assert_console_end();
+
+	/* Verify it appears in the mount list */
+	ut_assertok(run_command("fs mount", 0));
+	ut_assert_nextlinen("/host");
+	ut_assert_console_end();
+
+	/* Unmount */
+	ut_assertok(run_command("fs umount /host", 0));
+	ut_assert_console_end();
+
+	/* Mount list should now be empty */
+	ut_assertok(run_command("fs mount", 0));
+	ut_assert_console_end();
+
+	return 0;
+}
+DM_TEST(dm_test_vfs_cmd, UTF_SCAN_FDT);
+
 #endif