Mon 14 Oct 23:06:38 CEST 2024
This commit is contained in:
		
							parent
							
								
									cf34401210
								
							
						
					
					
						commit
						ff9a118e25
					
				
							
								
								
									
										639
									
								
								kernel/syscall_handler.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										639
									
								
								kernel/syscall_handler.c
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,639 @@ | ||||||
|  | /*
 | ||||||
|  | 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; | ||||||
|  | 	} | ||||||
|  | } | ||||||
		Loading…
	
		Reference in New Issue
	
	Block a user