]> Projects (at) Tadryanom (dot) Me - AdrOS.git/commitdiff
syscall: add open/read/close and per-process fd table
authorTulio A M Mendes <[email protected]>
Sat, 7 Feb 2026 18:16:03 +0000 (15:16 -0300)
committerTulio A M Mendes <[email protected]>
Sat, 7 Feb 2026 18:16:03 +0000 (15:16 -0300)
include/process.h
include/syscall.h
src/kernel/scheduler.c
src/kernel/syscall.c
user/init.c

index c6b1d2fc261ee47f37ed5a93d4615836c7de3c1b..eb02a7c01ac50dc1c2c97ae2c97f89516d25665a 100644 (file)
@@ -12,6 +12,10 @@ typedef enum {
     PROCESS_ZOMBIE
 } process_state_t;
 
+struct file;
+
+#define PROCESS_MAX_FILES 16
+
 struct process {
     uint32_t pid;
     uintptr_t sp;
@@ -19,6 +23,7 @@ struct process {
     uint32_t* kernel_stack;
     process_state_t state;
     uint32_t wake_at_tick;      // New: When to wake up (global tick count)
+    struct file* files[PROCESS_MAX_FILES];
     struct process* next;
     struct process* prev;       // Doubly linked list helps here too! (Optional but good)
 };
index b5c63ea42f4c66e6ef33ce3f9f0cb721ac1b4da1..280c1a28bcae4017d0ca28e75f5be0abb38369c2 100644 (file)
@@ -9,6 +9,10 @@ enum {
     SYSCALL_WRITE = 1,
     SYSCALL_EXIT  = 2,
     SYSCALL_GETPID = 3,
+
+    SYSCALL_OPEN  = 4,
+    SYSCALL_READ  = 5,
+    SYSCALL_CLOSE = 6,
 };
 
 #endif
index 59e7e62aea7e6791c58cd54dc33312107aa03845..a153098594b14d745c8963d7355ef26d40763326 100644 (file)
@@ -48,6 +48,10 @@ void process_init(void) {
     kernel_proc->state = PROCESS_RUNNING;
     kernel_proc->wake_at_tick = 0;
     kernel_proc->addr_space = hal_cpu_get_address_space();
+
+    for (int i = 0; i < PROCESS_MAX_FILES; i++) {
+        kernel_proc->files[i] = NULL;
+    }
     
     current_process = kernel_proc;
     ready_queue_head = kernel_proc;
@@ -80,6 +84,10 @@ struct process* process_create_kernel(void (*entry_point)(void)) {
     proc->state = PROCESS_READY;
     proc->addr_space = current_process->addr_space;
     proc->wake_at_tick = 0;
+
+    for (int i = 0; i < PROCESS_MAX_FILES; i++) {
+        proc->files[i] = NULL;
+    }
     
     void* stack_phys = pmm_alloc_page_low();
     if (!stack_phys) {
index 4d094fefb68d030a2cdeb3d40a26b9714dd37ef3..0b54f5fec96269674d79322c566dcf88a13ca177 100644 (file)
 #include "syscall.h"
 #include "idt.h"
+#include "fs.h"
+#include "heap.h"
+#include "process.h"
 #include "uart_console.h"
 #include "uaccess.h"
 
 #include <stddef.h>
 
+struct file {
+    fs_node_t* node;
+    uint32_t offset;
+    uint32_t flags;
+};
+
+static int fd_alloc(struct file* f) {
+    if (!current_process || !f) return -1;
+
+    for (int fd = 3; fd < PROCESS_MAX_FILES; fd++) {
+        if (current_process->files[fd] == NULL) {
+            current_process->files[fd] = f;
+            return fd;
+        }
+    }
+    return -1;
+}
+
+static struct file* fd_get(int fd) {
+    if (!current_process) return NULL;
+    if (fd < 0 || fd >= PROCESS_MAX_FILES) return NULL;
+    return current_process->files[fd];
+}
+
+static int fd_close(int fd) {
+    if (!current_process) return -1;
+    if (fd < 0 || fd >= PROCESS_MAX_FILES) return -1;
+
+    struct file* f = current_process->files[fd];
+    if (!f) return -1;
+    current_process->files[fd] = NULL;
+    kfree(f);
+    return 0;
+}
+
+static int syscall_open_impl(const char* user_path, uint32_t flags) {
+    (void)flags;
+    if (!user_path) return -1;
+
+    char path[128];
+    for (size_t i = 0; i < sizeof(path); i++) {
+        if (copy_from_user(&path[i], &user_path[i], 1) < 0) {
+            return -1;
+        }
+        if (path[i] == 0) break;
+        if (i + 1 == sizeof(path)) {
+            path[sizeof(path) - 1] = 0;
+            break;
+        }
+    }
+
+    fs_node_t* node = vfs_lookup(path);
+    if (!node) return -1;
+    if ((node->flags & FS_FILE) == 0) return -1;
+
+    struct file* f = (struct file*)kmalloc(sizeof(*f));
+    if (!f) return -1;
+    f->node = node;
+    f->offset = 0;
+    f->flags = 0;
+
+    int fd = fd_alloc(f);
+    if (fd < 0) {
+        kfree(f);
+        return -1;
+    }
+    return fd;
+}
+
+static int syscall_read_impl(int fd, void* user_buf, uint32_t len) {
+    if (len > 1024 * 1024) return -1;
+    if (user_range_ok(user_buf, (size_t)len) == 0) return -1;
+
+    struct file* f = fd_get(fd);
+    if (!f || !f->node) return -1;
+
+    uint8_t kbuf[256];
+    uint32_t total = 0;
+    while (total < len) {
+        uint32_t chunk = len - total;
+        if (chunk > sizeof(kbuf)) chunk = (uint32_t)sizeof(kbuf);
+
+        uint32_t rd = vfs_read(f->node, f->offset, chunk, kbuf);
+        if (rd == 0) break;
+
+        if (copy_to_user((uint8_t*)user_buf + total, kbuf, rd) < 0) {
+            return -1;
+        }
+
+        f->offset += rd;
+        total += rd;
+
+        if (rd < chunk) break;
+    }
+
+    return (int)total;
+}
+
 static void syscall_handler(struct registers* regs) {
     uint32_t syscall_no = regs->eax;
 
@@ -58,6 +159,27 @@ static void syscall_handler(struct registers* regs) {
         return;
     }
 
+    if (syscall_no == SYSCALL_OPEN) {
+        const char* path = (const char*)regs->ebx;
+        uint32_t flags = regs->ecx;
+        regs->eax = (uint32_t)syscall_open_impl(path, flags);
+        return;
+    }
+
+    if (syscall_no == SYSCALL_READ) {
+        int fd = (int)regs->ebx;
+        void* buf = (void*)regs->ecx;
+        uint32_t len = regs->edx;
+        regs->eax = (uint32_t)syscall_read_impl(fd, buf, len);
+        return;
+    }
+
+    if (syscall_no == SYSCALL_CLOSE) {
+        int fd = (int)regs->ebx;
+        regs->eax = (uint32_t)fd_close(fd);
+        return;
+    }
+
     if (syscall_no == SYSCALL_EXIT) {
         uart_print("[USER] exit()\n");
         for(;;) {
index 7178e64d12387f491c86bc59b2e5259eaf4329a5..349b16bc6d161124edbec8c1b0d408b709a7f8f8 100644 (file)
@@ -3,6 +3,9 @@
 enum {
     SYSCALL_WRITE = 1,
     SYSCALL_EXIT  = 2,
+    SYSCALL_OPEN  = 4,
+    SYSCALL_READ  = 5,
+    SYSCALL_CLOSE = 6,
 };
 
 static int sys_write(int fd, const void* buf, uint32_t len) {
@@ -16,6 +19,39 @@ static int sys_write(int fd, const void* buf, uint32_t len) {
     return ret;
 }
 
+static int sys_open(const char* path, uint32_t flags) {
+    int ret;
+    __asm__ volatile(
+        "int $0x80"
+        : "=a"(ret)
+        : "a"(SYSCALL_OPEN), "b"(path), "c"(flags)
+        : "memory"
+    );
+    return ret;
+}
+
+static int sys_read(int fd, void* buf, uint32_t len) {
+    int ret;
+    __asm__ volatile(
+        "int $0x80"
+        : "=a"(ret)
+        : "a"(SYSCALL_READ), "b"(fd), "c"(buf), "d"(len)
+        : "memory"
+    );
+    return ret;
+}
+
+static int sys_close(int fd) {
+    int ret;
+    __asm__ volatile(
+        "int $0x80"
+        : "=a"(ret)
+        : "a"(SYSCALL_CLOSE), "b"(fd)
+        : "memory"
+    );
+    return ret;
+}
+
 __attribute__((noreturn)) static void sys_exit(int code) {
     (void)code;
     __asm__ volatile(
@@ -39,5 +75,25 @@ void _start(void) {
 
     static const char msg[] = "[init] hello from init.elf\n";
     (void)sys_write(1, msg, (uint32_t)(sizeof(msg) - 1));
+
+    static const char path[] = "/init.elf";
+    int fd = sys_open(path, 0);
+    if (fd < 0) {
+        static const char emsg[] = "[init] open(/init.elf) failed\n";
+        (void)sys_write(1, emsg, (uint32_t)(sizeof(emsg) - 1));
+        sys_exit(1);
+    }
+
+    uint8_t hdr[4];
+    int rd = sys_read(fd, hdr, (uint32_t)sizeof(hdr));
+    (void)sys_close(fd);
+
+    if (rd == 4 && hdr[0] == 0x7F && hdr[1] == 'E' && hdr[2] == 'L' && hdr[3] == 'F') {
+        static const char ok[] = "[init] open/read/close OK (ELF magic)\n";
+        (void)sys_write(1, ok, (uint32_t)(sizeof(ok) - 1));
+    } else {
+        static const char bad[] = "[init] read failed or bad header\n";
+        (void)sys_write(1, bad, (uint32_t)(sizeof(bad) - 1));
+    }
     sys_exit(0);
 }