From ac9741e12222e72bad3414bc6f588e70a3d130cc Mon Sep 17 00:00:00 2001 From: Richard Qin Date: Tue, 14 Apr 2026 22:47:15 +0800 Subject: feat: implement FDT-based memory discovery and add comprehensive debug logging to exec syscalls --- src/drivers/plic.cc | 40 +++-- src/drivers/uart.cc | 22 +-- src/drivers/virtio_dist.cc | 10 +- src/fs/fs.cc | 28 +++- src/kernel/fdt.cc | 246 ++++++++++++++++++++++++----- src/kernel/main.cc | 11 +- src/kernel/mm/pmm.cc | 14 +- src/kernel/mm/vm.cc | 13 +- src/kernel/proc/exec.cc | 56 ++++++- src/kernel/syscall.cc | 377 ++++++++++++++++++++++----------------------- src/kernel/trap/handler.cc | 21 ++- src/ulib/syscalls.c | 153 ++++++++++++++++++ src/user/init.cc | 2 +- src/user/sh.cc | 6 +- src/user/usys.S | 57 +++---- 15 files changed, 734 insertions(+), 322 deletions(-) create mode 100644 src/ulib/syscalls.c (limited to 'src') diff --git a/src/drivers/plic.cc b/src/drivers/plic.cc index f9e306b..a975c44 100644 --- a/src/drivers/plic.cc +++ b/src/drivers/plic.cc @@ -1,18 +1,18 @@ // SPDX-License-Identifier: GPL-2.0-or-later /* - * Copyright (C) 2026 Richard QIn + * Copyright (C) 2026 Richard Qin */ #include "common/types.h" #include "kernel/riscv.h" #include "drivers/plic.h" #include "drivers/uart.h" +#include "kernel/fdt.h" -// Base Constants -constexpr uint64 PLIC_BASE = 0x0c000000L; -constexpr uint64 PLIC_PRIORITY = PLIC_BASE + 0x0; -constexpr uint64 PLIC_PENDING = PLIC_BASE + 0x1000; +// Helper Macros — all relative to PLIC base from FDT +#define PLIC_BASE (g_devices.plic.base_addr) +#define PLIC_PRIORITY (PLIC_BASE + 0x0) +#define PLIC_PENDING (PLIC_BASE + 0x1000) -// Helper Macros to calculate addresses #define PLIC_SENABLE_ADDR(hart) (PLIC_BASE + 0x2080 + (hart) * 0x100) #define PLIC_STHRESHOLD_ADDR(hart) (PLIC_BASE + 0x201000 + (hart) * 0x2000) #define PLIC_SCLAIM_ADDR(hart) (PLIC_BASE + 0x201004 + (hart) * 0x2000) @@ -27,12 +27,15 @@ namespace PLIC { void init() { - // Set Priority for UART (IRQ 10) and VirtIO (IRQ 1) - // Must use volatile write - *REG32(PLIC_PRIORITY + 10 * 4) = 1; - for (int i = 1; i <= 8; i++) + // Set priority for UART IRQ + if (g_devices.uart.irq > 0) + *REG32(PLIC_PRIORITY + g_devices.uart.irq * 4) = 1; + + // Set priority for all VirtIO IRQs + for (int i = 0; i < g_devices.virtio_count; i++) { - *REG32(PLIC_PRIORITY + i * 4) = 1; + if (g_devices.virtio[i].irq > 0) + *REG32(PLIC_PRIORITY + g_devices.virtio[i].irq * 4) = 1; } } @@ -40,8 +43,19 @@ namespace PLIC { int hart = static_cast(r_tp()); - // Enable UART(10) and VirtIO(1) for this Hart (S-Mode) - *REG32(PLIC_SENABLE_ADDR(hart)) = (1 << 10) | 0x1FE; + // Build enable bitmask from discovered devices + uint32 enable = 0; + + if (g_devices.uart.irq > 0 && g_devices.uart.irq < 32) + enable |= (1 << g_devices.uart.irq); + + for (int i = 0; i < g_devices.virtio_count; i++) + { + if (g_devices.virtio[i].irq > 0 && g_devices.virtio[i].irq < 32) + enable |= (1 << g_devices.virtio[i].irq); + } + + *REG32(PLIC_SENABLE_ADDR(hart)) = enable; // Set Priority Threshold to 0 (Allow all) *REG32(PLIC_STHRESHOLD_ADDR(hart)) = 0; diff --git a/src/drivers/uart.cc b/src/drivers/uart.cc index 96ae182..397a402 100644 --- a/src/drivers/uart.cc +++ b/src/drivers/uart.cc @@ -40,29 +40,29 @@ namespace Drivers uart_rx.w = 0; // Disable interrupts and configure - *(volatile uint8 *)(UART0 + IER) = 0x00; + *(volatile uint8 *)(uart_base() + IER) = 0x00; // Enter baud rate setting mode (LCR_DLAB) = 0x80; - *(volatile uint8 *)(UART0 + LCR) = 0x80; - *(volatile uint8 *)(UART0 + 0) = 0x03; // DLL: 38.4K baud - *(volatile uint8 *)(UART0 + 1) = 0x00; // DLM + *(volatile uint8 *)(uart_base() + LCR) = 0x80; + *(volatile uint8 *)(uart_base() + 0) = 0x03; // DLL: 38.4K baud + *(volatile uint8 *)(uart_base() + 1) = 0x00; // DLM // Exit baud rate setting, set 8-bit word length, no parity - *(volatile uint8 *)(UART0 + LCR) = 0x03; + *(volatile uint8 *)(uart_base() + LCR) = 0x03; // Reset and enable FIFO - *(volatile uint8 *)(UART0 + FCR) = 0x07; + *(volatile uint8 *)(uart_base() + FCR) = 0x07; // Enable Receive Data Available Interrupt - *(volatile uint8 *)(UART0 + IER) = 0x01; + *(volatile uint8 *)(uart_base() + IER) = 0x01; } void uart_putc(char c) { uart_tx_lock.acquire(); - while ((*(volatile uint8 *)(UART0 + LSR) & LSR_TX_IDLE) == 0) + while ((*(volatile uint8 *)(uart_base() + LSR) & LSR_TX_IDLE) == 0) ; - *(volatile uint8 *)(UART0 + THR) = c; + *(volatile uint8 *)(uart_base() + THR) = c; uart_tx_lock.release(); } @@ -113,10 +113,10 @@ namespace Drivers while (1) { - if ((*(volatile uint8 *)(UART0 + LSR) & LSR_RX_READY) == 0) + if ((*(volatile uint8 *)(uart_base() + LSR) & LSR_RX_READY) == 0) break; - char c = *(volatile uint8 *)(UART0 + RHR); + char c = *(volatile uint8 *)(uart_base() + RHR); uart_rx.buf[uart_rx.w % UART_RX_BUF_SIZE] = c; uart_rx.w++; diff --git a/src/drivers/virtio_dist.cc b/src/drivers/virtio_dist.cc index b2acd8e..8292874 100644 --- a/src/drivers/virtio_dist.cc +++ b/src/drivers/virtio_dist.cc @@ -3,6 +3,7 @@ * Copyright (C) 2026 Richard QIn */ #include "drivers/virtio.h" +#include "kernel/fdt.h" #include "kernel/riscv.h" #include "kernel/pmm.h" #include "kernel/spinlock.h" @@ -67,11 +68,14 @@ namespace VirtIO { disk.lock.init("virtio_disk"); - // 1. Probing for VirtIO-MMIO device + // 1. Probe VirtIO devices discovered by FDT bool found = false; - // Probe common VirtIO addresses in QEMU virt machine - for (uint64 addr = 0x10001000; addr < 0x10009000; addr += 0x1000) + for (int i = 0; i < g_devices.virtio_count; i++) { + uint64 addr = g_devices.virtio[i].base_addr; + if (addr == 0) + continue; + volatile uint32 *magic = (volatile uint32 *)(addr + VIRTIO_MMIO_MAGIC_VALUE); volatile uint32 *dev_id = (volatile uint32 *)(addr + VIRTIO_MMIO_DEVICE_ID); diff --git a/src/fs/fs.cc b/src/fs/fs.cc index b93f363..fc8f555 100644 --- a/src/fs/fs.cc +++ b/src/fs/fs.cc @@ -7,7 +7,7 @@ #include "drivers/uart.h" #include "kernel/spinlock.h" #include "kernel/proc.h" -#include "fs/fat32.h" +// #include "fs/fat32.h" // Decoupled #include "lib/string.h" static Inode *global_root_inode = nullptr; @@ -53,6 +53,18 @@ void Inode::getattr(struct kstat *st) namespace VFS { + // File System Registry + static FileSystem *filesystems[8]; + static int fs_count = 0; + + void register_fs(FileSystem *fs) + { + if (fs_count < 8) + { + filesystems[fs_count++] = fs; + } + } + void init() { Drivers::uart_puts("[VFS] Inode subsystem initialized.\n"); @@ -138,9 +150,17 @@ namespace VFS { if (global_root_inode == nullptr) { - Drivers::uart_puts("[VFS] Lazy init: Mounting FAT32...\n"); - fat32_fs.init(); - mount_root(fat32_fs.root()); + // Try to mount the first registered FS + if (fs_count > 0) + { + Drivers::uart_puts("[VFS] Lazy init: Mounting root FS...\n"); + filesystems[0]->init(); + mount_root(filesystems[0]->root()); + } + else + { + Drivers::uart_puts("[VFS] No filesystem registered!\n"); + } } if (!global_root_inode) return nullptr; diff --git a/src/kernel/fdt.cc b/src/kernel/fdt.cc index e9f8422..ae09c84 100644 --- a/src/kernel/fdt.cc +++ b/src/kernel/fdt.cc @@ -1,13 +1,24 @@ // SPDX-License-Identifier: GPL-2.0-or-later /* - * Copyright (C) 2026 Richard QIn + * Copyright (C) 2026 Richard Qin + * LumeOS - FDT Parser + * + * Parses the Flattened Device Tree to discover hardware. + * Populates g_devices for use by all drivers. */ #include "common/types.h" -#include "drivers/uart.h" -#include "kernel/config.h" +#include "kernel/fdt.h" #include "lib/string.h" -inline uint32_t bswap(uint32_t x) +// Global device registry +DeviceRegistry g_devices; + +// Keep g_dtb_addr for PMM to protect DTB pages +// g_dtb_addr is defined in entry.S, g_uart_base in config.cc +extern "C" uint64 g_dtb_addr; +extern uint64 g_uart_base; + +static inline uint32 bswap(uint32 x) { return ((x & 0xFF) << 24) | ((x & 0xFF00) << 8) | ((x & 0xFF0000) >> 8) | ((x >> 24) & 0xFF); @@ -34,74 +45,229 @@ struct fdt_header #define FDT_NOP 4 #define FDT_END 9 +// Check if 'str' starts with 'prefix' +static bool starts_with(const char *str, const char *prefix) +{ + while (*prefix) + { + if (*str != *prefix) + return false; + str++; + prefix++; + } + return true; +} + +// Check if 'haystack' contains 'needle' as a substring within 'len' bytes +// (compatible strings may have multiple null-separated entries) +static bool compat_match(const uint8 *data, uint32 len, const char *needle) +{ + uint32 nlen = strlen(needle); + for (uint32 i = 0; i + nlen <= len; i++) + { + if (memcmp(data + i, needle, nlen) == 0) + return true; + } + return false; +} + +// Add a MMIO region to the registry (avoids duplicates) +static void add_mmio_region(uint64 base, uint64 size) +{ + if (base == 0 || size == 0) + return; + // Only track I/O regions below RAM + if (base >= 0x80000000ULL) + return; + if (g_devices.mmio_count >= DeviceRegistry::MAX_MMIO) + return; + + // Check for overlap/duplicate + for (int i = 0; i < g_devices.mmio_count; i++) + { + if (g_devices.mmio_regions[i].base == base) + return; + } + + g_devices.mmio_regions[g_devices.mmio_count].base = base; + g_devices.mmio_regions[g_devices.mmio_count].size = size; + g_devices.mmio_count++; +} -void fdt_init(uint64 dtb) +void fdt_parse(uint64 dtb) { - if (dtb == 0) return; + // Clear registry + memset(&g_devices, 0, sizeof(g_devices)); + + if (dtb == 0) + return; - struct fdt_header* header = (struct fdt_header*)dtb; + g_dtb_addr = dtb; + + struct fdt_header *header = (struct fdt_header *)dtb; if (bswap(header->magic) != FDT_MAGIC) return; - - uint8* struct_ptr = (uint8*)(dtb + bswap(header->off_dt_struct)); - char* strings_ptr = (char *)(dtb + bswap(header->off_dt_strings)); + uint8 *struct_ptr = (uint8 *)(dtb + bswap(header->off_dt_struct)); + char *strings_ptr = (char *)(dtb + bswap(header->off_dt_strings)); + + // Parsing state + char current_node_name[64]; + current_node_name[0] = '\0'; + + // Per-node state uint64 current_reg_addr = 0; + uint64 current_reg_size = 0; + uint32 current_irq = 0; + const uint8 *current_compat = nullptr; + uint32 current_compat_len = 0; + bool has_reg = false; + bool has_compat = false; + // bool has_irq = false; // Unused + + // Depth tracking (for #address-cells / #size-cells) + // Default for root: 2 address-cells, 2 size-cells + int depth = 0; while (1) { - uint32 token = bswap(*(uint32*)struct_ptr); + uint32 token = bswap(*(uint32 *)struct_ptr); struct_ptr += 4; - if(token == FDT_END)break; - if(token == FDT_NOP)continue; + if (token == FDT_END) + break; + if (token == FDT_NOP) + continue; - if(token == FDT_BEGIN_NODE) + if (token == FDT_BEGIN_NODE) { - while (*struct_ptr != 0)struct_ptr++; + // Save node name + // char *name = (char *)struct_ptr; + int i = 0; + while (*struct_ptr != 0 && i < 63) + { + current_node_name[i++] = *struct_ptr; + struct_ptr++; + } + current_node_name[i] = '\0'; + while (*struct_ptr != 0) + struct_ptr++; struct_ptr++; - struct_ptr = (uint8*)(((uint64)struct_ptr + 3) & ~3); + struct_ptr = (uint8 *)(((uint64)struct_ptr + 3) & ~3); + + // Reset per-node state + current_reg_addr = 0; + current_reg_size = 0; + current_irq = 0; + current_compat = nullptr; + current_compat_len = 0; + has_reg = false; + has_compat = false; + // has_irq = false; + + depth++; } - else if(token == FDT_END_NODE) + else if (token == FDT_END_NODE) { - + // Process the node we just finished + if (has_reg && has_compat) + { + // UART: ns16550a + if (compat_match(current_compat, current_compat_len, "ns16550")) + { + g_devices.uart.base_addr = current_reg_addr; + g_devices.uart.size = current_reg_size ? current_reg_size : 0x100; + g_devices.uart.irq = current_irq; + add_mmio_region(current_reg_addr, g_devices.uart.size); + } + // PLIC + else if (compat_match(current_compat, current_compat_len, "plic")) + { + g_devices.plic.base_addr = current_reg_addr; + g_devices.plic.size = current_reg_size ? current_reg_size : 0x4000000; + g_devices.plic.irq = 0; + add_mmio_region(current_reg_addr, g_devices.plic.size); + } + // CLINT + else if (compat_match(current_compat, current_compat_len, "clint")) + { + g_devices.clint.base_addr = current_reg_addr; + g_devices.clint.size = current_reg_size ? current_reg_size : 0x10000; + g_devices.clint.irq = 0; + add_mmio_region(current_reg_addr, g_devices.clint.size); + } + // VirtIO + else if (compat_match(current_compat, current_compat_len, "virtio")) + { + if (g_devices.virtio_count < DeviceRegistry::MAX_VIRTIO) + { + int idx = g_devices.virtio_count++; + g_devices.virtio[idx].base_addr = current_reg_addr; + g_devices.virtio[idx].size = current_reg_size ? current_reg_size : 0x1000; + g_devices.virtio[idx].irq = current_irq; + add_mmio_region(current_reg_addr, g_devices.virtio[idx].size); + } + } + } + + // Memory node: name starts with "memory" + if (has_reg && starts_with(current_node_name, "memory")) + { + g_devices.mem_base = current_reg_addr; + g_devices.mem_size = current_reg_size; + } + + depth--; } else if (token == FDT_PROP) { - uint32 len = bswap(*(uint32*)struct_ptr); + uint32 len = bswap(*(uint32 *)struct_ptr); struct_ptr += 4; - uint32 nameoff = bswap(*(uint32*)struct_ptr); + uint32 nameoff = bswap(*(uint32 *)struct_ptr); struct_ptr += 4; - char* name = strings_ptr + nameoff; - uint8* data = struct_ptr; + char *name = strings_ptr + nameoff; + uint8 *data = struct_ptr; struct_ptr += len; - struct_ptr = (uint8*)(((uint64)struct_ptr + 3) & ~3); + struct_ptr = (uint8 *)(((uint64)struct_ptr + 3) & ~3); - if(strcmp(name, "reg") == 0 && len >= 8) + if (strcmp(name, "reg") == 0 && len >= 8) { - uint32 hi = bswap(*(uint32*)data); - uint32 lo = bswap(*(uint32*)(data + 4)); + // Assume 2 address-cells, 2 size-cells (standard for QEMU virt) + uint32 hi = bswap(*(uint32 *)data); + uint32 lo = bswap(*(uint32 *)(data + 4)); current_reg_addr = ((uint64)hi << 32) | lo; - } - if(strcmp(name, "compatible") == 0) - { - if (g_uart_base == 0) + if (len >= 16) { - for(uint32 i = 0; i < len; i++) - { - if (data[i] == 'n' && data[i + 1] == 's' && data[i + 2] == '1') - { - g_uart_base = current_reg_addr; - break; - } - } + uint32 shi = bswap(*(uint32 *)(data + 8)); + uint32 slo = bswap(*(uint32 *)(data + 12)); + current_reg_size = ((uint64)shi << 32) | slo; } - + has_reg = true; + } + else if (strcmp(name, "compatible") == 0) + { + current_compat = data; + current_compat_len = len; + has_compat = true; + } + else if (strcmp(name, "interrupts") == 0 && len >= 4) + { + current_irq = bswap(*(uint32 *)data); + // has_irq = true; + } + else if (strcmp(name, "interrupts-extended") == 0 && len >= 8) + { + // interrupts-extended = <&phandle irq_num> + // IRQ number is typically the second cell + current_irq = bswap(*(uint32 *)(data + 4)); + // has_irq = true; } } } - + + // Legacy compat + g_uart_base = g_devices.uart.base_addr; } \ No newline at end of file diff --git a/src/kernel/main.cc b/src/kernel/main.cc index 22cffd6..6a19915 100644 --- a/src/kernel/main.cc +++ b/src/kernel/main.cc @@ -20,16 +20,20 @@ #include "fs/fat32.h" #include "lib/string.h" -extern void fdt_init(uint64 dtb); +#include "kernel/fdt.h" // fdt_parse + extern uint64 g_dtb_addr; +// Placement new support (referenced from cxx.cc) +void *operator new(unsigned long size, void *ptr); + volatile static int started = 0; extern "C" void kernel_main(uint64 hartid, uint64 dtb) { if (hartid == 0) { - fdt_init(dtb); + fdt_parse(dtb); Drivers::uart_init(); Drivers::uart_puts("\n[Lume OS] Booting...\n"); @@ -47,6 +51,9 @@ extern "C" void kernel_main(uint64 hartid, uint64 dtb) VirtIO::init(); BufferCache::init(); VFS::init(); + // Initialize global FAT32 object manually (global constructors not supported yet) + new (&fat32_fs) FAT32FileSystem(); + VFS::register_fs(&fat32_fs); FileTable::init(); Timer::init(); ProcManager::init(); // Process Management diff --git a/src/kernel/mm/pmm.cc b/src/kernel/mm/pmm.cc index 2d0c44f..d3d99ba 100644 --- a/src/kernel/mm/pmm.cc +++ b/src/kernel/mm/pmm.cc @@ -6,6 +6,7 @@ #include "kernel/riscv.h" #include "kernel/pmm.h" #include "kernel/mm.h" +#include "kernel/fdt.h" // #include "kernel/spinlock.h" #include "drivers/uart.h" #include "lib/string.h" @@ -13,6 +14,9 @@ extern "C" char kernel_end[]; extern uint64 g_dtb_addr; +// Default memory size 128MB, will be overwritten by FDT +uint64 g_phys_size = 128 * 1024 * 1024; + namespace PMM { // Global metadata array pointer @@ -74,12 +78,20 @@ namespace PMM void init() { + // Use FDT memory size if available + if (g_devices.mem_size > 0) + { + g_phys_size = g_devices.mem_size; + } + pmm_lock.init("pmm"); uint64 kern_end_pa = PGROUNDUP((uint64)kernel_end); total_pages = (PHYSTOP - KERNBASE) / PGSIZE; - Drivers::uart_puts(ANSI_GREEN "[PMM] Total RAM size: 128MB\n" ANSI_RESET); + Drivers::uart_puts(ANSI_GREEN "[PMM] Total RAM size: "); + Drivers::uart_put_int(g_phys_size / (1024 * 1024)); + Drivers::uart_puts(" MB\n" ANSI_RESET); // Place the mem_map array // mem_map is located immediately after kernel_end mem_map = (struct Page*)kern_end_pa; diff --git a/src/kernel/mm/vm.cc b/src/kernel/mm/vm.cc index 47b80e9..be2f2f2 100644 --- a/src/kernel/mm/vm.cc +++ b/src/kernel/mm/vm.cc @@ -8,6 +8,7 @@ #include "common/types.h" #include "lib/string.h" #include "drivers/uart.h" +#include "kernel/fdt.h" extern "C" { @@ -421,9 +422,15 @@ namespace VM { kernel_pagetable = uvmcreate(); - kvmmap(0x10000000, 0x10000000, 0x10000, PTE_R | PTE_W); - kvmmap(0x0c000000, 0x0c000000, 0x400000, PTE_R | PTE_W); - kvmmap(0x02000000, 0x02000000, 0x10000, PTE_R | PTE_W); // CLINT + // 1. Map all device MMIO regions discovered by FDT + for (int i = 0; i < g_devices.mmio_count; i++) + { + uint64 base = g_devices.mmio_regions[i].base; + uint64 size = g_devices.mmio_regions[i].size; + kvmmap(base, base, size, PTE_R | PTE_W); + } + + // 2. Map Kernel Memory (PHYSTOP is now dynamic based on FDT) kvmmap(KERNBASE, KERNBASE, PHYSTOP - KERNBASE, PTE_R | PTE_W | PTE_X); } diff --git a/src/kernel/proc/exec.cc b/src/kernel/proc/exec.cc index e5294d9..8d8c467 100644 --- a/src/kernel/proc/exec.cc +++ b/src/kernel/proc/exec.cc @@ -11,7 +11,6 @@ #include "lib/string.h" #include "drivers/uart.h" #include "kernel/trap.h" -#include "drivers/uart.h" extern char trampoline[]; @@ -74,7 +73,10 @@ static int loadseg(uint64 *pagetable, uint64 va, Inode *ip, uint64 offset, uint6 { uint64 pa = VM::walkaddr(pagetable, va + i); if (pa == 0) + { + Drivers::uart_puts("[Exec Debug] loadseg: walkaddr failed\n"); return -1; + } uint64 n = PGSIZE - (va + i) % PGSIZE; if (i + n > sz) @@ -82,7 +84,10 @@ static int loadseg(uint64 *pagetable, uint64 va, Inode *ip, uint64 offset, uint6 // Read physical address (isUser=0) if (ip->read((char *)(pa + (va + i) % PGSIZE), offset + i, n, 0) != (int)n) + { + Drivers::uart_puts("[Exec Debug] loadseg: read failed\n"); return -1; + } } return 0; } @@ -91,29 +96,48 @@ namespace Exec { int exec(char *path, char **argv) { - // Get Inode + // 1. Get Inode Inode *raw_ip = VFS::namei(path); if (!raw_ip) + { + Drivers::uart_puts("[Exec Debug] namei failed for path: "); + Drivers::uart_puts(path); + Drivers::uart_puts("\n"); return -1; + } InodeGuard iguard(raw_ip); // Get ELF head struct elfhdr elf; if (raw_ip->read((char *)&elf, 0, sizeof(elf), 0) != sizeof(elf)) + { + Drivers::uart_puts("[Exec Debug] read elf header failed\n"); return -1; + } if (elf.magic != ELF_MAGIC) + { + Drivers::uart_puts("[Exec Debug] invalid elf magic\n"); return -1; + } + // Create new pagetable VmGuard vm_guard; if (!vm_guard.pagetable) + { + Drivers::uart_puts("[Exec Debug] uvmcreate failed\n"); return -1; + } + // Load Program Segment struct proghdr ph; for (int i = 0; i < elf.phnum; i++) { uint64 off = elf.phoff + i * sizeof(ph); if (raw_ip->read((char *)&ph, off, sizeof(ph), 0) != sizeof(ph)) + { + Drivers::uart_puts("[Exec Debug] read proghdr failed\n"); return -1; + } if (ph.type != ELF_PROG_LOAD) continue; @@ -124,7 +148,10 @@ namespace Exec uint64 sz1 = VM::uvmalloc(vm_guard.pagetable, vm_guard.sz, ph.vaddr + ph.memsz, PTE_W | PTE_X | PTE_R | PTE_U); if (sz1 == 0) + { + Drivers::uart_puts("[Exec Debug] uvmalloc failed (segment)\n"); return -1; + } vm_guard.sz = sz1; if (loadseg(vm_guard.pagetable, ph.vaddr, raw_ip, ph.off, ph.filesz) < 0) @@ -139,10 +166,13 @@ namespace Exec uint64 sz1 = VM::uvmalloc(vm_guard.pagetable, sz, sz + stack_total_pages * PGSIZE, PTE_W | PTE_R | PTE_U); if (sz1 == 0) + { + Drivers::uart_puts("[Exec Debug] uvmalloc failed (stack)\n"); return -1; + } vm_guard.sz = sz1; - VM::uvmunmap(vm_guard.pagetable, sz, 1, 0); // protected pagetable + VM::uvmunmap(vm_guard.pagetable, sz, 1, 0); uint64 sp = sz1; uint64 stackbase = sp - stack_data_pages * PGSIZE; @@ -157,10 +187,16 @@ namespace Exec sp -= strlen(argv[argc]) + 1; sp -= sp % 16; if (sp < stackbase) + { + Drivers::uart_puts("[Exec Debug] stack overflow (args)\n"); return -1; + } if (VM::copyout(vm_guard.pagetable, sp, argv[argc], strlen(argv[argc]) + 1) < 0) + { + Drivers::uart_puts("[Exec Debug] copyout arg string failed\n"); return -1; + } ustack[argc] = sp; } ustack[argc] = 0; @@ -169,25 +205,32 @@ namespace Exec sp -= (argc + 1) * sizeof(uint64); sp -= sp % 16; if (sp < stackbase) + { + Drivers::uart_puts("[Exec Debug] stack overflow (argv array)\n"); return -1; + } if (VM::copyout(vm_guard.pagetable, sp, (char *)ustack, (argc + 1) * sizeof(uint64)) < 0) + { + Drivers::uart_puts("[Exec Debug] copyout argv array failed\n"); return -1; + } // Commit Changes struct Proc *p = myproc(); if (VM::mappages(vm_guard.pagetable, TRAPFRAME, PGSIZE, (uint64)p->tf, PTE_R | PTE_W) < 0) + { + Drivers::uart_puts("[Exec Debug] mappages TRAPFRAME failed\n"); return -1; + } uint64 oldsz = p->sz; uint64 *oldpagetable = p->pagetable; - // setup Trapframe p->tf->a0 = argc; p->tf->a1 = sp; p->tf->sp = sp; p->tf->epc = elf.entry; - // update process name char *s = path, *last = path; while (*s) { @@ -195,7 +238,7 @@ namespace Exec last = s + 1; s++; } - // memmove(p->name, last, sizeof(p->name)); + size_t len = 0; while (last[len] && len < sizeof(p->name) - 1) { @@ -210,7 +253,6 @@ namespace Exec // release old pagetable VM::uvmfree(oldpagetable, oldsz); - asm volatile("fence.i"); return 0; // iguard unlocks and releases IP upon destruction diff --git a/src/kernel/syscall.cc b/src/kernel/syscall.cc index b891ada..0979c24 100644 --- a/src/kernel/syscall.cc +++ b/src/kernel/syscall.cc @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-or-later /* - * Copyright (C) 2026 Richard QIn + * Copyright (C) 2026 Richard Qin */ #include "kernel/syscall.h" #include "common/types.h" @@ -17,12 +17,13 @@ #include "fs/fat32.h" #include "fs/file.h" #include "lib/string.h" +#include "lib/errno.h" extern "C++" int fork(); namespace Exec { int exec(char *path, char **argv); -} +} namespace ProcManager { @@ -30,7 +31,6 @@ namespace ProcManager int wait(uint64_t addr); } - static uint64_t argraw(int n) { Proc *p = myproc(); @@ -69,26 +69,18 @@ struct KernelArgv { static const int MAX_ARGS = 32; static const int MAX_ARG_LEN = 128; - char *args[MAX_ARGS]; - KernelArgv() - { - memset(args, 0, sizeof(args)); - } - + KernelArgv() { memset(args, 0, sizeof(args)); } ~KernelArgv() { for (int i = 0; i < MAX_ARGS; i++) - { if (args[i]) { Slab::kfree(args[i]); args[i] = nullptr; } - } } - KernelArgv(const KernelArgv &) = delete; KernelArgv &operator=(const KernelArgv &) = delete; }; @@ -107,16 +99,17 @@ static int fdalloc(struct file *f) return -1; } -static uint64 sys_open() +// sys_openat(int dfd, const char *filename, int flags, mode_t mode) +static uint64 sys_openat() { char path[128]; - int omode; + int dfd, omode, mode_unused; int fd; struct file *f; Inode *ip; - if (argstr(0, path, 128) < 0 || argint(1, &omode) < 0) - return -1; + if (argint(0, &dfd) < 0 || argstr(1, path, 128) < 0 || argint(2, &omode) < 0 || argint(3, &mode_unused) < 0) + return -EINVAL; if (omode & O_CREATE) { @@ -139,9 +132,7 @@ static uint64 sys_open() } if (ip == nullptr) - { - return -1; - } + return -ENOENT; VFS::ilock(ip); if ((omode & O_TRUNC) && ip->type == T_FILE) @@ -154,7 +145,7 @@ static uint64 sys_open() if (f == nullptr) { VFS::iput(ip); - return -1; + return -ENFILE; } fd = fdalloc(f); @@ -163,7 +154,7 @@ static uint64 sys_open() f->ref = 0; f->type = FD_NONE; VFS::iput(ip); - return -1; + return -EMFILE; } f->type = FD_INODE; @@ -175,30 +166,33 @@ static uint64 sys_open() return fd; } -static uint64 sys_mkdir() +// sys_mkdirat(int dfd, const char *pathname, mode_t mode) +static uint64 sys_mkdirat() { char path[128]; - if (argstr(0, path, 128) < 0) - return -1; + int dfd, mode; + + if (argint(0, &dfd) < 0 || argstr(1, path, 128) < 0 || argint(2, &mode) < 0) + return -EINVAL; Inode *ip = VFS::namei(path); if (ip != nullptr) { VFS::iput(ip); - return -1; // the dir is exist + return -EEXIST; } char name[128]; Inode *dp = VFS::nameiparent(path, name); if (dp == nullptr) - return -1; + return -ENOENT; VFS::ilock(dp); ip = dp->create(name, T_DIR, 0, 0); VFS::iunlockput(dp); if (ip == nullptr) - return -1; + return -EIO; VFS::iput(ip); return 0; @@ -208,24 +202,24 @@ static uint64 sys_chdir() { char path[128]; if (argstr(0, path, 128) < 0) - return -1; + return -EFAULT; Inode *ip = VFS::namei(path); if (ip == nullptr) - return -1; + return -ENOENT; VFS::ilock(ip); if (ip->type != T_DIR) { VFS::iunlockput(ip); - return -1; + return -ENOTDIR; } VFS::iunlock(ip); struct Proc *p = myproc(); - VFS::iput(p->cwd); // release old cwd - p->cwd = ip; // switch to new cwd - + if (p->cwd) + VFS::iput(p->cwd); + p->cwd = ip; return 0; } @@ -233,18 +227,18 @@ static uint64 sys_dup() { int oldfd; if (argint(0, &oldfd) < 0) - return -1; + return -EINVAL; struct Proc *p = myproc(); if (oldfd < 0 || oldfd >= NOFILE || p->ofile[oldfd] == nullptr) - return -1; + return -EBADF; struct file *f = FileTable::dup(p->ofile[oldfd]); int newfd = fdalloc(f); if (newfd < 0) { - FileTable::close(f); // fdalloc failed - return -1; + FileTable::close(f); + return -EMFILE; } return newfd; } @@ -255,75 +249,86 @@ static uint64 sys_fstat() uint64 stat_addr; if (argint(0, &fd) < 0 || argint(1, (int *)&stat_addr) < 0) - return -1; + return -EINVAL; struct Proc *p = myproc(); if (fd < 0 || fd >= NOFILE || p->ofile[fd] == nullptr) - return -1; + return -EBADF; - return FileTable::stat(p->ofile[fd], stat_addr); + if (FileTable::stat(p->ofile[fd], stat_addr) < 0) + return -EIO; + + return 0; } -static uint64 sys_mknod() +// sys_mknodat(int dfd, const char *filename, mode_t mode, dev_t dev) +static uint64 sys_mknodat() { char path[128]; - int major, minor; + int dfd, mode, dev; - if (argstr(0, path, 128) < 0 || argint(1, &major) < 0 || argint(2, &minor) < 0) - return -1; + if (argint(0, &dfd) < 0 || argstr(1, path, 128) < 0 || argint(2, &mode) < 0 || argint(3, &dev) < 0) + return -EINVAL; Inode *ip = VFS::namei(path); if (ip != nullptr) { VFS::iput(ip); - return -1; + return -EEXIST; } char name[128]; Inode *dp = VFS::nameiparent(path, name); if (dp == nullptr) - return -1; + return -ENOENT; + + // Decode dev_t (Assuming simplified minor/major for now) + int major = (dev >> 20) & 0xFFF; // Just a guess for Linux packing, or pass raw + int minor = dev & 0xFFFFF; + + // For Phase 1 compatibility with init.cc: + // init.cc passes raw major/minor. Shim will pack them. + // We just unpack naively or assume Shim passed us correct structure. VFS::ilock(dp); ip = dp->create(name, T_DEVICE, major, minor); VFS::iunlockput(dp); if (ip == nullptr) - return -1; + return -EIO; VFS::iput(ip); return 0; } - - static uint64 sys_close() { int fd; if (argint(0, &fd) < 0) - return -1; + return -EINVAL; struct Proc *p = myproc(); if (fd < 0 || fd >= NOFILE || p->ofile[fd] == 0) - return -1; + return -EBADF; FileTable::close(p->ofile[fd]); p->ofile[fd] = 0; return 0; } -static uint64 sys_pipe() +static uint64 sys_pipe2() { - uint64 fdarray; // int fd[2] + uint64 fdarray; + int flags; struct file *rf, *wf; int fd0, fd1; struct Proc *p = myproc(); - if (argint(0, (int *)&fdarray) < 0) - return -1; + if (argint(0, (int *)&fdarray) < 0 || argint(1, &flags) < 0) + return -EFAULT; - if(Pipe::create_pair(&rf, &wf) < 0) - return -1; + if (Pipe::create_pair(&rf, &wf) < 0) + return -ENFILE; if ((fd0 = fdalloc(rf)) < 0 || (fd1 = fdalloc(wf)) < 0) { @@ -331,7 +336,7 @@ static uint64 sys_pipe() p->ofile[fd0] = nullptr; FileTable::close(rf); FileTable::close(wf); - return -1; + return -EMFILE; } if (VM::copyout(p->pagetable, fdarray, (char *)&fd0, sizeof(int)) < 0 || @@ -341,56 +346,58 @@ static uint64 sys_pipe() p->ofile[fd1] = nullptr; FileTable::close(rf); FileTable::close(wf); - return -1; + return -EFAULT; } return 0; } -static uint64 sys_link() -{ - Drivers::uart_puts("Not supported now"); - return -1; -} - -static uint64 sys_unlink() +static uint64 sys_unlinkat() { char path[128], name[128]; - if (argstr(0, path, 128) < 0) - return -1; + int dfd, flag; + + if (argint(0, &dfd) < 0 || argstr(1, path, 128) < 0 || argint(2, &flag) < 0) + return -EINVAL; Inode *dp = VFS::nameiparent(path, name); if (!dp) - return -1; + return -ENOENT; VFS::ilock(dp); int ret = dp->unlink(name); VFS::iunlockput(dp); - return ret; + return (ret < 0) ? -EIO : 0; } -static uint64 sys_exec() +// sys_linkat(int olddirfd, const char *oldpath, int newdirfd, const char *newpath, int flags) +static uint64 sys_linkat() +{ + // FAT32 does not support hard links. + // Return Error to allow compilation/running to proceed (ln will fail gracefully). + return -EPERM; +} + +static uint64 sys_execve() { char path[128]; uint64 uargv_ptr; if (argstr(0, path, sizeof(path)) < 0) - { - return -1; - } + return -EFAULT; uargv_ptr = argraw(1); + // uenvp_ptr = argraw(2); // Ignored KernelArgv kargv; for (int i = 0; i < KernelArgv::MAX_ARGS; ++i) { uint64 uarg_str_ptr; - if (VM::copyin(myproc()->pagetable, (char *)&uarg_str_ptr, uargv_ptr + i * sizeof(uint64), sizeof(uint64)) < 0) - { - return -1; - } + { + return -EFAULT; + } if (uarg_str_ptr == 0) { @@ -400,16 +407,15 @@ static uint64 sys_exec() kargv.args[i] = (char *)Slab::kmalloc(KernelArgv::MAX_ARG_LEN); if (kargv.args[i] == nullptr) - { - return -1; - } + { + return -ENOMEM; + } if (VM::copyinstr(myproc()->pagetable, kargv.args[i], uarg_str_ptr, KernelArgv::MAX_ARG_LEN) < 0) - { - return -1; - } + { + return -EFAULT; + } } - return Exec::exec(path, kargv.args); } @@ -417,20 +423,29 @@ static uint64 sys_exit() { int n; if (argint(0, &n) < 0) - return static_cast(-1); + return -EINVAL; ProcManager::exit(n); return 0; } -static uint64 sys_fork() +static uint64 sys_clone() { return static_cast(fork()); } -static uint64 sys_wait() +static uint64 sys_wait4() { - uint64 p = argraw(0); - return static_cast(ProcManager::wait(p)); + uint64 status_addr; + + // argraw(0) is pid (ignored) + status_addr = argraw(1); + // argraw(2) is options (ignored) + // argraw(3) is rusage (ignored) + + if (status_addr == static_cast(-1)) + return -EINVAL; + + return static_cast(ProcManager::wait(status_addr)); } static uint64 sys_getpid() @@ -452,20 +467,14 @@ static uint64 sys_write() uint64 p; int fd; - if (argint(0, &fd) < 0 || argint(2, &n) < 0 || argint(1, (int *)&p) < 0) - return -1; - - struct Proc *proc = myproc(); + if (argint(0, &fd) < 0 || argint(1, (int *)&p) < 0 || argint(2, &n) < 0) + return -EINVAL; p = argraw(1); - // Drivers::uart_puts("DEBUG: sys_write fd="); - // Drivers::uart_put_int(fd); - // Drivers::uart_puts(" len="); - // Drivers::uart_put_int(n); - // Drivers::uart_puts("\n"); + struct Proc *proc = myproc(); - if (fd == 1 && proc->ofile[fd] == nullptr) // stdout + if (fd == 1 && proc->ofile[fd] == nullptr) { constexpr int MAX_WRITE_BUF = 128; char buf[MAX_WRITE_BUF]; @@ -478,10 +487,7 @@ static uint64 sys_write() len = MAX_WRITE_BUF; if (VM::copyin(proc->pagetable, buf, p + i, static_cast(len)) < 0) - { - Drivers::uart_puts("sys_write: copyin failed\n"); - return static_cast(-1); - } + return -EFAULT; for (int j = 0; j < len; j++) { @@ -491,8 +497,9 @@ static uint64 sys_write() } return static_cast(n); } + if (fd < 0 || fd >= NOFILE || (f = proc->ofile[fd]) == 0) - return static_cast(-1); + return -EBADF; return FileTable::write(f, p, n); } @@ -504,50 +511,39 @@ static uint64_t sys_read() uint64 p; int fd; - // get param: fd, buf, len - if (argint(0, &fd) < 0 || argint(2, &n) < 0 || argint(1, (int *)&p) < 0) - return -1; - + if (argint(0, &fd) < 0 || argint(1, (int *)&p) < 0 || argint(2, &n) < 0) + return -EINVAL; + p = argraw(1); - struct Proc* proc = myproc(); + struct Proc *proc = myproc(); if (fd == 0 && proc->ofile[fd] == nullptr) - { return Drivers::console_read(p, n); - } if (fd < 0 || fd >= NOFILE || (f = proc->ofile[fd]) == 0) - return -1; + return -EBADF; return FileTable::read(f, p, n); - - return -1; } -static uint64 sys_sbrk() +static uint64 sys_brk() { int n; if (argint(0, &n) < 0) - return -1; + return -EINVAL; uint64 addr = myproc()->sz; if (ProcManager::growproc(n) < 0) - return -1; + return -ENOMEM; return addr; } -static uint64 sys_uptime() -{ - return Timer::get_ticks(); -} - static uint64 sys_kill() { int pid; if (argint(0, &pid) < 0) - return -1; - + return -EINVAL; return ProcManager::kill(pid); } @@ -557,24 +553,20 @@ static uint64 sys_sleep() uint64 ticks0; if (argint(0, &n) < 0) - return -1; + return -EINVAL; Spinlock *lk = Timer::get_lock(); lk->acquire(); - ticks0 = Timer::get_ticks(); - while (Timer::get_ticks() - ticks0 < (uint64)n) { if (myproc()->killed) { lk->release(); - return -1; + return -EINTR; } - ProcManager::sleep(Timer::get_tick_chan(), lk); } - lk->release(); return 0; } @@ -591,20 +583,18 @@ static uint64 sys_lseek() { int fd, offset, whence; if (argint(0, &fd) < 0 || argint(1, &offset) < 0 || argint(2, &whence) < 0) - return -1; + return -EINVAL; struct Proc *p = myproc(); if (fd < 0 || fd >= NOFILE || p->ofile[fd] == 0) - return -1; + return -EBADF; return FileTable::lseek(p->ofile[fd], offset, whence); } -static uint64 sys_shutdown() +static uint64 sys_reboot() { SBI::sbi_shutdown(); - while (1) - ; return 0; } @@ -612,98 +602,95 @@ void syscall() { Proc *p = myproc(); int num = p->tf->a7; - uint64 ret = static_cast(-1); - - /* Just For Debug */ - // Drivers::uart_puts("Syscall: "); - // Drivers::print_hex(num); - // Drivers::uart_puts("\n"); + uint64 ret = static_cast(-ENOSYS); switch (num) { - case SYS_open: - ret = sys_open(); + case SYS_mknodat: + ret = sys_mknodat(); break; - case SYS_close: - ret = sys_close(); + case SYS_mkdirat: + ret = sys_mkdirat(); break; - case SYS_write: - ret = sys_write(); + case SYS_unlinkat: + ret = sys_unlinkat(); break; - case SYS_read: - ret = sys_read(); + case SYS_linkat: + ret = sys_linkat(); break; - case SYS_putc: - ret = sys_putc(); - break; - case SYS_fork: - ret = sys_fork(); - break; - case SYS_exec: - ret = sys_exec(); - if (ret != static_cast(-1)) - return; + case SYS_chdir: + ret = sys_chdir(); break; - case SYS_exit: - ret = sys_exit(); + case SYS_openat: + ret = sys_openat(); break; - case SYS_wait: - ret = sys_wait(); + case SYS_dup: + ret = sys_dup(); break; - case SYS_getpid: - ret = sys_getpid(); + case SYS_close: + ret = sys_close(); break; - case SYS_sbrk: - ret = sys_sbrk(); - break; - case SYS_disk_test: - ret = sys_disk_test(); + case SYS_pipe2: + ret = sys_pipe2(); break; case SYS_lseek: ret = sys_lseek(); break; - case SYS_dup: - ret = sys_dup(); + case SYS_read: + ret = sys_read(); + break; + case SYS_write: + ret = sys_write(); break; case SYS_fstat: ret = sys_fstat(); break; - case SYS_chdir: - ret = sys_chdir(); + case SYS_exit: + ret = sys_exit(); + break; + case SYS_exit_group: + ret = sys_exit(); + break; + case SYS_kill: + ret = sys_kill(); break; - case SYS_mkdir: - ret = sys_mkdir(); + case SYS_getpid: + ret = sys_getpid(); break; - case SYS_mknod: - ret = sys_mknod(); + case SYS_brk: + ret = sys_brk(); break; - case SYS_pipe: - ret = sys_pipe(); + case SYS_clone: + ret = sys_clone(); break; - case SYS_unlink: - ret = sys_unlink(); + case SYS_execve: + ret = sys_execve(); + if (ret == 0) + return; break; - case SYS_link: - Drivers::uart_puts("Unimplemented syscall\n"); - ret = sys_link(); + case SYS_wait4: + ret = sys_wait4(); break; - case SYS_uptime: - ret = sys_uptime(); + + // Custom / Debug + case SYS_reboot: + ret = sys_reboot(); break; - case SYS_sleep: - ret = sys_sleep(); + case SYS_putc: + ret = sys_putc(); break; - case SYS_kill: - ret = sys_kill(); + case SYS_disk_test: + ret = sys_disk_test(); break; - case SYS_shutdown: - ret = sys_shutdown(); + case SYS_nanosleep: + ret = sys_sleep(); break; + default: Drivers::uart_puts("Unknown Syscall ID: "); Drivers::print_hex(num); Drivers::uart_puts("\n"); - ret = static_cast(-1); + ret = -ENOSYS; break; } diff --git a/src/kernel/trap/handler.cc b/src/kernel/trap/handler.cc index 11af409..b7bd5f0 100644 --- a/src/kernel/trap/handler.cc +++ b/src/kernel/trap/handler.cc @@ -11,6 +11,7 @@ #include "kernel/timer.h" #include "drivers/plic.h" #include "drivers/virtio.h" +#include "kernel/fdt.h" #include "lib/string.h" @@ -66,17 +67,23 @@ namespace Trap // Supervisor External Interrupt (IRQ 9) int irq = PLIC::claim(); - if (irq == 10) + if (irq == (int)g_devices.uart.irq) { Drivers::uart_intr(); - // Debug - // Drivers::uart_puts("[Interrupt] UART Input detected!\n"); } - else if (irq >= 1 && irq <= 8) + else { - VirtIO::intr(); - // Debug - // Drivers::uart_puts("[Interrupt] VirtIO disk finished!\n"); + // Check if it's a VirtIO IRQ + bool handled = false; + for (int i = 0; i < g_devices.virtio_count; i++) + { + if (irq == (int)g_devices.virtio[i].irq) + { + VirtIO::intr(); + handled = true; + break; + } + } } if (irq > 0) diff --git a/src/ulib/syscalls.c b/src/ulib/syscalls.c new file mode 100644 index 0000000..676bf18 --- /dev/null +++ b/src/ulib/syscalls.c @@ -0,0 +1,153 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Copyright (C) 2026 Richard Qin + * Libc Syscall Shims + */ + +#include "common/types.h" +#include "user/user.h" + +// Define external raw syscalls from usys.S +extern int sys_openat(int dfd, const char *filename, int flags, int mode); +extern int sys_mknodat(int dfd, const char *filename, int mode, int dev); +extern int sys_mkdirat(int dfd, const char *path, int mode); +extern int sys_unlinkat(int dfd, const char *path, int flags); +extern int sys_linkat(int olddfd, const char *oldpath, int newdfd, const char *newpath, int flags); +extern int sys_chdir(const char *path); +extern int sys_dup(int oldfd); +extern int sys_fstat(int fd, void *statbuf); +extern int sys_read(int fd, void *buf, int count); +extern int sys_write(int fd, const void *buf, int count); +extern int sys_close(int fd); +extern int sys_pipe2(int pipefd[2], int flags); +extern int sys_clone(unsigned long flags, void *stack, int *ptid, void *tls, int *ctid); +extern int sys_execve(const char *path, char *const argv[], char *const envp[]); +extern int sys_wait4(int pid, int *status, int options, void *rusage); +extern int sys_exit(int status); +extern int sys_getpid(); +extern int sys_brk(int n); +extern int sys_kill(int pid, int sig); +extern int sys_nanosleep(void *req, void *rem); +extern int sys_reboot(int magic1, int magic2, int cmd, void *arg); +extern int sys_lseek(int fd, int offset, int whence); +extern void sys_putc(char c); +extern int sys_disk_test(); + +// --- POSIX Implementation --- + +int open(const char *path, int flags) +{ + return sys_openat(AT_FDCWD, path, flags, 0); +} + +int mknod(const char *path, short major, short minor) +{ + // Pack major/minor into simplified dev_t (major << 20 | minor) + int dev = (major << 20) | (minor & 0xFFFFF); + return sys_mknodat(AT_FDCWD, path, 0, dev); +} + +int mkdir(const char *path) +{ + return sys_mkdirat(AT_FDCWD, path, 0); +} + +int unlink(const char *path) +{ + return sys_unlinkat(AT_FDCWD, path, 0); +} + +int link(const char *oldpath, const char *newpath) +{ + return sys_linkat(AT_FDCWD, oldpath, AT_FDCWD, newpath, 0); +} + +int chdir(const char *path) +{ + return sys_chdir(path); +} + +int fork() +{ + return sys_clone(0, 0, 0, 0, 0); +} + +int exec(char *path, char **argv) +{ + return sys_execve(path, argv, 0); +} + +int wait(uint64 status_addr) +{ + return sys_wait4(-1, (int *)status_addr, 0, 0); +} + +int pipe(int p[]) +{ + return sys_pipe2(p, 0); +} + +int read(int fd, void *buf, int n) +{ + return sys_read(fd, buf, n); +} + +int write(int fd, const void *buf, int n) +{ + return sys_write(fd, buf, n); +} + +int close(int fd) +{ + return sys_close(fd); +} + +int fstat(int fd, void *st) +{ + return sys_fstat(fd, st); +} + +int dup(int fd) +{ + return sys_dup(fd); +} + +int getpid() +{ + return sys_getpid(); +} + +char *sbrk(int n) +{ + return (char *)(long)sys_brk(n); +} + +int kill(int pid) +{ + return sys_kill(pid, 0); +} + +int sleep(int ticks) +{ + return sys_nanosleep((void *)(long)ticks, 0); +} + +int shutdown() +{ + return sys_reboot(0, 0, 0, 0); +} + +void putc(char c) +{ + sys_putc(c); +} + +int disk_test() +{ + return sys_disk_test(); +} + +int lseek(int fd, int offset, int whence) +{ + return sys_lseek(fd, offset, whence); +} \ No newline at end of file diff --git a/src/user/init.cc b/src/user/init.cc index f1a6e29..376e697 100644 --- a/src/user/init.cc +++ b/src/user/init.cc @@ -12,7 +12,7 @@ int main() { char *argv[] = {(char *)"sh", 0}; - printf(ANSI_BLUE"\n[Init] Starting Lume OS Shell..."ANSI_RESET); + printf(ANSI_BLUE "\n[Init] Starting Lume OS Shell..." ANSI_RESET); printf("\n"); while (1) diff --git a/src/user/sh.cc b/src/user/sh.cc index 1bf9ebb..47aad9e 100644 --- a/src/user/sh.cc +++ b/src/user/sh.cc @@ -368,8 +368,8 @@ int main() static char buf[100]; - printf(ANSI_GREEN"\n[Lume Shell] Welcome! \n"ANSI_RESET); - printf(ANSI_YELLOW "[Lume Shell] Start your journey of exploration!"ANSI_RESET); + printf(ANSI_GREEN "\n[Lume Shell] Welcome! \n" ANSI_RESET); + printf(ANSI_YELLOW "[Lume Shell] Start your journey of exploration!" ANSI_RESET); printf("\n"); while (getcmd(buf, sizeof(buf)) >= 0) @@ -400,7 +400,7 @@ int main() } if (strcmp(buf, "shutdown") == 0 || strcmp(buf, "poweroff") == 0) { - printf(ANSI_BLUE"System shutting down..."ANSI_RESET); + printf(ANSI_BLUE "System shutting down..." ANSI_RESET); printf("\n"); shutdown(); diff --git a/src/user/usys.S b/src/user/usys.S index 885d45c..1e373d3 100644 --- a/src/user/usys.S +++ b/src/user/usys.S @@ -3,13 +3,6 @@ #include "kernel/syscall.h" -#define SYSCALL(name) \ - .global name; \ - name: \ - li a7, SYS_ ## name; \ - ecall; \ - ret - #define SYSCALL_NAME(name, sysname) \ .global name; \ name: \ @@ -17,29 +10,29 @@ ecall; \ ret -SYSCALL_NAME(sys_exit, exit) +SYSCALL_NAME(sys_openat, openat) +SYSCALL_NAME(sys_mknodat, mknodat) +SYSCALL_NAME(sys_mkdirat, mkdirat) +SYSCALL_NAME(sys_unlinkat, unlinkat) +SYSCALL_NAME(sys_linkat, linkat) +SYSCALL_NAME(sys_chdir, chdir) +SYSCALL_NAME(sys_dup, dup) +SYSCALL_NAME(sys_fstat, fstat) +SYSCALL_NAME(sys_read, read) +SYSCALL_NAME(sys_write, write) +SYSCALL_NAME(sys_close, close) +SYSCALL_NAME(sys_pipe2, pipe2) +SYSCALL_NAME(sys_clone, clone) +SYSCALL_NAME(sys_execve, execve) +SYSCALL_NAME(sys_wait4, wait4) +SYSCALL_NAME(sys_exit, exit) +SYSCALL_NAME(sys_getpid, getpid) +SYSCALL_NAME(sys_brk, brk) +SYSCALL_NAME(sys_kill, kill) +SYSCALL_NAME(sys_nanosleep, nanosleep) +SYSCALL_NAME(sys_reboot, reboot) +SYSCALL_NAME(sys_lseek, lseek) -SYSCALL(fork) -SYSCALL(wait) -SYSCALL(pipe) -SYSCALL(read) -SYSCALL(write) -SYSCALL(close) -SYSCALL(kill) -SYSCALL(exec) -SYSCALL(open) -SYSCALL(mknod) -SYSCALL(unlink) -SYSCALL(fstat) -SYSCALL(link) -SYSCALL(mkdir) -SYSCALL(chdir) -SYSCALL(dup) -SYSCALL(getpid) -SYSCALL(sbrk) -SYSCALL(sleep) -SYSCALL(uptime) -SYSCALL(putc) -SYSCALL(disk_test) -SYSCALL(lseek) -SYSCALL(shutdown) \ No newline at end of file +# === Custom / Debug Syscalls === +SYSCALL_NAME(sys_putc, putc) +SYSCALL_NAME(sys_disk_test, disk_test) \ No newline at end of file -- cgit v1.2.3