From 3b1bb9d531956b8c7877993eaff9e08264e7417f Mon Sep 17 00:00:00 2001 From: kamkow1 Date: Sat, 27 Sep 2025 15:16:26 +0200 Subject: [PATCH] WIP 2 --- base/scripts/init.tb | 2 +- kernel/Makefile | 2 +- kernel/arch/x86_64/x86_64.mk | 2 +- kernel/bitmap/bitmap.c | 11 +- kernel/bitmap/bitmap.h | 2 - kernel/dev/dev.h | 14 ++ kernel/dev/termdev.c | 19 ++ kernel/dev/termdev.h | 13 + kernel/dlmalloc/dlmalloc_port.inc | 2 +- kernel/hal/x86_64/gdt.c | 2 +- kernel/hal/x86_64/intr.c | 4 +- kernel/hal/x86_64/intr0.S | 4 +- kernel/hal/x86_64/switch.S | 12 +- kernel/hal/x86_64/vmm.c | 18 +- kernel/kmain.c | 2 + kernel/pmm/pmm.c | 3 + kernel/proc/proc.c | 24 +- kernel/proc/proc.h | 10 +- kernel/proc/ps2kbproc/ps2kbproc.c | 27 +- kernel/proc/ps2kbproc/ps2kbproc.h | 1 + kernel/proc/termproc/termproc.c | 25 -- kernel/proc/termproc/termproc.h | 11 - kernel/spinlock/spinlock.c | 51 +++- kernel/spinlock/spinlock.h | 3 - kernel/syscall/devctl.c | 65 +++++ kernel/syscall/devctl.h | 9 + kernel/syscall/mman.c | 4 +- kernel/syscall/processctl.c | 6 +- kernel/syscall/sched.c | 2 +- kernel/syscall/syscall.c | 2 + kernel/util/util.h | 6 +- mk/user/x86_64.mk | 5 +- share/sysdefs/devctl.h | 10 + share/sysdefs/processctl.h | 2 +- share/sysdefs/syscall.h | 1 + std/include/stdatomic.h | 30 ++- ulib/Makefile | 2 + ulib/_premain.c | 17 +- ulib/args/args.c | 92 +++++-- ulib/args/args.h | 4 - ulib/assert.h | 15 ++ ulib/devids.h | 8 + ulib/dlmalloc/dlmalloc_port.inc | 8 +- ulib/linklist.h | 6 +- ulib/log.h | 3 +- ulib/putchar.c | 6 +- ulib/string/string.c | 33 +++ ulib/string/string.h | 1 + ulib/syscall/syscall.c | 1 + ulib/system/system.c | 5 + ulib/system/system.h | 2 + ulib/ubsan/ubsan.c | 224 +++++++++++++++++ ulib/ulib.h | 2 + ulib/util/util.h | 6 +- ulib/write/write.c | 161 ++++++++++++ ulib/write/write.h | 10 + user/arch/x86_64/link.ld | 3 +- user/init/main.c | 3 +- user/pctl/ls.c | 2 +- user/tb/interp.c | 399 +++++++++++++++--------------- user/tb/interp.h | 10 +- user/tb/main.c | 40 +-- user/tb/runtime.c | 25 +- 63 files changed, 1087 insertions(+), 407 deletions(-) create mode 100644 kernel/dev/dev.h create mode 100644 kernel/dev/termdev.c create mode 100644 kernel/dev/termdev.h delete mode 100644 kernel/proc/termproc/termproc.c delete mode 100644 kernel/proc/termproc/termproc.h create mode 100644 kernel/syscall/devctl.c create mode 100644 kernel/syscall/devctl.h create mode 100644 share/sysdefs/devctl.h create mode 100644 ulib/assert.h create mode 100644 ulib/devids.h create mode 100644 ulib/ubsan/ubsan.c create mode 100644 ulib/write/write.c create mode 100644 ulib/write/write.h diff --git a/base/scripts/init.tb b/base/scripts/init.tb index a0e76d9..9320f52 100644 --- a/base/scripts/init.tb +++ b/base/scripts/init.tb @@ -1,3 +1,3 @@ -%print "this is an init script!" +%print 'this is an init script!' base:/bin/pctl ls base:/bin/tb -m interactive -preload base:/scripts/rc.tb diff --git a/kernel/Makefile b/kernel/Makefile index b87f1a6..7ca6857 100644 --- a/kernel/Makefile +++ b/kernel/Makefile @@ -55,7 +55,6 @@ SRCFILES += $(call GRABSRC, \ proc \ proc/kproc \ proc/ps2kbproc \ - proc/termproc \ proc/serialproc \ hal \ hal/$(ARCH) \ @@ -67,6 +66,7 @@ SRCFILES += $(call GRABSRC, \ rbuf \ ipc/pipe \ drivers/ps2kb \ + dev \ ) ifeq ($(ARCH),x86_64) diff --git a/kernel/arch/x86_64/x86_64.mk b/kernel/arch/x86_64/x86_64.mk index e87d823..7eb27bd 100644 --- a/kernel/arch/x86_64/x86_64.mk +++ b/kernel/arch/x86_64/x86_64.mk @@ -11,7 +11,7 @@ CFLAGS += -m64 \ -mno-red-zone \ -fno-stack-protector \ -fno-stack-check \ - -O0 \ + -Os \ LDFLAGS += -m elf_x86_64 \ -pie \ diff --git a/kernel/bitmap/bitmap.c b/kernel/bitmap/bitmap.c index 00b3c59..52a41c0 100644 --- a/kernel/bitmap/bitmap.c +++ b/kernel/bitmap/bitmap.c @@ -3,6 +3,7 @@ #include #include "bitmap.h" #include "util/util.h" +#include "kprintf.h" void *bitmap_toptr(BitMap *bm, size_t block) { uint8_t *ptr = (uint8_t *)(bm->mem_start + (block * BITMAP_BLOCK_SIZE)); @@ -104,13 +105,3 @@ void *bitmap_alloc(BitMap *bm, size_t blocks) { void bitmap_free(BitMap *bm, void *base, size_t blocks) { bitmap_markregion(bm, base, BITMAP_BLOCK_SIZE * blocks, 0); } - -size_t bitmap_allocpageframe(BitMap *bm) { - size_t pickedreg = bitmap_freeregion(bm, 1); - bitmap_markblocks(bm, pickedreg, 1, 1); - return (bm->mem_start + (pickedreg * BITMAP_BLOCK_SIZE)); -} - -void bitmap_freepageframe(BitMap *bm, void *addr) { - bitmap_markregion(bm, addr, BITMAP_BLOCK_SIZE * 1, 0); -} diff --git a/kernel/bitmap/bitmap.h b/kernel/bitmap/bitmap.h index e7eff93..f061112 100644 --- a/kernel/bitmap/bitmap.h +++ b/kernel/bitmap/bitmap.h @@ -31,7 +31,5 @@ void bitmap_markregion(BitMap *bm, void *baseptr, size_t size, bool is_used); size_t bitmap_freeregion(BitMap *bm, size_t blocks); void *bitmap_alloc(BitMap *bm, size_t blocks); void bitmap_free(BitMap *bm, void *base, size_t blocks); -size_t bitmap_allocpageframe(BitMap *bm); -void bitmap_freepageframe(BitMap *bm, void *addr); #endif // BITMAP_BITMAP_H_ diff --git a/kernel/dev/dev.h b/kernel/dev/dev.h new file mode 100644 index 0000000..7a16a9e --- /dev/null +++ b/kernel/dev/dev.h @@ -0,0 +1,14 @@ +#ifndef DEV_DEV_H_ +#define DEV_DEV_H_ + +#include + +#define DEV_FNS_MAX 32 + +typedef int32_t (*DevFn)(uint8_t *buffer, size_t len, void *extra); + +typedef struct { + DevFn fns[DEV_FNS_MAX]; +} Dev; + +#endif // DEV_DEV_H_ diff --git a/kernel/dev/termdev.c b/kernel/dev/termdev.c new file mode 100644 index 0000000..6a47a7f --- /dev/null +++ b/kernel/dev/termdev.c @@ -0,0 +1,19 @@ +#include +#include +#include "kprintf.h" +#include "hal/hal.h" +#include "termdev.h" +#include "dev.h" +#include "errors.h" + +Dev TERMDEV; + +int32_t termdev_putch(uint8_t *buffer, size_t len, void *extra) { + kprintf("%.*s", (int)len, (char *)buffer); + return E_OK; +} + +void termdev_init(void) { + hal_memset(&TERMDEV, 0, sizeof(TERMDEV)); + TERMDEV.fns[0] = &termdev_putch; +} diff --git a/kernel/dev/termdev.h b/kernel/dev/termdev.h new file mode 100644 index 0000000..6c72f07 --- /dev/null +++ b/kernel/dev/termdev.h @@ -0,0 +1,13 @@ +#ifndef DEV_TERMDEV_H_ +#define DEV_TERMDEV_H_ + +#include +#include +#include "dev.h" + +int32_t termdev_putch(uint8_t *buffer, size_t len, void *extra); +void termdev_init(void); + +extern Dev TERMDEV; + +#endif // DEV_TERMDEV_H_ diff --git a/kernel/dlmalloc/dlmalloc_port.inc b/kernel/dlmalloc/dlmalloc_port.inc index 2e4613a..5c670cb 100644 --- a/kernel/dlmalloc/dlmalloc_port.inc +++ b/kernel/dlmalloc/dlmalloc_port.inc @@ -49,7 +49,7 @@ int RELEASE_LOCK(SpinLock *sl) { } int INITIAL_LOCK(SpinLock *sl) { - spinlock_release(sl); + spinlock_init(sl); return 0; } diff --git a/kernel/hal/x86_64/gdt.c b/kernel/hal/x86_64/gdt.c index 2634fb7..e69c7e8 100644 --- a/kernel/hal/x86_64/gdt.c +++ b/kernel/hal/x86_64/gdt.c @@ -7,7 +7,7 @@ #define GDT_PRESENT 0x80 #define GDT_TSS 0x89 -#define KSTACK 8192 +#define KSTACK (1024*2*4096) ALIGNED(16) static uint8_t kernelstack[KSTACK]; typedef struct { diff --git a/kernel/hal/x86_64/intr.c b/kernel/hal/x86_64/intr.c index 640b541..60e32aa 100644 --- a/kernel/hal/x86_64/intr.c +++ b/kernel/hal/x86_64/intr.c @@ -178,8 +178,6 @@ void hal_syscalldispatch(IntrStackFrame *frame) { frame->regs.rax = E_BADSYSCALL; return; } - uint64_t cr3; - asm volatile("mov %%cr3, %0" : "=r"(cr3)); int32_t ret = fn(frame, frame->regs.rdi, frame->regs.rsi, frame->regs.rdx, frame->regs.r10, frame->regs.r8, frame->regs.r9); @@ -215,7 +213,7 @@ void intr_handleintr(IntrStackFrame *frame) { break; case INTR_IRQBASE+1: int32_t c = ps2kb_intr(); - if (c >= 0) { + if (c >= 0 && PS2KB_BUF.init) { uint8_t b = c; spinlock_acquire(&PS2KB_BUF.spinlock); rbuf_push(&PS2KB_BUF.rbuf, b); diff --git a/kernel/hal/x86_64/intr0.S b/kernel/hal/x86_64/intr0.S index bcada08..62a6c50 100644 --- a/kernel/hal/x86_64/intr0.S +++ b/kernel/hal/x86_64/intr0.S @@ -62,13 +62,13 @@ .endm .macro _vecintr_bodygen + cli _push_regs cld - mov %rsp, %rdi + movq %rsp, %rdi call intr_handleintr _pop_regs add $0x10, %rsp - iretq .endm diff --git a/kernel/hal/x86_64/switch.S b/kernel/hal/x86_64/switch.S index 91a9363..670ceed 100644 --- a/kernel/hal/x86_64/switch.S +++ b/kernel/hal/x86_64/switch.S @@ -2,15 +2,11 @@ .global hal_switchproc hal_switchproc: - mov %cr3, %rcx - cmp %rsi, %rcx - je .done - mov %rsi, %cr3 -.done: + testq %rsi, %rsi + je 1f + movq %rsi, %cr3 +1: mov %rdi, %rsp - _pop_regs add $0x10, %rsp - iretq - diff --git a/kernel/hal/x86_64/vmm.c b/kernel/hal/x86_64/vmm.c index 2ba999c..e2a57ea 100644 --- a/kernel/hal/x86_64/vmm.c +++ b/kernel/hal/x86_64/vmm.c @@ -29,12 +29,16 @@ PgIndex hal_vmm_pageindex(uint64_t vaddr) { return ret; } -uint64_t *hal_vmm_nexttable(uint64_t *table, uint64_t ent) { +uint64_t *hal_vmm_nexttable(uint64_t *table, uint64_t ent, bool alloc) { uint64_t entry = table[ent]; uint64_t phys; if (entry & HAL_PG_PRESENT) { phys = entry & ~0xFFFULL; } else { + if (!alloc) { + return NULL; + } + uint8_t *newphys = pmm_alloc(1); phys = (uint64_t)newphys; hal_memset(VIRT(phys), 0, HAL_PAGE_SIZE); @@ -47,9 +51,9 @@ void hal_vmm_map_page(uint64_t cr3phys, uint64_t virtaddr, uint64_t physaddr, ui uint64_t *pml4 = (uint64_t *)VIRT(cr3phys); PgIndex pi = hal_vmm_pageindex(virtaddr); - uint64_t *pml3 = hal_vmm_nexttable(pml4, pi.pml4); - uint64_t *pml2 = hal_vmm_nexttable(pml3, pi.pml3); - uint64_t *pml1 = hal_vmm_nexttable(pml2, pi.pml2); + uint64_t *pml3 = hal_vmm_nexttable(pml4, pi.pml4, true); + uint64_t *pml2 = hal_vmm_nexttable(pml3, pi.pml3, true); + uint64_t *pml1 = hal_vmm_nexttable(pml2, pi.pml2, true); uint64_t *pte = &pml1[pi.pml1]; *pte = (physaddr & ~0xFFFULL) | ((uint64_t)flags & 0x7ULL); @@ -59,9 +63,9 @@ void hal_vmm_unmap_page(uint64_t cr3phys, uint64_t virtaddr, uint64_t physaddr) uint64_t *pml4 = (uint64_t *)VIRT(cr3phys); PgIndex pi = hal_vmm_pageindex(virtaddr); - uint64_t *pml3 = hal_vmm_nexttable(pml4, pi.pml4); - uint64_t *pml2 = hal_vmm_nexttable(pml3, pi.pml3); - uint64_t *pml1 = hal_vmm_nexttable(pml2, pi.pml2); + uint64_t *pml3 = hal_vmm_nexttable(pml4, pi.pml4, false); + uint64_t *pml2 = hal_vmm_nexttable(pml3, pi.pml3, false); + uint64_t *pml1 = hal_vmm_nexttable(pml2, pi.pml2, false); uint64_t *pte = &pml1[pi.pml1]; *pte &= ~HAL_PG_PRESENT; diff --git a/kernel/kmain.c b/kernel/kmain.c index 3ad8da2..4dbe81f 100644 --- a/kernel/kmain.c +++ b/kernel/kmain.c @@ -11,6 +11,7 @@ #include "storedev/storedev.h" #include "util/util.h" #include "proc/proc.h" +#include "dev/termdev.h" const char *human_size(uint64_t bytes, char *buf, size_t bufsize) { static const char *units[] = { "B", "KiB", "MiB", "GiB", "TiB", "PiB" }; @@ -64,6 +65,7 @@ void kmain(void) { storedev_init(); baseimg_init(); vfs_init(); + termdev_init(); proc_init(); for(;;); diff --git a/kernel/pmm/pmm.c b/kernel/pmm/pmm.c index d8b742c..1f44a13 100644 --- a/kernel/pmm/pmm.c +++ b/kernel/pmm/pmm.c @@ -40,6 +40,9 @@ void pmm_init(void) { hal_memset(bm->map, 0xff, bm->nbytes); for (size_t i = 0; i < BOOT_INFO.memmap_entrycount; i++) { struct limine_memmap_entry *entry = BOOT_INFO.memmap_entries[i]; + if (entry == memmap_ent) { + continue; + } // mark usable as 0 and unusable as 1 bitmap_markregion(bm, (void *)entry->base, entry->length, entry->type != LIMINE_MEMMAP_USABLE); } diff --git a/kernel/proc/proc.c b/kernel/proc/proc.c index 44ecc46..0255854 100644 --- a/kernel/proc/proc.c +++ b/kernel/proc/proc.c @@ -15,7 +15,6 @@ #include "ipc/pipe/pipe.h" #include "kproc/kproc.h" #include "ps2kbproc/ps2kbproc.h" -#include "termproc/termproc.h" #include "serialproc/serialproc.h" #include "sysdefs/processctl.h" @@ -181,6 +180,7 @@ Proc *proc_spawnuser(char *mountpoint, char *path) { proc->mman_map_base = PROC_MMAN_MAP_BASE; spinlock_init(&proc->bcast_pipes.spinlock); spinlock_init(&proc->pipes_spinlock); + spinlock_init(&proc->devs_spinlock); proc->pipes[0] = dlmalloc(sizeof(IpcPipe)); ipc_pipeinit(proc->pipes[0], proc->pid); @@ -308,26 +308,20 @@ void proc_init(void) { spinlock_init(&PROCS.spinlock); PROCS.procs = NULL; - kproc_init(proc_spawnkern(&kproc_fn, "kproc")); - proc_register(KPROC); - PROCS.current = KPROC; - KPROC->state = PROC_READY; + /* kproc_init(proc_spawnkern(&kproc_fn, "kproc")); */ + /* proc_register(KPROC); */ + /* PROCS.current = KPROC; */ + /* KPROC->state = PROC_READY; */ - ps2kbproc_init(proc_spawnkern(&ps2kbproc_fn, "ps2kbproc")); - proc_register(PS2KBPROC); - PS2KBPROC->state = PROC_READY; - - termproc_init(proc_spawnkern(&termproc_fn, "termproc")); - proc_register(TERMPROC); - TERMPROC->state = PROC_READY; + /* ps2kbproc_init(proc_spawnkern(&ps2kbproc_fn, "ps2kbproc")); */ + /* proc_register(PS2KBPROC); */ + /* PS2KBPROC->state = PROC_READY; */ /* serialproc_init(proc_spawnkern(&serialproc_fn, "serialproc")); */ /* proc_register(SERIALPROC); */ Proc *init = proc_spawnuser("base", "/bin/init"); - ipc_pipefree(init->pipes[0]); - dlfree(init->pipes[0]); - init->pipes[0] = TERMPROC->pipes[1]; + PROCS.current = init; proc_register(init); init->state = PROC_READY; diff --git a/kernel/proc/proc.h b/kernel/proc/proc.h index 1b2461d..4344636 100644 --- a/kernel/proc/proc.h +++ b/kernel/proc/proc.h @@ -8,6 +8,7 @@ #include "vfs/vfs.h" #include "ipc/pipe/pipe.h" #include "sysdefs/processctl.h" +#include "dev/dev.h" #define PROC_NAME_MAX 0x100 @@ -18,9 +19,10 @@ #define PROC_VFSHANDLES_MAX 0x80 #define PROC_PIPEHANDLES_MAX 0x20 +#define PROC_DEVHANDLES_MAX 0x20 #define PROC_MMAN_MAP_BASE 0x0000100000000000ULL -#define PROC_USER_STACK_TOP 0x0000800000000000ULL +#define PROC_USER_STACK_TOP 0x00007FFFFFFFF000ULL typedef struct { IntrStackFrame trapframe; @@ -56,12 +58,18 @@ typedef struct Proc { VfsObj *vobjs[PROC_VFSHANDLES_MAX]; uint64_t vobjcnt; + IpcPipe *pipes[PROC_PIPEHANDLES_MAX]; SpinLock pipes_spinlock; + struct { IpcPipe *list; SpinLock spinlock; } bcast_pipes; + + Dev *devs[PROC_DEVHANDLES_MAX]; + SpinLock devs_spinlock; + struct { ProcArg *list; size_t len; diff --git a/kernel/proc/ps2kbproc/ps2kbproc.c b/kernel/proc/ps2kbproc/ps2kbproc.c index b6956e5..8e62045 100644 --- a/kernel/proc/ps2kbproc/ps2kbproc.c +++ b/kernel/proc/ps2kbproc/ps2kbproc.c @@ -7,7 +7,7 @@ #include "ps2kbproc.h" Proc *PS2KBPROC = NULL; -Ps2KbFastBuf PS2KB_BUF; +Ps2KbFastBuf PS2KB_BUF = {0}; void ps2kbproc_init(Proc *proc) { PS2KBPROC = proc; @@ -17,22 +17,23 @@ void ps2kbproc_init(Proc *proc) { uint8_t *buf = dlmalloc(IPC_PIPE_MAX); rbuf_init(&PS2KB_BUF.rbuf, buf, IPC_PIPE_MAX); spinlock_init(&PS2KB_BUF.spinlock); + PS2KB_BUF.init = true; } void ps2kbproc_fn(void) { for (;;) { - uint8_t b = 0; - spinlock_acquire(&PS2KB_BUF.spinlock); - if (rbuf_pop(&PS2KB_BUF.rbuf, &b) == 0) { - spinlock_acquire(&PS2KBPROC->bcast_pipes.spinlock); - IpcPipe *head = PS2KBPROC->bcast_pipes.list; - while (head != NULL) { - ipc_pipewrite(head, &b, 1); - head = head->next; - } - spinlock_release(&PS2KBPROC->bcast_pipes.spinlock); - } - spinlock_release(&PS2KB_BUF.spinlock); + /* uint8_t b = 0; */ + /* spinlock_acquire(&PS2KB_BUF.spinlock); */ + /* if (rbuf_pop(&PS2KB_BUF.rbuf, &b) == 0) { */ + /* spinlock_acquire(&PS2KBPROC->bcast_pipes.spinlock); */ + /* IpcPipe *head = PS2KBPROC->bcast_pipes.list; */ + /* while (head != NULL) { */ + /* ipc_pipewrite(head, &b, 1); */ + /* head = head->next; */ + /* } */ + /* spinlock_release(&PS2KBPROC->bcast_pipes.spinlock); */ + /* } */ + /* spinlock_release(&PS2KB_BUF.spinlock); */ } } diff --git a/kernel/proc/ps2kbproc/ps2kbproc.h b/kernel/proc/ps2kbproc/ps2kbproc.h index 710130b..36e3b88 100644 --- a/kernel/proc/ps2kbproc/ps2kbproc.h +++ b/kernel/proc/ps2kbproc/ps2kbproc.h @@ -9,6 +9,7 @@ typedef struct { RBuf rbuf; SpinLock spinlock; + bool init; } Ps2KbFastBuf; extern Proc *PS2KBPROC; diff --git a/kernel/proc/termproc/termproc.c b/kernel/proc/termproc/termproc.c deleted file mode 100644 index 16ad616..0000000 --- a/kernel/proc/termproc/termproc.c +++ /dev/null @@ -1,25 +0,0 @@ -#include -#include "proc/proc.h" -#include "ipc/pipe/pipe.h" -#include "kprintf.h" -#include "hal/hal.h" -#include "dlmalloc/malloc.h" -#include "spinlock/spinlock.h" - -Proc *TERMPROC; - -void termproc_init(Proc *proc) { - TERMPROC = proc; - TERMPROC->pipes[1] = dlmalloc(sizeof(IpcPipe)); - ipc_pipeinit(TERMPROC->pipes[1], TERMPROC->pid); -} - -void termproc_fn(void) { - for (;;) { - char c = 0; - int32_t read = ipc_piperead(TERMPROC->pipes[1], (uint8_t *)&c, 1); - if (read > 0) { - kprintf("%c", c); - } - } -} diff --git a/kernel/proc/termproc/termproc.h b/kernel/proc/termproc/termproc.h deleted file mode 100644 index ecb98e6..0000000 --- a/kernel/proc/termproc/termproc.h +++ /dev/null @@ -1,11 +0,0 @@ -#ifndef PROC_TERMPROC_TERMPROC_H_ -#define PROC_TERMPROC_TERMPROC_H_ - -#include "proc/proc.h" - -extern Proc *TERMPROC; - -void termproc_init(Proc *proc); -void termproc_fn(void); - -#endif // PROC_TERMPROC_TERMPROC_H_ diff --git a/kernel/spinlock/spinlock.c b/kernel/spinlock/spinlock.c index 23521a8..c290023 100644 --- a/kernel/spinlock/spinlock.c +++ b/kernel/spinlock/spinlock.c @@ -5,25 +5,62 @@ #include "hal/hal.h" #include "kprintf.h" +#define SPINLOCK_IRQ_DBG 1 + +#define SPINLOCK_HINT() asm volatile("pause") + +struct { + atomic_uint64_t irq_flags; + atomic_int irq_nest; +} IRQ_CTX; + void spinlock_init(SpinLock *sl) { atomic_store(&sl->lock, false); - sl->flags = 0; } -uint64_t spinlock_irqsave(void) { +uint64_t irqsave(void) { uint64_t flags; - asm volatile("pushfq; cli; popq %0" : "=r"(flags) :: "memory"); + asm volatile("pushfq; cli; popq %0" : "=r"(flags) :: "memory", "cc"); return flags; } -void spinlock_irqrestore(uint64_t flags) { +void irqrestore(uint64_t flags) { if (flags & (1<<9)) { - asm volatile("sti" ::: "memory"); + asm volatile("sti" ::: "memory", "cc"); + } +} + +void irqsave_nested(void) { + if (atomic_load(&IRQ_CTX.irq_nest) == 0) { + atomic_store(&IRQ_CTX.irq_flags, irqsave()); + } + atomic_inc(&IRQ_CTX.irq_nest); + + #if SPINLOCK_IRQ_DBG + if (atomic_load(&IRQ_CTX.irq_nest) < 0) { + kprintf("IRQ_CTX.irq_nest underflow\n"); + hal_hang(); + } + #endif +} + +void irqrestore_nested(void) { + #if SPINLOCK_IRQ_DBG + int irq_nest = atomic_load(&IRQ_CTX.irq_nest); + if (irq_nest <= 0) { + kprintf("spinlock: irqs restored too many times: %d\n", irq_nest); + hal_hang(); + } + #endif + + atomic_dec(&IRQ_CTX.irq_nest); + if (atomic_load(&IRQ_CTX.irq_nest) == 0) { + irqrestore(atomic_load(&IRQ_CTX.irq_flags)); } } void spinlock_acquire(SpinLock *sl) { - sl->flags = spinlock_irqsave(); + irqsave_nested(); while (atomic_test_and_set_explicit(&sl->lock, memory_order_acquire)) { SPINLOCK_HINT(); @@ -33,6 +70,6 @@ void spinlock_acquire(SpinLock *sl) { void spinlock_release(SpinLock *sl) { atomic_clear_flag_explicit(&sl->lock, memory_order_release); - spinlock_irqrestore(sl->flags); + irqrestore_nested(); } diff --git a/kernel/spinlock/spinlock.h b/kernel/spinlock/spinlock.h index c802060..80a46ea 100644 --- a/kernel/spinlock/spinlock.h +++ b/kernel/spinlock/spinlock.h @@ -6,11 +6,8 @@ typedef struct { atomic_bool lock; - uint64_t flags; } SpinLock; -#define SPINLOCK_HINT() asm volatile("pause") - void spinlock_init(SpinLock *sl); void spinlock_acquire(SpinLock *sl); void spinlock_release(SpinLock *sl); diff --git a/kernel/syscall/devctl.c b/kernel/syscall/devctl.c new file mode 100644 index 0000000..3e022c5 --- /dev/null +++ b/kernel/syscall/devctl.c @@ -0,0 +1,65 @@ +#include +#include +#include "kprintf.h" +#include "syscall.h" +#include "errors.h" +#include "spinlock/spinlock.h" +#include "proc/proc.h" +#include "sysdefs/devctl.h" +#include "dev/termdev.h" +#include "util/util.h" + +Dev *DEVS[] = { + [0x10] = &TERMDEV, +}; + +int32_t SYSCALL5(sys_devctl, devh1, cmd1, buffer1, len1, extra1) { + uint64_t *devh = (uint64_t *)devh1; + uint64_t cmd = cmd1; + int32_t ret = E_OK; + + spinlock_acquire(&PROCS.spinlock); + Proc *proc = PROCS.current; + spinlock_release(&PROCS.spinlock); + + switch (cmd) { + case DEVCTL_GET_HANDLE: { + uint64_t devid = buffer1; + if (devid >= LEN(DEVS)) { + ret = E_INVALIDARGUMENT; + goto done; + } + + bool found = false; + for (size_t i = 0; i < PROC_DEVHANDLES_MAX; i++) { + if (proc->devs[i] == NULL) { + found = true; + proc->devs[i] = DEVS[devid]; + break; + } + } + + if (!found) { + ret = E_NOENTRY; + goto done; + } + } break; + default: { + if (devh == NULL) { + ret = E_INVALIDARGUMENT; + goto done; + } + + if (cmd >= DEV_FNS_MAX) { + ret = E_INVALIDARGUMENT; + goto done; + } + + Dev *dev = proc->devs[*devh]; + ret = dev->fns[cmd]((uint8_t *)buffer1, (size_t)len1, (void *)extra1); + } break; + } + +done: + return ret; +} diff --git a/kernel/syscall/devctl.h b/kernel/syscall/devctl.h new file mode 100644 index 0000000..4a759f5 --- /dev/null +++ b/kernel/syscall/devctl.h @@ -0,0 +1,9 @@ +#ifndef SYSCALL_DEVCTL_H_ +#define SYSCALL_DEVCTL_H_ + +#include +#include "syscall.h" + +int32_t SYSCALL5(sys_devctl, devh1, cmd1, buffer1, len1, extra1); + +#endif // SYSCALL_DEVCTL_H_ diff --git a/kernel/syscall/mman.c b/kernel/syscall/mman.c index 4f5ad28..3414e99 100644 --- a/kernel/syscall/mman.c +++ b/kernel/syscall/mman.c @@ -10,6 +10,7 @@ #include "sysdefs/mman.h" #include "bootinfo/bootinfo.h" #include "dlmalloc/malloc.h" +#include "kprintf.h" int32_t SYSCALL5(sys_mman_map, addr1, size1, prot1, flags1, out1) { uint8_t *addr = (uint8_t *)addr1; @@ -27,9 +28,6 @@ int32_t SYSCALL5(sys_mman_map, addr1, size1, prot1, flags1, out1) { size_t pages = _DIV_ROUNDUP(size, HAL_PAGE_SIZE); uint8_t *phys = (uint8_t *)pmm_alloc(pages); - if (phys == NULL) { - return E_NOMEMORY; - } hal_memset(VIRT(phys), 0, pages * HAL_PAGE_SIZE); spinlock_acquire(&PROCS.spinlock); diff --git a/kernel/syscall/processctl.c b/kernel/syscall/processctl.c index 40f4752..33ec538 100644 --- a/kernel/syscall/processctl.c +++ b/kernel/syscall/processctl.c @@ -63,8 +63,10 @@ int32_t SYSCALL5(sys_processctl, pid1, cmd1, arg1, arg2, arg3) { size_t argslen = arg3; char *(*args)[] = (char *(*)[])arg2; - for (size_t i = 0; i < argslen; i++) { - PROC_ARG(newproc, (*args)[i]); + if (args != NULL && argslen > 0) { + for (size_t i = 0; i < argslen; i++) { + PROC_ARG(newproc, (*args)[i]); + } } for (size_t i = 0; i < PROC_PIPEHANDLES_MAX; i++) { diff --git a/kernel/syscall/sched.c b/kernel/syscall/sched.c index 29714e1..f659307 100644 --- a/kernel/syscall/sched.c +++ b/kernel/syscall/sched.c @@ -11,7 +11,7 @@ int32_t SYSCALL0(sys_schedrelease) { Proc *proc = PROCS.current; spinlock_release(&PROCS.spinlock); - proc_sched((void *)frame); + /* proc_sched((void *)frame); */ return E_OK; } diff --git a/kernel/syscall/syscall.c b/kernel/syscall/syscall.c index ee3d38a..479c961 100644 --- a/kernel/syscall/syscall.c +++ b/kernel/syscall/syscall.c @@ -8,6 +8,7 @@ #include "ipcpipe.h" #include "mman.h" #include "sched.h" +#include "devctl.h" int32_t SYSCALL1(sys_debugprint, string) { char *p = (char *)string; @@ -23,4 +24,5 @@ SyscallFn SYSCALL_TABLE[SYSCALLS_MAX] = { [SYS_MMAN_MAP] = &sys_mman_map, [SYS_MMAN_UNMAP] = &sys_mman_unmap, [SYS_SCHEDRELEASE] = &sys_schedrelease, + [SYS_DEVCTL] = &sys_devctl, }; diff --git a/kernel/util/util.h b/kernel/util/util.h index 0623711..c9b7de6 100644 --- a/kernel/util/util.h +++ b/kernel/util/util.h @@ -58,14 +58,14 @@ } while(0) #define LL_FOREACH_SAFE(head, var, tmp) \ - for (typeof(head) var = (head), tmp = (var ? var->next : NULL); \ + for (var = (head), tmp = (var ? var->next : NULL); \ var != NULL; \ var = tmp, tmp = (var ? var->next : NULL) \ ) #define LL_FOREACH_SAFE_IDX(head, var, tmp, idx) \ - for (typeof(head) var = (head), tmp = (var ? var->next : NULL); \ - var != NULL && ((idx) = 0, 1); \ + for ((idx) = 0, var = (head), tmp = (var ? var->next : NULL); \ + var != NULL; \ var = tmp, tmp = (var ? var->next : NULL), (idx)++) #define LL_FOREACH_SAFE_IDX_LIMIT(head, var, tmp, idx, max) \ diff --git a/mk/user/x86_64.mk b/mk/user/x86_64.mk index 9f65ffb..91d4159 100644 --- a/mk/user/x86_64.mk +++ b/mk/user/x86_64.mk @@ -10,4 +10,7 @@ CFLAGS += -m64 \ -fno-stack-check \ -fno-builtin \ -fno-omit-frame-pointer \ - -O0 \ + -fno-strict-aliasing \ + -O1 \ + -mno-tls-direct-seg-refs \ + #-fsanitize=undefined diff --git a/share/sysdefs/devctl.h b/share/sysdefs/devctl.h new file mode 100644 index 0000000..22acb9b --- /dev/null +++ b/share/sysdefs/devctl.h @@ -0,0 +1,10 @@ +#ifndef SHARE_SYSDEFS_DEVCTL_H_ +#define SHARE_SYSDEFS_DEVCTL_H_ + +enum { + DEVCTL_GET_HANDLE = 100, +}; + +typedef uint64_t Dev_t; + +#endif // SHARE_SYSDEFS_DEVCTL_H_ diff --git a/share/sysdefs/processctl.h b/share/sysdefs/processctl.h index cde07fd..2f57e25 100644 --- a/share/sysdefs/processctl.h +++ b/share/sysdefs/processctl.h @@ -1,7 +1,7 @@ #ifndef SHARE_HDRS_PROCESSCTL_H_ #define SHARE_HDRS_PROCESSCTL_H_ -#define PROC_ARG_MAX 0x400 +#define PROC_ARG_MAX 128 enum { PCTL_KILL = 0, diff --git a/share/sysdefs/syscall.h b/share/sysdefs/syscall.h index 3f6e0b3..c547489 100644 --- a/share/sysdefs/syscall.h +++ b/share/sysdefs/syscall.h @@ -9,6 +9,7 @@ enum { SYS_MMAN_MAP = 5, SYS_MMAN_UNMAP = 6, SYS_SCHEDRELEASE = 7, + SYS_DEVCTL = 8, }; #endif // SHARE_HDRS_SYSCALL_H_ diff --git a/std/include/stdatomic.h b/std/include/stdatomic.h index c111f3a..a2185a4 100644 --- a/std/include/stdatomic.h +++ b/std/include/stdatomic.h @@ -11,14 +11,14 @@ #define atomic_load_explicit __atomic_load_n #define atomic_store_explicit __atomic_store_n -#define atomic_store(p, v) atomic_store_explicit(p, v, memory_order_relaxed) -#define atomic_load(p) atomic_load_explicit(p, memory_order_relaxed) +#define atomic_store(p, v) atomic_store_explicit(p, v, memory_order_seq_cst) +#define atomic_load(p) atomic_load_explicit(p, memory_order_seq_cst) #define atomic_compare_exchange_weak(p, old, new) \ - __atomic_compare_exchange_n(p, old, new, true, memory_order_relaxed, memory_order_relaxed) + __atomic_compare_exchange_n(p, old, new, true, memory_order_seq_cst, memory_order_seq_cst) #define atomic_compare_exchange_strong(p, old, new) \ - __atomic_compare_exchange_n(p, old, new, false, memory_order_relaxed, memory_order_relaxed) + __atomic_compare_exchange_n(p, old, new, false, memory_order_seq_cst, memory_order_seq_cst) #define atomic_test_and_set_explicit(p, memory_order) \ __atomic_test_and_set(p, memory_order) @@ -26,6 +26,28 @@ #define atomic_clear_flag_explicit(p, memory_order) \ __atomic_clear(p, memory_order) +#define atomic_inc_explicit(p, memory_order) \ + __atomic_fetch_add(p, 1, memory_order) + +#define atomic_inc(p) \ + atomic_inc_explicit(p, memory_order_seq_cst) + +#define atomic_dec_explicit(p, memory_order) \ + __atomic_fetch_sub(p, 1, memory_order) + +#define atomic_dec(p) \ + atomic_dec_explicit(p, memory_order_seq_cst) + #define atomic_bool _Atomic(bool) +#define atomic_int _Atomic(int) +#define atomic_uint _Atomic(unsigned int) +#define atomic_int8_t _Atomic(int8_t) +#define atomic_uint8_t _Atomic(uint8_t) +#define atomic_int16_t _Atomic(int16_t) +#define atomic_uint16_t _Atomic(uint16_t) +#define atomic_int32_t _Atomic(int32_t) +#define atomic_uint32_t _Atomic(uint32_t) +#define atomic_int64_t _Atomic(int64_t) +#define atomic_uint64_t _Atomic(uint64_t) #endif diff --git a/ulib/Makefile b/ulib/Makefile index b9309ad..38830d1 100644 --- a/ulib/Makefile +++ b/ulib/Makefile @@ -14,6 +14,8 @@ SRCFILES := $(call GRABSRC, \ sync \ args \ util \ + ubsan \ + write \ ) CFLAGS += -isystem $(ROOT)/share -isystem $(ROOT)/ulib -isystem $(ROOT)/std/include \ diff --git a/ulib/_premain.c b/ulib/_premain.c index 81f4a95..3b38dea 100644 --- a/ulib/_premain.c +++ b/ulib/_premain.c @@ -2,10 +2,13 @@ #include #include #include +#include #include #include #include #include +#include +#include extern void main(void); extern uint8_t _bss_start[]; @@ -18,24 +21,28 @@ void clearbss(void) { } } -char **_args; +#define MAX_ARGS 15 +static char *_args[MAX_ARGS]; + size_t _argslen; char **args(void) { - return _args; + return (char **)_args; } size_t argslen(void) { return _argslen; } +Dev_t termdev; + // ulib initialization goes here void _premain(void) { clearbss(); - #define MAX_ARGS 30 - _args = (char **)dlmalloc(MAX_ARGS * sizeof(char *)); - for (size_t i = 0; i < MAX_ARGS; i++) { + devctl(&termdev, DEVCTL_GET_HANDLE, (uint8_t *)DEV_TERMDEV, 0, 0); + + for (size_t i = 0; i < ARRLEN(_args); i++) { _args[i] = dlmalloc(PROC_ARG_MAX); } diff --git a/ulib/args/args.c b/ulib/args/args.c index 61f0d8f..24cb5fe 100644 --- a/ulib/args/args.c +++ b/ulib/args/args.c @@ -5,35 +5,89 @@ #include #include #include +#include int32_t parse_args(char **argv, size_t argc, Arg *defs) { + #define CONSUME_TK() i++ + + if (!argv || !defs) { + return E_INVALIDARGUMENT; + } + for (size_t i = 0; i < argc; i++) { - if (argv[i][0] == '-' && argv[i][1] != '\0') { - char *optname = argv[i]; + char *arg = argv[i]; + if (!arg) { + continue; + } + + if (arg[0] == '-' && arg[1] != '\0') { size_t j = 0; while (!defs[j].end) { Arg *def = &defs[j]; - if (string_strcmp(def->shortname, optname) == 0) { - if (i < argc - 1) { - switch (def->expected_value) { - case ARG_STRING: - *((char **)def->ptr) = argv[i+1]; - break; - case ARG_BOOL: - *((bool *)def->ptr) = string_strcmp(argv[i+1], "yes") == 0; - break; - case ARG_INT: { - char *end; - *((int32_t *)def->ptr) = string_conv_strtol(argv[i+1], &end, 10); - } break; - } - i++; - } + + if (!def->shortname || !def->ptr) { + j++; + continue; } + + if (string_strcmp(def->shortname, arg) == 0) { + bool have_next = (i + 1) < argc && argv[i + 1] != NULL; + char *nexttk = have_next ? argv[i + 1] : NULL; + + if (nexttk && nexttk[0] == '-' && nexttk[1] != '\0') { + have_next = false; + nexttk = NULL; + } + + switch (def->expected_value) { + case ARG_STRING: + if (!have_next) { + break; + } + *((char **)def->ptr) = nexttk; + CONSUME_TK(); + break; + case ARG_BOOL: + if (!have_next) { + *((bool *)def->ptr) = true; + } else { + if (string_strcmp(nexttk, "yes") == 0) { + *((bool *)def->ptr) = true; + CONSUME_TK(); + } else if (string_strcmp(nexttk, "no") == 0) { + *((bool *)def->ptr) = false; + CONSUME_TK(); + } else { + *((bool *)def->ptr) = true; + } + } + break; + case ARG_INT: + if (!have_next) { + break; + } + char *endptr = NULL; + long val = string_conv_strtol(nexttk, &endptr, 10); + if (endptr == NULL) { + break; + } + if (*endptr != '\0') { + break; + } + *((int32_t *)def->ptr) = (int32_t)val; + CONSUME_TK(); + break; + default: + break; + } + + break; + } + j++; } } } - return ARGP_OK; + return E_OK; } diff --git a/ulib/args/args.h b/ulib/args/args.h index f9a2039..1e59d1e 100644 --- a/ulib/args/args.h +++ b/ulib/args/args.h @@ -28,10 +28,6 @@ typedef struct { #define ARG_END() ((Arg){ .end = true, }) -enum { - ARGP_OK = 0, -}; - int32_t parse_args(char **argv, size_t argc, Arg *defs); #endif // ULIB_ARGS_H_ diff --git a/ulib/assert.h b/ulib/assert.h new file mode 100644 index 0000000..ae48801 --- /dev/null +++ b/ulib/assert.h @@ -0,0 +1,15 @@ +#ifndef ULIB_ASSERT_H_ +#define ULIB_ASSERT_H_ + +#include +#include + +#define ASSERT(X, fmt, ...) \ + do { \ + if (!(X)) { \ + uprintf("ASSERT %s:%d in %s "fmt, __FILE__, __LINE__, __func__, ##__VA_ARGS__); \ + quit(); \ + } \ + } while(0) + +#endif // ULIB_ASSERT_H_ diff --git a/ulib/devids.h b/ulib/devids.h new file mode 100644 index 0000000..6269b76 --- /dev/null +++ b/ulib/devids.h @@ -0,0 +1,8 @@ +#ifndef ULIB_DEVIDS_H_ +#define ULIB_DEVIDS_H_ + +enum { + DEV_TERMDEV = 0x10, +}; + +#endif // ULIB_DEVIDS_H_ diff --git a/ulib/dlmalloc/dlmalloc_port.inc b/ulib/dlmalloc/dlmalloc_port.inc index 65abcd6..ec6ed27 100644 --- a/ulib/dlmalloc/dlmalloc_port.inc +++ b/ulib/dlmalloc/dlmalloc_port.inc @@ -8,6 +8,7 @@ #include #include #include +#include #define USE_DL_PREFIX 1 #define LACKS_SYS_TYPES_H 1 @@ -23,7 +24,7 @@ #define LACKS_SCHED_H 1 #define HAVE_MMAP 1 #define HAVE_MORECORE 0 -#define ABORT uprintf("dlmalloc: Aborting...\n") +#define ABORT writefmt("dlmalloc: Aborting...\n") #define MALLOC_FAILURE_ACTION #define USE_LOCKS 2 #define malloc_getpagesize 0x1000 @@ -61,8 +62,9 @@ static size_t _roundpage(size_t sz) { #define O_RDWR 0 #define EMUL_DEV_ZERO_FD 123 +#define EMUL_MAP_FAILED ((void *)-1) -int open(char *path, int flags) { +int open(const char *path, int flags, ...) { return EMUL_DEV_ZERO_FD; } @@ -73,7 +75,7 @@ void *mmap(void *addr, size_t len, int prot, int flags, int fd, int off) { int32_t err = mman_map(NULL, need, MMAN_MAP_PF_RW, 0, &outaddr); if (err != E_OK || outaddr == NULL) { - return NULL; + return EMUL_MAP_FAILED; } if (fd == EMUL_DEV_ZERO_FD) { diff --git a/ulib/linklist.h b/ulib/linklist.h index 8f66b13..07df5e7 100644 --- a/ulib/linklist.h +++ b/ulib/linklist.h @@ -53,14 +53,14 @@ } while(0) #define LL_FOREACH_SAFE(head, var, tmp) \ - for (typeof(head) var = (head), tmp = (var ? var->next : NULL); \ + for (var = (head), tmp = (var ? var->next : NULL); \ var != NULL; \ var = tmp, tmp = (var ? var->next : NULL) \ ) #define LL_FOREACH_SAFE_IDX(head, var, tmp, idx) \ - for (typeof(head) var = (head), tmp = (var ? var->next : NULL); \ - var != NULL && ((idx) = 0, 1); \ + for ((idx) = 0, var = (head), tmp = (var ? var->next : NULL); \ + var != NULL; \ var = tmp, tmp = (var ? var->next : NULL), (idx)++) #define LL_FOREACH_SAFE_IDX_LIMIT(head, var, tmp, idx, max) \ diff --git a/ulib/log.h b/ulib/log.h index 757ae8f..1f0d138 100644 --- a/ulib/log.h +++ b/ulib/log.h @@ -2,6 +2,7 @@ #define ULIB_LOG_H_ #include +#include enum { LOG_ERR, @@ -12,6 +13,6 @@ enum { static const char *_LOG_STR[] = { "ERROR", "DEBUG", "INFO", "WARNING" }; -#define LOG(mode, fmt, ...) uprintf("%s: "fmt, _LOG_STR[(mode)], ##__VA_ARGS__); +#define LOG(mode, fmt, ...) writefmt("{s}: "fmt, _LOG_STR[(mode)], ##__VA_ARGS__); #endif // ULIB_LOG_H_ diff --git a/ulib/putchar.c b/ulib/putchar.c index 7e0b4c6..61994da 100644 --- a/ulib/putchar.c +++ b/ulib/putchar.c @@ -1,9 +1,11 @@ #include #include #include +#include #include +extern Dev_t termdev; + void putchar_(char c) { - char buf = c; - ipcpipe(IPCPIPE_SELFPID, IPCPIPE_OUT, IPCPIPE_WRITE, (uint8_t *)&buf, sizeof(buf)); + devctl(&termdev, 0x00, (uint8_t *)&c, 1, 0); } diff --git a/ulib/string/string.c b/ulib/string/string.c index 9664a50..88ab50f 100644 --- a/ulib/string/string.c +++ b/ulib/string/string.c @@ -1,5 +1,6 @@ #include #include +#include size_t string_len(const char *s) { size_t l = 0; @@ -130,3 +131,35 @@ int string_strncmp( const char * s1, const char * s2, size_t n ) return ( *(unsigned char *)s1 - *(unsigned char *)s2 ); } } + +#define STRING_TOKENIZEALLOC_TOK_SIZE 0xff + +char *string_tokenizealloc(char *s, char *delim) { + static int curridx = 0; + if (!s || !delim || !s[curridx]) { + return NULL; + } + + char *w = (char *)dlmalloc(sizeof(char) * STRING_TOKENIZEALLOC_TOK_SIZE); + string_memset(w, 0, sizeof(char) * STRING_TOKENIZEALLOC_TOK_SIZE); + int i = curridx, k = 0, j = 0; + + while (s[i] != '\0') { + j = 0; + while (delim[j] != '\0') { + if (s[i] != delim[j]) { + w[k] = s[i]; + } else { + goto it; + } + j++; + } + i++; + k++; + } + it: { + w[i] = 0; + curridx = i + 1; + return w; + } +} diff --git a/ulib/string/string.h b/ulib/string/string.h index 52e861d..31d3e8f 100644 --- a/ulib/string/string.h +++ b/ulib/string/string.h @@ -16,6 +16,7 @@ size_t string_strspn(const char *s, const char *accept); char *string_strcpy(char *dest, const char *src); char *string_strchr(const char *s, int c); int string_strncmp(const char * s1, const char * s2, size_t n); +char *string_tokenizealloc(char *s, char *delim); #endif diff --git a/ulib/syscall/syscall.c b/ulib/syscall/syscall.c index c03a979..fab57d3 100644 --- a/ulib/syscall/syscall.c +++ b/ulib/syscall/syscall.c @@ -1,4 +1,5 @@ #include +#include uint64_t syscall(uint64_t num, uint64_t arg1, uint64_t arg2, uint64_t arg3, uint64_t arg4, uint64_t arg5, uint64_t arg6) { diff --git a/ulib/system/system.c b/ulib/system/system.c index c301e40..7da9c67 100644 --- a/ulib/system/system.c +++ b/ulib/system/system.c @@ -5,6 +5,7 @@ #include #include #include +#include #include void debugprint(const char *string) { @@ -34,3 +35,7 @@ int32_t mman_unmap(uint8_t *addr) { int32_t schedrelease(void) { return syscall(SYS_SCHEDRELEASE, 0, 0, 0, 0, 0, 0); } + +int32_t devctl(Dev_t *devh, uint64_t cmd, uint8_t *buffer, size_t len, uint64_t extra) { + return syscall(SYS_DEVCTL, (uint64_t)devh, cmd, (uint64_t)buffer, (uint64_t)len, (uint64_t)extra, 0); +} diff --git a/ulib/system/system.h b/ulib/system/system.h index 73a0685..c48f6b4 100644 --- a/ulib/system/system.h +++ b/ulib/system/system.h @@ -3,6 +3,7 @@ #include #include +#include void debugprint(const char *string); int32_t ioctl(uint64_t ioh, uint64_t cmd, uint64_t arg1, uint64_t arg2, uint64_t arg3); @@ -11,5 +12,6 @@ int32_t ipcpipe(uint64_t pid, uint64_t pipenum, uint64_t cmd, uint8_t *buffer, s int32_t mman_map(uint8_t *addr, size_t size, uint64_t prot, uint64_t flags, uint8_t **out); int32_t mman_unmap(uint8_t *addr); int32_t schedrelease(void); +int32_t devctl(Dev_t *devh, uint64_t cmd, uint8_t *buffer, size_t len, uint64_t extra); #endif // ULIB_SYSTEM_SYSTEM_H_ diff --git a/ulib/ubsan/ubsan.c b/ulib/ubsan/ubsan.c new file mode 100644 index 0000000..7eb0486 --- /dev/null +++ b/ulib/ubsan/ubsan.c @@ -0,0 +1,224 @@ +// REFERENCES: +// https://wiki.osdev.org/Undefined_Behavior_Sanitization + +#include +#include +#include + +struct source_location { + const char *file; + uint32_t line; + uint32_t column; +}; + + +struct type_descriptor { + uint16_t type_kind; + uint16_t type_info; + char *type_name; +}; + + +struct type_mismatch_data { + struct source_location loc; + struct type_descriptor *type; + unsigned long alignment; + unsigned char type_check_kind; +}; + + +struct type_mismatch_data_v1 { + struct source_location loc; + struct type_descriptor *type; + unsigned char alignment; + unsigned char type_check_kind; +}; + + +struct overflow_data { + struct source_location loc; + struct type_descriptor *type; +}; + + +struct shift_out_of_bounds_data { + struct source_location loc; + struct type_descriptor *lhs_type; + struct type_descriptor *rhs_type; +}; + + +struct out_of_bounds_data { + struct source_location loc; + struct type_descriptor *array_type; + struct type_descriptor *index_type; +}; + + +struct unreachable_data { + struct source_location loc; +}; + + +struct vla_bound_data { + struct source_location loc; + struct type_descriptor *type; +}; + + +struct invalid_value_data { + struct source_location loc; + struct type_descriptor *type; +}; + + +struct nonnull_arg_data { + struct source_location loc; +}; + + +struct nonnull_return_data { + struct source_location loc; + struct source_location attr_loc; +}; + + +struct invalid_builtin_data { + struct source_location loc; + uint8_t kind; +}; + + +struct pointer_overflow_data { + struct source_location loc; +}; + + +static void ubsan_print(struct source_location *loc, const char *message) +{ + uprintf("UBSAN error %s:%d:%d %s\n", loc->file, loc->line, loc->column, message); +} + +void __ubsan_handle_add_overflow(struct overflow_data *data) +{ + ubsan_print(&data->loc, "addition overflow"); +} + + +void __ubsan_handle_sub_overflow(struct overflow_data *data) +{ + ubsan_print(&data->loc, "subtraction overflow"); +} + + +void __ubsan_handle_mul_overflow(struct overflow_data *data) +{ + ubsan_print(&data->loc, "multiplication overflow"); +} + + +void __ubsan_handle_divrem_overflow(struct overflow_data *data) +{ + ubsan_print(&data->loc, "division overflow"); +} + + +void __ubsan_handle_negate_overflow(struct overflow_data *data) +{ + ubsan_print(&data->loc, "negation overflow"); +} + + +void __ubsan_handle_pointer_overflow(struct overflow_data *data) +{ + ubsan_print(&data->loc, "pointer overflow"); +} + + +void __ubsan_handle_shift_out_of_bounds(struct shift_out_of_bounds_data *data) +{ + ubsan_print(&data->loc, "shift out of bounds"); +} + + +void __ubsan_handle_out_of_bounds(struct out_of_bounds_data *data) +{ + ubsan_print(&data->loc, "array out of bounds"); +} + + +void __ubsan_handle_load_invalid_value(struct invalid_value_data *data) +{ + ubsan_print(&data->loc, "invalid load value"); +} + + +void __ubsan_handle_type_mismatch(struct type_mismatch_data *data, uintptr_t ptr) +{ + if (ptr == (uintptr_t)NULL) { + ubsan_print(&data->loc, "null pointer access"); + } + else if ((data->alignment != 0) && ((ptr & (((uintptr_t)1 << data->alignment) - (uintptr_t)1)) != 0)) { + ubsan_print(&data->loc, "misaligned pointer is used"); + } + else { + ubsan_print(&data->loc, "insufficient space for an object"); + } +} + + +void __ubsan_handle_type_mismatch_v1(struct type_mismatch_data_v1 *data, uintptr_t ptr) +{ + if (ptr == (uintptr_t)NULL) { + ubsan_print(&data->loc, "null pointer access"); + } + else if ((data->alignment != 0) && ((ptr & (((uintptr_t)1 << data->alignment) - (uintptr_t)1)) != 0)) { + ubsan_print(&data->loc, "misaligned pointer is used"); + } + else { + ubsan_print(&data->loc, "insufficient space for an object"); + } +} + + +void __ubsan_handle_vla_bound_not_positive(struct vla_bound_data *data) +{ + ubsan_print(&data->loc, "variable-length argument out of bounds"); +} + + +void __ubsan_handle_nonnull_return(struct nonnull_return_data *data) +{ + ubsan_print(&data->loc, "null pointer returned from a function 'nonnull' specified"); +} + + +void __ubsan_handle_nonnull_return_v1(struct nonnull_return_data *data, struct source_location *loc) +{ + ubsan_print(&data->loc, "null pointer returned from a function 'nonnull' specified"); +} + + +void __ubsan_handle_nonnull_arg(struct nonnull_arg_data *data) +{ + ubsan_print(&data->loc, "non-null argument is null"); +} + + +void __ubsan_handle_builtin_unreachable(struct unreachable_data *data) +{ + ubsan_print(&data->loc, "unreachable code reached"); +} + + +void __ubsan_handle_invalid_builtin(struct invalid_builtin_data *data) +{ + ubsan_print(&data->loc, "invalid builtin"); +} + + +void __ubsan_handle_missing_return(struct unreachable_data *data) +{ + ubsan_print(&data->loc, "missing return value"); +} + diff --git a/ulib/ulib.h b/ulib/ulib.h index bd7596e..4e77319 100644 --- a/ulib/ulib.h +++ b/ulib/ulib.h @@ -13,6 +13,8 @@ #include #include #include +#include +#include #include #include diff --git a/ulib/util/util.h b/ulib/util/util.h index 6999973..db43075 100644 --- a/ulib/util/util.h +++ b/ulib/util/util.h @@ -5,11 +5,7 @@ #define ARRLEN(X) (sizeof((X))/sizeof((X)[0])) -#define ZERO(X) \ -({ \ - string_memset((X), 0, sizeof(*(X))); \ - *(X); \ -}) \ +#define ZERO(X) string_memset((X), 0, sizeof(*(X))) #define MIN(a, b) \ ({ \ diff --git a/ulib/write/write.c b/ulib/write/write.c new file mode 100644 index 0000000..e793714 --- /dev/null +++ b/ulib/write/write.c @@ -0,0 +1,161 @@ +#include +#include +#include +#include +#include +#include +#include +#include + +char *utoa(uintmax_t v, int base, bool uppercase) { + if (base < 2 || base > 36) { + return NULL; + } + + static char buf[sizeof(uintmax_t) * CHAR_BIT + 3]; + const char *digits = uppercase ? "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ" : "0123456789abcdefghijklmnopqrstuvwxyz"; + + size_t i = sizeof(buf) - 1; + buf[i] = '\0'; + + if (v == 0) { + buf[--i] = '0'; + return &buf[i]; + } + + while (v != 0) { + if (i == 0) { + return NULL; + } + buf[--i] = digits[v % base]; + v /= base; + } + + return &buf[i]; +} + +char *itoa(intmax_t v, int base, bool uppercase) { + if (base < 2 || base > 36) { + return NULL; + } + + static char buf[sizeof(uintmax_t) * CHAR_BIT + 3]; + const char *digits = uppercase ? "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ" : "0123456789abcdefghijklmnopqrstuvwxyz"; + + size_t i = sizeof(buf) - 1; + buf[i] = '\0'; + + if (v == 0) { + buf[--i] = '0'; + return &buf[i]; + } + + bool neg = (v < 0); + uintmax_t u; + if (neg) { + u = (uintmax_t)(-(v + 1)) + 1; + } else { + u = (uintmax_t)v; + } + + while (u != 0) { + if (i == 0) { + return NULL; + } + buf[--i] = digits[u % base]; + u /= base; + } + + if (neg) { + if (i == 0) { + return NULL; + } + buf[--i] = '-'; + } + + return &buf[i]; +} + +#define FMTBUF_MAX 2048 + +extern Dev_t termdev; + +enum { + WRITE_FORMATMODE, + WRITE_NORMALMODE, +}; + +const char *convstr1 = "0123456789abcdef"; +const char *convstr2 = "0123456789ABCDEF"; + +void writefmt(char *fmt, ...) { + va_list list; + va_start(list, fmt); + writevfmt(fmt, list); + va_end(list); +} + +#define ITOA_BUF_SIZE 32 + +void writevsfmt(char *buf, char *fmt, va_list list) { + size_t c = 0; + int WRITE_STATE = WRITE_NORMALMODE; + + for (size_t i = 0; fmt[i] != '\0'; i++) { + if (WRITE_STATE == WRITE_NORMALMODE) { + switch (fmt[i]) { + case '{': + WRITE_STATE = WRITE_FORMATMODE; + break; + default: + buf[c++] = fmt[i]; + break; + } + } else if (WRITE_STATE == WRITE_FORMATMODE) { + switch (fmt[i]) { + case '}': + WRITE_STATE = WRITE_NORMALMODE; + break; + case 's': { + char *string = va_arg(list, char *); + while (*string) { buf[c++] = *string; string++; } + } break; + case 'd': { + int int1 = va_arg(list, int); + char *string = itoa(int1, 10, false); + while (*string) { buf[c++] = *string; string++; } + } break; + case 'x': { + unsigned int int1 = va_arg(list, unsigned int); + char *string = utoa(int1, 16, false); + while (*string) { buf[c++] = *string; string++; } + } break; + case 'X': { + unsigned int int1 = va_arg(list, unsigned int); + char *string = utoa(int1, 16, true); + while (*string) { buf[c++] = *string; string++; } + } break; + case 'p': { + uintptr_t ptr = (uintptr_t)va_arg(list, void *); + char *string = utoa(ptr, 16, false); + while (*string) { buf[c++] = *string; string++; } + } break; + case 'P': { + uintptr_t ptr = (uintptr_t)va_arg(list, void *); + char *string = utoa(ptr, 16, true); + while (*string) { buf[c++] = *string; string++; } + } break; + case 'c': { + char c1 = (char)va_arg(list, char); + buf[c++] = c1; + } break; + } + } + } +} + +void writevfmt(char *fmt, va_list list) { + char buf[FMTBUF_MAX]; + writevsfmt(buf, fmt, list); + devctl(&termdev, 0x00, buf, sizeof(buf), 0); +} diff --git a/ulib/write/write.h b/ulib/write/write.h new file mode 100644 index 0000000..cc2239a --- /dev/null +++ b/ulib/write/write.h @@ -0,0 +1,10 @@ +#ifndef ULIB_WRITE_WRITE_H_ +#define ULIB_WRITE_WRITE_H_ + +#include + +void writefmt(char *fmt, ...); +void writevfmt(char *fmt, va_list list); +void writevsfmt(char *buf, char *fmt, va_list list); + +#endif // ULIB_WRITE_WRITE_H_ diff --git a/user/arch/x86_64/link.ld b/user/arch/x86_64/link.ld index 5f7ec45..398786d 100644 --- a/user/arch/x86_64/link.ld +++ b/user/arch/x86_64/link.ld @@ -1,7 +1,7 @@ ENTRY(_start) SECTIONS { - . = 0x400000; + . = 0x1000; .text ALIGN(4K): { @@ -22,6 +22,7 @@ SECTIONS { { _bss_start = .; *(.bss .bss*) + . = ALIGN(4K); _bss_end = .; } } diff --git a/user/init/main.c b/user/init/main.c index 39c133e..d20ab0f 100644 --- a/user/init/main.c +++ b/user/init/main.c @@ -21,8 +21,7 @@ void main(void) { tb_runinitscript(); - uprintf("Shell exited! Please reboot the system.\n"); + writefmt("Shell exited! Please reboot the system.\n"); for(;;); } - diff --git a/user/pctl/ls.c b/user/pctl/ls.c index d6eb595..dd363e3 100644 --- a/user/pctl/ls.c +++ b/user/pctl/ls.c @@ -66,7 +66,7 @@ void pctl_ls(void) { uprintf("%-30s %s %-6s %-15s %-8s\n", "NAME", "PID", "TYPE", "MEMORY", "STATE"); for (size_t i = 0; i < procslen; i++) { - ProcStat stat = ZERO(&stat); + ProcStat stat; ZERO(&stat); string_memset(namebuf, 0, 34); string_memset(membuf, 0, 20); diff --git a/user/tb/interp.c b/user/tb/interp.c index 355778a..970489a 100644 --- a/user/tb/interp.c +++ b/user/tb/interp.c @@ -9,183 +9,199 @@ extern uint64_t PID; static InterpResult RES; -void tz_init(Tokenizer *tz, const char *str, size_t len) { +void tz_init(Tokenizer *tz, char *str) { tz->str = str; - tz->len = len; - tz->pos = 0; + tz->tokens = NULL; } void tz_free(Tokenizer *tz) { - Token *tk = tz->tokens; - while (tk) { - Token *tmp = tk; - tk = tk->next; - dlfree(tmp); + Token *tk, *tktmp; + LL_FOREACH_SAFE(tz->tokens, tk, tktmp) { + dlfree(tk); } + tz->tokens = NULL; } -int tz_next(Tokenizer *tz, Token *out) { - while (tz->pos < tz->len && string_chr_isspace(tz->str[tz->pos])) { - tz->pos++; - } +#define TZ_MAX_TK 1024 - if (tz->pos >= tz->len) { - return 0; - } - - size_t start = tz->pos; - if (tz->str[start] == '"') { - start++; - tz->pos++; - while (tz->pos < tz->len && tz->str[tz->pos] != '"') { - tz->pos++; - } - - if (tz->pos >= tz->len) { - out->ptr = tz->str + start; - out->len = tz->len - start; - tz->pos = tz->len; +void tz_tokenize(Tokenizer *tz) { + size_t len = string_len(tz->str); + for (size_t i = 0; i < len; i++) { + if (tz->str[i] == '\'') { + char *str = dlmalloc(TZ_MAX_TK); + string_memset(str, 0, TZ_MAX_TK); + i++; + size_t j = 0; + while (i < len && tz->str[i] != '\'') { + str[j++] = tz->str[i++]; + } + Token *tk = dlmalloc(sizeof(*tk)); + tk->str = str; + tk->next = NULL; + LL_APPEND(tz->tokens, tk); } else { - out->ptr = tz->str + start; - out->len = tz->pos - start; - tz->pos++; - } - } else { - while (tz->pos < tz->len && !string_chr_isspace(tz->str[tz->pos])) { - tz->pos++; - } - out->ptr = tz->str + start; - out->len = tz->pos - start; - } - - return 1; -} - -void tz_classify(Tokenizer *tz) { - const int tmpbufsz = 256; - char *tmpbuf = dlmalloc(tmpbufsz); - Token *tk = tz->tokens; - while (tk) { - if (tk->ptr[0] == '"' && tk->ptr[tk->len - 1] == '"') { - tk->type = TOK_STRING; - } else if (tk->ptr[0] == '%') { - RtCmd *cmd = RTCMDS; - while (cmd) { - string_memset(tmpbuf, 0, tmpbufsz); - usnprintf(tmpbuf, tmpbufsz, "%.*s", (int)tk->len, tk->ptr); - if (string_strcmp(tmpbuf, cmd->cmdname) == 0) { - tk->type = TOK_CMD; - tk->cmd = cmd; - break; - } - cmd = cmd->next; + char *tkstr = dlmalloc(TZ_MAX_TK); + string_memset(tkstr, 0, TZ_MAX_TK); + size_t j = 0; + while (i < len && !string_chr_isspace(tz->str[i])) { + tkstr[j++] = tz->str[i++]; } - } else { - tk->type = TOK_MISC; + Token *tk = dlmalloc(sizeof(*tk)); + tk->str = tkstr; + tk->next = NULL; + LL_APPEND(tz->tokens, tk); } - tk = tk->next; - } - dlfree(tmpbuf); -} - -void tz_expandspecial(Tokenizer *tz) { - Token *tk = tz->tokens; - while (tk) { - if (tk->ptr[0] == '$' && tk->len > 1) { - char *aliasbuf = dlmalloc(RTALIAS_NAMEBUF_MAX); - usnprintf(aliasbuf, RTALIAS_NAMEBUF_MAX, "%.*s", (int)tk->len-1, &tk->ptr[1]); - RtAlias *alias = RTALIASES; - while (alias) { - if (string_strcmp(alias->namebuf, aliasbuf) == 0) { - tk->ptr = alias->valbuf; - tk->len = string_len(alias->valbuf); - break; - } - alias = alias->next; - } - dlfree(aliasbuf); - } - tk = tk->next; } } -bool interp_readline(char *data, const char **bgptr, const char **endptr) { - static char *nextstart; - if (data) { - nextstart = data; - return true; - } +/* void tz_classify(Tokenizer *tz) { */ +/* const int tmpbufsz = 256; */ +/* char *tmpbuf = dlmalloc(tmpbufsz); */ - if (*nextstart == '\0') { - return false; - } - *bgptr = nextstart; - const char *scn = nextstart; +/* Token *tk, *tktmp; */ +/* LL_FOREACH_SAFE(tz->tokens, tk, tktmp) { */ +/* if (tk->ptr[0] == '"' && tk->ptr[tk->len - 1] == '"') { */ +/* tk->type = TOK_STRING; */ +/* } else if (tk->ptr[0] == '%') { */ +/* RtCmd *cmd, *cmdtmp; */ +/* LL_FOREACH_SAFE(RTCMDS, cmd, cmdtmp) { */ +/* string_memset(tmpbuf, 0, tmpbufsz); */ +/* string_memcpy(tmpbuf, tk->ptr, MIN(tk->len, tmpbufsz)); */ +/* if (string_strcmp(tmpbuf, cmd->cmdname) == 0) { */ +/* tk->type = TOK_CMD; */ +/* tk->cmd = cmd; */ +/* break; */ +/* } */ +/* } */ +/* } else { */ +/* tk->type = TOK_MISC; */ +/* } */ +/* } */ +/* dlfree(tmpbuf); */ +/* } */ - for (;;) { - while (*scn != '\0' && *scn != '\n') { - scn++; - } - if (*scn == '\n') { - if (scn > *bgptr && *(scn - 1) == '\\') { - scn--; - nextstart = scn; - *nextstart = ' '; - scn++; - if (*scn == '\n') { - scn++; - } - nextstart = scn; - continue; - } - } - break; - } +/* void tz_expandspecial(Tokenizer *tz) { */ +/* Token *tk, *tktmp; */ +/* LL_FOREACH_SAFE(tz->tokens, tk, tktmp) { */ +/* if (tk->ptr[0] == '$' && tk->len > 1) { */ +/* char aliasbuf[RTALIAS_NAMEBUF_MAX]; */ +/* string_memset(aliasbuf, 0, sizeof(aliasbuf)); */ +/* string_memcpy(aliasbuf, &tk->ptr[1], MIN(tk->len - 1, RTALIAS_NAMEBUF_MAX)); */ +/* RtAlias *alias, *aliastmp; */ +/* LL_FOREACH_SAFE(RTALIASES, alias, aliastmp) { */ +/* if (string_strcmp(alias->namebuf, aliasbuf) == 0) { */ +/* tk->ptr = alias->valbuf; */ +/* tk->len = string_len(alias->valbuf); */ +/* break; */ +/* } */ +/* } */ +/* } */ +/* } */ +/* } */ - *endptr = scn - 1; - - while (string_chr_isspace(**bgptr) && *bgptr < *endptr) { - (*bgptr)++; - } +#define LINE_MAX 1024 - while (string_chr_isspace(**endptr) && *endptr >= *bgptr) { - (*endptr)--; - } - - (*endptr)++; - - if (*scn == '\n') { - scn++; - } - nextstart = scn; - - return true; -} - -bool interp_runstring(const char *string, InterpResult **res, bool logcmds, bool interactive) { +bool interp_runstring(char *string, InterpResult **res, bool logcmds, bool interactive) { *res = &RES; string_memset(RES.errmsg, 0, sizeof(RES.errmsg)); - + rt_init(); bool ok = true; - const char *bg, *end; - interp_readline((char *)string, NULL, NULL); - while (interp_readline(NULL, &bg, &end)) { - size_t linelen = end - bg; + + char *line = string_tokenizealloc(string, "\n"); + while (line != NULL) { if (logcmds) { - uprintf("+ %.*s\n", (int)linelen, bg); + writefmt("+{s}\n", line); } - Tokenizer tz = {0}; - tz_init(&tz, bg, linelen); + Tokenizer tz; ZERO(&tz); + tz_init(&tz, line); + + tz_tokenize(&tz); + /* Token tktmp; ZERO(&tktmp); */ + /* while (tz_next(&tz, &tktmp)) { */ + /* Token *tk = dlmalloc(sizeof(*tk)); */ + /* tk->ptr = tktmp.ptr; */ + /* tk->len = tktmp.len; */ + /* LL_APPEND(tz.tokens, tk); */ + /* } */ + + /* tz_classify(&tz); */ + /* tz_expandspecial(&tz); */ + + /* dlfree((void *)line); */ + line = string_tokenizealloc(NULL, "\n"); + } + +#if 0 + char line[LINE_MAX]; + size_t pos = 0; + while (string[pos] != '\0') { + string_memset(line, 0, sizeof(line)); + size_t next = inter_readline(string, pos, line, sizeof(line)); + if (next == pos) { + break; + } + + if (logcmds) { + uprintf("+%s\n", line); + } + + /* Tokenizer tz; ZERO(&tz); */ + /* tz_init(&tz, line, string_len(line)); */ + + /* Token tktmp; ZERO(&tktmp); */ + /* while (tz_next(&tz, &tktmp)) { */ + /* Token *tk = dlmalloc(sizeof(*tk)); */ + /* tk->ptr = tktmp.ptr; */ + /* tk->len = tktmp.len; */ + /* tk->next = NULL; */ + /* LL_APPEND(tz.tokens, tk); */ + /* } */ + + /* tz_classify(&tz); */ + /* tz_expandspecial(&tz); */ + + /* Token *cmdtk = tz.tokens; */ + /* if (cmdtk->type == TOK_CMD) { */ + /* ok = cmdtk->cmd->fn(cmdtk->next); */ + /* if (!ok) { */ + /* usprintf(RES.errmsg, "cmd %.*s failed", (int)cmdtk->len, cmdtk->ptr); */ + /* tz_free(&tz); */ + /* goto done; */ + /* } */ + /* } else if (cmdtk->type == TOK_MISC) { */ + + /* } */ + + /* nextline: { */ + /* tz_free(&tz); */ + pos = next; + /* } */ + } + + /* char *bg = NULL, *end = NULL; */ + /* interp_readline((char *)string, NULL, NULL); */ + /* while (interp_readline(NULL, &bg, &end)) { */ + /* size_t linelen = (size_t)(end - bg); */ + + /* if (logcmds) { */ + /* uprintf("+ %.*s\n", (int)linelen, bg); */ + /* } */ + + /* Tokenizer tz = {0}; */ + /* tz_init(&tz, bg, linelen); */ - Token toktmp = {0}; + /* Token toktmp = {0}; */ +#if 0 while (tz_next(&tz, &toktmp)) { Token *tok = dlmalloc(sizeof(*tok)); tok->ptr = toktmp.ptr; tok->len = toktmp.len; + tok->next = NULL; LL_APPEND(tz.tokens, tok); + string_memset(&toktmp, 0, sizeof(toktmp)); } tz_classify(&tz); @@ -193,67 +209,62 @@ bool interp_runstring(const char *string, InterpResult **res, bool logcmds, bool Token *cmdtk = tz.tokens; if (cmdtk->type == TOK_CMD) { - ok = cmdtk->cmd->fn(cmdtk->next); - if (!ok) { - ok = false; - usprintf(RES.errmsg, "cmd %.*s failed", (int)cmdtk->len, cmdtk->ptr); - tz_free(&tz); - goto done; - } + /* ok = cmdtk->cmd->fn(cmdtk->next); */ + /* if (!ok) { */ + /* usprintf(RES.errmsg, "cmd %.*s failed", (int)cmdtk->len, cmdtk->ptr); */ + /* tz_free(&tz); */ + /* goto done; */ + /* } */ } else if (cmdtk->type == TOK_MISC) { - char *appname = dlmalloc(1024); - usprintf(appname, "%.*s", (int)cmdtk->len, cmdtk->ptr); + /* const int appname_max = 128; */ + /* char *appname = dlmalloc(appname_max); */ + /* string_memset(appname, 0, appname_max); */ + /* string_memcpy(appname, cmdtk->ptr, MIN(cmdtk->len, appname_max)); */ + /* usnprintf(appname, appname_max, "%.*s", (int)cmdtk->len, cmdtk->ptr); */ - size_t argslen1 = 0; - Token *argtk = cmdtk->next; - while (argtk) { - argslen1++; - argtk = argtk->next; - } + /* size_t argslen1; */ + /* LL_FOREACH_SAFE_IDX(cmdtk->next, argtk, argtktmp, argslen1); */ - char **args1 = (char **)dlmalloc(sizeof(char *) * argslen1); - argtk = cmdtk->next; - size_t i = 0; - while (argtk) { - args1[i] = (char *)dlmalloc(PROC_ARG_MAX); - string_memset(args1[i], 0, PROC_ARG_MAX); - string_memcpy(args1[i], argtk->ptr, argtk->len); - i++; - argtk = argtk->next; - } + /* size_t i; */ + /* char **args1 = (char **)dlmalloc(sizeof(char *) * argslen1); */ + /* LL_FOREACH_SAFE_IDX(cmdtk->next, argtk, argtktmp, i) { */ + /* args1[i] = (char *)dlmalloc(PROC_ARG_MAX); */ + /* string_memset(args1[i], 0, PROC_ARG_MAX); */ + /* string_memcpy(args1[i], argtk->ptr, argtk->len); */ + /* } */ - int32_t app = processctl(-1, PCTL_SPAWN, (uint64_t)appname, (uint64_t)args1, argslen1); - if (app < 0) { - usprintf(RES.errmsg, "Could not run %s: %s\n", appname, ERRSTRING(app)); - ok = false; - goto cleanup; - } + /* int32_t app = processctl(-1, PCTL_SPAWN, (uint64_t)appname, (uint64_t)args1, argslen1); */ + /* if (app < 0) { */ + /* usprintf(RES.errmsg, "Could not run %s: %s\n", appname, ERRSTRING(app)); */ + /* ok = false; */ + /* goto cleanup; */ + /* } */ - processctl(app, PCTL_RUN, 0, 0, 0); + /* processctl(app, PCTL_RUN, 0, 0, 0); */ - uint8_t b; - while(processctl(app, PCTL_POLLSTATE, 0, 0, 0) != 4) { - if (interactive) { - int32_t nrd = ipcpipe(PID, IPCPIPE_IN, IPCPIPE_READ, &b, 1); - if (nrd > 0 && b == C('S')) { - processctl(app, PCTL_KILL, 0, 0, 0); - goto cleanup; - } - } - schedrelease(); - } + /* uint8_t b; */ + /* while(processctl(app, PCTL_POLLSTATE, 0, 0, 0) != 4) { */ + /* if (interactive) { */ + /* int32_t nrd = ipcpipe(PID, IPCPIPE_IN, IPCPIPE_READ, &b, 1); */ + /* if (nrd > 0 && b == C('S')) { */ + /* processctl(app, PCTL_KILL, 0, 0, 0); */ + /* goto cleanup; */ + /* } */ + /* } */ + /* schedrelease(); */ + /* } */ cleanup: { - for (size_t j = 0; j < argslen1; j++) { - dlfree(args1[j]); - } - dlfree(args1); - dlfree(appname); + /* for (size_t j = 0; j < argslen1; j++) dlfree(args1[j]); */ + /* dlfree(args1); */ + /* dlfree((void*)appname); */ } } tz_free(&tz); - } +#endif + /* } */ +#endif done: return ok; } diff --git a/user/tb/interp.h b/user/tb/interp.h index 6c46f13..af719f9 100644 --- a/user/tb/interp.h +++ b/user/tb/interp.h @@ -13,8 +13,7 @@ typedef struct { typedef struct Token { struct Token *next; - const char *ptr; - size_t len; + char *str; enum { TOK_STRING, @@ -26,13 +25,10 @@ typedef struct Token { } Token; typedef struct { - const char *str; - size_t len; - size_t pos; - + char *str; Token *tokens; } Tokenizer; -bool interp_runstring(const char *string, InterpResult **res, bool logcmds, bool interactive); +bool interp_runstring(char *string, InterpResult **res, bool logcmds, bool interactive); #endif // TB_INTERP_H_ diff --git a/user/tb/main.c b/user/tb/main.c index f52b53e..1a4f1d2 100644 --- a/user/tb/main.c +++ b/user/tb/main.c @@ -32,7 +32,7 @@ void do_file(char *filepath); void set_config(void) { int32_t ret; if ((ret = parse_args(args(), argslen(), ARGS)) < 0) { - uprintf("Could not parse args: %d\n", ret); + writefmt("Could not parse args: {d}\n", ret); } if (CONFIG.modestr != NULL) { @@ -41,7 +41,7 @@ void set_config(void) { } else if (string_strcmp(CONFIG.modestr, "runfile") == 0) { CONFIG.mode = MODE_RUNFILE; } else { - LOG(LOG_ERR, "Unknown mode %s\n", CONFIG.modestr); + LOG(LOG_ERR, "Unknown mode {s}\n", CONFIG.modestr); } } else { CONFIG.mode = MODE_RUNFILE; @@ -53,7 +53,7 @@ void do_file(char *filepath) { int32_t ioh = ioctl(IOCTL_NOHANDLE, IOCTL_OPENF, (uint64_t)filepath, IOCTL_F_READ, 0); if (ioh < 0) { - LOG(LOG_ERR, "Could not open %s: %s\n", filepath, ERRSTRING(ioh)); + LOG(LOG_ERR, "Could not open {s}: {s}\n", filepath, ERRSTRING(ioh)); return; } @@ -61,27 +61,27 @@ void do_file(char *filepath) { ioctl(ioh, IOCTL_STAT, (uint64_t)&statbuf, 0, 0); if (statbuf.type != IOCTLSTAT_FILE) { - LOG(LOG_ERR, "%s is not a file (%d)\n", filepath, statbuf.type); + LOG(LOG_ERR, "{s} is not a file ({d})\n", filepath, statbuf.type); return; } uint8_t *buf = dlmalloc(statbuf.size+1); string_memset(buf, 0, statbuf.size+1); if ((ret = ioctl(ioh, IOCTL_READ, (uint64_t)buf, statbuf.size, 0)) < 0) { - LOG(LOG_ERR, "Could not read %s (%d): %s\n", filepath, ioh, ERRSTRING(ioh)); + LOG(LOG_ERR, "Could not read {s} ({d}): {s}\n", filepath, ioh, ERRSTRING(ioh)); goto done; } InterpResult *res; - bool ok = interp_runstring((const char *)buf, &res, CONFIG.logcmds, CONFIG.mode == MODE_INTERACTIVE); + bool ok = interp_runstring((char *)buf, &res, CONFIG.logcmds, CONFIG.mode == MODE_INTERACTIVE); if (!ok) { - uprintf("Interpreter error:\n"); - uprintf("%s\n", res->errmsg); + writefmt("Interpreter error:\n"); + writefmt("{s}\n", res->errmsg); goto done; } done: - dlfree(buf); + /* dlfree(buf); */ ioctl(ioh, IOCTL_CLOSEF, 0, 0, 0); } @@ -90,7 +90,7 @@ void do_mode_interactive(void) { size_t cursor; for(;;) { begin: - uprintf("tb# "); + writefmt("tb# "); cursor = 0; string_memset(linebuf, 0, LINEBUF_MAX); @@ -102,12 +102,12 @@ void do_mode_interactive(void) { switch (b) { case C('C'): case 0xE9: - uprintf("\n"); + writefmt("\n"); goto begin; break; case C('L'): - uprintf(ANSIQ_CUR_SET(0, 0)); - uprintf(ANSIQ_SCR_CLR_ALL); + writefmt(ANSIQ_CUR_SET(0, 0)); + writefmt(ANSIQ_SCR_CLR_ALL); goto begin; break; } @@ -118,7 +118,7 @@ void do_mode_interactive(void) { if (string_chr_isascii(b) && b != 0 && cursor < LINEBUF_MAX) { linebuf[cursor++] = b; - uprintf("%c", b); + writefmt("{c}", b); } } else { schedrelease(); @@ -128,10 +128,10 @@ void do_mode_interactive(void) { if (cursor < LINEBUF_MAX) { linebuf[cursor] = '\0'; } - uprintf("\n"); + writefmt("\n"); InterpResult *res; if (!interp_runstring(linebuf, &res, CONFIG.logcmds, CONFIG.mode == MODE_INTERACTIVE)) { - LOG(LOG_ERR, "%s\n", res->errmsg); + LOG(LOG_ERR, "{s}\n", res->errmsg); } } } @@ -140,17 +140,17 @@ void main(void) { PID = processctl(-1, PCTL_GETPID, 0, 0, 0); set_config(); - + if (CONFIG.preloadpath != NULL) { - LOG(LOG_INF, "Preloading script: %s\n", CONFIG.preloadpath); + LOG(LOG_INF, "Preloading script: {s}\n", CONFIG.preloadpath); do_file(CONFIG.preloadpath); } if (CONFIG.mode == MODE_INTERACTIVE) { - do_mode_interactive(); + /* do_mode_interactive(); */ } else if (CONFIG.mode == MODE_RUNFILE) { if (CONFIG.filepath == NULL) { - uprintf("No file provided\n"); + writefmt("No file provided\n"); return; } do_file(CONFIG.filepath); diff --git a/user/tb/runtime.c b/user/tb/runtime.c index 99071e0..714ee25 100644 --- a/user/tb/runtime.c +++ b/user/tb/runtime.c @@ -16,32 +16,31 @@ RtAlias *RTALIASES = NULL; } while(0) bool rt_print(Token *tks) { - Token *tk = tks; - while (tk) { - uprintf("%.*s", (int)tk->len, tk->ptr); + Token *tk, *tktmp; + LL_FOREACH_SAFE(tks, tk, tktmp) { + writefmt("{s}", tk->str); if (tk->next != NULL) { - uprintf(" "); + writefmt(" "); } - tk = tk->next; } - uprintf("\n"); + writefmt("\n"); return true; } bool rt_mkalias(Token *tks) { RtAlias *alias = dlmalloc(sizeof(*alias)); string_memset(alias, 0, sizeof(*alias)); - Token *tk = tks; - size_t i = 0; - while (tk) { + + size_t i; + Token *tk, *tktmp; + LL_FOREACH_SAFE_IDX(tks, tk, tktmp, i) { if (i == 0) { - usprintf(alias->namebuf, "%.*s", (int)tk->len, tk->ptr); + string_memcpy(alias->namebuf, tk->str, MIN(string_len(tk->str), RTALIAS_NAMEBUF_MAX)); } else if (i == 1) { - usprintf(alias->valbuf, "%.*s", (int)tk->len, tk->ptr); + string_memcpy(alias->valbuf, tk->str, MIN(string_len(tk->str), RTALIAS_VALBUF_MAX)); } - i++; - tk = tk->next; } + LL_APPEND(RTALIASES, alias); return true; }