diff options
author | Sean Anderson <sean.anderson@seco.com> | 2022-03-22 16:59:20 -0400 |
---|---|---|
committer | Tom Rini <trini@konsulko.com> | 2022-04-01 15:03:13 -0400 |
commit | f676b45151c33986501e5f8f9bcc64f4a9511089 (patch) | |
tree | 7a893e7f077239f473c820069f054d25ec1d6d37 /fs | |
parent | 8e1c9fe243a31a0b0a40a80cc20fc3c06246d675 (diff) | |
download | u-boot-f676b45151c33986501e5f8f9bcc64f4a9511089.zip u-boot-f676b45151c33986501e5f8f9bcc64f4a9511089.tar.gz u-boot-f676b45151c33986501e5f8f9bcc64f4a9511089.tar.bz2 |
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 <sean.anderson@seco.com>
Diffstat (limited to 'fs')
-rw-r--r-- | fs/Makefile | 1 | ||||
-rw-r--r-- | fs/fs.c | 20 | ||||
-rw-r--r-- | fs/semihostingfs.c | 115 |
3 files changed, 136 insertions, 0 deletions
diff --git a/fs/Makefile b/fs/Makefile index f05a21c..4bed2ff 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/ @@ -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 0000000..96eb334 --- /dev/null +++ b/fs/semihostingfs.c @@ -0,0 +1,115 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2022, Sean Anderson <sean.anderson@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; +} |