From f676b45151c33986501e5f8f9bcc64f4a9511089 Mon Sep 17 00:00:00 2001 From: Sean Anderson Date: Tue, 22 Mar 2022 16:59:20 -0400 Subject: fs: Add semihosting filesystem 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 --- fs/Makefile | 1 + fs/fs.c | 20 ++++++++++ fs/semihostingfs.c | 115 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 136 insertions(+) create mode 100644 fs/semihostingfs.c (limited to 'fs') 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 #include #include +#include #include #include #include @@ -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 + * Copyright (c) 2012, Google Inc. + */ + +#include +#include +#include +#include +#include +#include + +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; +} -- cgit v1.2.3