From 29dc401e5ba2c3f5676d426c4c1b10f1fc475fcd Mon Sep 17 00:00:00 2001 From: Pixel Date: Sun, 30 Jan 2011 00:53:28 -0800 Subject: Added semihosting support. --- os/src/semifs.c | 190 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 190 insertions(+) create mode 100644 os/src/semifs.c (limited to 'os/src') diff --git a/os/src/semifs.c b/os/src/semifs.c new file mode 100644 index 0000000..fc7d0b1 --- /dev/null +++ b/os/src/semifs.c @@ -0,0 +1,190 @@ +/* Copyright (c) 2010 James Snyder, eLua Project. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to + * deal in the Software without restriction, including without limitation the right + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include +#include +#include +#include + +#include + +#include "filesystem.h" +#include "fio.h" +#include "semifs.h" +#include "osdebug.h" + +struct semifs_fds_t { + uint32_t file; + uint32_t cursor; +}; + +static struct semifs_fds_t semifs_fds[MAX_FDS]; + +// These structures provided by Simon Ford of mbed +struct semifs_FTime { + uint8_t hr; // Hours [0..23] + uint8_t min; // Minutes [0..59] + uint8_t sec; // Seconds [0..59] + uint8_t day; // Day [1..31] + uint8_t mon; // Month [1..12] + uint16_t year; // Year [1980..2107] +}; + +// File Search info record +struct semifs_XF_Info { + char name[32]; // File - 32-bytes + uint32_t size; // File size in bytes - 4-bytes + uint16_t fileID; // System File Identification - 2-bytes + struct semifs_FTime create_time; // Date & time file was created + struct semifs_FTime write_time; // Date & time of last write +}; + +struct semifs_SearchInfo { + const char *pattern; + struct semifs_XF_Info file_info; +}; + +/*****************************************************************************/ + +static int semifs_close(void * opaque) { + struct semifs_fds_t * f = (struct semifs_fds_t *) opaque; +// DBGOUT("semifs_close(%p)\r\n", opaque); + + return Semihost_SYS_CLOSE(&f->file); +} + +static ssize_t semifs_write(void * opaque, const void * ptr, size_t len) { + struct semifs_fds_t * f = (struct semifs_fds_t *) opaque; +// DBGOUT("semifs_write(%p, %p, %i)\r\n", opaque, ptr, len); + + uint32_t args[3]; + args[0] = (uint32_t) f->file; + args[1] = (uint32_t) ptr; + args[2] = (uint32_t) len; + + // Perform write + int res = Semihost_SYS_WRITE(args); +// DBGOUT("semifs_read: Semihost_SYS_WRITE returned %i\r\n", res); + if (res == -1 || res == len) + return -1; + + // Update position + f->cursor += len - res; + return len - res; +} + +static ssize_t semifs_read(void * opaque, void * ptr, size_t len) { + struct semifs_fds_t * f = (struct semifs_fds_t *) opaque; +// DBGOUT("semifs_read(%p, %p, %i)\r\n", opaque, ptr, len); + + uint32_t args[3]; + args[0] = (uint32_t) f->file; + args[1] = (uint32_t) ptr; + args[2] = (uint32_t) len; + + // Perform read + int res = Semihost_SYS_READ(args); + DBGOUT("semifs_read: Semihost_SYS_READ returned %i\r\n", res); + if (res < 0) + return -1; + + // Update position + f->cursor += len - res; + return len - res; +} + +static off_t semifs_seek(void * opaque, off_t off, int whence) { + uint32_t args[2], len; + struct semifs_fds_t * f = (struct semifs_fds_t *) opaque; +// DBGOUT("semifs_seek(%p, %i, %i)\r\n", opaque, off, whence); + + switch (whence) { + case SEEK_CUR: + // seek from current position + off += f->cursor; + whence = SEEK_SET; + break; + + case SEEK_END: + // seek from end of file + args[0] = (uint32_t) f->file; + len = Semihost_SYS_FLEN(args); +// DBGOUT("semifs_seek: Semihost_SYS_FLEN returned %i\r\n", len); + off += len; + break; + } + // Do absolute seek + args[0] = (uint32_t) f->file; + args[1] = (uint32_t) off; + int res = Semihost_SYS_SEEK(args); +// DBGOUT("semifs_seek: Semihost_SYS_SEEK returned %i\r\n", res); + + if (res == 0) + f->cursor = off; + + /* This is expected to return the position in the file. */ + return res == 0 ? off : -1; +} + +static int semifs_open(void * opaque, const char *path, int flags, int mode) { + int aflags = 0; + unsigned int fh; + uint32_t args[3]; +// DBGOUT("semifs_open(%p, \"%s\", %i, %i)\r\n"); + + if (flags & O_RDWR) + aflags |= 2; + + if (flags & O_CREAT) + aflags |= 4; + + if (flags & O_TRUNC) + aflags |= 4; + + if (flags & O_APPEND) { + aflags &= ~4; // Can't ask for w AND a; means just 'a'. + aflags |= 8; + } + + // Find file and open it (via semihosting call) + args[0] = (uint32_t) path; + args[1] = (uint32_t) aflags; + args[2] = (uint32_t) strlen(path); + fh = Semihost_SYS_OPEN(args); +// DBGOUT("Semihost_SYS_OPEN returns: %i\r\n", fh); + + if (fh >= 0) { + int fd = fio_open(semifs_read, semifs_write, semifs_seek, semifs_close, (void *) fh); +// DBGOUT("semifs_open: fio_open returned %i\r\n", fd); + if (fd < 0) + Semihost_SYS_CLOSE((uint32_t *) &fd); + semifs_fds[fd].file = fh; + semifs_fds[fd].cursor = 0; + fio_set_opaque(fd, semifs_fds + fd); + return fd; + } + return -1; +} + +void register_semifs() { + DBGOUT("Registering semihost fs\r\n"); + register_fs("host", semifs_open, NULL); +} -- cgit v1.2.3