/* * Copyright 2010 Stefan Lankes, Chair for Operating Systems, * RWTH Aachen University * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * This file is part of MetalSVM. */ #include #include #include #include #include #include #include #include static int sys_write(int fd, const char *buf, size_t len) { unsigned int wrotebytes; wrotebytes = write_fs(per_core(current_task)->fildes_table[fd].node, (uint8_t*)buf, len, per_core(current_task)->fildes_table[fd].offset); //kprintf("writing into filesystem -- fd:%i, Filelength:%i, Writtenbytes: %i, Bufferlength: %s \n", fd, len, wrotebytes, buf); per_core(current_task)->fildes_table[fd].offset += wrotebytes; return wrotebytes; } static int sys_open(const char* file, int flags, int mode) { int fd; for (fd = 3; fd < NR_OPEN; fd++) { if (per_core(current_task)->fildes_table[fd].node == NULL) { per_core(current_task)->fildes_table[fd].node = findnode_fs((char*) file); return fd; } } if (fd >= NR_OPEN) { kprintf("Unable to create filedescriptor"); return -EINVAL; } } static int sys_close(int fd) { close_fs(per_core(current_task)->fildes_table[fd].node); per_core(current_task)->fildes_table[fd].node = NULL; per_core(current_task)->fildes_table[fd].offset = 0; return 0; } static int sys_read(int fd, const char *buf, size_t len) { unsigned int readbytes; readbytes = read_fs( per_core(current_task)->fildes_table[fd].node, (uint8_t*)buf, len, per_core(current_task)->fildes_table[fd].offset); per_core(current_task)->fildes_table[fd].offset += readbytes; /*kprintf("fd:%i, Filelength:%i, Bufferlength: %s X: %i\n", fd, len, buf, readbytes); */ /* Beware: still reading above file limit! */ return readbytes; } static int sys_lseek(int fd, off_t pos, int origin) { int ret = -EINVAL; if (BUILTIN_EXPECT(per_core(current_task)->fildes_table[fd].node->type != FS_FILE, 0)) return -EINVAL; switch(origin) { case SEEK_SET: { /* set file offset to offset */ per_core(current_task)->fildes_table[fd].offset = pos; ret = 0; break; } case SEEK_CUR: { /* set file offset to current plus offset */ ret = pos + per_core(current_task)->fildes_table[fd].offset; break; } case SEEK_END: { /* set file offset to EOF plus offset */ per_core(current_task)->fildes_table[fd].offset = pos + per_core(current_task)->fildes_table[fd].node->block_size; ret = 0; break; } default: ret = -EINVAL; break; } return ret; } static int sys_sbrk(int incr) { task_t* task = per_core(current_task); vma_t* tmp = NULL; int ret; spinlock_lock(&task->vma_lock); tmp = task->vma_list; while(tmp && !((task->end_heap >= tmp->start) && (task->end_heap <= tmp->end))) tmp = tmp->next; ret = (int) task->end_heap; task->end_heap += incr; if (task->end_heap < task->start_heap) task->end_heap = task->start_heap; // resize virtual memory area if (tmp && (tmp->end <= task->end_heap)) tmp->end = task->end_heap; spinlock_unlock(&task->vma_lock); return ret; } int syscall_handler(uint32_t sys_nr, ...) { int ret = -EINVAL; va_list vl; check_workqueues(); va_start(vl, sys_nr); switch(sys_nr) { case __NR_exit: sys_exit(va_arg(vl, uint32_t)); ret = 0; break; case __NR_write: { int fd = va_arg(vl, int); const char* buf = va_arg(vl, const char*); size_t len = va_arg(vl, size_t); ret = sys_write(fd, buf, len); break; } case __NR_open: { const char* file = va_arg(vl, const char*); int flags = va_arg(vl, int); int mode = va_arg(vl, int); ret = sys_open(file, flags, mode); break; } case __NR_close: { int fd = va_arg(vl, int); ret = sys_close(fd); break; } case __NR_read: { int fd = va_arg(vl, int); const char* buf = va_arg(vl, const char*); size_t len = va_arg(vl, size_t); ret = sys_read(fd, buf, len); break; } case __NR_lseek: { int fd = va_arg(vl, int); off_t pos = va_arg(vl, off_t); int origin = va_arg(vl, int); ret = sys_lseek(fd, pos, origin); break; } case __NR_sbrk: { int incr = va_arg(vl, int); ret = sys_sbrk(incr); break; } case __NR_getpid: ret = per_core(current_task)->id; break; case __NR_fork: ret = sys_fork(); break; case __NR_wait: { int32_t* status = va_arg(vl, int32_t*); ret = wait(status); break; } case __NR_execve: { const char* name = va_arg(vl, const char*); char** argv = va_arg(vl, char**); char** env = va_arg(vl, char**); ret = sys_execve(name, argv, env); break; } case __NR_times: { struct tms* buffer = va_arg(vl, struct tms*); clock_t* clock = va_arg(vl, clock_t*); ret = sys_times(buffer, clock); break; } default: kputs("invalid system call\n"); ret = -ENOSYS; break; }; va_end(vl); return ret; }