Merge branch 'vfs-dev'

This commit is contained in:
notsomeidiot123 2026-07-11 15:08:39 -04:00
commit eecdfcb8bb
20 changed files with 618 additions and 470 deletions

View File

@ -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" LDFLAGS_i386="-Ttext 0xc0000000 --oformat binary -melf_i386"
cd src/kernel/ cd src/kernel/

View File

@ -21,13 +21,16 @@ bits 16
;Load part2 |x| ;Load part2 |x|
;Get video mode information |0| ;Get video mode information |0|
;Set video mode |0| ;Set video mode |0|
;get memory map |0| ;get memory map |x|
;enable paging |0| ;enable paging |x|
;read filesystem |0| ;read filesystem |x|
;load kernel |0| ;load kernel |x|
;parse ELF format |0| ;parse ELF format |x|
;pass memory and video information to kernel|0| ;pass memory and video information to kernel|x|
;relocate and jump to kernel |0| ;relocate and jump to kernel |x|
;TODO 7/4/26
;Remember to ZERO THE BSS
jump: jump:
jmp short start jmp short start

View File

@ -4,6 +4,7 @@
#include "../system/vfs.h" #include "../system/vfs.h"
#include "../shared/string.h" #include "../shared/string.h"
#include "../shared/memory.h" #include "../shared/memory.h"
#include "../drivers/serial.h"
#define MODULE_NAME "PCI" #define MODULE_NAME "PCI"
char *classes[][20] = { 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){ void pci_write_file(vfile_t *file, uint32_t *buffer, uint32_t offset, uint32_t count){
return; 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){ void pci_make_file(uint32_t class, uint8_t bus, uint8_t slot, uint8_t func){
char *str = kmalloc(1); char str[256] = "/dev/pci/\0";
memcpy("/dev/pci/", str, 9);
char *dev = classes[class >> 8][class & 0xf]; char *dev = classes[class >> 8][class & 0xf];
switch(class >> 8){ switch(class >> 8){
case 0x1://PCI class 0x1 is disks case 0x1://PCI class 0x1 is disks
// printf("!!STR: %s, LEN: %d!!", str, strlen(str));
strcpy("disk/", 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; 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); pci_write_config(bus, slot, func, 0x4, l | 4);
break; break;
case 0x2://PCI class 0x2 is network controllers case 0x2://PCI class 0x2 is network controllers
strcpy("net/", str + strlen(str)); 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]; char cpy[256];
vfile_t *file = 0; vfile_t *file = 0;
uint8_t tries = 0; uint8_t tries = 0;
while(file == 0){ // while(file == 0){
itoa(tries++, num, 10); itoa(tries++, num, 10);
strcpy(str, cpy); strcpy(str, cpy);
strcpy(num, cpy + strlen(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); 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(){ void pci_init(){
mlog(MODULE_NAME, "Enumerating PCI Buses\n", MLOG_PRINT); mlog(MODULE_NAME, "Enumerating PCI Buses\n", MLOG_PRINT);
vfile_t *file = fcreate("dev/pci/", VFILE_DIRECTORY, kmalloc(1), 1); vfile_t *file = fcreate("/dev/pci/", FS_FILE_IS_DIR);
fcreate("dev/pci/disk", VFILE_DIRECTORY, kmalloc(1), 1); fcreate("/dev/pci/disk", FS_FILE_IS_DIR);
fcreate("dev/pci/net", VFILE_DIRECTORY, kmalloc(1), 1); fcreate("/dev/pci/net", FS_FILE_IS_DIR);
fcreate("dev/pci/video", VFILE_DIRECTORY, kmalloc(1), 1); fcreate("/dev/pci/video", FS_FILE_IS_DIR);
fcreate("dev/pci/bridge", VFILE_DIRECTORY, kmalloc(1), 1); fcreate("/dev/pci/bridge", FS_FILE_IS_DIR);
for(uint32_t i = 0 ; i < 256; i++){ for(uint32_t i = 0 ; i < 256; i++){
pci_enumerate_bus(i); pci_enumerate_bus(i);
} }

View File

@ -83,6 +83,10 @@ void vprintf(char *string, va_list vars){
num = va_arg(vars, int32_t); num = va_arg(vars, int32_t);
printf((char[]){num, 0}); printf((char[]){num, 0});
continue; continue;
case 'b':
string++;
num = va_arg(vars, int32_t);
printf(num ? "true" : "false");
} }
} }
outb(com_ports[0], *string); outb(com_ports[0], *string);

View File

@ -36,8 +36,18 @@ int read_initrd(initrd_t *initrd){
// } // }
char final_fname[80] = "/boot/"; char final_fname[80] = "/boot/";
strcat(file->filename, final_fname); 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); // printf("%s, %d, %d\n", final_fname, filesize, fsize_pgs);
offset += (((filesize + 511) / 512) + 1) * 512; offset += (((filesize + 511) / 512) + 1) * 512;
} }
return 0;
} }

View File

@ -12,6 +12,7 @@
#include "system/vfs.h" #include "system/vfs.h"
#include "drivers/ustar.h" #include "drivers/ustar.h"
#include "system/initrc.h" #include "system/initrc.h"
#include "system/ramfs.h"
kernel_info_t *boot_info = 0; kernel_info_t *boot_info = 0;
@ -23,21 +24,16 @@ void sysinit(){
pci_init(); pci_init();
// modules_init(boot_info, 0); // modules_init(boot_info, 0);
read_initrd(boot_info->initrd); 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(); modules_init();
initrc_read(initrc); vfile_t *initrc = fopen("/boot/initrc.conf");
// vfile_t *disk_dir = fget_file("/dev/disk"); mlog("RAE", "\033[1;32mDid you remember to migrate your modules to the new API?\033[0m\n", MLOG_PRINT);
// if(disk_dir == 0){ if(initrc){
// mlog("KERNEL", "Error: /dev/disk does not exist\n", MLOG_PRINT); mlog("KERNEL", "Found initrc\n", MLOG_PRINT);
// } initrc_read(initrc);
// vfile_t **dir_data = disk_dir->access.data.ptr; }
// for(uint32_t i = 0; dir_data[i]; i++){ else{
// mlog("KERNEL", "Filename: %s\n", MLOG_PRINT, dir_data[i]->name); mlog("KERNEL", "ERROR: Initrc could not be located!\n", MLOG_PRINT);
// vfs_detect_partitions(dir_data[i]); }
// }
// dispatch_message(0); // dispatch_message(0);
printf("Bleh\n"); printf("Bleh\n");
//why did i stop working on this? what was wrong with this? //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){ extern void kmain(kernel_info_t *kernel_info){
serial_init(); serial_init();
pm_init(kernel_info); pm_init(kernel_info);
vfs_init(); ramfs_init();
mlog("KERNEL", "Initializing IDT\n", MLOG_PRINT); mlog("KERNEL", "Initializing IDT\n", MLOG_PRINT);
idt_load(); idt_load();
pic_init(0x20); pic_init(0x20);
pic_setmask(0x0, PIC1_DATA); pic_setmask(0x0, PIC1_DATA);
pic_setmask(0x0, PIC2_DATA); pic_setmask(0x0, PIC2_DATA);
vfs_init();
fcreate("/dev", VFILE_DIRECTORY, kmalloc(1), 1); fcreate("/tmp", FS_FILE_IS_DIR);
fcreate("/dev/disk", VFILE_DIRECTORY, kmalloc(1), 1); fcreate("/dev", FS_FILE_IS_DIR);
fcreate("/tmp", VFILE_DIRECTORY, kmalloc(1), 1); fcreate("/boot", FS_FILE_IS_DIR);
fcreate("/boot", VFILE_DIRECTORY, kmalloc(1), 1); fcreate("/dev/disk", FS_FILE_IS_DIR);
mlog("KERNEL", "Initializing Scheduler & starting PID 1\n", MLOG_PRINT); mlog("KERNEL", "Initializing Scheduler & starting PID 1\n", MLOG_PRINT);
boot_info = kernel_info; boot_info = kernel_info;
scheduler_init(); scheduler_init();
//scheduler doesn't work if there is no PID0, and I don't know why. //scheduler doesn't work if there is no PID0, and I don't know why.
thread_start(pid0); thread_start(pid0);
thread_start(sysinit); thread_start(sysinit);
// for(;;);
enable_interrupts(); enable_interrupts();
for(;;);//we actually **shouldn't** return, like, ever. That's bad. for(;;);//we actually **shouldn't** return, like, ever. That's bad.
return; return;

View File

@ -4,6 +4,12 @@
#include "../drivers/serial.h" #include "../drivers/serial.h"
#include "interrupts.h" #include "interrupts.h"
#define true 1
#define false 0
#define null 0
#define MLOG_DEBUG 1 #define MLOG_DEBUG 1
#define MLOG_PRINT 2 #define MLOG_PRINT 2
#define MLOG_WARN 3 #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_push(vector_t *vector, void *new_element);
void vector_pop(uint32_t pos, vector_t *vector, void *element); void vector_pop(uint32_t pos, vector_t *vector, void *element);
uint32_t atoi(char *str, uint32_t base); 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;
}

View File

@ -39,6 +39,8 @@
#define KMALLOC_LINK_NEXT 2 #define KMALLOC_LINK_NEXT 2
#define KMALLOC_LINK_LAST 4 #define KMALLOC_LINK_LAST 4
#define PAGE_SIZE_BYTES 4096
typedef struct BIOS_data{ typedef struct BIOS_data{
uint16_t com_ports[4]; uint16_t com_ports[4];
uint16_t lpt_ports[3]; uint16_t lpt_ports[3];

View File

@ -0,0 +1,13 @@
#include <stdatomic.h>
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);
}

View File

@ -21,6 +21,21 @@ inline uint32_t strcmp(char *str1, char *str2){
if(str1[i] == str2[i]) return 0; if(str1[i] == str2[i]) return 0;
else return 1; 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); char *strtok(char *str, char delim);
void strcpy(char *src, char *dest); void strcpy(char *src, char *dest);
void memcpy(char *src, char *dest, uint32_t c); void memcpy(char *src, char *dest, uint32_t c);

View File

@ -1,5 +1,6 @@
#include "elf.h" #include "elf.h"
#include "../shared/kstdlib.h" #include "../shared/kstdlib.h"
#include "../shared/string.h"
#include "../shared/memory.h" #include "../shared/memory.h"
#define MODULE_NAME "ELFLOAD" #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); // printf("Base: %x\n", base_segment);
if(entry.type == 1){ if(entry.type == 1){
if(((elf_header_t *)(file_data))->type == ELF_TYPE_SHARED){ if(((elf_header_t *)(file_data))->type == ELF_TYPE_SHARED){
if(base_segment == 0){ segment = base_segment + (entry.vaddr & 0xfffff000);
segment = kmalloc(entry.msize/4096 + 1); memclr(segment, entry.msize);
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);
}
}
for(uint32_t i = 0; i < entry.fsize/sizeof(uint32_t) + 1; i++){ 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)]; 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? //What is this for?
//TODO: Find out how to handle Dynamic sections //TODO: Find out how to handle Dynamic sections
} }
// printf("data_offset: %x\n", data_offset); // printf("data_offset: %x\n", data_offset);
return base_segment; 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; program_entry_t *program_header = file_data + header->program_header_offset;
uint32_t program_header_count = header->program_entry_count; uint32_t program_header_count = header->program_entry_count;
mlog(MODULE_NAME, "PROGRAM ENTRIES: %d\n", MLOG_PRINT, program_header_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++){ for(uint32_t i = 0; i < program_header_count; i++){
base_segment = load_segment(program_header[i], file_data, base_segment, map_flags); base_segment = load_segment(program_header[i], file_data, base_segment, map_flags);
} }

View File

@ -17,8 +17,12 @@ int is_num(char c){
void initrc_read(vfile_t *file){ void initrc_read(vfile_t *file){
mlog("KERNEL", "Reading initrc:\n", MLOG_PRINT); mlog("KERNEL", "Reading initrc:\n", MLOG_PRINT);
char *ptr = file->access.data.ptr; if(!file || !file->private){
uint32_t size = file->access.data.size_pgs * 4096; mlog("KERNEL", "Failed to read initrc!\n", MLOG_PRINT);
return;
}
char *ptr = file->private;
uint32_t size = file->size;
char statement[512]; char statement[512];
uint32_t i = 0; uint32_t i = 0;
while(strcmp(statement, "END")){ while(strcmp(statement, "END")){
@ -52,18 +56,18 @@ void initrc_read(vfile_t *file){
i++; i++;
char module_name[512]; char module_name[512];
int j = 0; 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]; module_name[j] = ptr[i + j];
} }
i+=j; i+=j;
module_name[j] = 0; module_name[j] = 0;
// printf("%s\n", module_name); // printf("%s\n", module_name);
vfile_t *module = fget_file(module_name); vfile_t *module = fopen(module_name);
if(!module){ if(!module){
printf("Error: Could not find module in Initrc.conf: %s\n", module_name); printf("Error: Could not find module in Initrc.conf: %s\n", module_name);
continue; continue;
} }
module_start(module->access.data.ptr); module_start(module->private);
} }
else if(!strcmp(statement, "MOUNT")){ else if(!strcmp(statement, "MOUNT")){
char mount_src_name[512] = {0}; char mount_src_name[512] = {0};
@ -71,12 +75,12 @@ void initrc_read(vfile_t *file){
uint32_t offset = 0; uint32_t offset = 0;
i++; i++;
int j = 0; 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]; mount_src_name[j] = ptr[i + j];
} }
i+=j; i+=j;
mount_src_name[j] = 0; 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]; 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]); // 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)){ 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); 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")){ else if(!strcmp(statement, "END")){

View File

@ -69,26 +69,26 @@ uint32_t module_api(uint32_t func, ...){
uint32_t count = va_arg(vars, uint32_t); uint32_t count = va_arg(vars, uint32_t);
return_value = fread(file, buffer, offset, count); return_value = fread(file, buffer, offset, count);
break; break;
case MODULE_API_WRITE: case MODULE_API_WRITE:
file = va_arg(vars, vfile_t *); file = va_arg(vars, vfile_t *);
buffer = va_arg(vars, char *); buffer = va_arg(vars, char *);
offset = va_arg(vars, uint32_t), count = va_arg(vars, uint32_t); 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); return_value = fwrite(file, buffer, offset, count);
break; break;
case MODULE_API_CREAT: case MODULE_API_CREAT:
name = va_arg(vars, char *); name = va_arg(vars, char *);
VFILE_TYPE ftype = va_arg(vars, VFILE_TYPE); FS_FILE_FLAGS ftype = va_arg(vars, FS_FILE_FLAGS);
void *arg1, *arg2; return_value = (uint32_t)fcreate(name, ftype);
arg1 = va_arg(vars, void *);
arg2 = va_arg(vars, void *);
return_value = (uint32_t)fcreate(name, ftype, arg1, arg2);
break; break;
case MODULE_API_DELET: case MODULE_API_DELET:
return_value = -1; file = va_arg(vars, vfile_t *);
return_value = fdelete(file);
break; break;
case MODULE_API_OPEN: case MODULE_API_OPEN:
name = va_arg(vars, char *); 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; break;
case MODULE_API_MAP: case MODULE_API_MAP:
return_value = 0; return_value = 0;

212
src/kernel/system/ramfs.c Normal file
View File

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

14
src/kernel/system/ramfs.h Normal file
View File

@ -0,0 +1,14 @@
#pragma once
#include <stdint.h>
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);

View File

@ -1,308 +1,120 @@
#include "vfs.h" #include "vfs.h"
#include "ramfs.h"
#include "../shared/kstdlib.h" #include "../shared/kstdlib.h"
#include "../shared/memory.h" #include "../shared/memory.h"
#include "../shared/string.h" #include "../shared/string.h"
#define MODULE_NAME "KVFS" #define MODULE_NAME "KVFS"
vfile_t root_dir = {"/", VFILE_DIRECTORY};
// !TODO: Modify code to become thread-safe // !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){ // void add_file(vfile_t *vfile, vfile_t *current_dir){
if(get_paddr(file) == 0 || file->type >= VFILE_MOUNT){ // return;
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;
// }
// }
// } // }
spinlock_t vfs_lock;
void vfs_init(){ void vfs_init(){
mlog(MODULE_NAME, "Initializing VFS\n", MLOG_PRINT); spinlock_release(vfs_lock);
root_dir.access.data.ptr = kmalloc(1);
root_dir.access.data.size_pgs = 1;
} }
void add_file(vfile_t *vfile, vfile_t *current_dir){ vfile_t *fcreate(char *path, FS_FILE_FLAGS flags){
vfile_t **dir_data = current_dir->access.data.ptr; // return 0;
int i = 0; spinlock_acquire(vfs_lock);
while(dir_data[i] && (i * sizeof(vfile_t *))/4096 < current_dir->access.data.size_pgs){ vfile_t *returnable = vfcreate(get_root_dir(), path, flags);
i++; spinlock_release(vfs_lock);
return returnable;
}
vfile_t *vfcreate(vfile_t *parent_dir, char *relpath, FS_FILE_FLAGS flags){
if(!relpath){
return 0;
} }
dir_data[i] = vfile;
dir_data[i + 1] = 0;
}
/*
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;
va_list args; char *name = kmalloc((strlen(relpath) + 4095)/4096);//don't make modifications to the original string
va_start(args, type); strcpy(relpath, name);
while(tmp != 0){ if(name[0] == '/') name++;//first slash just indicates that it's an absolute path, we don't want to include that into the filename.
// dir = tmp; uint32_t name_length = strlen(name);
tmpfile = search_dir(tmp, *current_dir); if(name[name_length-1] == '/') name[name_length - 1] = 0;
// printf("%s\n", name + filename_offset); uint32_t name_index = 0;
if(!tmpfile){ uint32_t subpath_start = 0;
//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){ vfile_t *new_file = 0;
case VFILE_POINTER:
case VFILE_DIRECTORY: subpath_start = name_index;
case VFILE_MOUNT: while(name[name_index] && name[name_index] != '/'){//split the string at directories
case VFILE_SYMLINK: name_index++;
case VFILE_FILE: }
void *ptr = va_arg(args, void*); name[name_index] = 0;
vfile->access.data.ptr = ptr;
vfile->access.data.size_pgs = va_arg(args, uint32_t); if(name_index >= name_length){//if there is no other directory
// *(uint32_t *)(ptr + (vfile->access.data.size_pgs * 4096)) = 0; new_file = parent_dir->fileops->create(parent_dir, name, flags);
// what was the above line even for }
add_file(vfile, current_dir); else{
break; vfile_t *new_parent = rfopen(name, parent_dir);
case VFILE_DEVICE: if(!new_parent){
void *write = va_arg(args, void *); printf("No new parent found from name: %s!\n", name);
void *read = va_arg(args, void *); kfree(name);
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; return 0;
break;
} }
filename_offset += strlen(tmp) + 1; new_file = vfcreate(new_parent, name+name_index+1, flags);
tmp = strtok(0, '/'); // fclose(new_parent);
} }
return 0; kfree(name);
return new_file;
// return 0;
} }
//who needs a way to delete things? int fdelete(vfile_t *file_entry){
//TODO: Write a function to delete files spinlock_acquire(vfs_lock);
void fdelete(); if(!file_entry || !file_entry->fileops || !file_entry->fileops->delete){
return 0;
// 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);
} }
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){ int fread(vfile_t *file_entry, void *byte_array, uint32_t offset, uint32_t count){
switch(file_entry->type){ if(!file_entry || !file_entry->fileops || !file_entry->fileops->read || !byte_array || count == 0){
case VFILE_DIRECTORY: return 0;
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);
} }
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){ //fopen but relative to *dir
vfile_t **dir_data = (vfile_t **)dir.access.data.ptr; vfile_t *rfopen(char *name, vfile_t *dir){
uint32_t i = 0; if(!dir || !name || !dir->fileops || !dir->fileops->rfopen){
while(dir_data[i]){ return 0;
if(!strcmp(dir_data[i]->name, name)){
return dir_data[i];
}
i++;
} }
return dir->fileops->rfopen(name, dir);
}
int readdir(vfile_t* file, vfile_t* buffer, uint32_t offset, uint32_t count){
return 0; return 0;
} }
vfile_t *fget_file(char *name){ vfile_t *fopen(char *name){
if(name[0] == '/'){ if(!name){
if(strlen(name) == 1){ return 0;
return &root_dir;
}
name++;
} }
if(name[strlen(name) - 1] == '/'){ vfile_t *root = get_root_dir();
name[strlen(name) - 1] = 0; if(!strcmp(name, "/")){
return root;
} }
// printf("%s\n", name); return root->fileops->rfopen(name + (name[0] == '/'), root);
char *dir = strtok(name, '/'); }
// printf("%s", name);
char *tmp = dir; vfile_t *fclose(vfile_t *file){
uint32_t filename_offset = 0; if(!file || !file->fileops || !file->fileops->close);
vfile_t *current_dir = &root_dir; file->fileops->close(file);
vfile_t *tmpfile = 0; return 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;
} }

View File

@ -1,87 +1,59 @@
#pragma once #pragma once
#include <stdint.h> #include <stdint.h>
#include "../shared/spinlock.h"
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;
typedef enum fs_flags{ typedef enum fs_flags{
FS_FILE_READ_ONLY = 1, FS_FILE_READ_ONLY = 1,
FS_FILE_HIDDEN = 2, FS_FILE_HIDDEN = 2,
FS_FILE_SYSTEM = 4, FS_FILE_SYSTEM = 4,
FS_FILE_IS_DIR = 0x10, 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; }FS_FILE_FLAGS;
typedef struct mount_funcs{ typedef struct fileops{
int (*write)(vfile_t *file, void *data, uint32_t offset, uint32_t count); struct virtual_file *(*create)(struct virtual_file *parent, char *path, FS_FILE_FLAGS flags);
int (*read)(vfile_t *file, void *data, uint32_t offset, uint32_t count); int (*delete)(struct virtual_file *file_entry);
int (*open)(char *filename, vfile_t *file); int (*write)(struct virtual_file *file_entry, void *data, uint32_t offset, uint32_t count);
void (*delete)(vfile_t *file); int (*read)(struct virtual_file *file_entry, void *data, uint32_t offset, uint32_t count);
void (*create)(char *filename, FS_FILE_FLAGS flags); // struct virtual_file *(*open)(char *path);
}mount_t; 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{ //note: this is EXACTLY 256 bytes. This is for simplicity's sake.
uint8_t attributes; //PLEASE if you MUST reorganize or add fields, try and keep it to a power of 2?
uint8_t chs_start[3]; typedef struct virtual_file{
uint8_t type; char name[212];
uint8_t chs_end[3]; uint16_t flags;
uint32_t lba_start; fileops_t *fileops;
uint32_t lba_size; uint32_t refcount; //filesystem MUST remain operational until all child refcounts == 0
}__attribute__((packed))partition_t;
#define MBR_MAGIC 0xaa55 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
typedef struct mbr{ uint8_t owner_uid;
char code[440]; uint8_t owner_gid;
char id[4]; uint32_t last_modified;
char res[2]; uint32_t created;
partition_t partitions[4]; uint16_t permissions; //same format as linux
uint16_t magic; spinlock_t lock;
}__attribute__((packed)) mbr_t; }vfile_t;
void vfs_init(); 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 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); int fread(vfile_t *file_entry, void *byte_array, uint32_t offset, uint32_t count);
vfile_t *search_dir(char *name, vfile_t dir); // int readdir(vfile_t* file, vfile_t *buffer, uint32_t offset, uint32_t count);
vfile_t *fget_file(char *name);
// void vfs_del_mount_handler(uint32_t key); vfile_t *vfcreate(vfile_t *parent, char *relpath, FS_FILE_FLAGS flags);
// void vfs_add_mount_handler(int (*mount_handler)(vfile_t *device, MOUNT_OPERATION op, ...), uint32_t key); vfile_t *rfopen(char *name, vfile_t *dir);
void vfs_detect_partitions(vfile_t *file); vfile_t *fclose(vfile_t *);
vfile_t *fopen(char *path);

View File

@ -8,6 +8,17 @@
KOS_MAPI_FP api; 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: TODO:
Register module 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; if (count == 0) return -1;
ata_acquire_primary_lock(); 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 io_base = drive.BARs[0] &0xfffe;
uint16_t ctrl_base = drive.BARs[1] &0xfffe; uint16_t ctrl_base = drive.BARs[1] &0xfffe;
uint16_t bm_base = drive.BARs[4] & ~3; 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"); asm("sti");
transferring_disk_index = file->mount_id; transferring_disk_index = file->id;
uint8_t status = inb(ctrl_base); uint8_t status = inb(ctrl_base);
uint8_t bm_status = inb(bm_base + 2); 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) { int ata_read(vfile_t *file, uint8_t *ptr, uint32_t offset, uint32_t count) {
if (count == 0) return -1; 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 io_base = drive.BARs[0] &0xfffe;
uint16_t ctrl_base = drive.BARs[1] &0xfffe; uint16_t ctrl_base = drive.BARs[1] &0xfffe;
uint16_t bm_base = drive.BARs[4] & ~3; 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; recieved_ints = 0;
asm("cli"); asm("cli");
transferring_disk_index = file->mount_id; transferring_disk_index = file->id;
uint32_t cpid = api(MODULE_API_GET_CPID); uint32_t cpid = api(MODULE_API_GET_CPID);
// api(MODULE_API_PRINT, MODULE_NAME, "Cpid: %x", cpid); // api(MODULE_API_PRINT, MODULE_NAME, "Cpid: %x", cpid);
api(MODULE_API_BLOCK_PID, cpid); api(MODULE_API_BLOCK_PID, cpid);
transferring_pid = cpid; transferring_pid = cpid;
outb(bm_base, 0x09); 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 status = inb(ctrl_base);
uint8_t bm_status = inb(bm_base + 2); 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); uint32_t prdt_phys = api(MODULE_API_PMALLOC64K);
drives[index].PRDT = (void *)api(MODULE_API_KMALLOC_PADDR, prdt_phys, 16); drives[index].PRDT = (void *)api(MODULE_API_KMALLOC_PADDR, prdt_phys, 16);
itoa(ata_drives, fname + strlen(fname), 10); itoa(ata_drives, fname + strlen(fname), 10);
vfile_t *new_file = fcreate(api, fname, VFILE_DEVICE, ata_write, ata_read); vfile_t *new_file = fcreate(api, fname, FS_FILE_SYSTEM);
new_file->mount_id = index; 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"); puts(api, "KIDM", "Valid Drive!\n");
return 0; 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, 15, module_data.key, int_handler);
api(MODULE_API_ADDINT, 14, 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); // api(MODULE_API_ADDINT, 0, module_data.key, int_handler);
vfile_t *pci_drive_dir = fget_file(api, "/dev/pci/disk/"); vfile_t *pci_drive_dir = fopen(api, "/dev/pci/disk");
vfile_t **dir_data = (pci_drive_dir->access.data.ptr); if(!pci_drive_dir){
for(uint32_t i = 0; dir_data[i]; i++){ puts(api, MODULE_NAME, "Failed to open /dev/pci/disk\n");
vfile_t *current_file = dir_data[i]; 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; uint32_t class = 0;
fread(api, current_file, &class, 0x8, 1); fread(api, current_file, &class, 0x8, 1);
uint32_t progif = class >> 8 & 0xff; uint32_t progif = class >> 8 & 0xff;

View File

@ -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){ uint32_t fat32_mount(vfile_t *dev_file, char *destination, uint32_t offset){
char *bpb_buffer = malloc(api, 1); // char *bpb_buffer = malloc(api, 1);
fread(api, dev_file, bpb_buffer, offset, 4096); // fread(api, dev_file, bpb_buffer, offset, 4096);
fat32_bpb_t *bpb = bpb_buffer; // 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); // 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)){ // if(!fat32_check_valid(bpb)){
api(MODULE_API_PRINT, MODULE_NAME, "Error: No valid BPB\n"); // api(MODULE_API_PRINT, MODULE_NAME, "Error: No valid BPB\n");
return 0; // return 0;
} // }
puts(api, MODULE_NAME, "Valid BPB found!\n"); // puts(api, MODULE_NAME, "Valid BPB found!\n");
// fat32_make_mount(); // 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"); 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); int32_t status = api(MODULE_API_REGISTER, &module_data);
api(MODULE_MESSAGE_HANDLER, module_data.key, message_handler); // api(MODULE_MESSAGE_HANDLER, module_data.key, message_handler);
api(MODULE_API_PRINT, MODULE_NAME, "Key: %x\n", module_data.key); // api(MODULE_API_PRINT, MODULE_NAME, "Key: %x\n", module_data.key);
return; return;
} }

View File

@ -1,5 +1,6 @@
#pragma once #pragma once
#include <stdint.h> #include <stdint.h>
#include "../kernel/shared/spinlock.h"
enum MODULE_API_FUNCS{ enum MODULE_API_FUNCS{
@ -53,34 +54,47 @@ enum MESSAGES{
MESSAGE_BROADCAST = 0x80000000, //placeholder MESSAGE_BROADCAST = 0x80000000, //placeholder
}; };
typedef enum vfile_type{ typedef enum fs_flags{
VFILE_NULL, FS_FILE_READ_ONLY = 1,
VFILE_POINTER, FS_FILE_HIDDEN = 2,
VFILE_DEVICE, FS_FILE_SYSTEM = 4,
VFILE_MOUNT, FS_FILE_IS_DIR = 0x10,
VFILE_DIRECTORY, FS_FILE_ARCHIVE = 0x20,
VFILE_PDIR,//used for directories in physical filesystems. FS_FILE_PIPE = 0x40,
VFILE_FILE, FS_FILE_LINK = 0x80,
}VFILE_TYPE; 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{ typedef struct virtual_file{
char name[20]; char name[212];
VFILE_TYPE type; uint16_t flags;
uint32_t id;//to be assigned by driver; fileops_t *fileops;
uint32_t mount_id; uint32_t refcount; //filesystem MUST remain operational until all child refcounts == 0
uint8_t lock;
uint32_t size; uint32_t id;//for use in drivers
struct virtual_file *parent;//should point to A: a virtual directory, or B: a mounted filesystem void *private; //also for use in drivers
union{ uint32_t size; //should be in bytes
struct{ uint32_t offset; //for use in drivers
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); uint8_t owner_uid;
}funcs; uint8_t owner_gid;
struct{ uint32_t last_modified;
void *ptr; uint32_t created;
uint32_t size_pgs; uint16_t permissions; //same format as linux
}__attribute__((packed))data; spinlock_t lock;
}access;
}vfile_t; }vfile_t;
inline void *malloc(KOS_MAPI_FP api, uint32_t size_pages){ 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); api(MODULE_API_FREE, ptr);
return 0; 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); // vfile_t *file = malloc(api, 1);
return (void *)api(MODULE_API_OPEN, filename); 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); return api(MODULE_API_WRITE, file, buffer, offset, count);
} }
//read documenation for this one //read documenation for this one
inline vfile_t *fcreate(KOS_MAPI_FP api, char *filename, VFILE_TYPE type, char *pointer_write, char *size_read){ inline vfile_t *fcreate(KOS_MAPI_FP api, char *filename, FS_FILE_FLAGS type){
return (void *)api(MODULE_API_CREAT, filename, type, pointer_write, size_read); return (void *)api(MODULE_API_CREAT, filename, type);
} }
inline void puts(KOS_MAPI_FP api, char *mname, char *str){ inline void puts(KOS_MAPI_FP api, char *mname, char *str){
api(MODULE_API_PRINT, mname, str); api(MODULE_API_PRINT, mname, str);