Nucleus
Barry System headers (remove libc dependency) 18495cf (3 years, 2 months ago)
/*
* This file implements the system call handler. It is called by the exc128
* handler function and just switches the syscall number into the syscall list
* and runs the relevant function.
*/
#include <sys/errno.h>
#include <sys/exec.h>
#include <sys/file.h>
#include <sys/fs.h>
#include <sys/ioctl.h>
#include <sys/mman.h>
#include <sys/mount.h>
#include <sys/sched.h>
#include <sys/signal.h>
#include <sys/stat.h>
#include <sys/syscall.h>
#include <sys/utsname.h>
#include <sys/wait.h>
#include <nucleus/cpu.h>
#include <nucleus/kernel.h>
#include <nucleus/memory.h>
#include <nucleus/task.h>
#include <nucleus/vfs.h>
/* Structure for a System Call Entry */
struct SyscallEntry {
int argc;
void *function;
};
/* List of syscalls */
struct SyscallEntry syscalls[] = {
/* Kernel */
[SYSCALL_DBGPRINTF] = { 1, dbgprintf },
[SYSCALL_UNAME] = { 1, uname },
/* Task */
[SYSCALL_CLONE] = { 1, clone },
[SYSCALL_EXIT] = { 1, exit },
[SYSCALL_GETPID] = { 0, getpid },
[SYSCALL_GETUID] = { 0, getuid },
[SYSCALL_SETUID] = { 1, setuid },
[SYSCALL_GETEUID] = { 0, geteuid },
[SYSCALL_SETEUID] = { 1, seteuid },
[SYSCALL_GETGID] = { 0, getgid },
[SYSCALL_SETGID] = { 1, setgid },
[SYSCALL_GETEGID] = { 0, getegid },
[SYSCALL_SETEGID] = { 1, setegid },
[SYSCALL_EXECVE] = { 3, execve },
[SYSCALL_WAITPID] = { 3, waitpid },
// [SYSCALL_TIME] = { 1, time },
// [SYSCALL_TIMES] = { 1, times },
// [SYSCALL_SLEEP] = { 1, sleep },
/* Files */
[SYSCALL_OPEN] = { 3, open },
[SYSCALL_CLOSE] = { 1, close },
[SYSCALL_READ] = { 3, read },
[SYSCALL_WRITE] = { 3, write },
[SYSCALL_IOCTL] = { 3, ioctl },
[SYSCALL_LSEEK] = { 3, lseek },
[SYSCALL_STAT] = { 2, stat },
[SYSCALL_FSTAT] = { 2, fstat },
[SYSCALL_GETDENTS] = { 3, getdents },
[SYSCALL_MKDIR] = { 2, mkdir },
// [SYSCALL_RMDIR] = { 1, rmdir },
[SYSCALL_MKNOD] = { 3, mknod },
// [SYSCALL_RENAME] = { 2, rename },
[SYSCALL_DUP] = { 1, dup },
[SYSCALL_DUP2] = { 2, dup2 },
// [SYSCALL_ISATTY] = { 1, isatty },
// [SYSCALL_PIPE] = { 1, pipe },
/* File System */
[SYSCALL_MOUNT] = { 5, mount },
[SYSCALL_CHDIR] = { 1, chdir },
[SYSCALL_CHROOT] = { 1, chroot },
[SYSCALL_GETCWD] = { 2, getcwd },
/* Memory */
[SYSCALL_MMAP] = { 6, mmap },
/* Signals */
[SYSCALL_TGKILL] = { 3, tgkill },
[SYSCALL_KILL] = { 2, kill },
[SYSCALL_SIGNAL] = { 2, signal },
[SYSCALL_SIGPROCMASK] = { 3, sigprocmask },
};
/* Handle a syscall */
void
syscall_handler(struct InterruptFrame *frame)
{
int num = frame->eax;
uintptr_t args = frame->esi;
int ret = -EINVAL;
enter_syscall_context();
/* Find syscall entry */
if (num >= sizeof(syscalls) / sizeof(syscalls[0]))
goto end;
struct SyscallEntry *syscall = &syscalls[num];
if (!syscall->function)
goto end;
/* Copy arguments onto stack */
if (syscall->argc) {
int *val = (int *) args;
int argc = syscall->argc;
if (!verify_access(val, argc * sizeof(int), PROT_READ))
goto end;
while (argc--)
asm volatile("pushl %0" :: "r" (val[argc]));
}
/* Call function */
asm volatile(
"sti;"
"call *%1;"
"cli"
: "=a" (ret)
: "r" (syscall->function)
);
end:
exit_syscall_context();
frame->eax = ret;
}