vfs - kinda good vfs implementation

This commit is contained in:
RaphProductions 2025-05-16 20:53:35 +02:00
parent cfc9159ad9
commit 1e84bcedc9
13 changed files with 3650 additions and 12 deletions

56
kernel/src/dbg/sym.c Normal file
View file

@ -0,0 +1,56 @@
#include "dbg/sym.h"
#include "exec/elf.h"
#include "limine.h"
#include "sys/errhnd/panic.h"
#include "sys/log.h"
#include <lib/string.h>
#include <mm/liballoc/liballoc.h>
static Elf64_Sym *__ksym_symtab;
static char *__ksym_strtab;
static int __ksym_symcount = 0;
__attribute__((used, section(".limine_requests"))) static volatile struct
limine_executable_file_request exec_file_rq = {
.id = LIMINE_EXECUTABLE_FILE_REQUEST, .revision = 3};
void ksym_init() {
char *img = exec_file_rq.response->executable_file->address;
Elf64_Ehdr *ehdr = (Elf64_Ehdr *)img;
if (ehdr->e_ident[EI_MAG0] != ELFMAG0 || ehdr->e_ident[EI_MAG1] != ELFMAG1 ||
ehdr->e_ident[EI_MAG2] != ELFMAG2 || ehdr->e_ident[EI_MAG3] != ELFMAG3) {
panic("kernel - how did i even boot? *starts galaxy brain meme*");
}
Elf64_Shdr *shdr = (Elf64_Shdr *)(img + ehdr->e_shoff);
const char *shstrtab = (char *)img + shdr[ehdr->e_shstrndx].sh_offset;
for (int j = 0; j < ehdr->e_shnum; j++) {
if (shdr[j].sh_type == SHT_SYMTAB) {
__ksym_symtab = (Elf64_Sym *)(img + shdr[j].sh_offset);
__ksym_symcount = shdr[j].sh_size / shdr[j].sh_entsize;
} else if (shdr[j].sh_type == SHT_STRTAB &&
strcmp(shstrtab + shdr[j].sh_name, ".strtab") == 0) {
__ksym_strtab = (char *)(img + shdr[j].sh_offset);
}
}
log("kernel - loaded %d symbols\n", __ksym_symcount);
}
func *ksym_fromip(uint64_t ip) {
for (int i = 0; i < __ksym_symcount; i++) {
uint64_t value = __ksym_symtab[i].st_value;
uint64_t size = __ksym_symtab[i].st_size;
if (value <= ip && ip < (value + size)) {
func *f = malloc(sizeof(func));
f->base = value;
f->ip = ip;
f->name = (__ksym_strtab + __ksym_symtab[i].st_name);
return f;
}
}
return NULL;
}

12
kernel/src/dbg/sym.h Normal file
View file

@ -0,0 +1,12 @@
#pragma once
#include "mm/vmm.h"
typedef struct func {
uint64_t base;
uint64_t ip;
char *name;
} func;
void ksym_init();
func *ksym_fromip(uint64_t ip);

View file

@ -122,4 +122,32 @@ typedef struct {
Elf64_Ehdr *ehdr;
} elf_program_t;
program_t *elf_load(char *data, int user);
program_t *elf_load(char *data, int user);
// Those aren't used for loading, but used by
// the kernel to resolve symbols from an instruction
// pointer.
#define SHT_SYMTAB 2
#define SHT_STRTAB 3
typedef struct {
uint32_t st_name;
unsigned char st_info;
unsigned char st_other;
uint16_t st_shndx;
Elf64_Addr st_value;
uint64_t st_size;
} Elf64_Sym;
typedef struct {
uint32_t sh_name;
uint32_t sh_type;
uint64_t sh_flags;
Elf64_Addr sh_addr;
Elf64_Off sh_offset;
uint64_t sh_size;
uint32_t sh_link;
uint32_t sh_info;
uint64_t sh_addralign;
uint64_t sh_entsize;
} Elf64_Shdr;

101
kernel/src/fs/hellofs.c Normal file
View file

@ -0,0 +1,101 @@
#include "fs/hellofs.h"
#include "fs/vfs.h"
#include <mm/liballoc/liballoc.h>
#include <mm/memop.h>
#include <lib/string.h>
static int hellofs_read(vnode_t *vn, void *buf, size_t off, size_t size) {
if (!vn || !buf || size <= 0) {
return -1;
}
const char *hello = "hello";
const size_t hello_len = 5; // strlen("hello")
char *cbuf = (char *)buf;
size_t bytes_written = 0;
while (bytes_written < size) {
size_t pos = off % hello_len; // Position within "hello"
size_t remaining = hello_len - pos; // Remaining bytes in current "hello"
size_t to_copy = (size - bytes_written < remaining) ?
(size - bytes_written) : remaining;
memcpy(cbuf + bytes_written, hello + pos, to_copy);
bytes_written += to_copy;
off += to_copy;
}
return bytes_written;
}
vnode_ops_t hellofs_hello_ops = {
.read = hellofs_read,
.lookup = NULL,
};
static int hellofs_lookup(vnode_t *vn, const char *name, vnode_t **out) {
if (!vn || !name || !out) {
return -1;
}
if (strcmp(name, "hello") == 0) {
*out = vfs_create_node("hello", VN_FILE);
if (*out) {
(*out)->ops = &hellofs_hello_ops;
return 0;
}
return -1;
} else {
*out = NULL; // Not found
return -1;
}
}
vnode_ops_t hellofs_root_ops = {
.read = NULL,
.lookup = hellofs_lookup,
};
static int hellofs_mount(fs_t *fs, vnode_t *mountpoint) {
if (!fs || !mountpoint) {
return -1;
}
// mountpoint list isn't implemented.
/*mountpoint_t *mp = (mountpoint_t *)malloc(sizeof(mountpoint_t));
if (!mp) {
return -1;
}
memset(mp, 0, sizeof(mountpoint_t));
strncpy(mp->name, fs->name, sizeof(mp->name) - 1);
mp->fs = fs;
mp->mountpoint = mountpoint;*/
// Mounting is essentially just putting the file system's root directory operations
// on the mountpoint vnode.
mountpoint->ops = &hellofs_root_ops;
return 0;
}
fs_t *hellofs_init() {
fs_t *fs = (fs_t *)malloc(sizeof(fs_t));
if (!fs) {
return NULL;
}
memset(fs, 0, sizeof(fs_t));
strncpy(fs->name, "hellofs", sizeof(fs->name) - 1);
fs->mount = hellofs_mount;
fs->root = vfs_create_node("/", VN_DIR);
if (!fs->root) {
free(fs);
return NULL;
}
return fs;
}

5
kernel/src/fs/hellofs.h Normal file
View file

@ -0,0 +1,5 @@
#pragma once
#include <fs/vfs.h>
fs_t *hellofs_init(void);

View file

@ -2,6 +2,99 @@
#include "lib/string.h"
#include "mm/liballoc/liballoc.h"
#include "mm/memop.h"
#include "sys/errhnd/panic.h"
vnode_t *root = NULL;
void vfs_init() {
root = vfs_create_node("/", VN_DIR);
if (!root) {
panic("vfs - failed to create root node");
}
root->parent = root; // Root's parent is itself
}
// Not worth adding to the header, since it should only lookup
// for files/directories in dir, without going deeper.
int vfs_lookup(vnode_t *dir, const char *name, vnode_t **out) {
if (!dir || !name)
return -1;
if (dir->ops && dir->ops->lookup) {
return dir->ops->lookup(dir, name, out);
}
return -1;
}
int vfs_open(vnode_t *curdir, const char *path, vnode_t **out) {
if (strcmp(path, ".") == 0) {
*out = curdir;
return 0;
}
if (strcmp(path, "..") == 0) {
*out = curdir->parent;
return 0;
}
char *path_copy = strdup(path);
if (!path_copy) {
*out = NULL;
return -1;
}
vnode_t *cur_node = path[0] == '/' ? root : curdir;
char *token = strtok(path_copy, "/");
while (token) {
vnode_t *next;
vfs_lookup(cur_node, token, &next);
if (!next) {
free(path_copy);
*out = NULL;
return -1;
}
cur_node = next;
token = strtok(NULL, "/");
}
free(path_copy);
*out = cur_node;
return 0;
}
int vfs_mount(char *path, fs_t *fs) {
if (!fs || !path) {
return -1;
}
vnode_t *mp;
if (strcmp(path, "/") == 0) {
mp = root;
} else {
vfs_open(root, path, &mp);
}
if (fs->mount == NULL)
return -1; // why allocating a fs without the capability to mount to a node? lmao
return fs->mount(fs, mp);
}
int vfs_unmount(char *path) {
(void)path;
return -1;
}
int vfs_read(vnode_t *vn, void *buf, size_t off, size_t size) {
if (!vn || !buf || off < 0 || size <= 0) {
return -1;
}
if (vn->ops && vn->ops->read) {
return vn->ops->read(vn, buf, off, size);
}
return -1;
}
vnode_t *vfs_create_node(char *name, vnode_type_t type) {
vnode_t *node = (vnode_t *)malloc(sizeof(vnode_t));

View file

@ -12,14 +12,14 @@ typedef uint32_t vnode_type_t;
typedef struct vnode_ops {
int (*read)(struct vnode *vn, void *buf, size_t off, size_t size);
struct vnode *(*lookup)(struct vnode *vn, const char *name);
int (*lookup)(struct vnode *vn, const char *name, struct vnode **out);
} vnode_ops_t;
typedef struct vnode {
char name[256];
vnode_type_t type;
uint32_t refcount;
// struct vnode* parent;
struct vnode* parent; // If this vnode exists, then it's parent too.
// struct vnode* child;
// struct vnode* next;
@ -36,11 +36,12 @@ typedef struct mountpoint {
typedef struct fs {
char name[32];
struct vnode *root;
int (*mount)(struct vnode *mountpoint);
int (*mount)(struct fs *fs, struct vnode *mountpoint);
} fs_t;
void vfs_init(void);
int vfs_mount(char *path, fs_t *fs);
int vfs_unmount(char *path);
int vfs_open(const char *path, vnode_t **result);
int vfs_open(vnode_t *curdir, const char *path, vnode_t **out);
int vfs_read(vnode_t *vn, void *buf, size_t off, size_t size);
vnode_t *vfs_create_node(char *name, vnode_type_t type);

View file

@ -1,7 +1,10 @@
#include <lib/string.h>
#include <mm/liballoc/liballoc.h>
#include <mm/memop.h>
#include <stddef.h>
static char *olds;
int strlen(const char *str) {
int len = 0;
while (str[len])
@ -78,3 +81,54 @@ char *strncpy(char *dest, const char *src, size_t n) {
dest[i] = '\0';
return dest;
}
#define DICT_LEN 256
static int *create_delim_dict(char *delim) {
int *d = (int *)malloc(sizeof(int) * DICT_LEN);
memset((void *)d, 0, sizeof(int) * DICT_LEN);
int i;
for (i = 0; i < strlen(delim); i++) {
d[delim[i]] = 1;
}
return d;
}
char *strtok(char *str, char *delim) {
static char *last, *to_free;
int *deli_dict = create_delim_dict(delim);
if (!deli_dict) {
return NULL;
}
if (str) {
last = (char *)malloc(strlen(str) + 1);
if (!last) {
free(deli_dict);
}
to_free = last;
strcpy(last, str);
}
while (deli_dict[*last] && *last != '\0') {
last++;
}
str = last;
if (*last == '\0') {
free(deli_dict);
free(to_free);
return NULL;
}
while (*last != '\0' && !deli_dict[*last]) {
last++;
}
*last = '\0';
last++;
free(deli_dict);
return str;
}

View file

@ -8,4 +8,5 @@ char *strcpy(char *dest, const char *src);
char *strrchr(const char *s, int c);
int oct2bin(unsigned char *str, int size);
char *strdup(const char *str);
char *strncpy(char *dest, const char *src, size_t n);
char *strncpy(char *dest, const char *src, size_t n);
char *strtok(char *str, char *delim);

View file

@ -1,10 +1,12 @@
#include "arch/x86_64/pit.h"
#include "arch/x86_64/smp.h"
#include "arch/x86_64/sse.h"
#include "dbg/sym.h"
#include "dev/ioapic.h"
#include "dev/lapic.h"
#include "exec/elf.h"
#include "exec/exec.h"
#include "fs/hellofs.h"
#include "mm/liballoc/liballoc.h"
#include "mm/pmm.h"
#include "mm/vma.h"
@ -57,10 +59,6 @@ struct flanterm_context *ft_ctx;
char kstack[8192];
void test3() { *((uint8_t*)0x0) = (uint8_t)0xFF; }
void test2() { test3();}
void test1() { test2(); }
void __kmain(void) {
if (framebuffer_request.response != NULL) {
@ -92,6 +90,14 @@ void __kmain(void) {
asm("hlt");
}
ksym_init();
func *f = ksym_fromip((uint64_t)__kmain);
if (f) {
log("ksym: found %s at %p\n", f->name, f->ip);
} else {
log("ksym: not found\n");
}
acpi_init();
madt_init();
ioapic_init();
@ -99,9 +105,22 @@ void __kmain(void) {
pit_init();
smp_init();
vfs_init();
fs_t *hellofs = hellofs_init();
vfs_mount("/", hellofs);
vnode_t *vn;
vfs_open(NULL, "/hello", &vn);
if (vn) {
char buf[100];
vfs_read(vn, buf, 2, sizeof(buf));
log("Read from /hello: %s\n", buf);
} else {
log("Failed to open /hello\n");
}
syscall_init();
sched_init();
test1();
// vfs_init();

View file

@ -15,7 +15,7 @@ __attribute__((
.revision = 3,
.mode = LIMINE_PAGING_MODE_X86_64_4LVL};
__attribute__((used, section(".limine_requests"))) static volatile struct
__attribute__((used, section(".limine_requests"))) volatile struct
limine_executable_address_request karq = {
.id = LIMINE_EXECUTABLE_ADDRESS_REQUEST,
.revision = 0,