diff --git a/c_build_helper.sh b/c_build_helper.sh index 842d0a1..8a97716 100644 --- a/c_build_helper.sh +++ b/c_build_helper.sh @@ -1,4 +1,4 @@ -CFLAGS="-g -c -m32 -fno-pie -mno-sse -O3 -D __bits__=32 -Wno-int-to-pointer-cast -Wno-pointer-to-int-cast -Wno-incompatible-pointer-types -Wno-address-of-packed-member -Wno-discarded-qualifiers -fno-stack-protector -mno-red-zone -mno-sse -mno-sse2 -ffreestanding -nostdlib -mno-mmx" +CFLAGS="-g -c -m32 -fno-pie -mno-sse -O3 -D __bits__=32 -Wno-int-to-pointer-cast -Wno-pointer-to-int-cast -Wno-incompatible-pointer-types -fno-stack-protector -mno-red-zone -mno-sse -mno-sse2 -ffreestanding -nostdlib -mno-mmx" LDFLAGS_i386="-Ttext 0xc0000000 --oformat binary -melf_i386" cd src/kernel/ diff --git a/src/bootloader/main.s b/src/bootloader/main.s index 7270a4e..4a1afe7 100644 --- a/src/bootloader/main.s +++ b/src/bootloader/main.s @@ -21,13 +21,16 @@ bits 16 ;Load part2 |x| ;Get video mode information |0| ;Set video mode |0| -;get memory map |0| -;enable paging |0| -;read filesystem |0| -;load kernel |0| -;parse ELF format |0| -;pass memory and video information to kernel|0| -;relocate and jump to kernel |0| +;get memory map |x| +;enable paging |x| +;read filesystem |x| +;load kernel |x| +;parse ELF format |x| +;pass memory and video information to kernel|x| +;relocate and jump to kernel |x| + +;TODO 7/4/26 +;Remember to ZERO THE BSS jump: jmp short start diff --git a/src/kernel/drivers/pci.c b/src/kernel/drivers/pci.c index a915584..0a22eda 100644 --- a/src/kernel/drivers/pci.c +++ b/src/kernel/drivers/pci.c @@ -4,6 +4,7 @@ #include "../system/vfs.h" #include "../shared/string.h" #include "../shared/memory.h" +#include "../drivers/serial.h" #define MODULE_NAME "PCI" char *classes[][20] = { @@ -45,16 +46,23 @@ void pci_read_file(vfile_t *file, uint32_t *buffer, uint32_t offset, uint32_t co void pci_write_file(vfile_t *file, uint32_t *buffer, uint32_t offset, uint32_t count){ return; } + +fileops_t pci_fileops = { + 0, + 0, + pci_write_file, + pci_read_file, +}; + void pci_make_file(uint32_t class, uint8_t bus, uint8_t slot, uint8_t func){ - char *str = kmalloc(1); - memcpy("/dev/pci/", str, 9); + char str[256] = "/dev/pci/\0"; char *dev = classes[class >> 8][class & 0xf]; switch(class >> 8){ case 0x1://PCI class 0x1 is disks + // printf("!!STR: %s, LEN: %d!!", str, strlen(str)); strcpy("disk/", str + strlen(str)); uint32_t l = (uint32_t)pci_read_config(bus, slot, func, 0x4) | (uint32_t)pci_read_config(bus, slot, func, 0x6) << 16; pci_write_config(bus, slot, func, 0x4, l | 4); - break; case 0x2://PCI class 0x2 is network controllers strcpy("net/", str + strlen(str)); @@ -72,12 +80,21 @@ void pci_make_file(uint32_t class, uint8_t bus, uint8_t slot, uint8_t func){ char cpy[256]; vfile_t *file = 0; uint8_t tries = 0; - while(file == 0){ + // while(file == 0){ itoa(tries++, num, 10); strcpy(str, cpy); strcpy(num, cpy + strlen(cpy)); - file = fcreate(cpy, VFILE_DEVICE, pci_write_file, pci_read_file); - } + file = fcreate(cpy, 0); + // file->read = pci_read_file; + // file->write = pci_write_file; + // if(file == 0) break; + if(!file){ + mlog(MODULE_NAME, "Failed to make file for PCI device %s!\n", MLOG_PRINT, cpy); + return; + } + // printf("ASSERT file == null: %d\n", file == 0); + file->fileops = &pci_fileops; + // } file->id = (uint32_t)slot | ((uint32_t)func << 8) | ((uint32_t)bus << 16); } @@ -120,11 +137,11 @@ void pci_enumerate_bus(uint8_t bus){ void pci_init(){ mlog(MODULE_NAME, "Enumerating PCI Buses\n", MLOG_PRINT); - vfile_t *file = fcreate("dev/pci/", VFILE_DIRECTORY, kmalloc(1), 1); - fcreate("dev/pci/disk", VFILE_DIRECTORY, kmalloc(1), 1); - fcreate("dev/pci/net", VFILE_DIRECTORY, kmalloc(1), 1); - fcreate("dev/pci/video", VFILE_DIRECTORY, kmalloc(1), 1); - fcreate("dev/pci/bridge", VFILE_DIRECTORY, kmalloc(1), 1); + vfile_t *file = fcreate("/dev/pci/", FS_FILE_IS_DIR); + fcreate("/dev/pci/disk", FS_FILE_IS_DIR); + fcreate("/dev/pci/net", FS_FILE_IS_DIR); + fcreate("/dev/pci/video", FS_FILE_IS_DIR); + fcreate("/dev/pci/bridge", FS_FILE_IS_DIR); for(uint32_t i = 0 ; i < 256; i++){ pci_enumerate_bus(i); } diff --git a/src/kernel/drivers/serial.c b/src/kernel/drivers/serial.c index 1c7a372..e68ce6d 100644 --- a/src/kernel/drivers/serial.c +++ b/src/kernel/drivers/serial.c @@ -83,6 +83,10 @@ void vprintf(char *string, va_list vars){ num = va_arg(vars, int32_t); printf((char[]){num, 0}); continue; + case 'b': + string++; + num = va_arg(vars, int32_t); + printf(num ? "true" : "false"); } } outb(com_ports[0], *string); diff --git a/src/kernel/drivers/ustar.c b/src/kernel/drivers/ustar.c index 0ec5dcf..2d8d764 100644 --- a/src/kernel/drivers/ustar.c +++ b/src/kernel/drivers/ustar.c @@ -36,8 +36,18 @@ int read_initrd(initrd_t *initrd){ // } char final_fname[80] = "/boot/"; strcat(file->filename, final_fname); - fcreate(final_fname, VFILE_POINTER, (archive + offset + sizeof(USTAR_file_t)), fsize_pgs); + vfile_t *tmp = fcreate(final_fname, 0); + if(!tmp){ + mlog("INITRD", "Failed to read critical boot file: %s\n", MLOG_PRINT, file->filename); + return 1; + } + if(tmp->private){ + kfree(tmp->private); + } + tmp->private = (archive + offset + sizeof(USTAR_file_t)); + tmp->size = fsize_pgs * 4096; // printf("%s, %d, %d\n", final_fname, filesize, fsize_pgs); offset += (((filesize + 511) / 512) + 1) * 512; } + return 0; } \ No newline at end of file diff --git a/src/kernel/kmain.c b/src/kernel/kmain.c index 5629a74..b0cc3d5 100644 --- a/src/kernel/kmain.c +++ b/src/kernel/kmain.c @@ -12,6 +12,7 @@ #include "system/vfs.h" #include "drivers/ustar.h" #include "system/initrc.h" +#include "system/ramfs.h" kernel_info_t *boot_info = 0; @@ -23,21 +24,16 @@ void sysinit(){ pci_init(); // modules_init(boot_info, 0); read_initrd(boot_info->initrd); - vfile_t *initrc = fget_file("/boot/initrc.conf"); - if(initrc){ - mlog("KERNEL", "Found initrc at: %x\n", MLOG_PRINT, initrc->access.data.ptr); - } modules_init(); - initrc_read(initrc); - // vfile_t *disk_dir = fget_file("/dev/disk"); - // if(disk_dir == 0){ - // mlog("KERNEL", "Error: /dev/disk does not exist\n", MLOG_PRINT); - // } - // vfile_t **dir_data = disk_dir->access.data.ptr; - // for(uint32_t i = 0; dir_data[i]; i++){ - // mlog("KERNEL", "Filename: %s\n", MLOG_PRINT, dir_data[i]->name); - // vfs_detect_partitions(dir_data[i]); - // } + vfile_t *initrc = fopen("/boot/initrc.conf"); + mlog("RAE", "\033[1;32mDid you remember to migrate your modules to the new API?\033[0m\n", MLOG_PRINT); + if(initrc){ + mlog("KERNEL", "Found initrc\n", MLOG_PRINT); + initrc_read(initrc); + } + else{ + mlog("KERNEL", "ERROR: Initrc could not be located!\n", MLOG_PRINT); + } // dispatch_message(0); printf("Bleh\n"); //why did i stop working on this? what was wrong with this? @@ -46,23 +42,24 @@ void sysinit(){ extern void kmain(kernel_info_t *kernel_info){ serial_init(); pm_init(kernel_info); - vfs_init(); + ramfs_init(); mlog("KERNEL", "Initializing IDT\n", MLOG_PRINT); idt_load(); pic_init(0x20); pic_setmask(0x0, PIC1_DATA); pic_setmask(0x0, PIC2_DATA); - - fcreate("/dev", VFILE_DIRECTORY, kmalloc(1), 1); - fcreate("/dev/disk", VFILE_DIRECTORY, kmalloc(1), 1); - fcreate("/tmp", VFILE_DIRECTORY, kmalloc(1), 1); - fcreate("/boot", VFILE_DIRECTORY, kmalloc(1), 1); + vfs_init(); + fcreate("/tmp", FS_FILE_IS_DIR); + fcreate("/dev", FS_FILE_IS_DIR); + fcreate("/boot", FS_FILE_IS_DIR); + fcreate("/dev/disk", FS_FILE_IS_DIR); mlog("KERNEL", "Initializing Scheduler & starting PID 1\n", MLOG_PRINT); boot_info = kernel_info; scheduler_init(); //scheduler doesn't work if there is no PID0, and I don't know why. thread_start(pid0); thread_start(sysinit); + // for(;;); enable_interrupts(); for(;;);//we actually **shouldn't** return, like, ever. That's bad. return; diff --git a/src/kernel/shared/kstdlib.h b/src/kernel/shared/kstdlib.h index af3e847..00f6908 100644 --- a/src/kernel/shared/kstdlib.h +++ b/src/kernel/shared/kstdlib.h @@ -4,6 +4,12 @@ #include "../drivers/serial.h" #include "interrupts.h" +#define true 1 +#define false 0 + +#define null 0 + + #define MLOG_DEBUG 1 #define MLOG_PRINT 2 #define MLOG_WARN 3 @@ -27,6 +33,23 @@ void vector_set(uint32_t pos, vector_t *vector, void *new_element); void vector_push(vector_t *vector, void *new_element); void vector_pop(uint32_t pos, vector_t *vector, void *element); uint32_t atoi(char *str, uint32_t base); +inline int32_t signed_max(int32_t i1, int32_t i2){ + if(i1 > i2) return i1; + else return i2; +} +inline uint32_t unsigned_max(uint32_t i1, uint32_t i2){ + if(i1 > i2) return i1; + else return i2; +} +inline int32_t signed_min(int32_t i1, int32_t i2){ + if(i1 < i2) return i1; + else return i2; +} +inline uint32_t unsigned_min(uint32_t i1, uint32_t i2){ + if(i1 < i2) return i1; + else return i2; +} + diff --git a/src/kernel/shared/memory.h b/src/kernel/shared/memory.h index 888a138..28d0aa3 100644 --- a/src/kernel/shared/memory.h +++ b/src/kernel/shared/memory.h @@ -39,6 +39,8 @@ #define KMALLOC_LINK_NEXT 2 #define KMALLOC_LINK_LAST 4 +#define PAGE_SIZE_BYTES 4096 + typedef struct BIOS_data{ uint16_t com_ports[4]; uint16_t lpt_ports[3]; diff --git a/src/kernel/shared/spinlock.h b/src/kernel/shared/spinlock.h new file mode 100644 index 0000000..16eafb1 --- /dev/null +++ b/src/kernel/shared/spinlock.h @@ -0,0 +1,13 @@ +#include + +typedef struct spinlock{ + atomic_flag lock; +}spinlock_t; + +inline void spinlock_acquire(spinlock_t spinlock){ + // atomic_compare_exchange_strong(&spinlock.lock, &spinlock.unlocked, spinlock.locked); + while(atomic_flag_test_and_set_explicit(&spinlock.lock, memory_order_acquire)); +} +inline void spinlock_release(spinlock_t spinlock){ + atomic_flag_clear_explicit(&spinlock.lock, memory_order_release); +} \ No newline at end of file diff --git a/src/kernel/shared/string.h b/src/kernel/shared/string.h index d29ce20..73370bf 100644 --- a/src/kernel/shared/string.h +++ b/src/kernel/shared/string.h @@ -21,6 +21,21 @@ inline uint32_t strcmp(char *str1, char *str2){ if(str1[i] == str2[i]) return 0; else return 1; } + +inline void memclr(char *ptr, uint32_t count){ + if(count % 4 == 0){ + uint32_t *intptr = (uint32_t *)ptr; + for(uint32_t i = 0; i < count/4; i++){ + intptr[i] = 0; + } + return; + } + for(uint32_t i = 0; i < count; i++){ + ptr[i] = 0; + } + return; +} + char *strtok(char *str, char delim); void strcpy(char *src, char *dest); void memcpy(char *src, char *dest, uint32_t c); diff --git a/src/kernel/system/elf.c b/src/kernel/system/elf.c index 2fc29f6..881dc5d 100644 --- a/src/kernel/system/elf.c +++ b/src/kernel/system/elf.c @@ -1,5 +1,6 @@ #include "elf.h" #include "../shared/kstdlib.h" +#include "../shared/string.h" #include "../shared/memory.h" #define MODULE_NAME "ELFLOAD" @@ -14,19 +15,9 @@ void *load_segment(program_entry_t entry, void *file_data, void *base_segment, u // printf("Base: %x\n", base_segment); if(entry.type == 1){ if(((elf_header_t *)(file_data))->type == ELF_TYPE_SHARED){ - if(base_segment == 0){ - segment = kmalloc(entry.msize/4096 + 1); - base_segment = segment; - } - else{ - segment = base_segment + (entry.vaddr & 0xfffff000); - uint32_t count = 1; - count += ((entry.vaddr+entry.msize) - entry.vaddr) ? 1 : 0; - count += entry.msize/4096 + 1; - for(uint32_t i = 0; i < count; i++){ - map(segment + (i << 12)/4, (void *)pm_alloc(), PT_PRESENT | map_flags); - } - } + segment = base_segment + (entry.vaddr & 0xfffff000); + memclr(segment, entry.msize); + for(uint32_t i = 0; i < entry.fsize/sizeof(uint32_t) + 1; i++){ segment[i] = ((uint32_t *)(file_data))[i + entry.data_offset/sizeof(uint32_t)]; } @@ -40,6 +31,7 @@ void *load_segment(program_entry_t entry, void *file_data, void *base_segment, u //What is this for? //TODO: Find out how to handle Dynamic sections } + // printf("data_offset: %x\n", data_offset); return base_segment; } @@ -53,7 +45,12 @@ void *load_elf(void *file_data, uint32_t map_flags){ program_entry_t *program_header = file_data + header->program_header_offset; uint32_t program_header_count = header->program_entry_count; mlog(MODULE_NAME, "PROGRAM ENTRIES: %d\n", MLOG_PRINT, program_header_count); - void *base_segment = 0; + uint32_t size_pages = 0; + for(uint32_t i = 0; i < program_header_count; i++){ + size_pages += (program_header[i].msize + PAGE_SIZE_BYTES - 1) / PAGE_SIZE_BYTES; + } + // printf("Requires %d pages\n", size_pages) + void *base_segment = kmalloc(size_pages); for(uint32_t i = 0; i < program_header_count; i++){ base_segment = load_segment(program_header[i], file_data, base_segment, map_flags); } diff --git a/src/kernel/system/intirc.c b/src/kernel/system/intirc.c index da9a1e1..bde4ffa 100644 --- a/src/kernel/system/intirc.c +++ b/src/kernel/system/intirc.c @@ -17,8 +17,12 @@ int is_num(char c){ void initrc_read(vfile_t *file){ mlog("KERNEL", "Reading initrc:\n", MLOG_PRINT); - char *ptr = file->access.data.ptr; - uint32_t size = file->access.data.size_pgs * 4096; + if(!file || !file->private){ + mlog("KERNEL", "Failed to read initrc!\n", MLOG_PRINT); + return; + } + char *ptr = file->private; + uint32_t size = file->size; char statement[512]; uint32_t i = 0; while(strcmp(statement, "END")){ @@ -52,18 +56,18 @@ void initrc_read(vfile_t *file){ i++; char module_name[512]; int j = 0; - for(; j < 512 && ptr[i + j] && ptr[i+j] != '\n' && ptr[i + j] != ' '; j++){ + for(; j < 512 && ptr[i + j] && ptr[i+j] != '\n' && ptr[i + j] != ' ' && i+j < size; j++){ module_name[j] = ptr[i + j]; } i+=j; module_name[j] = 0; // printf("%s\n", module_name); - vfile_t *module = fget_file(module_name); + vfile_t *module = fopen(module_name); if(!module){ printf("Error: Could not find module in Initrc.conf: %s\n", module_name); continue; } - module_start(module->access.data.ptr); + module_start(module->private); } else if(!strcmp(statement, "MOUNT")){ char mount_src_name[512] = {0}; @@ -71,12 +75,12 @@ void initrc_read(vfile_t *file){ uint32_t offset = 0; i++; int j = 0; - for(; j < 512 && ptr[i + j] && ptr[i+j] != '\n' && ptr[i+j] != ' '; j++){ + for(; j < 512 && ptr[i + j] && ptr[i+j] != '\n' && ptr[i+j] != ' ' && i+j < size; j++){ mount_src_name[j] = ptr[i + j]; } i+=j; mount_src_name[j] = 0; - for(j = 1; ptr[i + j] && ptr[i + j] != '\n' && ptr[i + j] != ' '; j++){ + for(j = 1; ptr[i + j] && ptr[i + j] != '\n' && ptr[i + j] != ' ' && i+j < size; j++){ mount_dest[j-1] = ptr[i + j]; } @@ -115,10 +119,14 @@ void initrc_read(vfile_t *file){ // printf("TEST: %s, %s, %d\n", mount_src_name, mount_dest, ptr[i]); - vfile_t *to_mount = fget_file(mount_src_name); + vfile_t *to_mount = fopen(mount_src_name); + if(!to_mount){ + mlog("KERNEL", "Could not locate file: %s. Aborting mount.\n", MLOG_PRINT, mount_src_name); + continue; + } if(!dispatch_message(MESSAGE_MOUNT_FS, to_mount, mount_dest, offset)){ mlog("INITRC", "Error: Could not mount device %s at %s", MLOG_PRINT, mount_src_name, mount_dest); - asm("int $13"); + // asm("int $13"); } } else if(!strcmp(statement, "END")){ diff --git a/src/kernel/system/modules.c b/src/kernel/system/modules.c index ca09bd4..253ae9c 100644 --- a/src/kernel/system/modules.c +++ b/src/kernel/system/modules.c @@ -69,26 +69,26 @@ uint32_t module_api(uint32_t func, ...){ uint32_t count = va_arg(vars, uint32_t); return_value = fread(file, buffer, offset, count); break; - case MODULE_API_WRITE: + case MODULE_API_WRITE: file = va_arg(vars, vfile_t *); buffer = va_arg(vars, char *); offset = va_arg(vars, uint32_t), count = va_arg(vars, uint32_t); + count = va_arg(vars, uint32_t); return_value = fwrite(file, buffer, offset, count); break; case MODULE_API_CREAT: name = va_arg(vars, char *); - VFILE_TYPE ftype = va_arg(vars, VFILE_TYPE); - void *arg1, *arg2; - arg1 = va_arg(vars, void *); - arg2 = va_arg(vars, void *); - return_value = (uint32_t)fcreate(name, ftype, arg1, arg2); + FS_FILE_FLAGS ftype = va_arg(vars, FS_FILE_FLAGS); + return_value = (uint32_t)fcreate(name, ftype); break; case MODULE_API_DELET: - return_value = -1; + file = va_arg(vars, vfile_t *); + return_value = fdelete(file); break; case MODULE_API_OPEN: name = va_arg(vars, char *); - return_value = (uint32_t)fget_file(name); + printf("Requested file: %s\n", name); + return_value = (uint32_t)fopen(name); break; case MODULE_API_MAP: return_value = 0; diff --git a/src/kernel/system/ramfs.c b/src/kernel/system/ramfs.c new file mode 100644 index 0000000..84b5678 --- /dev/null +++ b/src/kernel/system/ramfs.c @@ -0,0 +1,212 @@ +#include "vfs.h" +#include "ramfs.h" +#include "../shared/kstdlib.h" +#include "../shared/memory.h" +#include "../shared/string.h" +#define MODULE_NAME "RAMFS" + +fileops_t ramfs_ops = +{ + ramfs_create, + ramfs_delete, + ramfs_write, + ramfs_read, + // ramfs_open, + ramfs_close, + ramfs_rfopen, +}; + +vfile_t root_dir = {"/", FS_FILE_IS_DIR | FS_FILE_SYSTEM, &ramfs_ops}; + +void ramfs_init(){ + mlog(MODULE_NAME, "Initializing VFS\n", MLOG_PRINT); + root_dir.private = 0; + root_dir.size = 0; +} + +vfile_t *search_dir(char *subname, vfile_t *directory){ + if(!directory) return 0; + vfile_t **children = (vfile_t **)directory->private; + if(!children){ + return 0; + } + for(int i = 0; i < directory->size / sizeof(vfile_t *); i++){ + if(children[i] && !strcmp(children[i]->name, subname)){ + return children[i]; + } + } + + return 0; +} + +//resolves the path relative to start +vfile_t *resolve_path(char *pathname, vfile_t *start, uint32_t get_last_child){ + const uint32_t MAX_TOKENS = PAGE_SIZE_BYTES/4; + + if(!start){ + return 0; + } + char *path = kmalloc(1); + strcpy(pathname, path); + + char **path_tokens = kmalloc(1); + uint32_t pathname_entries = 0; + char *pathtok = path; + char *i = path; + while (*i != '\0') { + if (*i == '/') { + *i = '\0'; + if (pathname_entries < MAX_TOKENS) { + path_tokens[pathname_entries++] = pathtok; + } + pathtok = i + 1; + } + i++; + } + if (pathname_entries < MAX_TOKENS) { + path_tokens[pathname_entries++] = pathtok; + } + + // vfile_t **buffer = (vfile_t **)start->private; + vfile_t *entry = start; + char *current_path = pathname; + for(int i = 0; i < pathname_entries - !get_last_child; i++){ + entry = search_dir(path_tokens[i], entry); + current_path += strlen(path_tokens[i]) + 1; + if(!entry){ + break; + } + if(entry->flags & FS_FILE_MOUNT){ + if(!get_last_child){ + entry = 0; + break; + } + entry = entry->fileops->rfopen(current_path, entry); + break; + } + } + kfree(path); + kfree(path_tokens); + return entry; +} + +char *get_filename(char *path){ + char *filename = path + strlen(path) - 1;//get last character in pathname + while(*filename != path[0] && (*filename != '/' || filename == path)) filename--; + filename += filename != path;//if the new filename is at the beginning of the path, don't adjust for '/' character + return filename; +} + +int ramfs_resize(vfile_t *file, uint32_t new_size_bytes){ + if(new_size_bytes == file->size) return new_size_bytes; + uint32_t new_size_pages = (new_size_bytes + PAGE_SIZE_BYTES - 1)/PAGE_SIZE_BYTES; + uint32_t old_size_pages = (file->size + PAGE_SIZE_BYTES - 1)/PAGE_SIZE_BYTES; + do{ + if(old_size_pages == new_size_pages){ + break; + } + void *new_ptr = kmalloc(new_size_pages); + if(!new_ptr){ + mlog(MODULE_NAME, "Failed to allocate memory for virtual file!\n", MLOG_PRINT); + return 0; + } + if(file->private){ + memcpy((uint32_t *)file->private, (uint32_t*)new_ptr, file->size); + kfree(file->private); + } + file->private = new_ptr; + }while(0); + file->size = new_size_bytes; + return new_size_bytes; +} + +vfile_t *ramfs_create(vfile_t *root, char *path, FS_FILE_FLAGS flags){ + if(!path){ + return 0; + } + if(path[0] == '/') path++; + // vfile_t *parent = resolve_path(path, root, false); + vfile_t *parent = root; + if(!parent || !parent->flags & FS_FILE_IS_DIR){ + mlog(MODULE_NAME, "Could not locate parent directory for %s\n", MLOG_PRINT, path); + path--; + return 0; + } + char *new_name = path; + vfile_t **dirents = (vfile_t **)parent->private; + uint32_t insert_index = 0; + for(uint32_t i = 0; i < parent->size/sizeof(vfile_t *); i++){ + if(dirents[i]){ + continue; + } + //Empty dirent, can insert + vfile_t *new_file = kmalloc(1); + *new_file = (vfile_t){0}; + // new_file->name = new_name; + strcpy(new_name, new_file->name); + new_file->flags = flags; + dirents[i] = new_file; + new_file->fileops = &ramfs_ops; + path--; + return new_file; + } + //no empty dirents, must resize + if( !ramfs_resize(parent, parent->size + 4)) return 0; + dirents = parent->private; + vfile_t *new_file = kmalloc(1); + if(!new_file) return 0; + *new_file = (vfile_t){0}; + strcpy(new_name, new_file->name); + new_file->flags = flags; + dirents[parent->size/(sizeof(vfile_t*)) - 1] = new_file; + new_file->fileops = &ramfs_ops; + path--; + return new_file; +} + +int ramfs_translate_dir(vfile_t *file, void *buffer, uint32_t offset, uint32_t count){ + uint32_t dirents_requested = count / sizeof(vfile_t); + uint32_t dirents_availible = file->size / sizeof(vfile_t *); + uint32_t to_copy = unsigned_min(dirents_availible, dirents_requested); + vfile_t **dirents = (vfile_t **)file->private; + for(uint32_t i = 0; i < to_copy; i++){ + memcpy(dirents[i], buffer + i * sizeof(vfile_t), sizeof(vfile_t)); + } + return to_copy * sizeof(vfile_t); +} + +int ramfs_delete(vfile_t *file){ + return 0; +} +int ramfs_write(vfile_t *file, char *buffer, uint32_t offset, uint32_t count){ + //file->private can be null here, as ramfs_resize will handle assigning if it is not already assigned + if(!file || !buffer || (file->flags & (FS_FILE_READ_ONLY | FS_FILE_IS_DIR | FS_FILE_MOUNT))) return 0; + if(!ramfs_resize(file, count + offset)) return 0; + memcpy(buffer, file->private + offset, count); + return count; +} +int ramfs_read(vfile_t *file, char *buffer, uint32_t offset, uint32_t count){ + if(!file || !buffer || !file->private || file->flags & (FS_FILE_MOUNT)) return 0; + if(file->flags & FS_FILE_IS_DIR){ + return ramfs_translate_dir(file, buffer, offset, count); + } + memcpy(file->private + offset, buffer, count); + return count; +} +// vfile_t *ramfs_open(char *path){ +// return 0; +// } +void ramfs_close(vfile_t *file){ + file->refcount--; + if(file->refcount < 0) file->refcount = 0; + return; +} +vfile_t *ramfs_rfopen(char *name, vfile_t *parent){ + vfile_t *returnable = resolve_path(name, parent, true); + // for(;;); + return returnable; +} + +vfile_t *get_root_dir(){ + return &root_dir; +} \ No newline at end of file diff --git a/src/kernel/system/ramfs.h b/src/kernel/system/ramfs.h new file mode 100644 index 0000000..22240db --- /dev/null +++ b/src/kernel/system/ramfs.h @@ -0,0 +1,14 @@ +#pragma once +#include + +void ramfs_init(); +vfile_t *ramfs_create(vfile_t *parent, char *path, FS_FILE_FLAGS flags); +//Will never create a new reference +vfile_t *get_root_dir(); + +int ramfs_delete(vfile_t *file); +int ramfs_write(vfile_t *file, char *buffer, uint32_t offset, uint32_t count); +int ramfs_read(vfile_t *file, char *buffer, uint32_t offset, uint32_t count); +// vfile_t *ramfs_open(char *path); +void ramfs_close(vfile_t *file); +vfile_t *ramfs_rfopen(char *name, vfile_t *parent); \ No newline at end of file diff --git a/src/kernel/system/vfs.c b/src/kernel/system/vfs.c index 080a55c..2a79014 100644 --- a/src/kernel/system/vfs.c +++ b/src/kernel/system/vfs.c @@ -1,308 +1,120 @@ #include "vfs.h" +#include "ramfs.h" #include "../shared/kstdlib.h" #include "../shared/memory.h" #include "../shared/string.h" #define MODULE_NAME "KVFS" -vfile_t root_dir = {"/", VFILE_DIRECTORY}; // !TODO: Modify code to become thread-safe +// 3 months later: does this count? -struct mount_handler{ - int (*callback)(vfile_t *device, MOUNT_OPERATION op, ...); - uint32_t key; -}mount_handlers[32]; -int vfs_link_exists(vfile_t *file){ - if(get_paddr(file) == 0 || file->type >= VFILE_MOUNT){ - return 0; - } - return 1; -} - -void vfs_write_part(vfile_t *file, void *data, uint32_t offset, uint32_t count){ - if(!vfs_link_exists(file->parent) || count > file->size){ - return; - } - fread(file->parent, data, offset + file->id, count); -} -void vfs_read_part(vfile_t *file, void *data, uint32_t offset, uint32_t count){ - if(!vfs_link_exists(file->parent) || count > file->size){ - return; - } - fwrite(file->parent, data, offset + file->id, count); -} - -void vfs_detect_partitions(vfile_t *file){ - char *buffer = kmalloc(1); - fread(file, buffer, 0, 512); - mbr_t *mbr = buffer; - if(mbr->magic != MBR_MAGIC){ - mlog(MODULE_NAME, "No MBR!\n", MLOG_PRINT); - mlog(MODULE_NAME, "Magic: %x\n", mbr->magic, MLOG_PRINT); - return; - } - char cat[2] = {'a', 0}; - char nfname[512] = {0}; - strcpy(file->name, nfname); - strcat(cat, nfname); - char finalfname[512] = {0}; - strcpy("/dev/", finalfname); - strcat(nfname, finalfname); - for(int i = 0; i < 4; i++){ - partition_t part = mbr->partitions[i]; - if(part.type == 0xee){ - mlog(MODULE_NAME, "Found gpt\n", MLOG_PRINT); - return; - } - if((part.attributes != 0 && part.attributes != 0x80) ){ - //check disk for filesystem - mlog(MODULE_NAME, "No partitions in %s\n", MLOG_PRINT, file->name); - // fcreate() new file representing partition - vfile_t *nfile = fcreate(finalfname, VFILE_DEVICE, vfs_write_part, vfs_read_part); - nfile->id = 0; - nfile->size = file->size; - nfile->parent = file; - return; - } - - finalfname[strlen(finalfname)-1]++; - } - mlog(MODULE_NAME, "Magic: %x\n", MLOG_PRINT, mbr->magic); - return; -} - -// void vfs_add_mount_handler(int (*mount_handler)(vfile_t *device, MOUNT_OPERATION op, ...), uint32_t key){ -// if(mount_handler == 0){ -// return; -// } -// for(uint32_t i = 0; i < 32; i++){ -// if(mount_handlers[i].callback == 0){ -// mount_handlers[i].callback = mount_handler; -// mount_handlers[i].key = key; -// } -// } -// } -// void vfs_del_mount_handler(uint32_t key){ -// for(uint32_t i = 0; i < 32; i++){ -// if(mount_handlers[i].key == key){ -// mount_handlers[i].callback = 0; -// mount_handlers[i].key = 0; -// } -// } +// void add_file(vfile_t *vfile, vfile_t *current_dir){ +// return; // } +spinlock_t vfs_lock; + void vfs_init(){ - mlog(MODULE_NAME, "Initializing VFS\n", MLOG_PRINT); - root_dir.access.data.ptr = kmalloc(1); - root_dir.access.data.size_pgs = 1; + spinlock_release(vfs_lock); } -void add_file(vfile_t *vfile, vfile_t *current_dir){ - vfile_t **dir_data = current_dir->access.data.ptr; - int i = 0; - while(dir_data[i] && (i * sizeof(vfile_t *))/4096 < current_dir->access.data.size_pgs){ - i++; - } - dir_data[i] = vfile; - dir_data[i + 1] = 0; +vfile_t *fcreate(char *path, FS_FILE_FLAGS flags){ + // return 0; + spinlock_acquire(vfs_lock); + vfile_t *returnable = vfcreate(get_root_dir(), path, flags); + spinlock_release(vfs_lock); + return returnable; } -/* -Long comment cause this one's a complicated one. - Create a file of the specified path in name - if the path leads to a mounted filesystem then - use the mounted filesystem's specified create() function to create the file. - else, create a pointer in the virtual path that points to a file entry for the new file. - If this new file is a Directory or Pointer, specify a pointer to be used as a buffer to store data for this file, as well as the size of the buffer, in pages. - If this new file is a Mounted filesystem, this pointer must be an array of functions as defined below: - int fwrite(vfile_t *file, void *data, uint32_t offset, uint32_t count); - //must write count bytes from data to file offset by offset bytes. - int fread(vfile_t *file, void *data, uint32_t offset, uint32_t count); - //must read count bytes from data to file offset by offset bytes. - int fopen(char *filename, vfile_t *file); - //must return a vfile_t struct written to the address specified in file, to represent a file named name (from the mount's filename) - (eg. /mount/root/test is passed as /root/test) - fcreate(char *filename, FS_FILE_FLAGS flags); - FS_FILE_FLAGS is in the same format as FAT's file attribute byte of dirents. - filenames are truncated, as with the previous example. - fdelete(vfile_t *file); - //the file specified in the file pointer must be deleted. - else, if the file is a virtual representation of a device, of of a file (any miscellaneous file object that does not fit the other types) then - specify a pointer to be used as the read function, as defined below: - void read(struct virtual_file *file, void *data, uint32_t offset, uint32_t count); - specify a pointer to be used as the write function, with the same function prototype as the function above - void write(struct virtual_file *file, void *data, uint32_t offset, uint32_t count); -*/ -vfile_t *fcreate(char *name, VFILE_TYPE type, ...){ - name += name[0]== '/'; - char *last = strtok(name, '/'); - char *tmp = last; - uint32_t filename_offset = 0; - vfile_t *current_dir = &root_dir; - vfile_t *tmpfile; + +vfile_t *vfcreate(vfile_t *parent_dir, char *relpath, FS_FILE_FLAGS flags){ + if(!relpath){ + return 0; + } - va_list args; - va_start(args, type); - while(tmp != 0){ - // dir = tmp; - tmpfile = search_dir(tmp, *current_dir); - // printf("%s\n", name + filename_offset); - if(!tmpfile){ - //create file in folder; - vfile_t *vfile = kmalloc(1); - vfile->type = type; - vfile->parent = current_dir; - uint32_t tmpnsize = strlen(tmp); - if(tmp[tmpnsize - 1] == '/'){ - tmp[tmpnsize - 1] = 0; - } - strcpy(tmp, vfile->name); - - switch(type){ - case VFILE_POINTER: - case VFILE_DIRECTORY: - case VFILE_MOUNT: - case VFILE_SYMLINK: - case VFILE_FILE: - void *ptr = va_arg(args, void*); - vfile->access.data.ptr = ptr; - vfile->access.data.size_pgs = va_arg(args, uint32_t); - // *(uint32_t *)(ptr + (vfile->access.data.size_pgs * 4096)) = 0; - // what was the above line even for - add_file(vfile, current_dir); - break; - case VFILE_DEVICE: - void *write = va_arg(args, void *); - void *read = va_arg(args, void *); - vfile->access.funcs.write = write; - vfile->access.funcs.read = read; - // strcpy - add_file(vfile, current_dir); - break; - } - return vfile; //allow drivers to make last minute changes before it's sent to the user - } - if(tmpfile->type == VFILE_SYMLINK){ - tmpfile = (vfile_t *)tmpfile->access.data.ptr; - } - switch(tmpfile->type){ - case VFILE_DIRECTORY: - current_dir = tmpfile; - break; - case VFILE_MOUNT: - ((mount_t*)(tmpfile->access.data.ptr))->create(name + filename_offset, type == VFILE_DIRECTORY ? FS_FILE_IS_DIR : 0); - return (void *)-1; - default: - // mlog(MODULE_NAME, "Error: Cannot create file with same name as another file! %d\n", MLOG_ERR, tmpfile->type); - return 0; - break; - } - filename_offset += strlen(tmp) + 1; - tmp = strtok(0, '/'); + char *name = kmalloc((strlen(relpath) + 4095)/4096);//don't make modifications to the original string + strcpy(relpath, name); + if(name[0] == '/') name++;//first slash just indicates that it's an absolute path, we don't want to include that into the filename. + uint32_t name_length = strlen(name); + if(name[name_length-1] == '/') name[name_length - 1] = 0; + uint32_t name_index = 0; + uint32_t subpath_start = 0; + + vfile_t *new_file = 0; + + subpath_start = name_index; + while(name[name_index] && name[name_index] != '/'){//split the string at directories + name_index++; } - return 0; + name[name_index] = 0; + + if(name_index >= name_length){//if there is no other directory + new_file = parent_dir->fileops->create(parent_dir, name, flags); + } + else{ + vfile_t *new_parent = rfopen(name, parent_dir); + if(!new_parent){ + printf("No new parent found from name: %s!\n", name); + kfree(name); + return 0; + } + new_file = vfcreate(new_parent, name+name_index+1, flags); + // fclose(new_parent); + } + kfree(name); + return new_file; + // return 0; } -//who needs a way to delete things? -//TODO: Write a function to delete files -void fdelete(); - -// navya was here https://github.com/novabansal -int fwrite(vfile_t *file_entry, void *byte_array, uint32_t offset, uint32_t count){ - //sorry navya, I deleted the comment and it's not coming back :( - switch(file_entry->type){ - case VFILE_DIRECTORY: - case VFILE_POINTER: - memcpy(byte_array, file_entry->access.data.ptr + offset, count); - return 0; //always successful. If it's not, there's been a page fault. Yk, quantum sort style. - break; - case VFILE_MOUNT: - case VFILE_FILE: - mount_t *funcs = file_entry->access.data.ptr; - return funcs->write(file_entry, byte_array, offset, count); - case VFILE_PDIR: - case VFILE_DEVICE: - return file_entry->access.funcs.write(file_entry, byte_array, offset, count); - break; - case VFILE_SYMLINK: - return fwrite(file_entry->access.data.ptr, byte_array, offset, count); +int fdelete(vfile_t *file_entry){ + spinlock_acquire(vfs_lock); + if(!file_entry || !file_entry->fileops || !file_entry->fileops->delete){ + return 0; } - return INT32_MIN;//how did we get here? + spinlock_release(vfs_lock); + return file_entry->fileops->delete(file_entry); +} +//Is expected to overwrite, not append if it is an actual file +//Devices and anything Not A File is exempt (i.e. Blockdevs, chardevs, etc) +int fwrite(vfile_t *file_entry, void *byte_array, uint32_t offset, uint32_t count){ + if(!file_entry || !file_entry->fileops || !file_entry->fileops->write ||!byte_array || count == 0){ + return 0; + } + return file_entry->fileops->write(file_entry, byte_array, offset, count); } int fread(vfile_t *file_entry, void *byte_array, uint32_t offset, uint32_t count){ - switch(file_entry->type){ - case VFILE_DIRECTORY: - case VFILE_POINTER: - memcpy(file_entry->access.data.ptr + offset, byte_array, count); - return 0; //always successful. If it's not, there's been a page fault. Yk, quantum sort style. - break; - case VFILE_MOUNT: - case VFILE_FILE: - mount_t *funcs = file_entry->access.data.ptr; - return funcs->read(file_entry, byte_array, offset, count); - case VFILE_PDIR: - case VFILE_DEVICE: - return file_entry->access.funcs.read(file_entry, byte_array, offset, count); - break; - case VFILE_SYMLINK: - return fread(file_entry->access.data.ptr, byte_array, offset, count); + if(!file_entry || !file_entry->fileops || !file_entry->fileops->read || !byte_array || count == 0){ + return 0; } - return INT32_MIN; //Okay, alright, funny joke guys but we really shouldn't be able to get here + return file_entry->fileops->read(file_entry, byte_array, offset, count); } -vfile_t *search_dir(char *name, vfile_t dir){ - vfile_t **dir_data = (vfile_t **)dir.access.data.ptr; - uint32_t i = 0; - while(dir_data[i]){ - if(!strcmp(dir_data[i]->name, name)){ - return dir_data[i]; - } - i++; +//fopen but relative to *dir +vfile_t *rfopen(char *name, vfile_t *dir){ + if(!dir || !name || !dir->fileops || !dir->fileops->rfopen){ + return 0; } + return dir->fileops->rfopen(name, dir); +} + +int readdir(vfile_t* file, vfile_t* buffer, uint32_t offset, uint32_t count){ return 0; } -vfile_t *fget_file(char *name){ - if(name[0] == '/'){ - if(strlen(name) == 1){ - return &root_dir; - } - name++; +vfile_t *fopen(char *name){ + if(!name){ + return 0; } - if(name[strlen(name) - 1] == '/'){ - name[strlen(name) - 1] = 0; + vfile_t *root = get_root_dir(); + if(!strcmp(name, "/")){ + return root; } - // printf("%s\n", name); - char *dir = strtok(name, '/'); - // printf("%s", name); - char *tmp = dir; - uint32_t filename_offset = 0; - vfile_t *current_dir = &root_dir; - vfile_t *tmpfile = 0; - while(tmp != 0){ - dir = tmp; - tmpfile = search_dir(tmp, *current_dir); - if(!tmpfile){ - // printf("not found\n"); - return 0; - } - if(tmpfile->type == VFILE_SYMLINK){ - tmpfile = (vfile_t *)tmpfile->access.data.ptr; - } - switch(tmpfile->type){ - case VFILE_DIRECTORY: - // printf("found directory in %s: %s\n", current_dir->name, tmpfile->name); - current_dir = tmpfile; - break; - case VFILE_MOUNT: - vfile_t *file = kmalloc(1); - ((mount_t*)(tmpfile->access.data.ptr))->open(name + filename_offset, file); - return file; - default: - return tmpfile; - } - filename_offset += strlen(tmp) + 1; - tmp = strtok(0, '/'); - } - return tmpfile; + return root->fileops->rfopen(name + (name[0] == '/'), root); +} + +vfile_t *fclose(vfile_t *file){ + if(!file || !file->fileops || !file->fileops->close); + file->fileops->close(file); + return 0; } \ No newline at end of file diff --git a/src/kernel/system/vfs.h b/src/kernel/system/vfs.h index 47c2022..06b4daa 100644 --- a/src/kernel/system/vfs.h +++ b/src/kernel/system/vfs.h @@ -1,87 +1,59 @@ #pragma once #include - -typedef enum vfile_type{ - VFILE_NULL, - VFILE_POINTER,//virtual files - VFILE_DEVICE, - VFILE_MOUNT,//in the pointer passed to the function, must specify a read, write, open, create, and delete function. - VFILE_DIRECTORY, - VFILE_PDIR,//used for directories in physical filesystems. - VFILE_FILE,//physical files - VFILE_SYMLINK, - VFILE_PIPE //yay we have pipes -}VFILE_TYPE; - -typedef enum mount_ops{ - MOUNT_NEW, - MOUNT_UNMOUNT, -}MOUNT_OPERATION; - - -//this code is gonna be ***really*** unsafe -typedef struct virtual_file{ - char name[20]; - VFILE_TYPE type; - uint32_t id;//to be assigned by driver; - uint32_t mount_id; - uint8_t lock; - uint32_t size; - struct virtual_file *parent;//should point to A: a virtual directory, or B: a mounted filesystem - union{ - struct{ - int (*read)(struct virtual_file *file, void *data, uint32_t offset, uint32_t count); - int (*write)(struct virtual_file *file, void *data, uint32_t offset, uint32_t count); - }funcs; - struct{ - void *ptr; - uint32_t size_pgs; - }__attribute__((packed))data; - }access; -}vfile_t; - +#include "../shared/spinlock.h" typedef enum fs_flags{ FS_FILE_READ_ONLY = 1, FS_FILE_HIDDEN = 2, FS_FILE_SYSTEM = 4, FS_FILE_IS_DIR = 0x10, - FS_FILE_ARCHIVE = 0x20 + FS_FILE_ARCHIVE = 0x20, + FS_FILE_PIPE = 0x40, + FS_FILE_LINK = 0x80, + FS_FILE_MOUNT = 0x100, // MUST be assigned to any file that represents a physical filesystem or physical device. }FS_FILE_FLAGS; -typedef struct mount_funcs{ - int (*write)(vfile_t *file, void *data, uint32_t offset, uint32_t count); - int (*read)(vfile_t *file, void *data, uint32_t offset, uint32_t count); - int (*open)(char *filename, vfile_t *file); - void (*delete)(vfile_t *file); - void (*create)(char *filename, FS_FILE_FLAGS flags); -}mount_t; +typedef struct fileops{ + struct virtual_file *(*create)(struct virtual_file *parent, char *path, FS_FILE_FLAGS flags); + int (*delete)(struct virtual_file *file_entry); + int (*write)(struct virtual_file *file_entry, void *data, uint32_t offset, uint32_t count); + int (*read)(struct virtual_file *file_entry, void *data, uint32_t offset, uint32_t count); + // struct virtual_file *(*open)(char *path); + void (*close)(struct virtual_file *file); + // int (*readdir)(struct virtual_file* file, struct virtual_file *buffer, uint32_t count, uint32_t offset); + struct virtual_file *(*rfopen)(char *name, struct virtual_file *parent); +} fileops_t; -typedef struct partition{ - uint8_t attributes; - uint8_t chs_start[3]; - uint8_t type; - uint8_t chs_end[3]; - uint32_t lba_start; - uint32_t lba_size; -}__attribute__((packed))partition_t; - -#define MBR_MAGIC 0xaa55 - -typedef struct mbr{ - char code[440]; - char id[4]; - char res[2]; - partition_t partitions[4]; - uint16_t magic; -}__attribute__((packed)) mbr_t; +//note: this is EXACTLY 256 bytes. This is for simplicity's sake. +//PLEASE if you MUST reorganize or add fields, try and keep it to a power of 2? +typedef struct virtual_file{ + char name[212]; + uint16_t flags; + fileops_t *fileops; + uint32_t refcount; //filesystem MUST remain operational until all child refcounts == 0 + + uint32_t id;//for use in drivers + void *private; //also for use in drivers + uint32_t size; //should be in bytes + uint32_t offset; //for use in drivers + + uint8_t owner_uid; + uint8_t owner_gid; + uint32_t last_modified; + uint32_t created; + uint16_t permissions; //same format as linux + spinlock_t lock; +}vfile_t; void vfs_init(); -vfile_t *fcreate(char *name, VFILE_TYPE type, ...); -void fdelete(); + +// vfile_t *rfopen(char *name, vfile_t dir); +vfile_t *fcreate(char *path, FS_FILE_FLAGS flags); +int fdelete(vfile_t* file_entry); int fwrite(vfile_t *file_entry, void *byte_array, uint32_t offset, uint32_t count); int fread(vfile_t *file_entry, void *byte_array, uint32_t offset, uint32_t count); -vfile_t *search_dir(char *name, vfile_t dir); -vfile_t *fget_file(char *name); -// void vfs_del_mount_handler(uint32_t key); -// void vfs_add_mount_handler(int (*mount_handler)(vfile_t *device, MOUNT_OPERATION op, ...), uint32_t key); -void vfs_detect_partitions(vfile_t *file); \ No newline at end of file +// int readdir(vfile_t* file, vfile_t *buffer, uint32_t offset, uint32_t count); + +vfile_t *vfcreate(vfile_t *parent, char *relpath, FS_FILE_FLAGS flags); +vfile_t *rfopen(char *name, vfile_t *dir); +vfile_t *fclose(vfile_t *); +vfile_t *fopen(char *path); \ No newline at end of file diff --git a/src/kmodules/disk_driver.c b/src/kmodules/disk_driver.c index bf79e49..c280c44 100644 --- a/src/kmodules/disk_driver.c +++ b/src/kmodules/disk_driver.c @@ -8,6 +8,17 @@ KOS_MAPI_FP api; +int ata_read(vfile_t *file, uint8_t *ptr, uint32_t offset, uint32_t count); +int ata_write(vfile_t *file, void *ptr, uint32_t offset, uint32_t count); +fileops_t ide_fileops = { + 0, + 0, + ata_write, + ata_read, + 0, + 0, +}; + /* TODO: Register module @@ -208,7 +219,7 @@ int ata_write(vfile_t *file, void *ptr, uint32_t offset, uint32_t count){ if (count == 0) return -1; ata_acquire_primary_lock(); // } - drive_t drive = drives[file->mount_id]; + drive_t drive = drives[file->id]; uint16_t io_base = drive.BARs[0] &0xfffe; uint16_t ctrl_base = drive.BARs[1] &0xfffe; uint16_t bm_base = drive.BARs[4] & ~3; @@ -283,7 +294,7 @@ int ata_write(vfile_t *file, void *ptr, uint32_t offset, uint32_t count){ asm("sti"); - transferring_disk_index = file->mount_id; + transferring_disk_index = file->id; uint8_t status = inb(ctrl_base); uint8_t bm_status = inb(bm_base + 2); @@ -303,7 +314,7 @@ int ata_write(vfile_t *file, void *ptr, uint32_t offset, uint32_t count){ int ata_read(vfile_t *file, uint8_t *ptr, uint32_t offset, uint32_t count) { if (count == 0) return -1; - drive_t drive = drives[file->mount_id]; + drive_t drive = drives[file->id]; uint16_t io_base = drive.BARs[0] &0xfffe; uint16_t ctrl_base = drive.BARs[1] &0xfffe; uint16_t bm_base = drive.BARs[4] & ~3; @@ -372,14 +383,15 @@ int ata_read(vfile_t *file, uint8_t *ptr, uint32_t offset, uint32_t count) { recieved_ints = 0; asm("cli"); - transferring_disk_index = file->mount_id; + transferring_disk_index = file->id; uint32_t cpid = api(MODULE_API_GET_CPID); // api(MODULE_API_PRINT, MODULE_NAME, "Cpid: %x", cpid); api(MODULE_API_BLOCK_PID, cpid); transferring_pid = cpid; outb(bm_base, 0x09); - asm("sti"); + // asm("sti"); // TODO: Make it so that instead of sti(), restore interrupt flag + if(!api(MODULE_API_IS_INTERRUPT)) asm("sti"); uint8_t status = inb(ctrl_base); uint8_t bm_status = inb(bm_base + 2); @@ -522,8 +534,19 @@ uint8_t ata_identify(uint32_t index, uint16_t disk){ uint32_t prdt_phys = api(MODULE_API_PMALLOC64K); drives[index].PRDT = (void *)api(MODULE_API_KMALLOC_PADDR, prdt_phys, 16); itoa(ata_drives, fname + strlen(fname), 10); - vfile_t *new_file = fcreate(api, fname, VFILE_DEVICE, ata_write, ata_read); - new_file->mount_id = index; + vfile_t *new_file = fcreate(api, fname, FS_FILE_SYSTEM); + api(MODULE_API_PRINT, MODULE_NAME, "New File: %x, Name: %s\n", new_file, new_file->name); + // + // + // + // RIGHT HERE + // + // + // + // new_file->read = ata_read; + // new_file->write = ata_write; + new_file->id = index; + new_file->fileops = &ide_fileops; puts(api, "KIDM", "Valid Drive!\n"); return 0; } @@ -596,10 +619,22 @@ void init(KOS_MAPI_FP module_api, uint32_t api_version){ api(MODULE_API_ADDINT, 15, module_data.key, int_handler); api(MODULE_API_ADDINT, 14, module_data.key, int_handler); // api(MODULE_API_ADDINT, 0, module_data.key, int_handler); - vfile_t *pci_drive_dir = fget_file(api, "/dev/pci/disk/"); - vfile_t **dir_data = (pci_drive_dir->access.data.ptr); - for(uint32_t i = 0; dir_data[i]; i++){ - vfile_t *current_file = dir_data[i]; + vfile_t *pci_drive_dir = fopen(api, "/dev/pci/disk"); + if(!pci_drive_dir){ + puts(api, MODULE_NAME, "Failed to open /dev/pci/disk\n"); + return; + } + // vfile_t **dir_data = (pci_drive_dir->ptr); + + const uint32_t PCI_SEARCH_COUNT = 64; + + vfile_t *dir_data = malloc(api, (PCI_SEARCH_COUNT * sizeof(vfile_t) + 4095)/4096); + + uint32_t file_count = api(MODULE_API_READ, pci_drive_dir, dir_data, 0, PCI_SEARCH_COUNT * sizeof(vfile_t))/sizeof(vfile_t); + api(MODULE_API_PRINT, MODULE_NAME, "File count: %x\n", file_count); + + for(uint32_t i = 0; i < file_count; i++){ + vfile_t *current_file = &(dir_data[i]); uint32_t class = 0; fread(api, current_file, &class, 0x8, 1); uint32_t progif = class >> 8 & 0xff; diff --git a/src/kmodules/fs_driver.c b/src/kmodules/fs_driver.c index d6fbe3d..fb8f159 100644 --- a/src/kmodules/fs_driver.c +++ b/src/kmodules/fs_driver.c @@ -23,16 +23,16 @@ uint8_t fat32_check_valid(fat32_bpb_t *bpb){ uint32_t fat32_mount(vfile_t *dev_file, char *destination, uint32_t offset){ - char *bpb_buffer = malloc(api, 1); - fread(api, dev_file, bpb_buffer, offset, 4096); - fat32_bpb_t *bpb = bpb_buffer; + // char *bpb_buffer = malloc(api, 1); + // fread(api, dev_file, bpb_buffer, offset, 4096); + // fat32_bpb_t *bpb = bpb_buffer; - api(MODULE_API_PRINT, MODULE_NAME, "Sizeof struct: %d, sig: %x, boot sig: %x\n", sizeof(fat32_bpb_t), bpb->signature, bpb->bootable_sig); - if(!fat32_check_valid(bpb)){ - api(MODULE_API_PRINT, MODULE_NAME, "Error: No valid BPB\n"); - return 0; - } - puts(api, MODULE_NAME, "Valid BPB found!\n"); + // api(MODULE_API_PRINT, MODULE_NAME, "Sizeof struct: %d, sig: %x, boot sig: %x\n", sizeof(fat32_bpb_t), bpb->signature, bpb->bootable_sig); + // if(!fat32_check_valid(bpb)){ + // api(MODULE_API_PRINT, MODULE_NAME, "Error: No valid BPB\n"); + // return 0; + // } + // puts(api, MODULE_NAME, "Valid BPB found!\n"); // fat32_make_mount(); @@ -59,8 +59,8 @@ void init(KOS_MAPI_FP module_api, uint32_t api_version){ api(MODULE_API_PRINT, MODULE_NAME, "KIFSM Filesystem Driver Module v0.1.0\nSupported Filesystems:\n"); int32_t status = api(MODULE_API_REGISTER, &module_data); - api(MODULE_MESSAGE_HANDLER, module_data.key, message_handler); - api(MODULE_API_PRINT, MODULE_NAME, "Key: %x\n", module_data.key); + // api(MODULE_MESSAGE_HANDLER, module_data.key, message_handler); + // api(MODULE_API_PRINT, MODULE_NAME, "Key: %x\n", module_data.key); return; } \ No newline at end of file diff --git a/src/kmodules/modlib.h b/src/kmodules/modlib.h index a933da1..3837bb1 100644 --- a/src/kmodules/modlib.h +++ b/src/kmodules/modlib.h @@ -1,5 +1,6 @@ #pragma once #include +#include "../kernel/shared/spinlock.h" enum MODULE_API_FUNCS{ @@ -53,34 +54,47 @@ enum MESSAGES{ MESSAGE_BROADCAST = 0x80000000, //placeholder }; -typedef enum vfile_type{ - VFILE_NULL, - VFILE_POINTER, - VFILE_DEVICE, - VFILE_MOUNT, - VFILE_DIRECTORY, - VFILE_PDIR,//used for directories in physical filesystems. - VFILE_FILE, -}VFILE_TYPE; +typedef enum fs_flags{ + FS_FILE_READ_ONLY = 1, + FS_FILE_HIDDEN = 2, + FS_FILE_SYSTEM = 4, + FS_FILE_IS_DIR = 0x10, + FS_FILE_ARCHIVE = 0x20, + FS_FILE_PIPE = 0x40, + FS_FILE_LINK = 0x80, + FS_FILE_MOUNT = 0x100, // MUST be assigned to any file that represents a physical filesystem or physical device. +}FS_FILE_FLAGS; +typedef struct fileops{ + struct virtual_file *(*create)(struct virtual_file *parent, char *path, FS_FILE_FLAGS flags); + int (*delete)(struct virtual_file *file_entry); + int (*write)(struct virtual_file *file_entry, void *data, uint32_t offset, uint32_t count); + int (*read)(struct virtual_file *file_entry, void *data, uint32_t offset, uint32_t count); + // struct virtual_file *(*open)(char *path); + void (*close)(struct virtual_file *file); + // int (*readdir)(struct virtual_file* file, struct virtual_file *buffer, uint32_t count, uint32_t offset); + struct virtual_file *(*rfopen)(char *name, struct virtual_file *parent); +} fileops_t; + +//note: this is EXACTLY 256 bytes. This is for simplicity's sake. +//PLEASE if you MUST reorganize or add fields, try and keep it to a power of 2? typedef struct virtual_file{ - char name[20]; - VFILE_TYPE type; - uint32_t id;//to be assigned by driver; - uint32_t mount_id; - uint8_t lock; - uint32_t size; - struct virtual_file *parent;//should point to A: a virtual directory, or B: a mounted filesystem - union{ - struct{ - int (*read)(struct virtual_file *file, void *data, uint32_t offset, uint32_t count); - int (*write)(struct virtual_file *file, void *data, uint32_t offset, uint32_t count); - }funcs; - struct{ - void *ptr; - uint32_t size_pgs; - }__attribute__((packed))data; - }access; + char name[212]; + uint16_t flags; + fileops_t *fileops; + uint32_t refcount; //filesystem MUST remain operational until all child refcounts == 0 + + uint32_t id;//for use in drivers + void *private; //also for use in drivers + uint32_t size; //should be in bytes + uint32_t offset; //for use in drivers + + uint8_t owner_uid; + uint8_t owner_gid; + uint32_t last_modified; + uint32_t created; + uint16_t permissions; //same format as linux + spinlock_t lock; }vfile_t; inline void *malloc(KOS_MAPI_FP api, uint32_t size_pages){ @@ -90,7 +104,7 @@ inline void *free(KOS_MAPI_FP api, void *ptr){ api(MODULE_API_FREE, ptr); return 0; } -inline vfile_t *fget_file(KOS_MAPI_FP api, char *filename){ +inline vfile_t *fopen(KOS_MAPI_FP api, char *filename){ // vfile_t *file = malloc(api, 1); return (void *)api(MODULE_API_OPEN, filename); } @@ -101,8 +115,8 @@ inline int fwrite(KOS_MAPI_FP api, vfile_t *file, char *buffer, uint32_t offset, return api(MODULE_API_WRITE, file, buffer, offset, count); } //read documenation for this one -inline vfile_t *fcreate(KOS_MAPI_FP api, char *filename, VFILE_TYPE type, char *pointer_write, char *size_read){ - return (void *)api(MODULE_API_CREAT, filename, type, pointer_write, size_read); +inline vfile_t *fcreate(KOS_MAPI_FP api, char *filename, FS_FILE_FLAGS type){ + return (void *)api(MODULE_API_CREAT, filename, type); } inline void puts(KOS_MAPI_FP api, char *mname, char *str){ api(MODULE_API_PRINT, mname, str);