Mon 14 Oct 23:06:38 CEST 2024
This commit is contained in:
		
							parent
							
								
									d72aae7bf9
								
							
						
					
					
						commit
						96b735904c
					
				
							
								
								
									
										414
									
								
								kernel/kobject.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										414
									
								
								kernel/kobject.c
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,414 @@ | ||||||
|  | /*
 | ||||||
|  |  * Copyright (C) 2016-2019 The University of Notre Dame This software is | ||||||
|  |  * distributed under the GNU General Public License. See the file LICENSE | ||||||
|  |  * for details. | ||||||
|  |  */ | ||||||
|  | 
 | ||||||
|  | #include "console.h" | ||||||
|  | #include "kobject.h" | ||||||
|  | #include "kmalloc.h" | ||||||
|  | #include "string.h" | ||||||
|  | 
 | ||||||
|  | #include "device.h" | ||||||
|  | #include "fs.h" | ||||||
|  | #include "window.h" | ||||||
|  | #include "console.h" | ||||||
|  | #include "pipe.h" | ||||||
|  | 
 | ||||||
|  | #include "kernel/error.h" | ||||||
|  | 
 | ||||||
|  | static struct kobject *kobject_create() | ||||||
|  | { | ||||||
|  | 	struct kobject *k = kmalloc(sizeof(*k)); | ||||||
|  | 	k->refcount = 1; | ||||||
|  | 	k->offset = 0; | ||||||
|  | 	k->tag = 0; | ||||||
|  | 	k->data.file = 0; | ||||||
|  | 	return k; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | struct kobject *kobject_create_file(struct fs_dirent *f) | ||||||
|  | { | ||||||
|  | 	struct kobject *k = kobject_create(); | ||||||
|  | 	k->type = KOBJECT_FILE; | ||||||
|  | 	k->data.file = f; | ||||||
|  | 	return k; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | struct kobject *kobject_create_dir( struct fs_dirent *d ) | ||||||
|  | { | ||||||
|  | 	struct kobject *k = kobject_create(); | ||||||
|  | 	k->type = KOBJECT_DIR; | ||||||
|  | 	k->data.dir = d; | ||||||
|  | 	return k; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | struct kobject *kobject_create_device(struct device *d) | ||||||
|  | { | ||||||
|  | 	struct kobject *k = kobject_create(); | ||||||
|  | 	k->type = KOBJECT_DEVICE; | ||||||
|  | 	k->data.device = d; | ||||||
|  | 	return k; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | struct kobject *kobject_create_window(struct window *g) | ||||||
|  | { | ||||||
|  | 	struct kobject *k = kobject_create(); | ||||||
|  | 	k->type = KOBJECT_WINDOW; | ||||||
|  | 	k->data.window = g; | ||||||
|  | 	return k; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | struct kobject *kobject_create_console(struct console *c) | ||||||
|  | { | ||||||
|  | 	struct kobject *k = kobject_create(); | ||||||
|  | 	k->type = KOBJECT_CONSOLE; | ||||||
|  | 	k->data.console = c; | ||||||
|  | 	return k; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | struct kobject *kobject_create_pipe(struct pipe *p) | ||||||
|  | { | ||||||
|  | 	struct kobject *k = kobject_create(); | ||||||
|  | 	k->type = KOBJECT_PIPE; | ||||||
|  | 	k->data.pipe = p; | ||||||
|  | 	return k; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | struct kobject *kobject_addref(struct kobject *k) | ||||||
|  | { | ||||||
|  | 	k->refcount++; | ||||||
|  | 	return k; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | struct kobject * kobject_copy( struct kobject *ksrc ) | ||||||
|  | { | ||||||
|  | 	struct kobject *kdst = kobject_create(); | ||||||
|  | 
 | ||||||
|  | 	kdst->data = ksrc->data; | ||||||
|  | 	kdst->type = ksrc->type; | ||||||
|  | 	kdst->offset = ksrc->offset; | ||||||
|  | 	kdst->refcount = 1; | ||||||
|  | 
 | ||||||
|  | 	if(ksrc->tag) { | ||||||
|  | 		kdst->tag = strdup(ksrc->tag); | ||||||
|  | 	} else { | ||||||
|  | 		kdst->tag = 0; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	switch (ksrc->type) { | ||||||
|  | 	case KOBJECT_WINDOW: | ||||||
|  | 		window_addref(ksrc->data.window); | ||||||
|  | 		break; | ||||||
|  | 	case KOBJECT_CONSOLE: | ||||||
|  | 		console_addref(ksrc->data.console); | ||||||
|  | 		break; | ||||||
|  | 	case KOBJECT_FILE: | ||||||
|  | 		fs_dirent_addref(ksrc->data.file); | ||||||
|  | 		break; | ||||||
|  | 	case KOBJECT_DIR: | ||||||
|  | 		fs_dirent_addref(ksrc->data.dir); | ||||||
|  | 		break; | ||||||
|  | 	case KOBJECT_DEVICE: | ||||||
|  | 		device_addref(ksrc->data.device); | ||||||
|  | 		break; | ||||||
|  | 	case KOBJECT_PIPE: | ||||||
|  | 		pipe_addref(ksrc->data.pipe); | ||||||
|  | 		break; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	return kdst; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | struct kobject *kobject_create_window_from_window( struct kobject *k, int x, int y, int width, int height ) | ||||||
|  | { | ||||||
|  | 	if(k->type!=KOBJECT_WINDOW) return 0; | ||||||
|  | 
 | ||||||
|  | 	struct window *w = window_create(k->data.window,x,y,width,height); | ||||||
|  | 	if(w) { | ||||||
|  | 		return kobject_create_window(w); | ||||||
|  | 	} else { | ||||||
|  | 		return 0; | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | struct kobject *kobject_create_console_from_window( struct kobject *k ) | ||||||
|  | { | ||||||
|  | 	if(k->type!=KOBJECT_WINDOW) return 0; | ||||||
|  | 	struct console *c = console_create(k->data.window); | ||||||
|  | 	if(!c) return 0; | ||||||
|  | 	return kobject_create_console(c); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | struct kobject * kobject_create_file_from_dir( struct kobject *kobject, const char *name ) | ||||||
|  | { | ||||||
|  | 	if(kobject->type==KOBJECT_DIR) { | ||||||
|  | 		struct fs_dirent *d = fs_dirent_mkfile(kobject->data.dir,name); | ||||||
|  | 		if(d) { | ||||||
|  | 			return kobject_create_file(d); | ||||||
|  | 		} else { | ||||||
|  | 			return 0; | ||||||
|  | 		} | ||||||
|  | 	} else { | ||||||
|  | 		return 0; | ||||||
|  | 		// XXX KERROR_NOT_IMPLEMENTED;
 | ||||||
|  | 	} | ||||||
|  | 	return 0; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | struct kobject * kobject_create_dir_from_dir( struct kobject *kobject, const char *name ) | ||||||
|  | { | ||||||
|  | 	if(kobject->type==KOBJECT_DIR) { | ||||||
|  | 		struct fs_dirent *d = fs_dirent_mkdir(kobject->data.dir,name); | ||||||
|  | 		if(d) { | ||||||
|  | 			return kobject_create_dir(d); | ||||||
|  | 		} else { | ||||||
|  | 			return 0; | ||||||
|  | 		} | ||||||
|  | 	} else { | ||||||
|  | 		return 0; | ||||||
|  | 		// XXX KERROR_NOT_IMPLEMENTED;
 | ||||||
|  | 	} | ||||||
|  | 	return 0; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | int kobject_read(struct kobject *kobject, void *buffer, int size, kernel_io_flags_t flags ) | ||||||
|  | { | ||||||
|  | 	int actual = 0; | ||||||
|  | 
 | ||||||
|  | 	switch (kobject->type) { | ||||||
|  | 	case KOBJECT_FILE: | ||||||
|  | 		actual = fs_dirent_read(kobject->data.file, (char *) buffer, (uint32_t) size, kobject->offset); | ||||||
|  | 		break; | ||||||
|  | 	case KOBJECT_DIR: | ||||||
|  | 		return KERROR_INVALID_REQUEST; | ||||||
|  | 		break; | ||||||
|  | 	case KOBJECT_DEVICE: | ||||||
|  | 		if(flags&KERNEL_IO_NONBLOCK) { | ||||||
|  | 			actual = device_read_nonblock(kobject->data.device, buffer, size / device_block_size(kobject->data.device), 0); | ||||||
|  | 		} else { | ||||||
|  | 			actual = device_read(kobject->data.device, buffer, size / device_block_size(kobject->data.device), 0); | ||||||
|  | 		} | ||||||
|  | 		break; | ||||||
|  | 	case KOBJECT_PIPE: | ||||||
|  | 		if(flags&KERNEL_IO_NONBLOCK) { | ||||||
|  | 			actual = pipe_read_nonblock(kobject->data.pipe, buffer, size); | ||||||
|  | 		} else { | ||||||
|  | 			actual = pipe_read(kobject->data.pipe, buffer, size); | ||||||
|  | 		} | ||||||
|  | 		break; | ||||||
|  | 	case KOBJECT_WINDOW: | ||||||
|  | 		if(flags&KERNEL_IO_NONBLOCK) { | ||||||
|  | 			actual = window_read_events_nonblock(kobject->data.window, buffer, size); | ||||||
|  | 		} else { | ||||||
|  | 			actual = window_read_events(kobject->data.window, buffer, size); | ||||||
|  | 		} | ||||||
|  | 		break; | ||||||
|  | 	case KOBJECT_CONSOLE: | ||||||
|  | 		if(flags&KERNEL_IO_NONBLOCK) { | ||||||
|  | 			actual = console_read_nonblock(kobject->data.console,buffer,size); | ||||||
|  | 		} else { | ||||||
|  | 			actual = console_read(kobject->data.console,buffer,size); | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		break; | ||||||
|  | 	default: | ||||||
|  | 		actual = 0; | ||||||
|  | 		break; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	if(actual > 0) kobject->offset += actual; | ||||||
|  | 
 | ||||||
|  | 	return actual; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | int kobject_write(struct kobject *kobject, void *buffer, int size, kernel_io_flags_t flags ) | ||||||
|  | { | ||||||
|  | 	switch (kobject->type) { | ||||||
|  | 	case KOBJECT_WINDOW: | ||||||
|  | 		if(flags&KERNEL_IO_POST) { | ||||||
|  | 			return window_post_events(kobject->data.window,buffer,size); | ||||||
|  | 		} else { | ||||||
|  | 			return window_write_graphics(kobject->data.window,buffer,size); | ||||||
|  | 		} | ||||||
|  | 		break; | ||||||
|  | 	case KOBJECT_CONSOLE: | ||||||
|  | 		if(flags&KERNEL_IO_POST) { | ||||||
|  | 			return console_post(kobject->data.console,buffer,size); | ||||||
|  | 		} else { | ||||||
|  | 			return console_write(kobject->data.console, buffer, size ); | ||||||
|  | 		} | ||||||
|  | 		break; | ||||||
|  | 	case KOBJECT_FILE:{ | ||||||
|  | 			int actual = fs_dirent_write(kobject->data.file, (char *) buffer, (uint32_t) size, kobject->offset); | ||||||
|  | 			if(actual > 0) | ||||||
|  | 				kobject->offset += actual; | ||||||
|  | 			return actual; | ||||||
|  | 		} | ||||||
|  | 	case KOBJECT_DEVICE: | ||||||
|  | 		return device_write(kobject->data.device, buffer, size / device_block_size(kobject->data.device), 0); | ||||||
|  | 	case KOBJECT_PIPE: | ||||||
|  | 		if(flags&KERNEL_IO_NONBLOCK) { | ||||||
|  | 			return pipe_write_nonblock(kobject->data.pipe, buffer, size); | ||||||
|  | 		} else { | ||||||
|  | 			return pipe_write(kobject->data.pipe, buffer, size); | ||||||
|  | 		} | ||||||
|  | 	default: | ||||||
|  | 		return 0; | ||||||
|  | 	} | ||||||
|  | 	return 0; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | int kobject_list(struct kobject *kobject, void *buffer, int size) | ||||||
|  | { | ||||||
|  | 	if(kobject->type==KOBJECT_DIR) { | ||||||
|  | 		return fs_dirent_list(kobject->data.dir,buffer,size); | ||||||
|  | 	} else { | ||||||
|  | 		return KERROR_NOT_A_DIRECTORY; | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | int kobject_lookup( struct kobject *kobject, const char *name, struct kobject **newobj ) | ||||||
|  | { | ||||||
|  | 	if(kobject->type==KOBJECT_DIR) { | ||||||
|  | 		struct fs_dirent *d; | ||||||
|  | 		d = fs_dirent_traverse(kobject->data.dir,name); | ||||||
|  | 		if(d) { | ||||||
|  | 			if(fs_dirent_isdir(d)) { | ||||||
|  | 				*newobj = kobject_create_dir(d); | ||||||
|  | 			} else { | ||||||
|  | 				*newobj = kobject_create_file(d); | ||||||
|  | 			} | ||||||
|  | 			return 0; | ||||||
|  | 		} else { | ||||||
|  | 			return KERROR_NOT_FOUND; | ||||||
|  | 		} | ||||||
|  | 	} else { | ||||||
|  | 		return KERROR_NOT_IMPLEMENTED; | ||||||
|  | 	} | ||||||
|  | 	return 0; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | int kobject_remove( struct kobject *kobject, const char *name ) | ||||||
|  | { | ||||||
|  | 	if(kobject->type==KOBJECT_DIR) { | ||||||
|  | 		return fs_dirent_remove(kobject->data.dir,name); | ||||||
|  | 	} else { | ||||||
|  | 		return KERROR_NOT_IMPLEMENTED; | ||||||
|  | 	} | ||||||
|  | 	return 0; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | int kobject_close(struct kobject *kobject) | ||||||
|  | { | ||||||
|  | 	kobject->refcount--; | ||||||
|  | 
 | ||||||
|  | 	if(kobject->refcount==0) { | ||||||
|  | 		switch (kobject->type) { | ||||||
|  | 		case KOBJECT_WINDOW: | ||||||
|  | 			window_delete(kobject->data.window); | ||||||
|  | 			break; | ||||||
|  | 		case KOBJECT_CONSOLE: | ||||||
|  | 			console_delete(kobject->data.console); | ||||||
|  | 			break; | ||||||
|  | 		case KOBJECT_FILE: | ||||||
|  | 			fs_dirent_close(kobject->data.file); | ||||||
|  | 			break; | ||||||
|  | 		case KOBJECT_DIR: | ||||||
|  | 			fs_dirent_close(kobject->data.dir); | ||||||
|  | 			break; | ||||||
|  | 		case KOBJECT_DEVICE: | ||||||
|  | 			device_close(kobject->data.device); | ||||||
|  | 			break; | ||||||
|  | 		case KOBJECT_PIPE: | ||||||
|  | 			pipe_delete(kobject->data.pipe); | ||||||
|  | 			break; | ||||||
|  | 		default: | ||||||
|  | 			break; | ||||||
|  | 		} | ||||||
|  | 		if (kobject->tag) | ||||||
|  | 			kfree(kobject->tag); | ||||||
|  | 		kfree(kobject); | ||||||
|  | 		return 0; | ||||||
|  | 	} else if(kobject->refcount>1 ) { | ||||||
|  | 		if(kobject->type==KOBJECT_PIPE) { | ||||||
|  | 			pipe_flush(kobject->data.pipe); | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 	return 0; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | int kobject_size(struct kobject *kobject, int *dims, int n) | ||||||
|  | { | ||||||
|  | 	switch (kobject->type) { | ||||||
|  | 	case KOBJECT_WINDOW: | ||||||
|  | 		if(n==2) { | ||||||
|  | 			dims[0] = window_width(kobject->data.window); | ||||||
|  | 			dims[1] = window_height(kobject->data.window); | ||||||
|  | 			return 0; | ||||||
|  | 		} else { | ||||||
|  | 			return KERROR_INVALID_REQUEST; | ||||||
|  | 		} | ||||||
|  | 	case KOBJECT_CONSOLE: | ||||||
|  | 		if(n==2) { | ||||||
|  | 			console_size(kobject->data.console,&dims[0],&dims[1]); | ||||||
|  | 			return 0; | ||||||
|  | 		} else { | ||||||
|  | 			return KERROR_INVALID_REQUEST; | ||||||
|  | 		} | ||||||
|  | 	case KOBJECT_FILE: | ||||||
|  | 		if(n==1) { | ||||||
|  | 			dims[0] = fs_dirent_size(kobject->data.file); | ||||||
|  | 			return 0; | ||||||
|  | 		} else { | ||||||
|  | 			return KERROR_INVALID_REQUEST; | ||||||
|  | 		} | ||||||
|  | 	case KOBJECT_DIR: | ||||||
|  | 		if(n==1) { | ||||||
|  | 			dims[0] = fs_dirent_size(kobject->data.dir); | ||||||
|  | 			return 0; | ||||||
|  | 		} else { | ||||||
|  | 			return KERROR_INVALID_REQUEST; | ||||||
|  | 		} | ||||||
|  | 	case KOBJECT_DEVICE: | ||||||
|  | 		if(n==2) { | ||||||
|  | 			dims[0] = device_nblocks(kobject->data.device); | ||||||
|  | 			dims[1] = device_block_size(kobject->data.device); | ||||||
|  | 			return 0; | ||||||
|  | 		} else { | ||||||
|  | 			return KERROR_INVALID_REQUEST; | ||||||
|  | 		} | ||||||
|  | 	case KOBJECT_PIPE: | ||||||
|  | 		if(n==1) { | ||||||
|  | 			dims[0] = pipe_size(kobject->data.pipe); | ||||||
|  | 			return 0; | ||||||
|  | 		} else { | ||||||
|  | 			return KERROR_INVALID_REQUEST; | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 	return KERROR_INVALID_REQUEST; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | int kobject_get_type(struct kobject *kobject) | ||||||
|  | { | ||||||
|  | 	return kobject->type; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | int kobject_set_tag(struct kobject *kobject, char *new_tag) | ||||||
|  | { | ||||||
|  | 	if(kobject->tag != 0) { | ||||||
|  | 		kfree(kobject->tag); | ||||||
|  | 	} | ||||||
|  | 	kobject->tag = kmalloc(strlen(new_tag) * sizeof(char)); | ||||||
|  | 	strcpy(kobject->tag, new_tag); | ||||||
|  | 	return 1; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | int kobject_get_tag(struct kobject *kobject, char *buffer, int buffer_size) | ||||||
|  | { | ||||||
|  | 	if(kobject->tag != 0) { | ||||||
|  | 		strcpy(buffer, kobject->tag); | ||||||
|  | 		return 1; | ||||||
|  | 	} | ||||||
|  | 	return 0; | ||||||
|  | } | ||||||
		Loading…
	
		Reference in New Issue
	
	Block a user