640 lines
		
	
	
		
			16 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			640 lines
		
	
	
		
			16 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| /*
 | |
| Copyright (C) 2015-2019 The University of Notre Dame
 | |
| This software is distributed under the GNU General Public License.
 | |
| See the file LICENSE for details.
 | |
| */
 | |
| 
 | |
| #include "kernel/syscall.h"
 | |
| #include "kernel/gfxstream.h"
 | |
| #include "syscall_handler.h"
 | |
| #include "console.h"
 | |
| #include "keyboard.h"
 | |
| #include "process.h"
 | |
| #include "kmalloc.h"
 | |
| #include "kobject.h"
 | |
| #include "cdromfs.h"
 | |
| #include "string.h"
 | |
| #include "memorylayout.h"
 | |
| #include "main.h"
 | |
| #include "fs.h"
 | |
| #include "kobject.h"
 | |
| #include "pagetable.h"
 | |
| #include "clock.h"
 | |
| #include "rtc.h"
 | |
| #include "elf.h"
 | |
| #include "kmalloc.h"
 | |
| #include "page.h"
 | |
| #include "ata.h"
 | |
| #include "window.h"
 | |
| #include "is_valid.h"
 | |
| #include "bcache.h"
 | |
| 
 | |
| /*
 | |
| syscall_handler() is responsible for decoding system calls
 | |
| as they arrive, converting raw integers into the appropriate
 | |
| types, depending on the system call number.  Then, each
 | |
| individual handler routine checks the validity of each
 | |
| argument (fd in range, valid path, etc) and invokes the
 | |
| underlying system within the kernel.  Ideally, each of these
 | |
| handler functions should be short (only a few lines)
 | |
| and simply make use of functionality within other kernel modules.
 | |
| 
 | |
| sys_run/fork/exec are notable exceptions and could benefit
 | |
| from simplification.
 | |
| */
 | |
| 
 | |
| /*
 | |
| Here follow the handlers for each individual system call
 | |
| For all of these system calls, a return value of zero or
 | |
| greater indiciates success, and return of less than zero
 | |
| indicates an error and the reason.
 | |
| */
 | |
| 
 | |
| int sys_debug(const char *str)
 | |
| {
 | |
| 	if(!is_valid_string(str)) return KERROR_INVALID_ADDRESS;
 | |
| 	printf("%s", str);
 | |
| 	return 0;
 | |
| }
 | |
| 
 | |
| int sys_process_yield()
 | |
| {
 | |
| 	process_yield();
 | |
| 	return 0;
 | |
| }
 | |
| 
 | |
| int sys_process_exit(int status)
 | |
| {
 | |
| 	process_exit(status);
 | |
| 	return 0;
 | |
| }
 | |
| 
 | |
| /* Helper routines to duplicate/free an argv array locally */
 | |
| 
 | |
| static char **argv_copy(int argc, const char **argv)
 | |
| {
 | |
| 	char **pp;
 | |
| 
 | |
| 	pp = kmalloc(sizeof(char *) * argc);
 | |
| 	int i;
 | |
| 	for(i = 0; i < argc; i++) {
 | |
| 		pp[i] = strdup(argv[i]);
 | |
| 	}
 | |
| 
 | |
| 	return pp;
 | |
| }
 | |
| 
 | |
| static void argv_delete(int argc, char **argv)
 | |
| {
 | |
| 	int i;
 | |
| 	for(i = 0; i < argc; i++) {
 | |
| 		kfree(argv[i]);
 | |
| 	}
 | |
| 	kfree(argv);
 | |
| }
 | |
| 
 | |
| /*
 | |
| process_run() creates a child process in a more efficient
 | |
| way than fork/exec by creating the child without duplicating
 | |
| the memory state, then loading
 | |
| */
 | |
| 
 | |
| int sys_process_run( int fd, int argc, const char **argv)
 | |
| {
 | |
| 	if(!is_valid_object_type(fd,KOBJECT_FILE)) return KERROR_INVALID_OBJECT;
 | |
| 
 | |
| 	struct kobject *k = current->ktable[fd];
 | |
| 
 | |
| 	/* Copy argv into kernel memory. */
 | |
| 	char **copy_argv = argv_copy(argc, argv);
 | |
| 
 | |
| 	/* Create the child process */
 | |
| 	struct process *p = process_create();
 | |
| 	process_inherit(current, p);
 | |
| 
 | |
| 	/* SWITCH TO ADDRESS SPACE OF CHILD PROCESS */
 | |
| 	struct pagetable *old_pagetable = current->pagetable;
 | |
| 	current->pagetable = p->pagetable;
 | |
| 	pagetable_load(p->pagetable);
 | |
| 
 | |
| 	/* Attempt to load the program image. */
 | |
| 	addr_t entry;
 | |
| 	int r = elf_load(p, k->data.file, &entry);
 | |
| 	if(r >= 0) {
 | |
| 		/* If load succeeded, reset stack and pass arguments */
 | |
| 		process_stack_reset(p, PAGE_SIZE);
 | |
| 		process_kstack_reset(p, entry);
 | |
| 		process_pass_arguments(p, argc, copy_argv);
 | |
| 	}
 | |
| 
 | |
| 	/* SWITCH BACK TO ADDRESS SPACE OF PARENT PROCESS */
 | |
| 	current->pagetable = old_pagetable;
 | |
| 	pagetable_load(old_pagetable);
 | |
| 
 | |
| 	/* Delete the argument and path copies. */
 | |
| 	argv_delete(argc, copy_argv);
 | |
| 
 | |
| 	/* If any error happened, return in the context of the parent */
 | |
| 	if(r < 0) {
 | |
| 		if(r == KERROR_EXECUTION_FAILED) {
 | |
| 			process_delete(p);
 | |
| 		}
 | |
| 		return r;
 | |
| 	}
 | |
| 
 | |
| 	/* Otherwise, launch the new child process. */
 | |
| 	process_launch(p);
 | |
| 	return p->pid;
 | |
| }
 | |
| 
 | |
| /* Function creates a child process with the standard window replaced by wd */
 | |
| int sys_process_wrun( int fd, int argc, const char **argv, int *fds, int fd_len)
 | |
| {
 | |
| 	if(!is_valid_object_type(fd,KOBJECT_FILE)) return KERROR_INVALID_OBJECT;
 | |
| 	struct kobject *k = current->ktable[fd];
 | |
| 
 | |
| 	/* Copy argv array into kernel memory. */
 | |
| 	char **copy_argv = argv_copy(argc, argv);
 | |
| 
 | |
| 	/* Create the child process */
 | |
| 	struct process *p = process_create();
 | |
| 
 | |
| 	process_selective_inherit(current, p, fds, fd_len);
 | |
| 
 | |
| 	/* SWITCH TO ADDRESS SPACE OF CHILD PROCESS */
 | |
| 	struct pagetable *old_pagetable = current->pagetable;
 | |
| 	current->pagetable = p->pagetable;
 | |
| 	pagetable_load(p->pagetable);
 | |
| 
 | |
| 	/* Attempt to load the program image. */
 | |
| 	addr_t entry;
 | |
| 	int r = elf_load(p, k->data.file, &entry);
 | |
| 	if(r >= 0) {
 | |
| 		/* If load succeeded, reset stack and pass arguments */
 | |
| 		process_stack_reset(p, PAGE_SIZE);
 | |
| 		process_kstack_reset(p, entry);
 | |
| 		process_pass_arguments(p, argc, copy_argv);
 | |
| 	}
 | |
| 
 | |
| 	/* SWITCH BACK TO ADDRESS SPACE OF PARENT PROCESS */
 | |
| 	current->pagetable = old_pagetable;
 | |
| 	pagetable_load(old_pagetable);
 | |
| 
 | |
| 	/* Delete the argument copy. */
 | |
| 	argv_delete(argc, copy_argv);
 | |
| 
 | |
| 	/* If any error happened, return in the context of the parent */
 | |
| 	if(r < 0) {
 | |
| 		if(r == KERROR_EXECUTION_FAILED) {
 | |
| 			process_delete(p);
 | |
| 		}
 | |
| 		return r;
 | |
| 	}
 | |
| 
 | |
| 	/* Otherwise, launch the new child process. */
 | |
| 	process_launch(p);
 | |
| 	return p->pid;
 | |
| }
 | |
| 
 | |
| int sys_process_exec( int fd, int argc, const char **argv)
 | |
| {
 | |
| 	if(!is_valid_object_type(fd,KOBJECT_FILE)) return KERROR_INVALID_OBJECT;
 | |
| 	struct kobject *k = current->ktable[fd];
 | |
| 
 | |
| 	addr_t entry;
 | |
| 
 | |
| 	/* Duplicate the arguments into kernel space */
 | |
| 	char **copy_argv = argv_copy(argc, argv);
 | |
| 
 | |
| 	/* Attempt to load the program image into this process. */
 | |
| 	int r = elf_load(current, k->data.file, &entry);
 | |
| 
 | |
| 	/* On failure, return only if our address space is not corrupted. */
 | |
| 	if(r < 0) {
 | |
| 		if(r == KERROR_EXECUTION_FAILED) {
 | |
| 			process_kill(current->pid);
 | |
| 		}
 | |
| 		argv_delete(argc, copy_argv);
 | |
| 		return r;
 | |
| 	}
 | |
| 
 | |
| 	/* Reset the stack and pass in the program arguments */
 | |
| 	process_stack_reset(current, PAGE_SIZE);
 | |
| 	process_kstack_reset(current, entry);
 | |
| 	process_pass_arguments(current, argc, copy_argv);
 | |
| 
 | |
| 	/* Delete the local copy of the arguments. */
 | |
| 	argv_delete(argc, copy_argv);
 | |
| 
 | |
| 	/*
 | |
| 	   IMPORTANT: Following a successful exec, we cannot return via
 | |
| 	   the normal path, because our stack has been reset to that
 | |
| 	   of a fresh process.  We must switch in order to jump
 | |
| 	   to the new stack properly.
 | |
| 	 */
 | |
| 
 | |
| 	process_yield();
 | |
| 
 | |
| 	/* NOTREACHED */
 | |
| 	return 0;
 | |
| }
 | |
| 
 | |
| int sys_process_fork()
 | |
| {
 | |
| 	struct process *p = process_create();
 | |
| 	p->ppid = current->pid;
 | |
| 	pagetable_delete(p->pagetable);
 | |
| 	p->pagetable = pagetable_duplicate(current->pagetable);
 | |
| 	process_inherit(current, p);
 | |
| 	process_kstack_copy(current, p);
 | |
| 	process_launch(p);
 | |
| 	return p->pid;
 | |
| }
 | |
| 
 | |
| int sys_process_self()
 | |
| {
 | |
| 	return current->pid;
 | |
| }
 | |
| 
 | |
| int sys_process_parent()
 | |
| {
 | |
| 	return current->ppid;
 | |
| }
 | |
| 
 | |
| int sys_process_kill(int pid)
 | |
| {
 | |
| 	return process_kill(pid);
 | |
| }
 | |
| 
 | |
| int sys_process_reap(int pid)
 | |
| {
 | |
| 	return process_reap(pid);
 | |
| }
 | |
| 
 | |
| int sys_process_wait(struct process_info *info, int timeout)
 | |
| {
 | |
| 	if(!is_valid_pointer(info,sizeof(*info))) return KERROR_INVALID_ADDRESS;
 | |
| 	return process_wait_child(0, info, timeout);
 | |
| }
 | |
| 
 | |
| int sys_process_sleep(unsigned int ms)
 | |
| {
 | |
| 	clock_wait(ms);
 | |
| 	return 0;
 | |
| }
 | |
| 
 | |
| int sys_process_stats(struct process_stats *s, int pid)
 | |
| {
 | |
| 	if(!is_valid_pointer(s,sizeof(*s))) return KERROR_INVALID_ADDRESS;
 | |
| 	return process_stats(pid, s);
 | |
| }
 | |
| 
 | |
| int sys_process_heap(int delta)
 | |
| {
 | |
| 	process_data_size_set(current, current->vm_data_size + delta);
 | |
| 	return PROCESS_ENTRY_POINT + current->vm_data_size;
 | |
| }
 | |
| 
 | |
| int sys_object_list( int fd, char *buffer, int length)
 | |
| {
 | |
| 	if(!is_valid_object(fd)) return KERROR_INVALID_OBJECT;
 | |
| 	if(!is_valid_pointer(buffer,length)) return KERROR_INVALID_ADDRESS;
 | |
| 	if(kobject_get_type(current->ktable[fd])!=KOBJECT_DIR) return KERROR_NOT_A_DIRECTORY;
 | |
| 	return kobject_list(current->ktable[fd],buffer,length);
 | |
| }
 | |
| 
 | |
| int sys_open_file( int fd, const char *path, int mode, kernel_flags_t flags)
 | |
| {
 | |
| 	if(!is_valid_object(fd)) return KERROR_INVALID_OBJECT;
 | |
| 	if(!is_valid_path(path)) return KERROR_INVALID_PATH;
 | |
| 
 | |
| 	int newfd = process_available_fd(current);
 | |
| 	if(newfd<0) return KERROR_OUT_OF_OBJECTS;
 | |
| 
 | |
| 	struct kobject *newobj;
 | |
| 	int result = kobject_lookup(current->ktable[fd],path,&newobj);
 | |
| 
 | |
| 	if(result>=0) {
 | |
| 		current->ktable[newfd] = newobj;
 | |
| 		return newfd;
 | |
| 	} else {
 | |
| 		return result;
 | |
| 	}
 | |
| }
 | |
| 
 | |
| int sys_open_dir( int fd, const char *path, kernel_flags_t flags )
 | |
| {
 | |
| 	if(!is_valid_object(fd)) return KERROR_INVALID_OBJECT;
 | |
| 	if(!is_valid_path(path)) return KERROR_INVALID_PATH;
 | |
| 
 | |
|        	int newfd = process_available_fd(current);
 | |
| 	if(newfd<0) return KERROR_OUT_OF_OBJECTS;
 | |
| 
 | |
| 	struct kobject *newobj;
 | |
| 	int result;
 | |
| 
 | |
| 	if(flags&KERNEL_FLAGS_CREATE) {
 | |
| 		newobj = kobject_create_dir_from_dir( current->ktable[fd], path );
 | |
| 		if(newobj) {
 | |
| 			result = 0;
 | |
| 		} else {
 | |
| 			result = KERROR_NOT_FOUND;
 | |
| 		}
 | |
| 	} else {
 | |
| 		result = kobject_lookup( current->ktable[fd], path, &newobj );
 | |
| 	}
 | |
| 
 | |
| 	if(result>=0) {
 | |
| 		current->ktable[newfd] = newobj;
 | |
| 		return newfd;
 | |
| 	} else {
 | |
| 		return result;
 | |
| 	}
 | |
| }
 | |
| 
 | |
| int sys_open_console(int wd)
 | |
| {
 | |
| 	if(!is_valid_object_type(wd,KOBJECT_WINDOW)) return KERROR_INVALID_OBJECT;
 | |
| 
 | |
| 	int fd = process_available_fd(current);
 | |
| 	if(fd<0) return KERROR_OUT_OF_OBJECTS;
 | |
| 
 | |
| 	current->ktable[fd] = kobject_create_console_from_window(current->ktable[wd]);
 | |
| 	return fd;
 | |
| }
 | |
| 
 | |
| 
 | |
| int sys_open_window(int wd, int x, int y, int w, int h)
 | |
| {
 | |
| 	if(!is_valid_object_type(wd,KOBJECT_WINDOW)) return KERROR_INVALID_OBJECT;
 | |
| 
 | |
| 	struct kobject *k = current->ktable[wd];
 | |
| 
 | |
| 	int fd = process_available_fd(current);
 | |
| 	if(fd<0) return KERROR_OUT_OF_OBJECTS;
 | |
| 
 | |
| 	k = kobject_create_window_from_window(k,x,y,w,h);
 | |
| 	if(!k) {
 | |
| 		// XXX choose better errno
 | |
| 		return KERROR_INVALID_REQUEST;
 | |
| 	}
 | |
| 
 | |
| 	current->ktable[fd] = k;
 | |
| 
 | |
| 	return fd;
 | |
| }
 | |
| 
 | |
| int sys_open_pipe()
 | |
| {
 | |
| 	int fd = process_available_fd(current);
 | |
| 	if(fd < 0) {
 | |
| 		return KERROR_NOT_FOUND;
 | |
| 	}
 | |
| 	struct pipe *p = pipe_create();
 | |
| 	if(!p) {
 | |
| 		return KERROR_NOT_FOUND;
 | |
| 	}
 | |
| 	current->ktable[fd] = kobject_create_pipe(p);
 | |
| 	return fd;
 | |
| }
 | |
| 
 | |
| int sys_object_type(int fd)
 | |
| {
 | |
| 	if(!is_valid_object(fd)) return KERROR_INVALID_OBJECT;
 | |
| 
 | |
| 	int fd_type = kobject_get_type(current->ktable[fd]);
 | |
| 	if(!fd_type)
 | |
| 		return 0;
 | |
| 	return fd_type;
 | |
| }
 | |
| 
 | |
| int sys_object_copy( int src, int dst )
 | |
| {
 | |
| 	if(!is_valid_object(src)) return KERROR_INVALID_OBJECT;
 | |
| 	if(dst>PROCESS_MAX_OBJECTS) return KERROR_INVALID_OBJECT;
 | |
| 
 | |
| 	if(dst < 0) {
 | |
| 		dst = process_available_fd(current);
 | |
| 		if(dst<0) return KERROR_NOT_FOUND;
 | |
| 	}
 | |
| 
 | |
| 	sys_object_close(dst);
 | |
| 
 | |
| 	current->ktable[dst] = kobject_copy(current->ktable[src]);
 | |
| 
 | |
| 	return src;
 | |
| }
 | |
| 
 | |
| int sys_object_read(int fd, void *data, int length, kernel_io_flags_t flags )
 | |
| {
 | |
| 	if(!is_valid_object(fd)) return KERROR_INVALID_OBJECT;
 | |
| 	if(!is_valid_pointer(data,length)) return KERROR_INVALID_ADDRESS;
 | |
| 
 | |
| 	struct kobject *p = current->ktable[fd];
 | |
| 	return kobject_read(p, data, length, flags);
 | |
| }
 | |
| 
 | |
| int sys_object_write(int fd, void *data, int length, kernel_io_flags_t flags )
 | |
| {
 | |
| 	if(!is_valid_object(fd)) return KERROR_INVALID_OBJECT;
 | |
| 	if(!is_valid_pointer(data,length)) return KERROR_INVALID_ADDRESS;
 | |
| 
 | |
| 	struct kobject *p = current->ktable[fd];
 | |
| 	return kobject_write(p, data, length, flags);
 | |
| }
 | |
| 
 | |
| int sys_object_seek(int fd, int offset, int whence)
 | |
| {
 | |
| 	if(!is_valid_object(fd)) return KERROR_INVALID_OBJECT;
 | |
| 
 | |
| 	// XXX add kobject method here
 | |
| 	return KERROR_NOT_IMPLEMENTED;
 | |
| }
 | |
| 
 | |
| int sys_object_remove( int fd, const char *name )
 | |
| {
 | |
| 	if(!is_valid_object(fd)) return KERROR_INVALID_OBJECT;
 | |
| 	if(!is_valid_path(name)) return KERROR_INVALID_PATH;
 | |
| 	return kobject_remove( current->ktable[fd], name );
 | |
| }
 | |
| 
 | |
| int sys_object_close(int fd)
 | |
| {
 | |
| 	if(!is_valid_object(fd)) return KERROR_INVALID_OBJECT;
 | |
| 
 | |
| 	struct kobject *p = current->ktable[fd];
 | |
| 	kobject_close(p);
 | |
| 	current->ktable[fd] = 0;
 | |
| 	return 0;
 | |
| }
 | |
| 
 | |
| int sys_object_set_tag(int fd, char *tag)
 | |
| {
 | |
| 	if(!is_valid_object(fd)) return KERROR_INVALID_OBJECT;
 | |
| 	kobject_set_tag(current->ktable[fd], tag);
 | |
| 	return 0;
 | |
| }
 | |
| 
 | |
| int sys_object_get_tag(int fd, char *buffer, int buffer_size)
 | |
| {
 | |
| 	if(!is_valid_object(fd)) return KERROR_INVALID_OBJECT;
 | |
| 	return kobject_get_tag(current->ktable[fd], buffer, buffer_size);
 | |
| }
 | |
| 
 | |
| int sys_object_size(int fd, int *dims, int n)
 | |
| {
 | |
| 	if(!is_valid_object(fd)) return KERROR_INVALID_OBJECT;
 | |
| 	if(!is_valid_pointer(dims,sizeof(*dims)*n)) return KERROR_INVALID_ADDRESS;
 | |
| 
 | |
| 	struct kobject *p = current->ktable[fd];
 | |
| 	return kobject_size(p, dims, n);
 | |
| }
 | |
| 
 | |
| int sys_object_max()
 | |
| {
 | |
| 	int max_fd = process_object_max(current);
 | |
| 	return max_fd;
 | |
| }
 | |
| 
 | |
| int sys_system_stats(struct system_stats *s)
 | |
| {
 | |
| 	if(!is_valid_pointer(s,sizeof(*s))) return KERROR_INVALID_ADDRESS;
 | |
| 
 | |
| 	struct rtc_time t = { 0 };
 | |
| 	rtc_read(&t);
 | |
| 	s->time = rtc_time_to_timestamp(&t) - boottime;
 | |
| 
 | |
| 	struct ata_count a = ata_stats();
 | |
| 	for(int i = 0; i < 4; i++) {
 | |
| 		s->blocks_written[i] = a.blocks_written[i];
 | |
| 		s->blocks_read[i] = a.blocks_read[i];
 | |
| 	}
 | |
| 
 | |
| 	return 0;
 | |
| }
 | |
| 
 | |
| int sys_bcache_stats(struct bcache_stats * s)
 | |
| {
 | |
| 	if(!is_valid_pointer(s,sizeof(*s))) return KERROR_INVALID_ADDRESS;
 | |
| 	bcache_get_stats( s );
 | |
| 	return 0;
 | |
| }
 | |
| 
 | |
| int sys_bcache_flush()
 | |
| {
 | |
| 	bcache_flush_all();
 | |
| 	return 0;
 | |
| }
 | |
| 
 | |
| int sys_system_time( uint32_t *tm )
 | |
| {
 | |
| 	if(!is_valid_pointer(tm,sizeof(*tm))) return KERROR_INVALID_ADDRESS;
 | |
| 	struct rtc_time t;
 | |
| 	rtc_read(&t);
 | |
| 	*tm = rtc_time_to_timestamp(&t);
 | |
| 	return 0;
 | |
| }
 | |
| 
 | |
| int sys_system_rtc( struct rtc_time *t )
 | |
| {
 | |
| 	if(!is_valid_pointer(t,sizeof(*t))) return KERROR_INVALID_ADDRESS;
 | |
| 	rtc_read(t);
 | |
| 	return 0;
 | |
| }
 | |
| 
 | |
| int sys_device_driver_stats(const char * name, struct device_driver_stats * stats)
 | |
| {
 | |
| 	if(!is_valid_string(name)) return KERROR_INVALID_ADDRESS;
 | |
| 	if(!is_valid_pointer(stats,sizeof(*stats))) return KERROR_INVALID_ADDRESS;
 | |
| 
 | |
| 	device_driver_get_stats(name, stats);
 | |
| 	return 0;
 | |
| }
 | |
| 
 | |
| int32_t syscall_handler(syscall_t n, uint32_t a, uint32_t b, uint32_t c, uint32_t d, uint32_t e)
 | |
| {
 | |
| 	if((n < MAX_SYSCALL) && current) {
 | |
| 		current->stats.syscall_count[n]++;
 | |
| 	}
 | |
| 	switch (n) {
 | |
| 	case SYSCALL_DEBUG:
 | |
| 		return sys_debug((const char *) a);
 | |
| 	case SYSCALL_PROCESS_YIELD:
 | |
| 		return sys_process_yield();
 | |
| 	case SYSCALL_PROCESS_EXIT:
 | |
| 		return sys_process_exit(a);
 | |
| 	case SYSCALL_PROCESS_RUN:
 | |
| 		return sys_process_run(a, b, (const char **)c);
 | |
| 	case SYSCALL_PROCESS_WRUN:
 | |
| 		return sys_process_wrun(a, b, (const char **) c, (int *) d, e);
 | |
| 	case SYSCALL_PROCESS_FORK:
 | |
| 		return sys_process_fork();
 | |
| 	case SYSCALL_PROCESS_EXEC:
 | |
| 		return sys_process_exec(a, b, (const char **) c);
 | |
| 	case SYSCALL_PROCESS_SELF:
 | |
| 		return sys_process_self();
 | |
| 	case SYSCALL_PROCESS_PARENT:
 | |
| 		return sys_process_parent();
 | |
| 	case SYSCALL_PROCESS_KILL:
 | |
| 		return sys_process_kill(a);
 | |
| 	case SYSCALL_PROCESS_REAP:
 | |
| 		return sys_process_reap(a);
 | |
| 	case SYSCALL_PROCESS_WAIT:
 | |
| 		return sys_process_wait((struct process_info *) a, b);
 | |
| 	case SYSCALL_PROCESS_SLEEP:
 | |
| 		return sys_process_sleep(a);
 | |
| 	case SYSCALL_PROCESS_STATS:
 | |
| 		return sys_process_stats((struct process_stats *) a, b);
 | |
| 	case SYSCALL_PROCESS_HEAP:
 | |
| 		return sys_process_heap(a);
 | |
| 	case SYSCALL_OPEN_FILE:
 | |
| 		return sys_open_file(a, (const char *)b, c, d);
 | |
| 	case SYSCALL_OPEN_DIR:
 | |
| 		return sys_open_dir(a, (const char *)b, c );
 | |
| 	case SYSCALL_OPEN_WINDOW:
 | |
| 		return sys_open_window(a, b, c, d, e);
 | |
| 	case SYSCALL_OPEN_CONSOLE:
 | |
| 		return sys_open_console(a);
 | |
| 	case SYSCALL_OPEN_PIPE:
 | |
| 		return sys_open_pipe();
 | |
| 	case SYSCALL_OBJECT_TYPE:
 | |
| 		return sys_object_type(a);
 | |
| 	case SYSCALL_OBJECT_COPY:
 | |
| 		return sys_object_copy(a,b);
 | |
| 	case SYSCALL_OBJECT_READ:
 | |
| 		return sys_object_read(a, (void *) b, c, d );
 | |
| 	case SYSCALL_OBJECT_LIST:
 | |
| 		return sys_object_list(a, (char *) b, (int) c);
 | |
| 	case SYSCALL_OBJECT_WRITE:
 | |
| 		return sys_object_write(a, (void *) b, c, d);
 | |
| 	case SYSCALL_OBJECT_SEEK:
 | |
| 		return sys_object_seek(a, b, c);
 | |
| 	case SYSCALL_OBJECT_REMOVE:
 | |
| 		return sys_object_remove(a,(const char*)b);
 | |
| 	case SYSCALL_OBJECT_CLOSE:
 | |
| 		return sys_object_close(a);
 | |
| 	case SYSCALL_OBJECT_SET_TAG:
 | |
| 		return sys_object_set_tag(a, (char *) b);
 | |
| 	case SYSCALL_OBJECT_GET_TAG:
 | |
| 		return sys_object_get_tag(a, (char *) b, c);
 | |
| 	case SYSCALL_OBJECT_SIZE:
 | |
| 		return sys_object_size(a, (int *) b, c);
 | |
| 	case SYSCALL_OBJECT_MAX:
 | |
| 		return sys_object_max(a);
 | |
| 	case SYSCALL_SYSTEM_STATS:
 | |
| 		return sys_system_stats((struct system_stats *) a);
 | |
| 	case SYSCALL_BCACHE_STATS:
 | |
| 		return sys_bcache_stats((struct bcache_stats *) a);
 | |
| 	case SYSCALL_BCACHE_FLUSH:
 | |
| 		return sys_bcache_flush();
 | |
| 	case SYSCALL_SYSTEM_TIME:
 | |
| 		return sys_system_time((uint32_t*)a);
 | |
| 	case SYSCALL_SYSTEM_RTC:
 | |
| 		return sys_system_rtc((struct rtc_time *) a);
 | |
| 	case SYSCALL_DEVICE_DRIVER_STATS:
 | |
| 		return sys_device_driver_stats((char *) a, (struct device_driver_stats *) b);
 | |
| 	default:
 | |
| 		return KERROR_INVALID_SYSCALL;
 | |
| 	}
 | |
| }
 |