summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorIngo Albrecht <prom@berlin.ccc.de>2010-07-20 14:37:41 +0200
committerIngo Albrecht <prom@berlin.ccc.de>2010-08-17 00:29:08 +0200
commit97589cb38d3b0584585955ebadba13bf6910b12a (patch)
treeec947fe523405d3802e98ea409ebca4f0eedfec0
parent9bab7d304e9d976439384a38480f8c04eceef2dc (diff)
dietlibc: a more proper file descriptor layer
-rw-r--r--src/target/firmware/Makefile3
-rw-r--r--src/target/firmware/lib/system.c46
-rw-r--r--src/target/firmware/sys/Makefile5
-rw-r--r--src/target/firmware/sys/file.c311
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")));