Merge branch 'vfs-dev'
This commit is contained in:
commit
eecdfcb8bb
|
|
@ -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/
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -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];
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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")){
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -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);
|
||||
|
|
@ -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++;
|
||||
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;
|
||||
}
|
||||
|
||||
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;
|
||||
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);
|
||||
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;
|
||||
|
||||
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);
|
||||
vfile_t *new_file = 0;
|
||||
|
||||
subpath_start = name_index;
|
||||
while(name[name_index] && name[name_index] != '/'){//split the string at directories
|
||||
name_index++;
|
||||
}
|
||||
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;
|
||||
break;
|
||||
}
|
||||
filename_offset += strlen(tmp) + 1;
|
||||
tmp = strtok(0, '/');
|
||||
new_file = vfcreate(new_parent, name+name_index+1, flags);
|
||||
// fclose(new_parent);
|
||||
}
|
||||
return 0;
|
||||
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;
|
||||
}
|
||||
|
|
@ -1,87 +1,59 @@
|
|||
#pragma once
|
||||
#include <stdint.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;
|
||||
|
||||
#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;
|
||||
//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
|
||||
|
||||
#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{
|
||||
char code[440];
|
||||
char id[4];
|
||||
char res[2];
|
||||
partition_t partitions[4];
|
||||
uint16_t magic;
|
||||
}__attribute__((packed)) mbr_t;
|
||||
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);
|
||||
// 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);
|
||||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -1,5 +1,6 @@
|
|||
#pragma once
|
||||
#include <stdint.h>
|
||||
#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);
|
||||
|
|
|
|||
Loading…
Reference in New Issue