BarryServer : Git

All the code for all my projects
// BarryServer : Git / Nucleus / blob / master / task / syscall.c

// Related

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;
}