diff options
author | Ingo Albrecht <prom@berlin.ccc.de> | 2010-07-20 14:37:41 +0200 |
---|---|---|
committer | Ingo Albrecht <prom@berlin.ccc.de> | 2010-08-17 00:29:08 +0200 |
commit | 97589cb38d3b0584585955ebadba13bf6910b12a (patch) | |
tree | ec947fe523405d3802e98ea409ebca4f0eedfec0 | |
parent | 9bab7d304e9d976439384a38480f8c04eceef2dc (diff) |
dietlibc: a more proper file descriptor layer
-rw-r--r-- | src/target/firmware/Makefile | 3 | ||||
-rw-r--r-- | src/target/firmware/lib/system.c | 46 | ||||
-rw-r--r-- | src/target/firmware/sys/Makefile | 5 | ||||
-rw-r--r-- | src/target/firmware/sys/file.c | 311 |
4 files changed, 318 insertions, 47 deletions
diff --git a/src/target/firmware/Makefile b/src/target/firmware/Makefile index 30055398..d8361684 100644 --- a/src/target/firmware/Makefile +++ b/src/target/firmware/Makefile @@ -59,7 +59,7 @@ RF_OBJS=rf/trf6151.o # Objects that go in all applications ANY_APP_OBJS+=$(ABB_OBJS) $(RF_OBJS) $(DISPLAY_OBJS) $(FLASH_OBJS) -ANY_APP_LIBS+=calypso/libcalypso.a layer1/liblayer1.a lib/libmini.a comm/libcomm.a ../dietlibc/bin-arm/dietlibc.a ../../shared/libosmocore/build-target/src/.libs/libosmocore.a +ANY_APP_LIBS+=calypso/libcalypso.a layer1/liblayer1.a lib/libmini.a comm/libcomm.a sys/libsys.a ../dietlibc/bin-arm/dietlibc.a ../../shared/libosmocore/build-target/src/.libs/libosmocore.a # Libraries are defined in subdirectories @@ -67,6 +67,7 @@ ANY_APP_LIBS+=calypso/libcalypso.a layer1/liblayer1.a lib/libmini.a comm/libcomm -include layer1/Makefile -include comm/Makefile -include lib/Makefile +-include sys/Makefile # Include rules -include Makefile.inc diff --git a/src/target/firmware/lib/system.c b/src/target/firmware/lib/system.c index 9c6c6859..a77acbd1 100644 --- a/src/target/firmware/lib/system.c +++ b/src/target/firmware/lib/system.c @@ -11,10 +11,6 @@ int errno; -int ioctl(int fd, long int request, ...) { - return 0; -} - extern char _end; const char *heaptop = &_end; @@ -49,48 +45,6 @@ int munmap(void *addr, size_t length) { return 0; } -int fstat(int fd, struct stat *buf) { - errno = ENOENT; - return -1; -} - -int __libc_open(const char *pathname, int flags) { - errno = ENOENT; - return -1; -} - -int __libc_close(int fd) { - return 0; -} - -ssize_t __libc_read(int fd, void *buf, size_t count) { - errno = ENOTSUP; - return -1; -} - -ssize_t __libc_write(int fd, const void *buf, size_t count) { - char c; - int i; - - switch(fd) { - default: - case 0: - errno = EBADF; - return -1; - case 1: - case 2: - return sercomm_write(buf, count); - } -} - -ssize_t write(int fd, const void *buf, size_t count) { - return __libc_write(fd, buf, count); -} - -off_t lseek(int fd, off_t offset, int whence) { - return offset; -} - void _exit(int status) { puts("Program exit\n"); while(1) { } diff --git a/src/target/firmware/sys/Makefile b/src/target/firmware/sys/Makefile new file mode 100644 index 00000000..95dffe6e --- /dev/null +++ b/src/target/firmware/sys/Makefile @@ -0,0 +1,5 @@ + +LIBRARIES+=sys +sys_DIR=sys +sys_SRCS=file.c + diff --git a/src/target/firmware/sys/file.c b/src/target/firmware/sys/file.c new file mode 100644 index 00000000..e95721d4 --- /dev/null +++ b/src/target/firmware/sys/file.c @@ -0,0 +1,311 @@ + +#include <fcntl.h> +#include <errno.h> +#include <string.h> + +/* max number of file descriptors (would-be per-process) */ +#define MAXFDS 8 +/* max number of open files */ +#define MAXFILES 8 + +/* forward declarations */ +struct file; +struct file_operations; + +/* function pointer types for operations */ +typedef int (*fop_sync_t) (struct file *fd); +typedef off_t (*fop_seek_t) (struct file *fd, off_t offset, int whence); +typedef ssize_t (*fop_read_t) (struct file *fd, void *buf, size_t size); +typedef ssize_t (*fop_write_t) (struct file *fd, const void *buf, size_t size); +typedef int (*fop_close_t) (struct file *fd); + +/* structure describing operations for file */ +struct file_operations { + fop_sync_t fop_sync; + fop_seek_t fop_seek; + fop_read_t fop_read; + fop_write_t fop_write; + fop_close_t fop_close; +}; + +/* structure describing the state behind a file descriptor */ +struct file { + /* refcount, -1 used on allocation */ + int8_t f_used; + /* file flags (O_RDONLY and so forth) */ + int f_flags; + /* object-specific operation structure */ + struct file_operations *f_ops; + /* object-specific file structure */ + void *f_cookie; +}; + +/* "table" of all file descriptors */ +struct file *open_fds[MAXFDS]; + +/* pre-allocated descriptor structures */ +struct file open_files[MAXFILES]; + +ssize_t scc_write(struct file *f, const void *buf, size_t size) +{ + return sercomm_write(buf, size); +} + +struct file_operations sercomm_console_operations = { + .fop_write = &scc_write +}; + +__attribute__((constructor)) +void file_table_init(void) +{ + /* clear all structures */ + memset(open_files, 0, sizeof(open_files)); + memset(open_fds, 0, sizeof(open_fds)); + + /* stdin */ + open_files[0].f_used = 1; + open_files[0].f_flags = O_RDONLY; + open_files[0].f_ops = &sercomm_console_operations; + open_fds[0] = &open_files[0]; + + /* stdout */ + open_files[1].f_used = 1; + open_files[1].f_flags = O_WRONLY; + open_files[1].f_ops = &sercomm_console_operations; + open_fds[1] = &open_files[1]; + + /* stderr */ + open_files[2].f_used = 1; + open_files[2].f_flags = O_WRONLY; + open_files[2].f_ops = &sercomm_console_operations; + open_fds[2] = &open_files[2]; +} + + +struct file *file_alloc() +{ + int i; + for(i = 0; i < MAXFILES; i++) { + if(!open_files[i].f_used) { + open_files[i].f_used = -1; + return &open_files[i]; + } + } + + errno = ENFILE; + return NULL; +} + +int file_ref(struct file *fd) +{ + if(fd->f_used == -1) { + fd->f_used = 1; + } else { + fd->f_used++; + } + return fd->f_used; +} + +int file_unref(struct file *fd) +{ + if(fd->f_used <= 0) { + fd->f_used = 0; + } else { + fd->f_used--; + } + return fd->f_used; +} + + +int file_sync(struct file *fd) +{ + /* pass through to the implementation, if present. else fail. */ + if(fd->f_ops->fop_sync) { + return fd->f_ops->fop_sync(fd); + } else { + errno = EOPNOTSUPP; + return -1; + } +} + +off_t file_seek(struct file *fd, off_t offset, int whence) +{ + /* pass through to the implementation, if present. else fail. */ + if(fd->f_ops->fop_seek) { + return fd->f_ops->fop_seek(fd, offset, whence); + } else { + errno = EOPNOTSUPP; + return -1; + } +} + +size_t file_read(struct file *fd, void *buf, size_t count) +{ + /* pass through to the implementation, if present. else fail. */ + if(fd->f_ops->fop_read) { + return fd->f_ops->fop_read(fd, buf, count); + } else { + errno = EOPNOTSUPP; + return -1; + } +} + +size_t file_write(struct file *fd, const void *buf, size_t count) +{ + /* pass through to the implementation, if present. else fail. */ + if(fd->f_ops->fop_write) { + return fd->f_ops->fop_write(fd, buf, count); + } else { + errno = EOPNOTSUPP; + return -1; + } +} + +int file_close(struct file *fd) +{ + /* unref and really close if at last ref */ + if(!file_unref(fd)) { + return 0; + } + + /* call object implementation once */ + if(fd->f_ops->fop_close) { + return fd->f_ops->fop_close(fd); + } + + /* clear structure */ + memset(fd, 0, sizeof(struct file)); + + /* done */ + return 0; +} + + + +int fd_alloc(struct file *file) +{ + int i; + for(i = 0; i < MAXFDS; i++) { + if(!open_fds[i]) { + file_ref(file); + open_fds[i] = file; + return i; + } + } + + errno = EMFILE; + return -1; +} + +struct file *file_for_fd(int fd) +{ + if(fd >= MAXFDS) { + errno = EBADF; + return NULL; + } + + if(!open_fds[fd]) { + errno = EBADF; + return NULL; + } + + return open_fds[fd]; +} + + + +int __libc_open(const char *pathname, int flags, ...) +{ + errno = EOPNOTSUPP; + return -1; +} + +int open(const char *pathname, int flags, ...) + __attribute__((weak,alias("__libc_open"))); + + +int __libc_close(int fd) +{ + struct file *file = file_for_fd(fd); + if(!file) { + errno = EBADF; + return -1; + } + + int res = file_close(file); + if(res < 0) { + return res; + } + + open_fds[fd] = NULL; + + return 0; +} + +int close(int fd) + __attribute__((weak,alias("__libc_close"))); + + +ssize_t __libc_read(int fd, void *buf, size_t count) +{ + struct file *f = file_for_fd(fd); + if(!f) { + errno = EBADF; + return -1; + } + + return file_read(f, buf, count); +} + +ssize_t read(int fd, void *buf, size_t count) + __attribute__((weak,alias("__libc_read"))); + + +ssize_t __libc_write(int fd, const void *buf, size_t count) +{ + struct file *f = file_for_fd(fd); + if(!f) { + errno = EBADF; + return -1; + } + + return file_write(f, buf, count); +} + +ssize_t write(int fd, const void *buf, size_t count) + __attribute__((weak,alias("__libc_write"))); + + +off_t __libc_lseek(int fd, off_t offset, int whence) +{ + struct file *f = file_for_fd(fd); + if(!f) { + errno = EBADF; + return -1; + } + + return file_seek(f, offset, whence); +} + +off_t lseek(int fd, off_t offset, int whence) + __attribute__((weak,alias("__libc_lseek"))); + + +int __libc_fstat(int fd, struct stat *buf) +{ + errno = EOPNOTSUPP; + return -1; +} + +int fstat(int fd, struct stat *buf) + __attribute__((weak,alias("__libc_fstat"))); + + +int __libc_ioctl(int fd, long int request, ...) +{ + errno = EOPNOTSUPP; + return -1; +} + +int ioctl(int fd, long int request, ...) + __attribute__((weak,alias("__libc_ioctl"))); |