This commit is contained in:
2025-09-27 15:16:26 +02:00
parent 5af7c5276a
commit 3b1bb9d531
63 changed files with 1087 additions and 407 deletions

View File

@ -1,3 +1,3 @@
%print "this is an init script!" %print 'this is an init script!'
base:/bin/pctl ls base:/bin/pctl ls
base:/bin/tb -m interactive -preload base:/scripts/rc.tb base:/bin/tb -m interactive -preload base:/scripts/rc.tb

View File

@ -55,7 +55,6 @@ SRCFILES += $(call GRABSRC, \
proc \ proc \
proc/kproc \ proc/kproc \
proc/ps2kbproc \ proc/ps2kbproc \
proc/termproc \
proc/serialproc \ proc/serialproc \
hal \ hal \
hal/$(ARCH) \ hal/$(ARCH) \
@ -67,6 +66,7 @@ SRCFILES += $(call GRABSRC, \
rbuf \ rbuf \
ipc/pipe \ ipc/pipe \
drivers/ps2kb \ drivers/ps2kb \
dev \
) )
ifeq ($(ARCH),x86_64) ifeq ($(ARCH),x86_64)

View File

@ -11,7 +11,7 @@ CFLAGS += -m64 \
-mno-red-zone \ -mno-red-zone \
-fno-stack-protector \ -fno-stack-protector \
-fno-stack-check \ -fno-stack-check \
-O0 \ -Os \
LDFLAGS += -m elf_x86_64 \ LDFLAGS += -m elf_x86_64 \
-pie \ -pie \

View File

@ -3,6 +3,7 @@
#include <stdbool.h> #include <stdbool.h>
#include "bitmap.h" #include "bitmap.h"
#include "util/util.h" #include "util/util.h"
#include "kprintf.h"
void *bitmap_toptr(BitMap *bm, size_t block) { void *bitmap_toptr(BitMap *bm, size_t block) {
uint8_t *ptr = (uint8_t *)(bm->mem_start + (block * BITMAP_BLOCK_SIZE)); 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) { void bitmap_free(BitMap *bm, void *base, size_t blocks) {
bitmap_markregion(bm, base, BITMAP_BLOCK_SIZE * blocks, 0); 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);
}

View File

@ -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); size_t bitmap_freeregion(BitMap *bm, size_t blocks);
void *bitmap_alloc(BitMap *bm, size_t blocks); void *bitmap_alloc(BitMap *bm, size_t blocks);
void bitmap_free(BitMap *bm, void *base, 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_ #endif // BITMAP_BITMAP_H_

14
kernel/dev/dev.h Normal file
View File

@ -0,0 +1,14 @@
#ifndef DEV_DEV_H_
#define DEV_DEV_H_
#include <stdint.h>
#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_

19
kernel/dev/termdev.c Normal file
View File

@ -0,0 +1,19 @@
#include <stdint.h>
#include <stddef.h>
#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;
}

13
kernel/dev/termdev.h Normal file
View File

@ -0,0 +1,13 @@
#ifndef DEV_TERMDEV_H_
#define DEV_TERMDEV_H_
#include <stdint.h>
#include <stddef.h>
#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_

View File

@ -49,7 +49,7 @@ int RELEASE_LOCK(SpinLock *sl) {
} }
int INITIAL_LOCK(SpinLock *sl) { int INITIAL_LOCK(SpinLock *sl) {
spinlock_release(sl); spinlock_init(sl);
return 0; return 0;
} }

View File

@ -7,7 +7,7 @@
#define GDT_PRESENT 0x80 #define GDT_PRESENT 0x80
#define GDT_TSS 0x89 #define GDT_TSS 0x89
#define KSTACK 8192 #define KSTACK (1024*2*4096)
ALIGNED(16) static uint8_t kernelstack[KSTACK]; ALIGNED(16) static uint8_t kernelstack[KSTACK];
typedef struct { typedef struct {

View File

@ -178,8 +178,6 @@ void hal_syscalldispatch(IntrStackFrame *frame) {
frame->regs.rax = E_BADSYSCALL; frame->regs.rax = E_BADSYSCALL;
return; 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, int32_t ret = fn(frame, frame->regs.rdi, frame->regs.rsi, frame->regs.rdx,
frame->regs.r10, frame->regs.r8, frame->regs.r9); frame->regs.r10, frame->regs.r8, frame->regs.r9);
@ -215,7 +213,7 @@ void intr_handleintr(IntrStackFrame *frame) {
break; break;
case INTR_IRQBASE+1: case INTR_IRQBASE+1:
int32_t c = ps2kb_intr(); int32_t c = ps2kb_intr();
if (c >= 0) { if (c >= 0 && PS2KB_BUF.init) {
uint8_t b = c; uint8_t b = c;
spinlock_acquire(&PS2KB_BUF.spinlock); spinlock_acquire(&PS2KB_BUF.spinlock);
rbuf_push(&PS2KB_BUF.rbuf, b); rbuf_push(&PS2KB_BUF.rbuf, b);

View File

@ -62,13 +62,13 @@
.endm .endm
.macro _vecintr_bodygen .macro _vecintr_bodygen
cli
_push_regs _push_regs
cld cld
mov %rsp, %rdi movq %rsp, %rdi
call intr_handleintr call intr_handleintr
_pop_regs _pop_regs
add $0x10, %rsp add $0x10, %rsp
iretq iretq
.endm .endm

View File

@ -2,15 +2,11 @@
.global hal_switchproc .global hal_switchproc
hal_switchproc: hal_switchproc:
mov %cr3, %rcx testq %rsi, %rsi
cmp %rsi, %rcx je 1f
je .done movq %rsi, %cr3
mov %rsi, %cr3 1:
.done:
mov %rdi, %rsp mov %rdi, %rsp
_pop_regs _pop_regs
add $0x10, %rsp add $0x10, %rsp
iretq iretq

View File

@ -29,12 +29,16 @@ PgIndex hal_vmm_pageindex(uint64_t vaddr) {
return ret; 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 entry = table[ent];
uint64_t phys; uint64_t phys;
if (entry & HAL_PG_PRESENT) { if (entry & HAL_PG_PRESENT) {
phys = entry & ~0xFFFULL; phys = entry & ~0xFFFULL;
} else { } else {
if (!alloc) {
return NULL;
}
uint8_t *newphys = pmm_alloc(1); uint8_t *newphys = pmm_alloc(1);
phys = (uint64_t)newphys; phys = (uint64_t)newphys;
hal_memset(VIRT(phys), 0, HAL_PAGE_SIZE); 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); uint64_t *pml4 = (uint64_t *)VIRT(cr3phys);
PgIndex pi = hal_vmm_pageindex(virtaddr); PgIndex pi = hal_vmm_pageindex(virtaddr);
uint64_t *pml3 = hal_vmm_nexttable(pml4, pi.pml4); uint64_t *pml3 = hal_vmm_nexttable(pml4, pi.pml4, true);
uint64_t *pml2 = hal_vmm_nexttable(pml3, pi.pml3); uint64_t *pml2 = hal_vmm_nexttable(pml3, pi.pml3, true);
uint64_t *pml1 = hal_vmm_nexttable(pml2, pi.pml2); uint64_t *pml1 = hal_vmm_nexttable(pml2, pi.pml2, true);
uint64_t *pte = &pml1[pi.pml1]; uint64_t *pte = &pml1[pi.pml1];
*pte = (physaddr & ~0xFFFULL) | ((uint64_t)flags & 0x7ULL); *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); uint64_t *pml4 = (uint64_t *)VIRT(cr3phys);
PgIndex pi = hal_vmm_pageindex(virtaddr); PgIndex pi = hal_vmm_pageindex(virtaddr);
uint64_t *pml3 = hal_vmm_nexttable(pml4, pi.pml4); uint64_t *pml3 = hal_vmm_nexttable(pml4, pi.pml4, false);
uint64_t *pml2 = hal_vmm_nexttable(pml3, pi.pml3); uint64_t *pml2 = hal_vmm_nexttable(pml3, pi.pml3, false);
uint64_t *pml1 = hal_vmm_nexttable(pml2, pi.pml2); uint64_t *pml1 = hal_vmm_nexttable(pml2, pi.pml2, false);
uint64_t *pte = &pml1[pi.pml1]; uint64_t *pte = &pml1[pi.pml1];
*pte &= ~HAL_PG_PRESENT; *pte &= ~HAL_PG_PRESENT;

View File

@ -11,6 +11,7 @@
#include "storedev/storedev.h" #include "storedev/storedev.h"
#include "util/util.h" #include "util/util.h"
#include "proc/proc.h" #include "proc/proc.h"
#include "dev/termdev.h"
const char *human_size(uint64_t bytes, char *buf, size_t bufsize) { const char *human_size(uint64_t bytes, char *buf, size_t bufsize) {
static const char *units[] = { "B", "KiB", "MiB", "GiB", "TiB", "PiB" }; static const char *units[] = { "B", "KiB", "MiB", "GiB", "TiB", "PiB" };
@ -64,6 +65,7 @@ void kmain(void) {
storedev_init(); storedev_init();
baseimg_init(); baseimg_init();
vfs_init(); vfs_init();
termdev_init();
proc_init(); proc_init();
for(;;); for(;;);

View File

@ -40,6 +40,9 @@ void pmm_init(void) {
hal_memset(bm->map, 0xff, bm->nbytes); hal_memset(bm->map, 0xff, bm->nbytes);
for (size_t i = 0; i < BOOT_INFO.memmap_entrycount; i++) { for (size_t i = 0; i < BOOT_INFO.memmap_entrycount; i++) {
struct limine_memmap_entry *entry = BOOT_INFO.memmap_entries[i]; struct limine_memmap_entry *entry = BOOT_INFO.memmap_entries[i];
if (entry == memmap_ent) {
continue;
}
// mark usable as 0 and unusable as 1 // mark usable as 0 and unusable as 1
bitmap_markregion(bm, (void *)entry->base, entry->length, entry->type != LIMINE_MEMMAP_USABLE); bitmap_markregion(bm, (void *)entry->base, entry->length, entry->type != LIMINE_MEMMAP_USABLE);
} }

View File

@ -15,7 +15,6 @@
#include "ipc/pipe/pipe.h" #include "ipc/pipe/pipe.h"
#include "kproc/kproc.h" #include "kproc/kproc.h"
#include "ps2kbproc/ps2kbproc.h" #include "ps2kbproc/ps2kbproc.h"
#include "termproc/termproc.h"
#include "serialproc/serialproc.h" #include "serialproc/serialproc.h"
#include "sysdefs/processctl.h" #include "sysdefs/processctl.h"
@ -181,6 +180,7 @@ Proc *proc_spawnuser(char *mountpoint, char *path) {
proc->mman_map_base = PROC_MMAN_MAP_BASE; proc->mman_map_base = PROC_MMAN_MAP_BASE;
spinlock_init(&proc->bcast_pipes.spinlock); spinlock_init(&proc->bcast_pipes.spinlock);
spinlock_init(&proc->pipes_spinlock); spinlock_init(&proc->pipes_spinlock);
spinlock_init(&proc->devs_spinlock);
proc->pipes[0] = dlmalloc(sizeof(IpcPipe)); proc->pipes[0] = dlmalloc(sizeof(IpcPipe));
ipc_pipeinit(proc->pipes[0], proc->pid); ipc_pipeinit(proc->pipes[0], proc->pid);
@ -308,26 +308,20 @@ void proc_init(void) {
spinlock_init(&PROCS.spinlock); spinlock_init(&PROCS.spinlock);
PROCS.procs = NULL; PROCS.procs = NULL;
kproc_init(proc_spawnkern(&kproc_fn, "kproc")); /* kproc_init(proc_spawnkern(&kproc_fn, "kproc")); */
proc_register(KPROC); /* proc_register(KPROC); */
PROCS.current = KPROC; /* PROCS.current = KPROC; */
KPROC->state = PROC_READY; /* KPROC->state = PROC_READY; */
ps2kbproc_init(proc_spawnkern(&ps2kbproc_fn, "ps2kbproc")); /* ps2kbproc_init(proc_spawnkern(&ps2kbproc_fn, "ps2kbproc")); */
proc_register(PS2KBPROC); /* proc_register(PS2KBPROC); */
PS2KBPROC->state = PROC_READY; /* PS2KBPROC->state = PROC_READY; */
termproc_init(proc_spawnkern(&termproc_fn, "termproc"));
proc_register(TERMPROC);
TERMPROC->state = PROC_READY;
/* serialproc_init(proc_spawnkern(&serialproc_fn, "serialproc")); */ /* serialproc_init(proc_spawnkern(&serialproc_fn, "serialproc")); */
/* proc_register(SERIALPROC); */ /* proc_register(SERIALPROC); */
Proc *init = proc_spawnuser("base", "/bin/init"); Proc *init = proc_spawnuser("base", "/bin/init");
ipc_pipefree(init->pipes[0]); PROCS.current = init;
dlfree(init->pipes[0]);
init->pipes[0] = TERMPROC->pipes[1];
proc_register(init); proc_register(init);
init->state = PROC_READY; init->state = PROC_READY;

View File

@ -8,6 +8,7 @@
#include "vfs/vfs.h" #include "vfs/vfs.h"
#include "ipc/pipe/pipe.h" #include "ipc/pipe/pipe.h"
#include "sysdefs/processctl.h" #include "sysdefs/processctl.h"
#include "dev/dev.h"
#define PROC_NAME_MAX 0x100 #define PROC_NAME_MAX 0x100
@ -18,9 +19,10 @@
#define PROC_VFSHANDLES_MAX 0x80 #define PROC_VFSHANDLES_MAX 0x80
#define PROC_PIPEHANDLES_MAX 0x20 #define PROC_PIPEHANDLES_MAX 0x20
#define PROC_DEVHANDLES_MAX 0x20
#define PROC_MMAN_MAP_BASE 0x0000100000000000ULL #define PROC_MMAN_MAP_BASE 0x0000100000000000ULL
#define PROC_USER_STACK_TOP 0x0000800000000000ULL #define PROC_USER_STACK_TOP 0x00007FFFFFFFF000ULL
typedef struct { typedef struct {
IntrStackFrame trapframe; IntrStackFrame trapframe;
@ -56,12 +58,18 @@ typedef struct Proc {
VfsObj *vobjs[PROC_VFSHANDLES_MAX]; VfsObj *vobjs[PROC_VFSHANDLES_MAX];
uint64_t vobjcnt; uint64_t vobjcnt;
IpcPipe *pipes[PROC_PIPEHANDLES_MAX]; IpcPipe *pipes[PROC_PIPEHANDLES_MAX];
SpinLock pipes_spinlock; SpinLock pipes_spinlock;
struct { struct {
IpcPipe *list; IpcPipe *list;
SpinLock spinlock; SpinLock spinlock;
} bcast_pipes; } bcast_pipes;
Dev *devs[PROC_DEVHANDLES_MAX];
SpinLock devs_spinlock;
struct { struct {
ProcArg *list; ProcArg *list;
size_t len; size_t len;

View File

@ -7,7 +7,7 @@
#include "ps2kbproc.h" #include "ps2kbproc.h"
Proc *PS2KBPROC = NULL; Proc *PS2KBPROC = NULL;
Ps2KbFastBuf PS2KB_BUF; Ps2KbFastBuf PS2KB_BUF = {0};
void ps2kbproc_init(Proc *proc) { void ps2kbproc_init(Proc *proc) {
PS2KBPROC = proc; PS2KBPROC = proc;
@ -17,22 +17,23 @@ void ps2kbproc_init(Proc *proc) {
uint8_t *buf = dlmalloc(IPC_PIPE_MAX); uint8_t *buf = dlmalloc(IPC_PIPE_MAX);
rbuf_init(&PS2KB_BUF.rbuf, buf, IPC_PIPE_MAX); rbuf_init(&PS2KB_BUF.rbuf, buf, IPC_PIPE_MAX);
spinlock_init(&PS2KB_BUF.spinlock); spinlock_init(&PS2KB_BUF.spinlock);
PS2KB_BUF.init = true;
} }
void ps2kbproc_fn(void) { void ps2kbproc_fn(void) {
for (;;) { for (;;) {
uint8_t b = 0; /* uint8_t b = 0; */
spinlock_acquire(&PS2KB_BUF.spinlock); /* spinlock_acquire(&PS2KB_BUF.spinlock); */
if (rbuf_pop(&PS2KB_BUF.rbuf, &b) == 0) { /* if (rbuf_pop(&PS2KB_BUF.rbuf, &b) == 0) { */
spinlock_acquire(&PS2KBPROC->bcast_pipes.spinlock); /* spinlock_acquire(&PS2KBPROC->bcast_pipes.spinlock); */
IpcPipe *head = PS2KBPROC->bcast_pipes.list; /* IpcPipe *head = PS2KBPROC->bcast_pipes.list; */
while (head != NULL) { /* while (head != NULL) { */
ipc_pipewrite(head, &b, 1); /* ipc_pipewrite(head, &b, 1); */
head = head->next; /* head = head->next; */
} /* } */
spinlock_release(&PS2KBPROC->bcast_pipes.spinlock); /* spinlock_release(&PS2KBPROC->bcast_pipes.spinlock); */
} /* } */
spinlock_release(&PS2KB_BUF.spinlock); /* spinlock_release(&PS2KB_BUF.spinlock); */
} }
} }

View File

@ -9,6 +9,7 @@
typedef struct { typedef struct {
RBuf rbuf; RBuf rbuf;
SpinLock spinlock; SpinLock spinlock;
bool init;
} Ps2KbFastBuf; } Ps2KbFastBuf;
extern Proc *PS2KBPROC; extern Proc *PS2KBPROC;

View File

@ -1,25 +0,0 @@
#include <stdint.h>
#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);
}
}
}

View File

@ -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_

View File

@ -5,25 +5,62 @@
#include "hal/hal.h" #include "hal/hal.h"
#include "kprintf.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) { void spinlock_init(SpinLock *sl) {
atomic_store(&sl->lock, false); atomic_store(&sl->lock, false);
sl->flags = 0;
} }
uint64_t spinlock_irqsave(void) { uint64_t irqsave(void) {
uint64_t flags; uint64_t flags;
asm volatile("pushfq; cli; popq %0" : "=r"(flags) :: "memory"); asm volatile("pushfq; cli; popq %0" : "=r"(flags) :: "memory", "cc");
return flags; return flags;
} }
void spinlock_irqrestore(uint64_t flags) { void irqrestore(uint64_t flags) {
if (flags & (1<<9)) { 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) { void spinlock_acquire(SpinLock *sl) {
sl->flags = spinlock_irqsave(); irqsave_nested();
while (atomic_test_and_set_explicit(&sl->lock, memory_order_acquire)) { while (atomic_test_and_set_explicit(&sl->lock, memory_order_acquire)) {
SPINLOCK_HINT(); SPINLOCK_HINT();
@ -33,6 +70,6 @@ void spinlock_acquire(SpinLock *sl) {
void spinlock_release(SpinLock *sl) { void spinlock_release(SpinLock *sl) {
atomic_clear_flag_explicit(&sl->lock, memory_order_release); atomic_clear_flag_explicit(&sl->lock, memory_order_release);
spinlock_irqrestore(sl->flags); irqrestore_nested();
} }

View File

@ -6,11 +6,8 @@
typedef struct { typedef struct {
atomic_bool lock; atomic_bool lock;
uint64_t flags;
} SpinLock; } SpinLock;
#define SPINLOCK_HINT() asm volatile("pause")
void spinlock_init(SpinLock *sl); void spinlock_init(SpinLock *sl);
void spinlock_acquire(SpinLock *sl); void spinlock_acquire(SpinLock *sl);
void spinlock_release(SpinLock *sl); void spinlock_release(SpinLock *sl);

65
kernel/syscall/devctl.c Normal file
View File

@ -0,0 +1,65 @@
#include <stdint.h>
#include <stddef.h>
#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;
}

9
kernel/syscall/devctl.h Normal file
View File

@ -0,0 +1,9 @@
#ifndef SYSCALL_DEVCTL_H_
#define SYSCALL_DEVCTL_H_
#include <stdint.h>
#include "syscall.h"
int32_t SYSCALL5(sys_devctl, devh1, cmd1, buffer1, len1, extra1);
#endif // SYSCALL_DEVCTL_H_

View File

@ -10,6 +10,7 @@
#include "sysdefs/mman.h" #include "sysdefs/mman.h"
#include "bootinfo/bootinfo.h" #include "bootinfo/bootinfo.h"
#include "dlmalloc/malloc.h" #include "dlmalloc/malloc.h"
#include "kprintf.h"
int32_t SYSCALL5(sys_mman_map, addr1, size1, prot1, flags1, out1) { int32_t SYSCALL5(sys_mman_map, addr1, size1, prot1, flags1, out1) {
uint8_t *addr = (uint8_t *)addr1; 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); size_t pages = _DIV_ROUNDUP(size, HAL_PAGE_SIZE);
uint8_t *phys = (uint8_t *)pmm_alloc(pages); uint8_t *phys = (uint8_t *)pmm_alloc(pages);
if (phys == NULL) {
return E_NOMEMORY;
}
hal_memset(VIRT(phys), 0, pages * HAL_PAGE_SIZE); hal_memset(VIRT(phys), 0, pages * HAL_PAGE_SIZE);
spinlock_acquire(&PROCS.spinlock); spinlock_acquire(&PROCS.spinlock);

View File

@ -63,8 +63,10 @@ int32_t SYSCALL5(sys_processctl, pid1, cmd1, arg1, arg2, arg3) {
size_t argslen = arg3; size_t argslen = arg3;
char *(*args)[] = (char *(*)[])arg2; char *(*args)[] = (char *(*)[])arg2;
for (size_t i = 0; i < argslen; i++) { if (args != NULL && argslen > 0) {
PROC_ARG(newproc, (*args)[i]); for (size_t i = 0; i < argslen; i++) {
PROC_ARG(newproc, (*args)[i]);
}
} }
for (size_t i = 0; i < PROC_PIPEHANDLES_MAX; i++) { for (size_t i = 0; i < PROC_PIPEHANDLES_MAX; i++) {

View File

@ -11,7 +11,7 @@ int32_t SYSCALL0(sys_schedrelease) {
Proc *proc = PROCS.current; Proc *proc = PROCS.current;
spinlock_release(&PROCS.spinlock); spinlock_release(&PROCS.spinlock);
proc_sched((void *)frame); /* proc_sched((void *)frame); */
return E_OK; return E_OK;
} }

View File

@ -8,6 +8,7 @@
#include "ipcpipe.h" #include "ipcpipe.h"
#include "mman.h" #include "mman.h"
#include "sched.h" #include "sched.h"
#include "devctl.h"
int32_t SYSCALL1(sys_debugprint, string) { int32_t SYSCALL1(sys_debugprint, string) {
char *p = (char *)string; char *p = (char *)string;
@ -23,4 +24,5 @@ SyscallFn SYSCALL_TABLE[SYSCALLS_MAX] = {
[SYS_MMAN_MAP] = &sys_mman_map, [SYS_MMAN_MAP] = &sys_mman_map,
[SYS_MMAN_UNMAP] = &sys_mman_unmap, [SYS_MMAN_UNMAP] = &sys_mman_unmap,
[SYS_SCHEDRELEASE] = &sys_schedrelease, [SYS_SCHEDRELEASE] = &sys_schedrelease,
[SYS_DEVCTL] = &sys_devctl,
}; };

View File

@ -58,14 +58,14 @@
} while(0) } while(0)
#define LL_FOREACH_SAFE(head, var, tmp) \ #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 != NULL; \
var = tmp, tmp = (var ? var->next : NULL) \ var = tmp, tmp = (var ? var->next : NULL) \
) )
#define LL_FOREACH_SAFE_IDX(head, var, tmp, idx) \ #define LL_FOREACH_SAFE_IDX(head, var, tmp, idx) \
for (typeof(head) var = (head), tmp = (var ? var->next : NULL); \ for ((idx) = 0, var = (head), tmp = (var ? var->next : NULL); \
var != NULL && ((idx) = 0, 1); \ var != NULL; \
var = tmp, tmp = (var ? var->next : NULL), (idx)++) var = tmp, tmp = (var ? var->next : NULL), (idx)++)
#define LL_FOREACH_SAFE_IDX_LIMIT(head, var, tmp, idx, max) \ #define LL_FOREACH_SAFE_IDX_LIMIT(head, var, tmp, idx, max) \

View File

@ -10,4 +10,7 @@ CFLAGS += -m64 \
-fno-stack-check \ -fno-stack-check \
-fno-builtin \ -fno-builtin \
-fno-omit-frame-pointer \ -fno-omit-frame-pointer \
-O0 \ -fno-strict-aliasing \
-O1 \
-mno-tls-direct-seg-refs \
#-fsanitize=undefined

10
share/sysdefs/devctl.h Normal file
View File

@ -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_

View File

@ -1,7 +1,7 @@
#ifndef SHARE_HDRS_PROCESSCTL_H_ #ifndef SHARE_HDRS_PROCESSCTL_H_
#define SHARE_HDRS_PROCESSCTL_H_ #define SHARE_HDRS_PROCESSCTL_H_
#define PROC_ARG_MAX 0x400 #define PROC_ARG_MAX 128
enum { enum {
PCTL_KILL = 0, PCTL_KILL = 0,

View File

@ -9,6 +9,7 @@ enum {
SYS_MMAN_MAP = 5, SYS_MMAN_MAP = 5,
SYS_MMAN_UNMAP = 6, SYS_MMAN_UNMAP = 6,
SYS_SCHEDRELEASE = 7, SYS_SCHEDRELEASE = 7,
SYS_DEVCTL = 8,
}; };
#endif // SHARE_HDRS_SYSCALL_H_ #endif // SHARE_HDRS_SYSCALL_H_

View File

@ -11,14 +11,14 @@
#define atomic_load_explicit __atomic_load_n #define atomic_load_explicit __atomic_load_n
#define atomic_store_explicit __atomic_store_n #define atomic_store_explicit __atomic_store_n
#define atomic_store(p, v) atomic_store_explicit(p, v, 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_relaxed) #define atomic_load(p) atomic_load_explicit(p, memory_order_seq_cst)
#define atomic_compare_exchange_weak(p, old, new) \ #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) \ #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) \ #define atomic_test_and_set_explicit(p, memory_order) \
__atomic_test_and_set(p, memory_order) __atomic_test_and_set(p, memory_order)
@ -26,6 +26,28 @@
#define atomic_clear_flag_explicit(p, memory_order) \ #define atomic_clear_flag_explicit(p, memory_order) \
__atomic_clear(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_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 #endif

View File

@ -14,6 +14,8 @@ SRCFILES := $(call GRABSRC, \
sync \ sync \
args \ args \
util \ util \
ubsan \
write \
) )
CFLAGS += -isystem $(ROOT)/share -isystem $(ROOT)/ulib -isystem $(ROOT)/std/include \ CFLAGS += -isystem $(ROOT)/share -isystem $(ROOT)/ulib -isystem $(ROOT)/std/include \

View File

@ -2,10 +2,13 @@
#include <stddef.h> #include <stddef.h>
#include <system/system.h> #include <system/system.h>
#include <sysdefs/processctl.h> #include <sysdefs/processctl.h>
#include <sysdefs/devctl.h>
#include <errors.h> #include <errors.h>
#include <dlmalloc/malloc.h> #include <dlmalloc/malloc.h>
#include <uprintf.h> #include <uprintf.h>
#include <log.h> #include <log.h>
#include <util/util.h>
#include <devids.h>
extern void main(void); extern void main(void);
extern uint8_t _bss_start[]; 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; size_t _argslen;
char **args(void) { char **args(void) {
return _args; return (char **)_args;
} }
size_t argslen(void) { size_t argslen(void) {
return _argslen; return _argslen;
} }
Dev_t termdev;
// ulib initialization goes here // ulib initialization goes here
void _premain(void) { void _premain(void) {
clearbss(); clearbss();
#define MAX_ARGS 30 devctl(&termdev, DEVCTL_GET_HANDLE, (uint8_t *)DEV_TERMDEV, 0, 0);
_args = (char **)dlmalloc(MAX_ARGS * sizeof(char *));
for (size_t i = 0; i < MAX_ARGS; i++) { for (size_t i = 0; i < ARRLEN(_args); i++) {
_args[i] = dlmalloc(PROC_ARG_MAX); _args[i] = dlmalloc(PROC_ARG_MAX);
} }

View File

@ -5,35 +5,89 @@
#include <string/conv.h> #include <string/conv.h>
#include <string/string.h> #include <string/string.h>
#include <uprintf.h> #include <uprintf.h>
#include <errors.h>
int32_t parse_args(char **argv, size_t argc, Arg *defs) { 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++) { for (size_t i = 0; i < argc; i++) {
if (argv[i][0] == '-' && argv[i][1] != '\0') { char *arg = argv[i];
char *optname = argv[i]; if (!arg) {
continue;
}
if (arg[0] == '-' && arg[1] != '\0') {
size_t j = 0; size_t j = 0;
while (!defs[j].end) { while (!defs[j].end) {
Arg *def = &defs[j]; Arg *def = &defs[j];
if (string_strcmp(def->shortname, optname) == 0) {
if (i < argc - 1) { if (!def->shortname || !def->ptr) {
switch (def->expected_value) { j++;
case ARG_STRING: continue;
*((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 (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++; j++;
} }
} }
} }
return ARGP_OK; return E_OK;
} }

View File

@ -28,10 +28,6 @@ typedef struct {
#define ARG_END() ((Arg){ .end = true, }) #define ARG_END() ((Arg){ .end = true, })
enum {
ARGP_OK = 0,
};
int32_t parse_args(char **argv, size_t argc, Arg *defs); int32_t parse_args(char **argv, size_t argc, Arg *defs);
#endif // ULIB_ARGS_H_ #endif // ULIB_ARGS_H_

15
ulib/assert.h Normal file
View File

@ -0,0 +1,15 @@
#ifndef ULIB_ASSERT_H_
#define ULIB_ASSERT_H_
#include <uprintf.h>
#include <util/util.h>
#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_

8
ulib/devids.h Normal file
View File

@ -0,0 +1,8 @@
#ifndef ULIB_DEVIDS_H_
#define ULIB_DEVIDS_H_
enum {
DEV_TERMDEV = 0x10,
};
#endif // ULIB_DEVIDS_H_

View File

@ -8,6 +8,7 @@
#include <string/string.h> #include <string/string.h>
#include <sysdefs/mman.h> #include <sysdefs/mman.h>
#include <system/system.h> #include <system/system.h>
#include <write/write.h>
#define USE_DL_PREFIX 1 #define USE_DL_PREFIX 1
#define LACKS_SYS_TYPES_H 1 #define LACKS_SYS_TYPES_H 1
@ -23,7 +24,7 @@
#define LACKS_SCHED_H 1 #define LACKS_SCHED_H 1
#define HAVE_MMAP 1 #define HAVE_MMAP 1
#define HAVE_MORECORE 0 #define HAVE_MORECORE 0
#define ABORT uprintf("dlmalloc: Aborting...\n") #define ABORT writefmt("dlmalloc: Aborting...\n")
#define MALLOC_FAILURE_ACTION #define MALLOC_FAILURE_ACTION
#define USE_LOCKS 2 #define USE_LOCKS 2
#define malloc_getpagesize 0x1000 #define malloc_getpagesize 0x1000
@ -61,8 +62,9 @@ static size_t _roundpage(size_t sz) {
#define O_RDWR 0 #define O_RDWR 0
#define EMUL_DEV_ZERO_FD 123 #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; 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); int32_t err = mman_map(NULL, need, MMAN_MAP_PF_RW, 0, &outaddr);
if (err != E_OK || outaddr == NULL) { if (err != E_OK || outaddr == NULL) {
return NULL; return EMUL_MAP_FAILED;
} }
if (fd == EMUL_DEV_ZERO_FD) { if (fd == EMUL_DEV_ZERO_FD) {

View File

@ -53,14 +53,14 @@
} while(0) } while(0)
#define LL_FOREACH_SAFE(head, var, tmp) \ #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 != NULL; \
var = tmp, tmp = (var ? var->next : NULL) \ var = tmp, tmp = (var ? var->next : NULL) \
) )
#define LL_FOREACH_SAFE_IDX(head, var, tmp, idx) \ #define LL_FOREACH_SAFE_IDX(head, var, tmp, idx) \
for (typeof(head) var = (head), tmp = (var ? var->next : NULL); \ for ((idx) = 0, var = (head), tmp = (var ? var->next : NULL); \
var != NULL && ((idx) = 0, 1); \ var != NULL; \
var = tmp, tmp = (var ? var->next : NULL), (idx)++) var = tmp, tmp = (var ? var->next : NULL), (idx)++)
#define LL_FOREACH_SAFE_IDX_LIMIT(head, var, tmp, idx, max) \ #define LL_FOREACH_SAFE_IDX_LIMIT(head, var, tmp, idx, max) \

View File

@ -2,6 +2,7 @@
#define ULIB_LOG_H_ #define ULIB_LOG_H_
#include <uprintf.h> #include <uprintf.h>
#include <write/write.h>
enum { enum {
LOG_ERR, LOG_ERR,
@ -12,6 +13,6 @@ enum {
static const char *_LOG_STR[] = { "ERROR", "DEBUG", "INFO", "WARNING" }; 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_ #endif // ULIB_LOG_H_

View File

@ -1,9 +1,11 @@
#include <stdint.h> #include <stdint.h>
#include <system/system.h> #include <system/system.h>
#include <sysdefs/ipcpipe.h> #include <sysdefs/ipcpipe.h>
#include <sysdefs/devctl.h>
#include <printf/printf.h> #include <printf/printf.h>
extern Dev_t termdev;
void putchar_(char c) { void putchar_(char c) {
char buf = c; devctl(&termdev, 0x00, (uint8_t *)&c, 1, 0);
ipcpipe(IPCPIPE_SELFPID, IPCPIPE_OUT, IPCPIPE_WRITE, (uint8_t *)&buf, sizeof(buf));
} }

View File

@ -1,5 +1,6 @@
#include <stddef.h> #include <stddef.h>
#include <string/string.h> #include <string/string.h>
#include <dlmalloc/malloc.h>
size_t string_len(const char *s) { size_t string_len(const char *s) {
size_t l = 0; 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 ); 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;
}
}

View File

@ -16,6 +16,7 @@ size_t string_strspn(const char *s, const char *accept);
char *string_strcpy(char *dest, const char *src); char *string_strcpy(char *dest, const char *src);
char *string_strchr(const char *s, int c); char *string_strchr(const char *s, int c);
int string_strncmp(const char * s1, const char * s2, size_t n); int string_strncmp(const char * s1, const char * s2, size_t n);
char *string_tokenizealloc(char *s, char *delim);
#endif #endif

View File

@ -1,4 +1,5 @@
#include <stdint.h> #include <stdint.h>
#include <uprintf.h>
uint64_t syscall(uint64_t num, uint64_t arg1, uint64_t arg2, uint64_t syscall(uint64_t num, uint64_t arg1, uint64_t arg2,
uint64_t arg3, uint64_t arg4, uint64_t arg5, uint64_t arg6) { uint64_t arg3, uint64_t arg4, uint64_t arg5, uint64_t arg6) {

View File

@ -5,6 +5,7 @@
#include <sysdefs/ioctl.h> #include <sysdefs/ioctl.h>
#include <sysdefs/processctl.h> #include <sysdefs/processctl.h>
#include <sysdefs/ipcpipe.h> #include <sysdefs/ipcpipe.h>
#include <sysdefs/devctl.h>
#include <uprintf.h> #include <uprintf.h>
void debugprint(const char *string) { void debugprint(const char *string) {
@ -34,3 +35,7 @@ int32_t mman_unmap(uint8_t *addr) {
int32_t schedrelease(void) { int32_t schedrelease(void) {
return syscall(SYS_SCHEDRELEASE, 0, 0, 0, 0, 0, 0); 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);
}

View File

@ -3,6 +3,7 @@
#include <stdint.h> #include <stdint.h>
#include <stddef.h> #include <stddef.h>
#include <sysdefs/devctl.h>
void debugprint(const char *string); void debugprint(const char *string);
int32_t ioctl(uint64_t ioh, uint64_t cmd, uint64_t arg1, uint64_t arg2, uint64_t arg3); 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_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 mman_unmap(uint8_t *addr);
int32_t schedrelease(void); 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_ #endif // ULIB_SYSTEM_SYSTEM_H_

224
ulib/ubsan/ubsan.c Normal file
View File

@ -0,0 +1,224 @@
// REFERENCES:
// https://wiki.osdev.org/Undefined_Behavior_Sanitization
#include <stdint.h>
#include <stddef.h>
#include <uprintf.h>
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");
}

View File

@ -13,6 +13,8 @@
#include <uprintf.h> #include <uprintf.h>
#include <linklist.h> #include <linklist.h>
#include <log.h> #include <log.h>
#include <assert.h>
#include <write/write.h>
#include <errors.h> #include <errors.h>
#include <sysdefs/ioctl.h> #include <sysdefs/ioctl.h>

View File

@ -5,11 +5,7 @@
#define ARRLEN(X) (sizeof((X))/sizeof((X)[0])) #define ARRLEN(X) (sizeof((X))/sizeof((X)[0]))
#define ZERO(X) \ #define ZERO(X) string_memset((X), 0, sizeof(*(X)))
({ \
string_memset((X), 0, sizeof(*(X))); \
*(X); \
}) \
#define MIN(a, b) \ #define MIN(a, b) \
({ \ ({ \

161
ulib/write/write.c Normal file
View File

@ -0,0 +1,161 @@
#include <stdarg.h>
#include <stdint.h>
#include <stddef.h>
#include <stdbool.h>
#include <limits.h>
#include <system/system.h>
#include <sysdefs/devctl.h>
#include <write/write.h>
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);
}

10
ulib/write/write.h Normal file
View File

@ -0,0 +1,10 @@
#ifndef ULIB_WRITE_WRITE_H_
#define ULIB_WRITE_WRITE_H_
#include <stdarg.h>
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_

View File

@ -1,7 +1,7 @@
ENTRY(_start) ENTRY(_start)
SECTIONS { SECTIONS {
. = 0x400000; . = 0x1000;
.text ALIGN(4K): .text ALIGN(4K):
{ {
@ -22,6 +22,7 @@ SECTIONS {
{ {
_bss_start = .; _bss_start = .;
*(.bss .bss*) *(.bss .bss*)
. = ALIGN(4K);
_bss_end = .; _bss_end = .;
} }
} }

View File

@ -21,8 +21,7 @@ void main(void) {
tb_runinitscript(); tb_runinitscript();
uprintf("Shell exited! Please reboot the system.\n"); writefmt("Shell exited! Please reboot the system.\n");
for(;;); for(;;);
} }

View File

@ -66,7 +66,7 @@ void pctl_ls(void) {
uprintf("%-30s %s %-6s %-15s %-8s\n", "NAME", "PID", "TYPE", "MEMORY", "STATE"); uprintf("%-30s %s %-6s %-15s %-8s\n", "NAME", "PID", "TYPE", "MEMORY", "STATE");
for (size_t i = 0; i < procslen; i++) { for (size_t i = 0; i < procslen; i++) {
ProcStat stat = ZERO(&stat); ProcStat stat; ZERO(&stat);
string_memset(namebuf, 0, 34); string_memset(namebuf, 0, 34);
string_memset(membuf, 0, 20); string_memset(membuf, 0, 20);

View File

@ -9,183 +9,199 @@ extern uint64_t PID;
static InterpResult RES; 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->str = str;
tz->len = len; tz->tokens = NULL;
tz->pos = 0;
} }
void tz_free(Tokenizer *tz) { void tz_free(Tokenizer *tz) {
Token *tk = tz->tokens; Token *tk, *tktmp;
while (tk) { LL_FOREACH_SAFE(tz->tokens, tk, tktmp) {
Token *tmp = tk; dlfree(tk);
tk = tk->next;
dlfree(tmp);
} }
tz->tokens = NULL;
} }
int tz_next(Tokenizer *tz, Token *out) { #define TZ_MAX_TK 1024
while (tz->pos < tz->len && string_chr_isspace(tz->str[tz->pos])) {
tz->pos++;
}
if (tz->pos >= tz->len) { void tz_tokenize(Tokenizer *tz) {
return 0; size_t len = string_len(tz->str);
} for (size_t i = 0; i < len; i++) {
if (tz->str[i] == '\'') {
size_t start = tz->pos; char *str = dlmalloc(TZ_MAX_TK);
if (tz->str[start] == '"') { string_memset(str, 0, TZ_MAX_TK);
start++; i++;
tz->pos++; size_t j = 0;
while (tz->pos < tz->len && tz->str[tz->pos] != '"') { while (i < len && tz->str[i] != '\'') {
tz->pos++; str[j++] = tz->str[i++];
} }
Token *tk = dlmalloc(sizeof(*tk));
if (tz->pos >= tz->len) { tk->str = str;
out->ptr = tz->str + start; tk->next = NULL;
out->len = tz->len - start; LL_APPEND(tz->tokens, tk);
tz->pos = tz->len;
} else { } else {
out->ptr = tz->str + start; char *tkstr = dlmalloc(TZ_MAX_TK);
out->len = tz->pos - start; string_memset(tkstr, 0, TZ_MAX_TK);
tz->pos++; size_t j = 0;
} while (i < len && !string_chr_isspace(tz->str[i])) {
} else { tkstr[j++] = tz->str[i++];
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;
} }
} else { Token *tk = dlmalloc(sizeof(*tk));
tk->type = TOK_MISC; 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) { /* void tz_classify(Tokenizer *tz) { */
static char *nextstart; /* const int tmpbufsz = 256; */
if (data) { /* char *tmpbuf = dlmalloc(tmpbufsz); */
nextstart = data;
return true;
}
if (*nextstart == '\0') { /* Token *tk, *tktmp; */
return false; /* LL_FOREACH_SAFE(tz->tokens, tk, tktmp) { */
} /* if (tk->ptr[0] == '"' && tk->ptr[tk->len - 1] == '"') { */
*bgptr = nextstart; /* tk->type = TOK_STRING; */
const char *scn = nextstart; /* } 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 (;;) { /* void tz_expandspecial(Tokenizer *tz) { */
while (*scn != '\0' && *scn != '\n') { /* Token *tk, *tktmp; */
scn++; /* LL_FOREACH_SAFE(tz->tokens, tk, tktmp) { */
} /* if (tk->ptr[0] == '$' && tk->len > 1) { */
if (*scn == '\n') { /* char aliasbuf[RTALIAS_NAMEBUF_MAX]; */
if (scn > *bgptr && *(scn - 1) == '\\') { /* string_memset(aliasbuf, 0, sizeof(aliasbuf)); */
scn--; /* string_memcpy(aliasbuf, &tk->ptr[1], MIN(tk->len - 1, RTALIAS_NAMEBUF_MAX)); */
nextstart = scn; /* RtAlias *alias, *aliastmp; */
*nextstart = ' '; /* LL_FOREACH_SAFE(RTALIASES, alias, aliastmp) { */
scn++; /* if (string_strcmp(alias->namebuf, aliasbuf) == 0) { */
if (*scn == '\n') { /* tk->ptr = alias->valbuf; */
scn++; /* tk->len = string_len(alias->valbuf); */
} /* break; */
nextstart = scn; /* } */
continue; /* } */
} /* } */
} /* } */
break; /* } */
}
*endptr = scn - 1; #define LINE_MAX 1024
while (string_chr_isspace(**bgptr) && *bgptr < *endptr) { bool interp_runstring(char *string, InterpResult **res, bool logcmds, bool interactive) {
(*bgptr)++;
}
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) {
*res = &RES; *res = &RES;
string_memset(RES.errmsg, 0, sizeof(RES.errmsg)); string_memset(RES.errmsg, 0, sizeof(RES.errmsg));
rt_init(); rt_init();
bool ok = true; bool ok = true;
const char *bg, *end;
interp_readline((char *)string, NULL, NULL); char *line = string_tokenizealloc(string, "\n");
while (interp_readline(NULL, &bg, &end)) { while (line != NULL) {
size_t linelen = end - bg;
if (logcmds) { if (logcmds) {
uprintf("+ %.*s\n", (int)linelen, bg); writefmt("+{s}\n", line);
} }
Tokenizer tz = {0}; Tokenizer tz; ZERO(&tz);
tz_init(&tz, bg, linelen); tz_init(&tz, line);
Token toktmp = {0}; 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}; */
#if 0
while (tz_next(&tz, &toktmp)) { while (tz_next(&tz, &toktmp)) {
Token *tok = dlmalloc(sizeof(*tok)); Token *tok = dlmalloc(sizeof(*tok));
tok->ptr = toktmp.ptr; tok->ptr = toktmp.ptr;
tok->len = toktmp.len; tok->len = toktmp.len;
tok->next = NULL;
LL_APPEND(tz.tokens, tok); LL_APPEND(tz.tokens, tok);
string_memset(&toktmp, 0, sizeof(toktmp));
} }
tz_classify(&tz); tz_classify(&tz);
@ -193,67 +209,62 @@ bool interp_runstring(const char *string, InterpResult **res, bool logcmds, bool
Token *cmdtk = tz.tokens; Token *cmdtk = tz.tokens;
if (cmdtk->type == TOK_CMD) { if (cmdtk->type == TOK_CMD) {
ok = cmdtk->cmd->fn(cmdtk->next); /* ok = cmdtk->cmd->fn(cmdtk->next); */
if (!ok) { /* if (!ok) { */
ok = false; /* usprintf(RES.errmsg, "cmd %.*s failed", (int)cmdtk->len, cmdtk->ptr); */
usprintf(RES.errmsg, "cmd %.*s failed", (int)cmdtk->len, cmdtk->ptr); /* tz_free(&tz); */
tz_free(&tz); /* goto done; */
goto done; /* } */
}
} else if (cmdtk->type == TOK_MISC) { } else if (cmdtk->type == TOK_MISC) {
char *appname = dlmalloc(1024); /* const int appname_max = 128; */
usprintf(appname, "%.*s", (int)cmdtk->len, cmdtk->ptr); /* 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; /* size_t argslen1; */
Token *argtk = cmdtk->next; /* LL_FOREACH_SAFE_IDX(cmdtk->next, argtk, argtktmp, argslen1); */
while (argtk) {
argslen1++;
argtk = argtk->next;
}
char **args1 = (char **)dlmalloc(sizeof(char *) * argslen1); /* size_t i; */
argtk = cmdtk->next; /* char **args1 = (char **)dlmalloc(sizeof(char *) * argslen1); */
size_t i = 0; /* LL_FOREACH_SAFE_IDX(cmdtk->next, argtk, argtktmp, i) { */
while (argtk) { /* args1[i] = (char *)dlmalloc(PROC_ARG_MAX); */
args1[i] = (char *)dlmalloc(PROC_ARG_MAX); /* string_memset(args1[i], 0, PROC_ARG_MAX); */
string_memset(args1[i], 0, PROC_ARG_MAX); /* string_memcpy(args1[i], argtk->ptr, argtk->len); */
string_memcpy(args1[i], argtk->ptr, argtk->len); /* } */
i++;
argtk = argtk->next;
}
int32_t app = processctl(-1, PCTL_SPAWN, (uint64_t)appname, (uint64_t)args1, argslen1); /* int32_t app = processctl(-1, PCTL_SPAWN, (uint64_t)appname, (uint64_t)args1, argslen1); */
if (app < 0) { /* if (app < 0) { */
usprintf(RES.errmsg, "Could not run %s: %s\n", appname, ERRSTRING(app)); /* usprintf(RES.errmsg, "Could not run %s: %s\n", appname, ERRSTRING(app)); */
ok = false; /* ok = false; */
goto cleanup; /* goto cleanup; */
} /* } */
processctl(app, PCTL_RUN, 0, 0, 0); /* processctl(app, PCTL_RUN, 0, 0, 0); */
uint8_t b; /* uint8_t b; */
while(processctl(app, PCTL_POLLSTATE, 0, 0, 0) != 4) { /* while(processctl(app, PCTL_POLLSTATE, 0, 0, 0) != 4) { */
if (interactive) { /* if (interactive) { */
int32_t nrd = ipcpipe(PID, IPCPIPE_IN, IPCPIPE_READ, &b, 1); /* int32_t nrd = ipcpipe(PID, IPCPIPE_IN, IPCPIPE_READ, &b, 1); */
if (nrd > 0 && b == C('S')) { /* if (nrd > 0 && b == C('S')) { */
processctl(app, PCTL_KILL, 0, 0, 0); /* processctl(app, PCTL_KILL, 0, 0, 0); */
goto cleanup; /* goto cleanup; */
} /* } */
} /* } */
schedrelease(); /* schedrelease(); */
} /* } */
cleanup: { cleanup: {
for (size_t j = 0; j < argslen1; j++) { /* for (size_t j = 0; j < argslen1; j++) dlfree(args1[j]); */
dlfree(args1[j]); /* dlfree(args1); */
} /* dlfree((void*)appname); */
dlfree(args1);
dlfree(appname);
} }
} }
tz_free(&tz); tz_free(&tz);
} #endif
/* } */
#endif
done: done:
return ok; return ok;
} }

View File

@ -13,8 +13,7 @@ typedef struct {
typedef struct Token { typedef struct Token {
struct Token *next; struct Token *next;
const char *ptr; char *str;
size_t len;
enum { enum {
TOK_STRING, TOK_STRING,
@ -26,13 +25,10 @@ typedef struct Token {
} Token; } Token;
typedef struct { typedef struct {
const char *str; char *str;
size_t len;
size_t pos;
Token *tokens; Token *tokens;
} Tokenizer; } 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_ #endif // TB_INTERP_H_

View File

@ -32,7 +32,7 @@ void do_file(char *filepath);
void set_config(void) { void set_config(void) {
int32_t ret; int32_t ret;
if ((ret = parse_args(args(), argslen(), ARGS)) < 0) { 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) { if (CONFIG.modestr != NULL) {
@ -41,7 +41,7 @@ void set_config(void) {
} else if (string_strcmp(CONFIG.modestr, "runfile") == 0) { } else if (string_strcmp(CONFIG.modestr, "runfile") == 0) {
CONFIG.mode = MODE_RUNFILE; CONFIG.mode = MODE_RUNFILE;
} else { } else {
LOG(LOG_ERR, "Unknown mode %s\n", CONFIG.modestr); LOG(LOG_ERR, "Unknown mode {s}\n", CONFIG.modestr);
} }
} else { } else {
CONFIG.mode = MODE_RUNFILE; 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); int32_t ioh = ioctl(IOCTL_NOHANDLE, IOCTL_OPENF, (uint64_t)filepath, IOCTL_F_READ, 0);
if (ioh < 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; return;
} }
@ -61,27 +61,27 @@ void do_file(char *filepath) {
ioctl(ioh, IOCTL_STAT, (uint64_t)&statbuf, 0, 0); ioctl(ioh, IOCTL_STAT, (uint64_t)&statbuf, 0, 0);
if (statbuf.type != IOCTLSTAT_FILE) { 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; return;
} }
uint8_t *buf = dlmalloc(statbuf.size+1); uint8_t *buf = dlmalloc(statbuf.size+1);
string_memset(buf, 0, statbuf.size+1); string_memset(buf, 0, statbuf.size+1);
if ((ret = ioctl(ioh, IOCTL_READ, (uint64_t)buf, statbuf.size, 0)) < 0) { 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; goto done;
} }
InterpResult *res; 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) { if (!ok) {
uprintf("Interpreter error:\n"); writefmt("Interpreter error:\n");
uprintf("%s\n", res->errmsg); writefmt("{s}\n", res->errmsg);
goto done; goto done;
} }
done: done:
dlfree(buf); /* dlfree(buf); */
ioctl(ioh, IOCTL_CLOSEF, 0, 0, 0); ioctl(ioh, IOCTL_CLOSEF, 0, 0, 0);
} }
@ -90,7 +90,7 @@ void do_mode_interactive(void) {
size_t cursor; size_t cursor;
for(;;) { for(;;) {
begin: begin:
uprintf("tb# "); writefmt("tb# ");
cursor = 0; cursor = 0;
string_memset(linebuf, 0, LINEBUF_MAX); string_memset(linebuf, 0, LINEBUF_MAX);
@ -102,12 +102,12 @@ void do_mode_interactive(void) {
switch (b) { switch (b) {
case C('C'): case C('C'):
case 0xE9: case 0xE9:
uprintf("\n"); writefmt("\n");
goto begin; goto begin;
break; break;
case C('L'): case C('L'):
uprintf(ANSIQ_CUR_SET(0, 0)); writefmt(ANSIQ_CUR_SET(0, 0));
uprintf(ANSIQ_SCR_CLR_ALL); writefmt(ANSIQ_SCR_CLR_ALL);
goto begin; goto begin;
break; break;
} }
@ -118,7 +118,7 @@ void do_mode_interactive(void) {
if (string_chr_isascii(b) && b != 0 && cursor < LINEBUF_MAX) { if (string_chr_isascii(b) && b != 0 && cursor < LINEBUF_MAX) {
linebuf[cursor++] = b; linebuf[cursor++] = b;
uprintf("%c", b); writefmt("{c}", b);
} }
} else { } else {
schedrelease(); schedrelease();
@ -128,10 +128,10 @@ void do_mode_interactive(void) {
if (cursor < LINEBUF_MAX) { if (cursor < LINEBUF_MAX) {
linebuf[cursor] = '\0'; linebuf[cursor] = '\0';
} }
uprintf("\n"); writefmt("\n");
InterpResult *res; InterpResult *res;
if (!interp_runstring(linebuf, &res, CONFIG.logcmds, CONFIG.mode == MODE_INTERACTIVE)) { 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);
} }
} }
} }
@ -142,15 +142,15 @@ void main(void) {
set_config(); set_config();
if (CONFIG.preloadpath != NULL) { 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); do_file(CONFIG.preloadpath);
} }
if (CONFIG.mode == MODE_INTERACTIVE) { if (CONFIG.mode == MODE_INTERACTIVE) {
do_mode_interactive(); /* do_mode_interactive(); */
} else if (CONFIG.mode == MODE_RUNFILE) { } else if (CONFIG.mode == MODE_RUNFILE) {
if (CONFIG.filepath == NULL) { if (CONFIG.filepath == NULL) {
uprintf("No file provided\n"); writefmt("No file provided\n");
return; return;
} }
do_file(CONFIG.filepath); do_file(CONFIG.filepath);

View File

@ -16,32 +16,31 @@ RtAlias *RTALIASES = NULL;
} while(0) } while(0)
bool rt_print(Token *tks) { bool rt_print(Token *tks) {
Token *tk = tks; Token *tk, *tktmp;
while (tk) { LL_FOREACH_SAFE(tks, tk, tktmp) {
uprintf("%.*s", (int)tk->len, tk->ptr); writefmt("{s}", tk->str);
if (tk->next != NULL) { if (tk->next != NULL) {
uprintf(" "); writefmt(" ");
} }
tk = tk->next;
} }
uprintf("\n"); writefmt("\n");
return true; return true;
} }
bool rt_mkalias(Token *tks) { bool rt_mkalias(Token *tks) {
RtAlias *alias = dlmalloc(sizeof(*alias)); RtAlias *alias = dlmalloc(sizeof(*alias));
string_memset(alias, 0, sizeof(*alias)); string_memset(alias, 0, sizeof(*alias));
Token *tk = tks;
size_t i = 0; size_t i;
while (tk) { Token *tk, *tktmp;
LL_FOREACH_SAFE_IDX(tks, tk, tktmp, i) {
if (i == 0) { 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) { } 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); LL_APPEND(RTALIASES, alias);
return true; return true;
} }