[PATCH v3 12/29] fs: Add semihosting filesystem

Sean Anderson sean.anderson at seco.com
Tue Mar 22 21:59:20 CET 2022


This adds a filesystem which is backed by the host's filesystem. It is
modeled off of sandboxfs, which has very similar aims. Semihosting
doesn't support listing directories (except with SYS_SYSTEM), so neither
do we. it's possible to optimize a bit for the common case of reading a
whole file by omitting a call to smh_seek, but this is left as a future
optimization.

Signed-off-by: Sean Anderson <sean.anderson at seco.com>
---

(no changes since v1)

 disk/part.c             |   4 +-
 fs/Makefile             |   1 +
 fs/fs.c                 |  20 +++++++
 fs/semihostingfs.c      | 115 ++++++++++++++++++++++++++++++++++++++++
 include/fs.h            |   1 +
 include/semihostingfs.h |  21 ++++++++
 6 files changed, 160 insertions(+), 2 deletions(-)
 create mode 100644 fs/semihostingfs.c
 create mode 100644 include/semihostingfs.h

diff --git a/disk/part.c b/disk/part.c
index 49e39a24e8..b95405bb49 100644
--- a/disk/part.c
+++ b/disk/part.c
@@ -455,7 +455,7 @@ int blk_get_device_part_str(const char *ifname, const char *dev_part_str,
 	int part;
 	struct disk_partition tmpinfo;
 
-#ifdef CONFIG_SANDBOX
+#if IS_ENABLED(CONFIG_SANDBOX) || IS_ENABLED(CONFIG_SEMIHOSTING)
 	/*
 	 * Special-case a pseudo block device "hostfs", to allow access to the
 	 * host's own filesystem.
@@ -467,7 +467,7 @@ int blk_get_device_part_str(const char *ifname, const char *dev_part_str,
 		info->blksz = 0;
 		info->bootable = 0;
 		strcpy((char *)info->type, BOOT_PART_TYPE);
-		strcpy((char *)info->name, "Sandbox host");
+		strcpy((char *)info->name, "Host filesystem");
 #if CONFIG_IS_ENABLED(PARTITION_UUIDS)
 		info->uuid[0] = 0;
 #endif
diff --git a/fs/Makefile b/fs/Makefile
index f05a21c9e6..4bed2ff2d9 100644
--- a/fs/Makefile
+++ b/fs/Makefile
@@ -21,6 +21,7 @@ obj-$(CONFIG_FS_FAT) += fat/
 obj-$(CONFIG_FS_JFFS2) += jffs2/
 obj-$(CONFIG_CMD_REISER) += reiserfs/
 obj-$(CONFIG_SANDBOX) += sandbox/
+obj-$(CONFIG_SEMIHOSTING) += semihostingfs.o
 obj-$(CONFIG_CMD_UBIFS) += ubifs/
 obj-$(CONFIG_YAFFS2) += yaffs2/
 obj-$(CONFIG_CMD_ZFS) += zfs/
diff --git a/fs/fs.c b/fs/fs.c
index 99dac0fd79..c3a2ed9754 100644
--- a/fs/fs.c
+++ b/fs/fs.c
@@ -18,6 +18,7 @@
 #include <fat.h>
 #include <fs.h>
 #include <sandboxfs.h>
+#include <semihostingfs.h>
 #include <ubifs_uboot.h>
 #include <btrfs.h>
 #include <asm/global_data.h>
@@ -247,6 +248,25 @@ static struct fstype_info fstypes[] = {
 		.ln = fs_ln_unsupported,
 	},
 #endif
+#ifdef CONFIG_SEMIHOSTING
+	{
+		.fstype = FS_TYPE_SEMIHOSTING,
+		.name = "semihosting",
+		.null_dev_desc_ok = true,
+		.probe = smh_fs_set_blk_dev,
+		.close = fs_close_unsupported,
+		.ls = fs_ls_unsupported,
+		.exists = fs_exists_unsupported,
+		.size = smh_fs_size,
+		.read = smh_fs_read,
+		.write = smh_fs_write,
+		.uuid = fs_uuid_unsupported,
+		.opendir = fs_opendir_unsupported,
+		.unlink = fs_unlink_unsupported,
+		.mkdir = fs_mkdir_unsupported,
+		.ln = fs_ln_unsupported,
+	},
+#endif
 #ifdef CONFIG_CMD_UBIFS
 	{
 		.fstype = FS_TYPE_UBIFS,
diff --git a/fs/semihostingfs.c b/fs/semihostingfs.c
new file mode 100644
index 0000000000..96eb3349a2
--- /dev/null
+++ b/fs/semihostingfs.c
@@ -0,0 +1,115 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2022, Sean Anderson <sean.anderson at seco.com>
+ * Copyright (c) 2012, Google Inc.
+ */
+
+#include <common.h>
+#include <fs.h>
+#include <malloc.h>
+#include <os.h>
+#include <semihosting.h>
+#include <semihostingfs.h>
+
+int smh_fs_set_blk_dev(struct blk_desc *rbdd, struct disk_partition *info)
+{
+	/*
+	 * Only accept a NULL struct blk_desc for the semihosting, which is when
+	 * hostfs interface is used
+	 */
+	return !!rbdd;
+}
+
+static int smh_fs_read_at(const char *filename, loff_t pos, void *buffer,
+			  loff_t maxsize, loff_t *actread)
+{
+	long fd, size, ret;
+
+	fd = smh_open(filename, MODE_READ | MODE_BINARY);
+	if (fd < 0)
+		return fd;
+	ret = smh_seek(fd, pos);
+	if (ret < 0) {
+		smh_close(fd);
+		return ret;
+	}
+	if (!maxsize) {
+		size = smh_flen(fd);
+		if (ret < 0) {
+			smh_close(fd);
+			return size;
+		}
+
+		maxsize = size;
+	}
+
+	size = smh_read(fd, buffer, maxsize);
+	smh_close(fd);
+	if (size < 0)
+		return size;
+
+	*actread = size;
+	return 0;
+}
+
+static int smh_fs_write_at(const char *filename, loff_t pos, void *buffer,
+			   loff_t towrite, loff_t *actwrite)
+{
+	long fd, size, ret;
+
+	fd = smh_open(filename, MODE_READ | MODE_BINARY | MODE_PLUS);
+	if (fd < 0)
+		return fd;
+	ret = smh_seek(fd, pos);
+	if (ret < 0) {
+		smh_close(fd);
+		return ret;
+	}
+
+	ret = smh_write(fd, buffer, towrite, &size);
+	smh_close(fd);
+	*actwrite = size;
+	return ret;
+}
+
+int smh_fs_size(const char *filename, loff_t *result)
+{
+	long fd, size;
+
+	fd = smh_open(filename, MODE_READ | MODE_BINARY);
+	if (fd < 0)
+		return fd;
+
+	size = smh_flen(fd);
+	smh_close(fd);
+
+	if (size < 0)
+		return size;
+
+	*result = size;
+	return 0;
+}
+
+int smh_fs_read(const char *filename, void *buf, loff_t offset, loff_t len,
+		loff_t *actread)
+{
+	int ret;
+
+	ret = smh_fs_read_at(filename, offset, buf, len, actread);
+	if (ret)
+		printf("** Unable to read file %s **\n", filename);
+
+	return ret;
+}
+
+int smh_fs_write(const char *filename, void *buf, loff_t offset,
+		 loff_t len, loff_t *actwrite)
+{
+	int ret;
+
+	ret = smh_fs_write_at(filename, offset, buf, len, actwrite);
+	if (ret)
+		printf("** Unable to write file %s **\n", filename);
+
+	return ret;
+}
diff --git a/include/fs.h b/include/fs.h
index b607b0028d..e2beba36b9 100644
--- a/include/fs.h
+++ b/include/fs.h
@@ -18,6 +18,7 @@ struct cmd_tbl;
 #define FS_TYPE_BTRFS	5
 #define FS_TYPE_SQUASHFS 6
 #define FS_TYPE_EROFS   7
+#define FS_TYPE_SEMIHOSTING 8
 
 struct blk_desc;
 
diff --git a/include/semihostingfs.h b/include/semihostingfs.h
new file mode 100644
index 0000000000..25ebdbbeff
--- /dev/null
+++ b/include/semihostingfs.h
@@ -0,0 +1,21 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * Copyright (C) 2022, Sean Anderson <sean.anderson at seco.com>
+ * Copyright (c) 2012, Google Inc.
+ */
+
+#ifndef __SEMIHOSTING_FS__
+#define __SEMIHOSTING_FS__
+
+struct blk_desc;
+struct disk_partition;
+
+int smh_fs_set_blk_dev(struct blk_desc *rbdd, struct disk_partition *info);
+void smh_fs_close(void);
+int smh_fs_size(const char *filename, loff_t *size);
+int smh_fs_read(const char *filename, void *buf, loff_t offset, loff_t len,
+		loff_t *actread);
+int smh_fs_write(const char *filename, void *buf, loff_t offset,
+		 loff_t len, loff_t *actwrite);
+
+#endif
-- 
2.25.1



More information about the U-Boot mailing list