From: Tulio A M Mendes Date: Sat, 7 Feb 2026 18:16:03 +0000 (-0300) Subject: syscall: add open/read/close and per-process fd table X-Git-Url: https://projects.tadryanom.me/sitemap.xml?a=commitdiff_plain;h=02cbceb874d65b50f8ccde59a8e745955b4f58a7;p=AdrOS.git syscall: add open/read/close and per-process fd table --- diff --git a/include/process.h b/include/process.h index c6b1d2f..eb02a7c 100644 --- a/include/process.h +++ b/include/process.h @@ -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) }; diff --git a/include/syscall.h b/include/syscall.h index b5c63ea..280c1a2 100644 --- a/include/syscall.h +++ b/include/syscall.h @@ -9,6 +9,10 @@ enum { SYSCALL_WRITE = 1, SYSCALL_EXIT = 2, SYSCALL_GETPID = 3, + + SYSCALL_OPEN = 4, + SYSCALL_READ = 5, + SYSCALL_CLOSE = 6, }; #endif diff --git a/src/kernel/scheduler.c b/src/kernel/scheduler.c index 59e7e62..a153098 100644 --- a/src/kernel/scheduler.c +++ b/src/kernel/scheduler.c @@ -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) { diff --git a/src/kernel/syscall.c b/src/kernel/syscall.c index 4d094fe..0b54f5f 100644 --- a/src/kernel/syscall.c +++ b/src/kernel/syscall.c @@ -1,10 +1,111 @@ #include "syscall.h" #include "idt.h" +#include "fs.h" +#include "heap.h" +#include "process.h" #include "uart_console.h" #include "uaccess.h" #include +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(;;) { diff --git a/user/init.c b/user/init.c index 7178e64..349b16b 100644 --- a/user/init.c +++ b/user/init.c @@ -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); }