From 48d61510290ea3380e4987d38e512d2d8304849a Mon Sep 17 00:00:00 2001 From: Andrey Smirnov Date: Wed, 28 Oct 2015 11:34:36 -0700 Subject: ARM: Add support for semihosting Add semihosting API implementation and implement a filesystem driver to access debugging host filesystem using it. Tested on Freescale SabreSD board (i.MX6Q) using OpenOCD Signed-off-by: Andrey Smirnov Signed-off-by: Sascha Hauer --- fs/smhfs.c | 178 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 178 insertions(+) create mode 100644 fs/smhfs.c (limited to 'fs/smhfs.c') diff --git a/fs/smhfs.c b/fs/smhfs.c new file mode 100644 index 0000000000..a0df06c31e --- /dev/null +++ b/fs/smhfs.c @@ -0,0 +1,178 @@ +/* + * smhfs.c -- Driver implementing pseudo FS interface on top of ARM + * semihosting + * + * Copyright (c) 2015 Zodiac Inflight Innovations + * Author: Andrey Smirnov + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ + +#include +#include +#include +#include +#include +#include +#include + +static int file_to_fd(const FILE *f) +{ + return (int)f->priv; +} + +static int smhfs_create(struct device_d __always_unused *dev, + const char __always_unused *pathname, + mode_t __always_unused mode) +{ + return 0; +} + +static int smhfs_mkdir(struct device_d __always_unused *dev, + const char __always_unused *pathname) +{ + return -ENOSYS; +} + +static int smhfs_rm(struct device_d __always_unused *dev, + const char *pathname) +{ + /* Get rid of leading '/' */ + pathname = &pathname[1]; + + if (semihosting_remove(pathname) != 0) + return -semihosting_errno(); + else + return 0; +} + +static int smhfs_truncate(struct device_d __always_unused *dev, + FILE __always_unused *f, + ulong __always_unused size) +{ + return -ENOSYS; +} + +static int smhfs_open(struct device_d __always_unused *dev, + FILE *file, const char *filename) +{ + int fd; + /* Get rid of leading '/' */ + filename = &filename[1]; + + fd = semihosting_open(filename, file->flags); + if (fd < 0) + goto error; + + file->priv = (void *)fd; + file->size = semihosting_flen(fd); + if (file->size < 0) + goto error; + + return 0; +error: + return -semihosting_errno(); +} + +static int smhfs_close(struct device_d __always_unused *dev, + FILE *f) +{ + if (semihosting_close(file_to_fd(f))) + return -semihosting_errno(); + else + return 0; +} + +static int smhfs_write(struct device_d __always_unused *dev, + FILE *f, const void *inbuf, size_t insize) +{ + if (semihosting_write(file_to_fd(f), inbuf, insize)) + return -semihosting_errno(); + else + return insize; +} + +static int smhfs_read(struct device_d __always_unused *dev, + FILE *f, void *buf, size_t insize) +{ + if (!semihosting_read(file_to_fd(f), buf, insize)) + return insize; + else + return -semihosting_errno(); +} + +static loff_t smhfs_lseek(struct device_d __always_unused *dev, + FILE *f, loff_t pos) +{ + if (semihosting_seek(file_to_fd(f), pos)) { + return -semihosting_errno(); + } else { + f->pos = pos; + return f->pos; + } +} + +static DIR* smhfs_opendir(struct device_d __always_unused *dev, + const char __always_unused *pathname) +{ + return NULL; +} + +static int smhfs_stat(struct device_d __always_unused *dev, + const char *filename, struct stat *s) +{ + FILE file; + + if (smhfs_open(NULL, &file, filename) == 0) { + s->st_mode = S_IFREG | S_IRWXU | S_IRWXG | S_IRWXO; + s->st_size = file.size; + } + smhfs_close(NULL, &file); + + return 0; +} + +static int smhfs_probe(struct device_d __always_unused *dev) +{ + /* TODO: Add provisions to detect if debugger is connected */ + return 0; +} + +static void smhfs_remove(struct device_d __always_unused *dev) +{ +} + +static struct fs_driver_d smhfs_driver = { + .open = smhfs_open, + .close = smhfs_close, + .read = smhfs_read, + .lseek = smhfs_lseek, + .opendir = smhfs_opendir, + .stat = smhfs_stat, + .create = smhfs_create, + .unlink = smhfs_rm, + .mkdir = smhfs_mkdir, + .rmdir = smhfs_rm, + .write = smhfs_write, + .truncate = smhfs_truncate, + .flags = FS_DRIVER_NO_DEV, + .drv = { + .probe = smhfs_probe, + .remove = smhfs_remove, + .name = "smhfs", + } +}; + +static int smhfs_init(void) +{ + return register_fs_driver(&smhfs_driver); +} +coredevice_initcall(smhfs_init); -- cgit v1.2.3