FEAT: VFS overhaul

This commit is contained in:
boreddevnl
2026-04-12 17:53:31 +02:00
parent 921e8a5658
commit 700839e6be
48 changed files with 1897 additions and 482 deletions

View File

@@ -0,0 +1,73 @@
#include "kernel_subsystem.h"
#include "memory_manager.h"
#include "spinlock.h"
static kernel_subsystem_t subsystems[MAX_SUBSYSTEMS];
static int subsystem_count = 0;
static spinlock_t sub_lock = SPINLOCK_INIT;
extern void mem_memset(void *dest, int val, size_t len);
extern void mem_memcpy(void *dest, const void *src, size_t len);
static void sub_strcpy(char *dest, const char *src) {
while (*src) *dest++ = *src++;
*dest = 0;
}
static int sub_strcmp(const char *a, const char *b) {
while (*a && *a == *b) { a++; b++; }
return (unsigned char)*a - (unsigned char)*b;
}
void subsystem_register(const char *name, kernel_subsystem_t **out_sub) {
uint64_t flags = spinlock_acquire_irqsave(&sub_lock);
if (subsystem_count >= MAX_SUBSYSTEMS) {
spinlock_release_irqrestore(&sub_lock, flags);
if (out_sub) *out_sub = NULL;
return;
}
// Check if already exists
for (int i = 0; i < subsystem_count; i++) {
if (sub_strcmp(subsystems[i].name, name) == 0) {
spinlock_release_irqrestore(&sub_lock, flags);
if (out_sub) *out_sub = &subsystems[i];
return;
}
}
kernel_subsystem_t *s = &subsystems[subsystem_count++];
mem_memset(s, 0, sizeof(kernel_subsystem_t));
sub_strcpy(s->name, name);
spinlock_release_irqrestore(&sub_lock, flags);
if (out_sub) *out_sub = s;
}
void subsystem_add_file(kernel_subsystem_t *sub, const char *name,
int (*read)(char*, int, int),
int (*write)(const char*, int, int)) {
if (!sub || sub->file_count >= MAX_SUBSYSTEM_FILES) return;
subsystem_file_t *f = &sub->files[sub->file_count++];
sub_strcpy(f->name, name);
f->read = read;
f->write = write;
}
kernel_subsystem_t* subsystem_get_by_name(const char *name) {
for (int i = 0; i < subsystem_count; i++) {
if (sub_strcmp(subsystems[i].name, name) == 0) return &subsystems[i];
}
return NULL;
}
int subsystem_get_count(void) {
return subsystem_count;
}
kernel_subsystem_t* subsystem_get_by_index(int index) {
if (index < 0 || index >= subsystem_count) return NULL;
return &subsystems[index];
}

View File

@@ -0,0 +1,32 @@
#ifndef KERNEL_SUBSYSTEM_H
#define KERNEL_SUBSYSTEM_H
#include <stdint.h>
#include <stdbool.h>
#include <stddef.h>
#define MAX_SUBSYSTEMS 16
#define MAX_SUBSYSTEM_FILES 32
typedef struct {
char name[64];
int (*read)(char *buffer, int size, int offset);
int (*write)(const char *buffer, int size, int offset);
} subsystem_file_t;
typedef struct {
char name[64];
subsystem_file_t files[MAX_SUBSYSTEM_FILES];
int file_count;
} kernel_subsystem_t;
void subsystem_register(const char *name, kernel_subsystem_t **out_sub);
void subsystem_add_file(kernel_subsystem_t *sub, const char *name,
int (*read)(char*, int, int),
int (*write)(const char*, int, int));
kernel_subsystem_t* subsystem_get_by_name(const char *name);
int subsystem_get_count(void);
kernel_subsystem_t* subsystem_get_by_index(int index);
#endif

29
src/sys/module_manager.c Normal file
View File

@@ -0,0 +1,29 @@
#include "module_manager.h"
#include "memory_manager.h"
#define MAX_MODULES 32
static kernel_module_t modules[MAX_MODULES];
static int module_count = 0;
static void mod_strcpy(char *dest, const char *src) {
while (*src) *dest++ = *src++;
*dest = 0;
}
void module_manager_register(const char *name, uint64_t addr, uint64_t size) {
if (module_count >= MAX_MODULES) return;
kernel_module_t *m = &modules[module_count++];
mod_strcpy(m->name, name);
m->address = addr;
m->size = size;
}
int module_manager_get_count(void) {
return module_count;
}
kernel_module_t* module_manager_get_index(int index) {
if (index < 0 || index >= module_count) return NULL;
return &modules[index];
}

17
src/sys/module_manager.h Normal file
View File

@@ -0,0 +1,17 @@
#ifndef MODULE_MANAGER_H
#define MODULE_MANAGER_H
#include <stdint.h>
#include <stddef.h>
typedef struct {
char name[64];
uint64_t address;
uint64_t size;
} kernel_module_t;
void module_manager_register(const char *name, uint64_t addr, uint64_t size);
int module_manager_get_count(void);
kernel_module_t* module_manager_get_index(int index);
#endif

View File

@@ -20,7 +20,6 @@ extern void serial_write(const char *str);
#define MAX_PROCESSES 16
#define MAX_CPUS_SCHED 32
process_t processes[MAX_PROCESSES] __attribute__((aligned(16)));
int process_count = 0;
static process_t* current_process[MAX_CPUS_SCHED] = {0}; // Per-CPU
static uint32_t next_pid = 0;
static void *free_kernel_stack_later[MAX_CPUS_SCHED] = {0};
@@ -34,9 +33,10 @@ void process_init(void) {
}
// Current kernel execution is PID 0
process_t *kernel_proc = &processes[process_count++];
process_t *kernel_proc = &processes[0];
kernel_proc->pid = next_pid++;
kernel_proc->is_user = false;
kernel_proc->is_idle = true;
// We don't have its RSP or PML4 yet, but it's already running.
// The timer interrupt will naturally capture its context on the first tick!
@@ -55,21 +55,39 @@ void process_init(void) {
kernel_proc->next = kernel_proc; // Circular linked list
kernel_proc->cpu_affinity = 0; // Kernel always on BSP
mem_memset(kernel_proc->cwd, 0, 1024);
kernel_proc->cwd[0] = '/';
current_process[0] = kernel_proc;
}
process_t* process_create(void (*entry_point)(void), bool is_user) {
uint64_t rflags = spinlock_acquire_irqsave(&runqueue_lock);
if (process_count >= MAX_PROCESSES) {
process_t *new_proc = NULL;
for (int i = 0; i < MAX_PROCESSES; i++) {
if (processes[i].pid == 0xFFFFFFFF) {
new_proc = &processes[i];
break;
}
}
if (!new_proc) {
spinlock_release_irqrestore(&runqueue_lock, rflags);
return NULL;
}
process_t *new_proc = &processes[process_count++];
new_proc->pid = next_pid++;
new_proc->is_user = is_user;
process_t *parent = process_get_current();
if (parent) {
extern void mem_memcpy(void *dest, const void *src, size_t len);
mem_memcpy(new_proc->cwd, parent->cwd, 1024);
} else {
mem_memset(new_proc->cwd, 0, 1024);
new_proc->cwd[0] = '/';
}
// 1. Setup Page Table
if (is_user) {
new_proc->pml4_phys = paging_create_user_pml4_phys();
@@ -163,9 +181,8 @@ process_t* process_create_elf(const char* filepath, const char* args_str) {
// Find an available slot
for (int i = 0; i < MAX_PROCESSES; i++) {
if (processes[i].pid == 0xFFFFFFFF || i >= process_count) {
if (processes[i].pid == 0xFFFFFFFF) {
new_proc = &processes[i];
if (i >= process_count) process_count = i + 1;
break;
}
}

View File

@@ -52,7 +52,9 @@ typedef struct process {
uint64_t ticks;
uint64_t sleep_until;
size_t used_memory;
uint32_t cpu_affinity; // Which CPU this process runs on (0 = BSP)
uint32_t cpu_affinity;
bool is_idle;
char cwd[1024];
} __attribute__((aligned(16))) process_t;
typedef struct {
@@ -60,6 +62,7 @@ typedef struct {
char name[64];
uint64_t ticks;
size_t used_memory;
bool is_idle;
} ProcessInfo;
void process_init(void);
@@ -73,7 +76,7 @@ uint64_t process_terminate_current(void);
void process_terminate(process_t *proc);
process_t* process_get_by_pid(uint32_t pid);
// SMP: IPI handler for AP scheduling (called from ISR)
// SMP: IPI handler for AP scheduling
uint64_t sched_ipi_handler(registers_t *regs);
void process_push_gui_event(process_t *proc, gui_event_t *ev);

View File

@@ -10,6 +10,7 @@
#include "paging.h"
#include "process.h"
#include "work_queue.h"
#include "core/kutils.h"
extern void serial_write(const char *str);
extern void serial_write_num(uint32_t n);
@@ -108,6 +109,11 @@ static void ap_entry(struct limine_smp_info *info) {
process_t *ap_idle = process_create(NULL, false);
ap_idle->cpu_affinity = my_id;
ap_idle->is_idle = true;
k_strcpy(ap_idle->name, "idle:");
char id_s[8]; k_itoa(my_id, id_s);
k_strcpy(ap_idle->name + 5, id_s);
process_set_current_for_cpu(my_id, ap_idle);
asm volatile("sti");

View File

@@ -861,6 +861,8 @@ static uint64_t syscall_handler_inner(registers_t *regs) {
const char *mode = (const char *)arg3;
if (!path || !mode) return -1;
// vfs_open now handles normalization internally with process_get_current()
// but let's be explicit if we can.
vfs_file_t *vf = vfs_open(path, mode);
if (!vf) return -1;
@@ -904,12 +906,33 @@ static uint64_t syscall_handler_inner(registers_t *regs) {
int fd = (int)arg2;
if (fd < 0 || fd >= MAX_PROCESS_FDS || !proc->fds[fd]) return -1;
return (uint64_t)vfs_file_size((vfs_file_t*)proc->fds[fd]);
} else if (cmd == FS_CMD_GETCWD) {
char *buf = (char *)arg2;
int size = (int)arg3;
if (!buf || size <= 0) return -1;
int len = (int)k_strlen(proc->cwd);
if (len >= size) return -1;
k_strcpy(buf, proc->cwd);
return (uint64_t)len;
} else if (cmd == FS_CMD_CHDIR) {
const char *path = (const char *)arg2;
if (!path) return -1;
char normalized[VFS_MAX_PATH];
vfs_normalize_path(proc->cwd, path, normalized);
if (vfs_is_directory(normalized)) {
k_strcpy(proc->cwd, normalized);
return 0;
}
return -1;
} else if (cmd == FS_CMD_LIST) {
const char *path = (const char *)arg2;
FAT32_FileInfo *u_entries = (FAT32_FileInfo *)arg3;
int max_entries = (int)arg4;
if (!path || !u_entries) return -1;
char normalized[VFS_MAX_PATH];
vfs_normalize_path(proc->cwd, path, normalized);
// Safety cap for kernel allocation
if (max_entries > 256) max_entries = 256;
if (max_entries <= 0) return 0;
@@ -917,7 +940,7 @@ static uint64_t syscall_handler_inner(registers_t *regs) {
vfs_dirent_t *v_entries = (vfs_dirent_t *)kmalloc(sizeof(vfs_dirent_t) * max_entries);
if (!v_entries) return -1;
int count = vfs_list_directory(path, v_entries, max_entries);
int count = vfs_list_directory(normalized, v_entries, max_entries);
if (count > 0) {
for (int i = 0; i < count; i++) {
// Direct copy as layouts are now aligned
@@ -934,14 +957,19 @@ static uint64_t syscall_handler_inner(registers_t *regs) {
} else if (cmd == FS_CMD_DELETE) {
const char *path = (const char *)arg2;
if (!path) return -1;
return vfs_delete(path) ? 0 : -1;
char normalized[VFS_MAX_PATH];
vfs_normalize_path(proc->cwd, path, normalized);
return vfs_delete(normalized) ? 0 : -1;
} else if (cmd == FS_CMD_GET_INFO) {
const char *path = (const char *)arg2;
FAT32_FileInfo *u_info = (FAT32_FileInfo *)arg3;
if (!path || !u_info) return -1;
char normalized[VFS_MAX_PATH];
vfs_normalize_path(proc->cwd, path, normalized);
vfs_dirent_t v_info;
int res = vfs_get_info(path, &v_info);
int res = vfs_get_info(normalized, &v_info);
if (res == 0) {
k_strcpy(u_info->name, v_info.name);
u_info->size = v_info.size;
@@ -1096,15 +1124,6 @@ static uint64_t syscall_handler_inner(registers_t *regs) {
extern void k_beep(int freq, int ms);
k_beep(freq, ms);
return 0;
} else if (cmd == 15) { // SYSTEM_CMD_MEMINFO
uint64_t *out = (uint64_t *)arg2;
if (!out) return -1;
MemStats stats = memory_get_stats();
out[0] = stats.total_memory;
out[1] = stats.used_memory;
return 0;
} else if (cmd == 16) { // SYSTEM_CMD_UPTIME
return wm_get_ticks();
} else if (cmd == 17) { // SYSTEM_CMD_PCI_LIST
typedef struct {
uint16_t vendor;
@@ -1265,54 +1284,7 @@ static uint64_t syscall_handler_inner(registers_t *regs) {
size_t max_len = (size_t)arg3;
extern int network_tcp_recv_nb(void *buf, size_t max_len);
return (uint64_t)network_tcp_recv_nb(buf, max_len);
} else if (cmd == SYSTEM_CMD_PROCESS_LIST) {
ProcessInfo *out = (ProcessInfo *)arg2;
int max_procs = (int)arg3;
if (!out) return 0;
extern process_t processes[];
// Dynamically calculate kernel usage as: Total System Used - User Process Sum
MemStats stats = memory_get_stats();
size_t total_used = stats.used_memory;
size_t user_used = 0;
for (int i = 0; i < 16; i++) {
if (processes[i].pid != 0xFFFFFFFF && processes[i].pid != 0 && processes[i].is_user) {
user_used += processes[i].used_memory;
}
}
if (total_used > user_used) processes[0].used_memory = total_used - user_used;
else processes[0].used_memory = 0;
int count = 0;
for (int i = 0; i < 16; i++) {
if (processes[i].pid != 0xFFFFFFFF && (processes[i].is_user || processes[i].pid == 0)) {
out[count].pid = processes[i].pid;
extern void mem_memcpy(void *dest, const void *src, size_t len);
mem_memcpy(out[count].name, processes[i].name, 64);
if (processes[i].pid == 0) {
out[count].name[0] = 'k'; out[count].name[1] = 'e'; out[count].name[2] = 'r';
out[count].name[3] = 'n'; out[count].name[4] = 'e'; out[count].name[5] = 'l';
out[count].name[6] = '\0';
}
out[count].ticks = processes[i].ticks;
out[count].used_memory = processes[i].used_memory;
count++;
if (count >= max_procs) break;
}
}
return (uint64_t)count;
} else if (cmd == SYSTEM_CMD_GET_CPU_MODEL) {
char *user_buf = (char *)arg2;
if (!user_buf) return -1;
char model[64];
platform_get_cpu_model(model);
extern void mem_memcpy(void *dest, const void *src, size_t len);
mem_memcpy(user_buf, model, 49);
return 0;
return -1;
} else if (cmd == 47) { // SYSTEM_CMD_SET_RESOLUTION
uint16_t req_w = (uint16_t)arg2;
uint16_t req_h = (uint16_t)arg3;
@@ -1351,12 +1323,7 @@ static uint64_t syscall_handler_inner(registers_t *regs) {
return 0;
}
return -1;
} else if (cmd == 49) { // SYSTEM_CMD_GET_OS_INFO
os_info_t *info = (os_info_t *)arg2;
if (!info) return -1;
extern void get_os_info(os_info_t *info);
get_os_info(info);
return 0;
return -1;
} else if (cmd == SYSTEM_CMD_PARALLEL_RUN) {
void (*user_fn)(void*) = (void (*)(void*))arg2;
void **args = (void **)arg3;

View File

@@ -6,7 +6,6 @@
#include <stdint.h>
// Forward declarations
typedef struct Window Window;
typedef struct registers_t registers_t;
@@ -53,11 +52,8 @@ typedef struct {
#define SYSTEM_CMD_SET_RAW_MODE 41
#define SYSTEM_CMD_TCP_RECV_NB 42
#define SYSTEM_CMD_YIELD 43
#define SYSTEM_CMD_PROCESS_LIST 44
#define SYSTEM_CMD_GET_CPU_MODEL 45
#define SYSTEM_CMD_SLEEP 46
#define SYSTEM_CMD_SET_RESOLUTION 47
#define SYSTEM_CMD_GET_OS_INFO 49
#define SYSTEM_CMD_PARALLEL_RUN 50
void syscall_init(void);

201
src/sys/sysfs_init.c Normal file
View File

@@ -0,0 +1,201 @@
#include "kernel_subsystem.h"
#include "smp.h"
#include "pci.h"
#include "memory_manager.h"
#include "module_manager.h"
#include "io.h"
#include "core/kutils.h"
#include "wm/graphics.h"
#include "core/platform.h"
// --- Helper: itoa ---
static void sys_itoa(int n, char *s) {
k_itoa(n, s);
}
// --- Graphics Implementation ---
static int read_gfx_drm(char *buf, int size, int offset) {
char out[512];
k_memset(out, 0, 512);
k_strcpy(out, "Driver: Simple Framebuffer\n");
k_strcpy(out + k_strlen(out), "Resolution: ");
char s[32]; k_itoa(get_screen_width(), s);
k_strcpy(out + k_strlen(out), s);
k_strcpy(out + k_strlen(out), "x");
k_itoa(get_screen_height(), s);
k_strcpy(out + k_strlen(out), s);
k_strcpy(out + k_strlen(out), "\nDepth: ");
k_itoa(graphics_get_fb_bpp(), s);
k_strcpy(out + k_strlen(out), s);
k_strcpy(out + k_strlen(out), " bpp\nAddress: 0x");
k_itoa_hex(graphics_get_fb_addr(), s);
k_strcpy(out + k_strlen(out), s);
k_strcpy(out + k_strlen(out), "\n");
int len = (int)k_strlen(out);
if (offset >= len) return 0;
int to_copy = len - offset;
if (to_copy > size) to_copy = size;
k_memcpy(buf, out + offset, to_copy);
return to_copy;
}
// --- Memory Tracking Implementation ---
static int read_mem_tracking(char *buf, int size, int offset) {
MemStats stats = memory_get_stats();
char out[1024];
k_memset(out, 0, 1024);
k_strcpy(out, "--- Kernel Heap Tracking ---\n");
k_strcpy(out + k_strlen(out), "Allocated Blocks: ");
char s[32]; k_itoa(stats.allocated_blocks, s);
k_strcpy(out + k_strlen(out), s);
k_strcpy(out + k_strlen(out), "\nFragmentation: ");
k_itoa(stats.fragmentation_percent, s);
k_strcpy(out + k_strlen(out), s);
k_strcpy(out + k_strlen(out), "%\n");
int len = (int)k_strlen(out);
if (offset >= len) return 0;
int to_copy = len - offset;
if (to_copy > size) to_copy = size;
k_memcpy(buf, out + offset, to_copy);
return to_copy;
}
// --- Module Implementation ---
static int read_sys_modules(char *buf, int size, int offset) {
int count = module_manager_get_count();
char out[2048] = "Loaded Modules:\n";
for (int i = 0; i < count; i++) {
kernel_module_t *mod = module_manager_get_index(i);
k_strcpy(out + k_strlen(out), " - ");
k_strcpy(out + k_strlen(out), mod->name);
k_strcpy(out + k_strlen(out), " (");
char sz_s[16]; k_itoa(mod->size / 1024, sz_s);
k_strcpy(out + k_strlen(out), sz_s);
k_strcpy(out + k_strlen(out), " KB)\n");
}
int len = k_strlen(out);
if (offset >= len) return 0;
int to_copy = len - offset;
if (to_copy > size) to_copy = size;
k_memcpy(buf, out + offset, to_copy);
return to_copy;
}
// --- PCI Bus Implementation ---
static int read_pci_bus(char *buf, int size, int offset) {
pci_device_t devices[64];
int count = pci_enumerate_devices(devices, 64);
char out[4096];
k_memset(out, 0, 4096);
k_strcpy(out, "PCI Bus Devices:\n");
for (int i = 0; i < count; i++) {
char line[128];
k_strcpy(line, " [");
char b_s[8]; k_itoa(devices[i].bus, b_s);
k_strcpy(line + k_strlen(line), b_s);
k_strcpy(line + k_strlen(line), ":");
k_itoa(devices[i].device, b_s);
k_strcpy(line + k_strlen(line), b_s);
k_strcpy(line + k_strlen(line), ":");
k_itoa(devices[i].function, b_s);
k_strcpy(line + k_strlen(line), b_s);
k_strcpy(line + k_strlen(line), "] Vendor:");
k_itoa_hex(devices[i].vendor_id, b_s);
k_strcpy(line + k_strlen(line), b_s);
k_strcpy(line + k_strlen(line), " Device:");
k_itoa_hex(devices[i].device_id, b_s);
k_strcpy(line + k_strlen(line), b_s);
k_strcpy(line + k_strlen(line), " Class:");
k_itoa_hex(devices[i].class_code, b_s);
k_strcpy(line + k_strlen(line), b_s);
k_strcpy(line + k_strlen(line), "\n");
if (k_strlen(out) + k_strlen(line) < 4095) {
k_strcpy(out + k_strlen(out), line);
}
}
int len = (int)k_strlen(out);
if (offset >= len) return 0;
int to_copy = len - offset;
if (to_copy > size) to_copy = size;
k_memcpy(buf, out + offset, to_copy);
return to_copy;
}
// --- CPU System Implementation ---
static int read_cpu_info(char *buf, int size, int offset) {
char out[1024];
k_memset(out, 0, 1024);
char vendor[16];
platform_get_cpu_vendor(vendor);
k_strcpy(out + k_strlen(out), vendor);
k_strcpy(out + k_strlen(out), "\nCores: ");
char c_s[16]; k_itoa(smp_cpu_count(), c_s);
k_strcpy(out + k_strlen(out), c_s);
k_strcpy(out + k_strlen(out), "\nSpeed: ~3.00 GHz\nFeatures: sse sse2 sse3 apic smp\n");
int len = (int)k_strlen(out);
if (offset >= len) return 0;
int to_copy = len - offset;
if (to_copy > size) to_copy = size;
k_memcpy(buf, out + offset, to_copy);
return to_copy;
}
// --- GPIO Implementation ---
static int read_gpio_debug(char *buf, int size, int offset) {
uint8_t p64 = inb(0x64);
char out[64] = "Port 0x64 Status: ";
char s[16]; k_itoa(p64, s);
k_strcpy(out + k_strlen(out), s);
k_strcpy(out + k_strlen(out), "\n");
int len = k_strlen(out);
if (offset >= len) return 0;
int to_copy = len - offset;
if (to_copy > size) to_copy = size;
k_memcpy(buf, out + offset, to_copy);
return to_copy;
}
void sysfs_init_subsystems(void) {
kernel_subsystem_t *kernel, *devices, *bus, *class, *debug, *mem_debug;
subsystem_register("kernel", &kernel);
subsystem_register("devices", &devices);
subsystem_register("bus", &bus);
subsystem_register("class", &class);
subsystem_register("kernel/debug", &debug);
// CPU info
subsystem_add_file(kernel, "cpuinfo", read_cpu_info, NULL);
// Bus info
kernel_subsystem_t *pci_bus;
subsystem_register("bus/pci", &pci_bus);
subsystem_add_file(pci_bus, "devices", read_pci_bus, NULL);
// Module info
kernel_subsystem_t *modules_sub;
subsystem_register("module", &modules_sub);
subsystem_add_file(modules_sub, "loaded", read_sys_modules, NULL);
// Memory Tracking
subsystem_register("kernel/debug/memory", &mem_debug);
subsystem_add_file(mem_debug, "tracking", read_mem_tracking, NULL);
// Graphics DRM
kernel_subsystem_t *gfx_debug;
subsystem_register("kernel/debug/graphics", &gfx_debug);
subsystem_add_file(gfx_debug, "drm", read_gfx_drm, NULL);
// GPIO
subsystem_add_file(debug, "gpio", read_gpio_debug, NULL);
}