Compare commits
17 Commits
d50bdd0051
...
e03e950879
Author | SHA1 | Date | |
---|---|---|---|
e03e950879 | |||
2b93d6d184 | |||
d7562b98c1 | |||
f5f44da5f6 | |||
1fd6c4e221 | |||
96ce9233ff | |||
c07a2c957b | |||
8d081bedb0 | |||
3b1bb9d531 | |||
5af7c5276a | |||
5c7fb3e1cf | |||
397379bca3 | |||
475f77d30f | |||
d5c2df7365 | |||
83a28bd25b | |||
3f2c35f4cb | |||
8a9687c007 |
@ -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
|
||||
|
@ -54,8 +54,6 @@ SRCFILES += $(call GRABSRC, \
|
||||
baseimg \
|
||||
proc \
|
||||
proc/kproc \
|
||||
proc/ps2kbproc \
|
||||
proc/termproc \
|
||||
proc/serialproc \
|
||||
hal \
|
||||
hal/$(ARCH) \
|
||||
@ -67,6 +65,7 @@ SRCFILES += $(call GRABSRC, \
|
||||
rbuf \
|
||||
ipc/pipe \
|
||||
drivers/ps2kb \
|
||||
dev \
|
||||
)
|
||||
|
||||
ifeq ($(ARCH),x86_64)
|
||||
|
@ -11,7 +11,7 @@ CFLAGS += -m64 \
|
||||
-mno-red-zone \
|
||||
-fno-stack-protector \
|
||||
-fno-stack-check \
|
||||
-O0 \
|
||||
-Os \
|
||||
|
||||
LDFLAGS += -m elf_x86_64 \
|
||||
-pie \
|
||||
|
@ -3,6 +3,7 @@
|
||||
#include <stdbool.h>
|
||||
#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);
|
||||
}
|
||||
|
@ -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_
|
||||
|
14
kernel/dev/dev.h
Normal file
14
kernel/dev/dev.h
Normal 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_
|
35
kernel/dev/ps2kbdev.c
Normal file
35
kernel/dev/ps2kbdev.c
Normal file
@ -0,0 +1,35 @@
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
#include "kprintf.h"
|
||||
#include "hal/hal.h"
|
||||
#include "ps2kbdev.h"
|
||||
#include "dev.h"
|
||||
#include "errors.h"
|
||||
#include "dlmalloc/malloc.h"
|
||||
|
||||
Dev PS2KBDEV;
|
||||
Ps2KbFastBuf PS2KB_BUF;
|
||||
|
||||
int32_t ps2kbdev_readch(uint8_t *buffer, size_t len, void *extra) {
|
||||
(void)buffer; (void)len; (void)extra;
|
||||
uint8_t b = 0;
|
||||
spinlock_acquire(&PS2KB_BUF.spinlock);
|
||||
int32_t r = rbuf_pop(&PS2KB_BUF.rbuf, &b);
|
||||
spinlock_release(&PS2KB_BUF.spinlock);
|
||||
|
||||
if (r == 0) {
|
||||
return b;
|
||||
} else {
|
||||
return E_NOTYET;
|
||||
}
|
||||
}
|
||||
|
||||
void ps2kbdev_init(void) {
|
||||
hal_memset(&PS2KBDEV, 0, sizeof(PS2KBDEV));
|
||||
PS2KBDEV.fns[0] = &ps2kbdev_readch;
|
||||
|
||||
const int bufsz = 0x1000;
|
||||
uint8_t *buf = dlmalloc(bufsz);
|
||||
rbuf_init(&PS2KB_BUF.rbuf, buf, bufsz);
|
||||
PS2KB_BUF.init = true;
|
||||
}
|
22
kernel/dev/ps2kbdev.h
Normal file
22
kernel/dev/ps2kbdev.h
Normal file
@ -0,0 +1,22 @@
|
||||
#ifndef DEV_PS2KBDEV_H_
|
||||
#define DEV_PS2KBDEV_H_
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
#include "dev.h"
|
||||
#include "rbuf/rbuf.h"
|
||||
#include "spinlock/spinlock.h"
|
||||
|
||||
typedef struct {
|
||||
RBuf rbuf;
|
||||
SpinLock spinlock;
|
||||
bool init;
|
||||
} Ps2KbFastBuf;
|
||||
|
||||
void ps2kbdev_init(void);
|
||||
|
||||
extern Dev PS2KBDEV;
|
||||
|
||||
extern Ps2KbFastBuf PS2KB_BUF;
|
||||
|
||||
#endif // DEV_PS2KBDEV_H_
|
19
kernel/dev/termdev.c
Normal file
19
kernel/dev/termdev.c
Normal 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
13
kernel/dev/termdev.h
Normal 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_
|
@ -49,7 +49,7 @@ int RELEASE_LOCK(SpinLock *sl) {
|
||||
}
|
||||
|
||||
int INITIAL_LOCK(SpinLock *sl) {
|
||||
spinlock_release(sl);
|
||||
spinlock_init(sl);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -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 {
|
||||
|
@ -14,8 +14,8 @@
|
||||
#include "errors.h"
|
||||
#include "drivers/ps2kb/ps2kb.h"
|
||||
#include "ipc/pipe/pipe.h"
|
||||
#include "proc/ps2kbproc/ps2kbproc.h"
|
||||
#include "rbuf/rbuf.h"
|
||||
#include "dev/ps2kbdev.h"
|
||||
|
||||
typedef struct BackTraceFrame {
|
||||
struct BackTraceFrame *rbp;
|
||||
@ -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);
|
||||
|
||||
@ -200,7 +198,7 @@ void intr_handleintr(IntrStackFrame *frame) {
|
||||
kprintf("ERROR %s, 0x%lX\n", exceptions[frame->trapnum], frame->errnum);
|
||||
intr_dumpframe(frame);
|
||||
backtrace((BackTraceFrame *)frame->regs.rbp);
|
||||
if (frame->errnum & 0x4) {
|
||||
if (hal_vmm_current_cr3() != KERNEL_CR3) {
|
||||
kprintf("killed pid %ld %s\n", PROCS.current->pid, PROCS.current->name);
|
||||
proc_killself();
|
||||
proc_sched((void *)frame);
|
||||
@ -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);
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
||||
|
@ -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;
|
||||
|
@ -30,10 +30,6 @@ typedef struct {
|
||||
uint16_t pml3;
|
||||
uint16_t pml2;
|
||||
uint16_t pml1;
|
||||
/* uint64_t pml4; */
|
||||
/* uint64_t pml3; */
|
||||
/* uint64_t pml2; */
|
||||
/* uint64_t pml1; */
|
||||
} PACKED PgIndex;
|
||||
|
||||
typedef struct {
|
||||
@ -50,11 +46,6 @@ typedef struct {
|
||||
uint64_t addr: 40;
|
||||
uint16_t osdef: 11;
|
||||
bool nx: 1;
|
||||
/* bool zero0: 1; */
|
||||
/* bool size: 1; */
|
||||
/* bool zero1: 1; */
|
||||
/* uint8_t avail: 3; */
|
||||
/* uint64_t addr: 52; */
|
||||
} PACKED Pte;
|
||||
|
||||
typedef struct {
|
||||
|
@ -11,6 +11,8 @@
|
||||
#include "storedev/storedev.h"
|
||||
#include "util/util.h"
|
||||
#include "proc/proc.h"
|
||||
#include "dev/termdev.h"
|
||||
#include "dev/ps2kbdev.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 +66,8 @@ void kmain(void) {
|
||||
storedev_init();
|
||||
baseimg_init();
|
||||
vfs_init();
|
||||
termdev_init();
|
||||
ps2kbdev_init();
|
||||
proc_init();
|
||||
|
||||
for(;;);
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -14,8 +14,6 @@
|
||||
#include "bootinfo/bootinfo.h"
|
||||
#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 +179,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);
|
||||
@ -211,12 +210,13 @@ Proc *proc_nextready(void) {
|
||||
|
||||
void proc_reaper(void) {
|
||||
spinlock_acquire(&PROCS.spinlock);
|
||||
Proc *head = PROCS.procs;
|
||||
while (head) {
|
||||
if (head->state == PROC_ZOMBIE) {
|
||||
Proc *zombie = head;
|
||||
head = head->next;
|
||||
Proc *head, *tmp;
|
||||
LL_FOREACH_SAFE(PROCS.procs, head, tmp) {
|
||||
if (head->state != PROC_ZOMBIE) {
|
||||
continue;
|
||||
}
|
||||
|
||||
Proc *zombie = head;
|
||||
LL_REMOVE(PROCS.procs, zombie);
|
||||
|
||||
for (size_t i = 0; i < zombie->vobjcnt; i++) {
|
||||
@ -238,31 +238,22 @@ void proc_reaper(void) {
|
||||
pmm_free((uintptr_t)(zombie->platformdata.pstack - PROC_STACKSIZE), PROC_STACKBLOCKS);
|
||||
|
||||
if (!zombie->kern) {
|
||||
VasRange *vashead = zombie->vas;
|
||||
size_t i = 0;
|
||||
while (vashead) {
|
||||
VasRange *tmp = vashead;
|
||||
vashead = vashead->next;
|
||||
hal_vmm_unmap_range(zombie->platformdata.cr3, tmp->virtstart, tmp->physstart, tmp->size);
|
||||
pmm_free((uintptr_t)tmp->physstart, tmp->size / HAL_PAGE_SIZE);
|
||||
dlfree(tmp);
|
||||
i++;
|
||||
VasRange *vas, *vastmp;
|
||||
LL_FOREACH_SAFE(zombie->vas, vas, vastmp) {
|
||||
hal_vmm_unmap_range(zombie->platformdata.cr3, vas->virtstart, vas->physstart, vas->size);
|
||||
pmm_free((uintptr_t)vas->physstart, vas->size / HAL_PAGE_SIZE);
|
||||
dlfree(vas);
|
||||
}
|
||||
|
||||
pmm_free((uintptr_t)zombie->platformdata.cr3, 1);
|
||||
|
||||
ProcArg *arg = zombie->procargs.list;
|
||||
while (arg) {
|
||||
ProcArg *arg, *argtmp;
|
||||
LL_FOREACH_SAFE(zombie->procargs.list, arg, argtmp) {
|
||||
dlfree(arg->string);
|
||||
ProcArg *tmp = arg;
|
||||
arg = arg->next;
|
||||
dlfree(tmp);
|
||||
dlfree(arg);
|
||||
}
|
||||
}
|
||||
dlfree(zombie);
|
||||
} else {
|
||||
head = head->next;
|
||||
}
|
||||
}
|
||||
spinlock_release(&PROCS.spinlock);
|
||||
}
|
||||
@ -316,26 +307,8 @@ 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;
|
||||
|
||||
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;
|
||||
|
||||
/* 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;
|
||||
|
||||
|
@ -8,19 +8,21 @@
|
||||
#include "vfs/vfs.h"
|
||||
#include "ipc/pipe/pipe.h"
|
||||
#include "sysdefs/processctl.h"
|
||||
#include "dev/dev.h"
|
||||
|
||||
#define PROC_NAME_MAX 0x100
|
||||
|
||||
#define PROC_STACKBLOCKS (1024*4)
|
||||
#define PROC_STACKBLOCKS (1024*2)
|
||||
#define PROC_STACKSIZE (PROC_STACKBLOCKS * BITMAP_BLOCK_SIZE)
|
||||
|
||||
#define PROC_MAX 0x100 // max amount of processes
|
||||
|
||||
#define PROC_VFSHANDLES_MAX 0x80
|
||||
#define PROC_PIPEHANDLES_MAX 0x20
|
||||
#define PROC_DEVHANDLES_MAX 0x20
|
||||
|
||||
#define PROC_MMAN_MAP_BASE 0x700000000000
|
||||
#define PROC_USER_STACK_TOP 0x800000000000
|
||||
#define PROC_MMAN_MAP_BASE 0x0000100000000000ULL
|
||||
#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;
|
||||
|
@ -1,38 +0,0 @@
|
||||
#include <stdint.h>
|
||||
#include "proc/proc.h"
|
||||
#include "dlmalloc/malloc.h"
|
||||
#include "ipc/pipe/pipe.h"
|
||||
#include "kprintf.h"
|
||||
#include "rbuf/rbuf.h"
|
||||
#include "ps2kbproc.h"
|
||||
|
||||
Proc *PS2KBPROC = NULL;
|
||||
Ps2KbFastBuf PS2KB_BUF;
|
||||
|
||||
void ps2kbproc_init(Proc *proc) {
|
||||
PS2KBPROC = proc;
|
||||
|
||||
PS2KBPROC->bcast_pipes.list = NULL;
|
||||
|
||||
uint8_t *buf = dlmalloc(IPC_PIPE_MAX);
|
||||
rbuf_init(&PS2KB_BUF.rbuf, buf, IPC_PIPE_MAX);
|
||||
spinlock_init(&PS2KB_BUF.spinlock);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
@ -1,20 +0,0 @@
|
||||
#ifndef PROC_PS2KB_PS2KBPROC_H_
|
||||
#define PROC_PS2KB_PS2KBPROC_H_
|
||||
|
||||
#include <stdbool.h>
|
||||
#include "proc/proc.h"
|
||||
#include "rbuf/rbuf.h"
|
||||
#include "spinlock/spinlock.h"
|
||||
|
||||
typedef struct {
|
||||
RBuf rbuf;
|
||||
SpinLock spinlock;
|
||||
} Ps2KbFastBuf;
|
||||
|
||||
extern Proc *PS2KBPROC;
|
||||
extern Ps2KbFastBuf PS2KB_BUF;
|
||||
|
||||
void ps2kbproc_fn(void);
|
||||
void ps2kbproc_init(Proc *proc);
|
||||
|
||||
#endif // PROC_PS2KB_PS2KBPROC_H_
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
@ -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_
|
@ -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();
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
|
68
kernel/syscall/devctl.c
Normal file
68
kernel/syscall/devctl.c
Normal file
@ -0,0 +1,68 @@
|
||||
#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 "dev/ps2kbdev.h"
|
||||
#include "util/util.h"
|
||||
|
||||
Dev *DEVS[] = {
|
||||
[0x10] = &TERMDEV,
|
||||
[0x11] = &PS2KBDEV,
|
||||
};
|
||||
|
||||
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];
|
||||
*devh = i;
|
||||
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
9
kernel/syscall/devctl.h
Normal 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_
|
@ -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);
|
||||
@ -86,13 +84,12 @@ int32_t SYSCALL1(sys_mman_unmap, addr1) {
|
||||
uint8_t *virt = NULL;
|
||||
VasRange *tofree = NULL;
|
||||
|
||||
VasRange *range = proc->vas;
|
||||
while (range) {
|
||||
if (range->virtstart == addr) {
|
||||
tofree = range;
|
||||
VasRange *vas, *vastmp;
|
||||
LL_FOREACH_SAFE(proc->vas, vas, vastmp) {
|
||||
if (vas->virtstart == addr) {
|
||||
tofree = vas;
|
||||
break;
|
||||
}
|
||||
range = range->next;
|
||||
}
|
||||
|
||||
if (tofree == NULL) {
|
||||
|
@ -63,9 +63,11 @@ int32_t SYSCALL5(sys_processctl, pid1, cmd1, arg1, arg2, arg3) {
|
||||
|
||||
size_t argslen = arg3;
|
||||
char *(*args)[] = (char *(*)[])arg2;
|
||||
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++) {
|
||||
if (newproc->pipes[i] != NULL) {
|
||||
@ -91,36 +93,32 @@ int32_t SYSCALL5(sys_processctl, pid1, cmd1, arg1, arg2, arg3) {
|
||||
ret = proc->procargs.len;
|
||||
} break;
|
||||
case PCTL_ARGV: {
|
||||
char **argbuf = (char **)arg1;
|
||||
size_t *argslen = (size_t *)arg1;
|
||||
char **argbuf = (char **)arg2;
|
||||
if (argbuf == NULL) {
|
||||
ret = E_INVALIDARGUMENT;
|
||||
goto done;
|
||||
}
|
||||
size_t len = arg2;
|
||||
ProcArg *arg = proc->procargs.list;
|
||||
size_t i = 0;
|
||||
while (arg) {
|
||||
if (i == len) {
|
||||
break;
|
||||
}
|
||||
size_t maxargs = (size_t)arg3;
|
||||
|
||||
ProcArg *arg, *argtmp;
|
||||
size_t i;
|
||||
LL_FOREACH_SAFE_IDX_LIMIT(proc->procargs.list, arg, argtmp, i, maxargs) {
|
||||
if (argbuf[i] == NULL) {
|
||||
ret = E_INVALIDARGUMENT;
|
||||
goto done;
|
||||
}
|
||||
hal_strcpy(argbuf[i], arg->string);
|
||||
arg = arg->next;
|
||||
i++;
|
||||
}
|
||||
*argslen = i;
|
||||
|
||||
ret = E_OK;
|
||||
} break;
|
||||
case PCTL_PLS_SZ: {
|
||||
size_t i = 0;
|
||||
Proc *p, *ptmp;
|
||||
size_t i;
|
||||
spinlock_acquire(&PROCS.spinlock);
|
||||
Proc *p = PROCS.procs;
|
||||
while (p) {
|
||||
i++;
|
||||
p = p->next;
|
||||
}
|
||||
LL_FOREACH_SAFE_IDX(PROCS.procs, p, ptmp, i);
|
||||
spinlock_release(&PROCS.spinlock);
|
||||
ret = i;
|
||||
} break;
|
||||
@ -133,26 +131,22 @@ int32_t SYSCALL5(sys_processctl, pid1, cmd1, arg1, arg2, arg3) {
|
||||
goto done;
|
||||
}
|
||||
|
||||
size_t i = 0;
|
||||
Proc *p, *ptmp;
|
||||
size_t i;
|
||||
spinlock_acquire(&PROCS.spinlock);
|
||||
Proc *p = PROCS.procs;
|
||||
while (p) {
|
||||
LL_FOREACH_SAFE_IDX(PROCS.procs, p, ptmp, i) {
|
||||
if (i == pidx) {
|
||||
stat->pid = p->pid;
|
||||
hal_strcpy(stat->name, p->name);
|
||||
stat->state = p->state;
|
||||
stat->kern = p->kern;
|
||||
|
||||
VasRange *range = p->vas;
|
||||
while (range) {
|
||||
stat->usemem += range->size;
|
||||
range = range->next;
|
||||
VasRange *vas, *vastmp;
|
||||
LL_FOREACH_SAFE(p->vas, vas, vastmp) {
|
||||
stat->usemem += vas->size;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
i++;
|
||||
p = p->next;
|
||||
}
|
||||
spinlock_release(&PROCS.spinlock);
|
||||
ret = E_OK;
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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,
|
||||
};
|
||||
|
@ -8,6 +8,7 @@
|
||||
|
||||
#define LL_APPEND(head, new) \
|
||||
do { \
|
||||
if ((new) != NULL) { \
|
||||
if ((head) != NULL) { \
|
||||
typeof((head)) __tmp; \
|
||||
(new)->next = NULL; \
|
||||
@ -20,23 +21,32 @@
|
||||
(new)->next = NULL; \
|
||||
(head) = (new); \
|
||||
} \
|
||||
} \
|
||||
} while(0)
|
||||
|
||||
#define LL_REMOVE(head, ele) \
|
||||
do { \
|
||||
if ((head) != NULL && (ele) != NULL) { \
|
||||
typeof((head)) __cur = (head); \
|
||||
typeof((head)) __prev = NULL; \
|
||||
while (__cur != (ele)) { \
|
||||
while (__cur != NULL && __cur != (ele)) { \
|
||||
__prev = __cur; \
|
||||
__cur = __cur->next; \
|
||||
} \
|
||||
if (__cur == (ele)) { \
|
||||
if (__prev != NULL) { \
|
||||
__prev->next = __cur->next; \
|
||||
} else { \
|
||||
(head) = __cur->next; \
|
||||
} \
|
||||
(ele)->next = NULL; \
|
||||
} \
|
||||
} \
|
||||
} while(0)
|
||||
|
||||
#define LL_FINDPROP(head, out, propname, propvalue) \
|
||||
do { \
|
||||
(out) = NULL; \
|
||||
typeof((head)) __tmp = (head); \
|
||||
while (__tmp) { \
|
||||
if (__tmp->propname == (propvalue)) { \
|
||||
@ -47,6 +57,22 @@
|
||||
} \
|
||||
} while(0)
|
||||
|
||||
#define LL_FOREACH_SAFE(head, var, tmp) \
|
||||
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 ((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) \
|
||||
for ((idx) = 0, var = (head), tmp = (var ? var->next : NULL); \
|
||||
var != NULL && (idx) < (max); \
|
||||
var = tmp, tmp = (var ? var->next : NULL), (idx)++)
|
||||
|
||||
char *util_get_filename(char *path);
|
||||
|
||||
#endif // UTIL_UTIL_H_
|
||||
|
@ -10,4 +10,7 @@ CFLAGS += -m64 \
|
||||
-fno-stack-check \
|
||||
-fno-builtin \
|
||||
-fno-omit-frame-pointer \
|
||||
-fno-strict-aliasing \
|
||||
-O0 \
|
||||
-mno-tls-direct-seg-refs \
|
||||
# -fsanitize=undefined
|
||||
|
@ -16,6 +16,7 @@ enum {
|
||||
E_INVALIDOPER = -11,
|
||||
E_RESOURCEAVAIL = -12,
|
||||
E_SPAWNERROR = -13,
|
||||
E_NOTYET = -14,
|
||||
};
|
||||
|
||||
static const char *_ERROR_STRINGS[] = {
|
||||
|
10
share/sysdefs/devctl.h
Normal file
10
share/sysdefs/devctl.h
Normal 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_
|
@ -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,
|
||||
|
@ -9,6 +9,7 @@ enum {
|
||||
SYS_MMAN_MAP = 5,
|
||||
SYS_MMAN_UNMAP = 6,
|
||||
SYS_SCHEDRELEASE = 7,
|
||||
SYS_DEVCTL = 8,
|
||||
};
|
||||
|
||||
#endif // SHARE_HDRS_SYSCALL_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
|
||||
|
@ -10,10 +10,11 @@ SRCFILES := $(call GRABSRC, \
|
||||
string \
|
||||
system \
|
||||
printf \
|
||||
dlmalloc \
|
||||
sync \
|
||||
args \
|
||||
util \
|
||||
ubsan \
|
||||
umalloc \
|
||||
)
|
||||
|
||||
CFLAGS += -isystem $(ROOT)/share -isystem $(ROOT)/ulib -isystem $(ROOT)/std/include \
|
||||
|
@ -2,10 +2,13 @@
|
||||
#include <stddef.h>
|
||||
#include <system/system.h>
|
||||
#include <sysdefs/processctl.h>
|
||||
#include <sysdefs/devctl.h>
|
||||
#include <errors.h>
|
||||
#include <dlmalloc/malloc.h>
|
||||
#include <uprintf.h>
|
||||
#include <log.h>
|
||||
#include <util/util.h>
|
||||
#include <umalloc/umalloc.h>
|
||||
#include <devids.h>
|
||||
|
||||
extern void main(void);
|
||||
extern uint8_t _bss_start[];
|
||||
@ -18,7 +21,9 @@ void clearbss(void) {
|
||||
}
|
||||
}
|
||||
|
||||
char **_args;
|
||||
#define MAX_ARGS 15
|
||||
static char *_args[MAX_ARGS];
|
||||
|
||||
size_t _argslen;
|
||||
|
||||
char **args(void) {
|
||||
@ -29,23 +34,19 @@ size_t argslen(void) {
|
||||
return _argslen;
|
||||
}
|
||||
|
||||
Dev_t termdev;
|
||||
|
||||
// ulib initialization goes here
|
||||
void _premain(void) {
|
||||
clearbss();
|
||||
|
||||
_argslen = processctl(-1, PCTL_ARGLEN, 0, 0, 0);
|
||||
_args = dlmalloc(_argslen * sizeof(*_args));
|
||||
if (_args == NULL) {
|
||||
return;
|
||||
}
|
||||
for (size_t i = 0; i < _argslen; i++) {
|
||||
_args[i] = dlmalloc(PROC_ARG_MAX);
|
||||
if (_args[i] == NULL) {
|
||||
return;
|
||||
}
|
||||
devctl(&termdev, DEVCTL_GET_HANDLE, (uint8_t *)DEV_TERMDEV, 0, 0);
|
||||
|
||||
for (size_t i = 0; i < ARRLEN(_args); i++) {
|
||||
_args[i] = umalloc(PROC_ARG_MAX);
|
||||
}
|
||||
|
||||
processctl(-1, PCTL_ARGV, (uint64_t)_args, _argslen, 0);
|
||||
processctl(-1, PCTL_ARGV, (uint64_t)&_argslen, (uint64_t)_args, MAX_ARGS);
|
||||
|
||||
main();
|
||||
}
|
||||
|
@ -5,35 +5,89 @@
|
||||
#include <string/conv.h>
|
||||
#include <string/string.h>
|
||||
#include <uprintf.h>
|
||||
#include <errors.h>
|
||||
|
||||
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) {
|
||||
|
||||
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:
|
||||
*((char **)def->ptr) = argv[i+1];
|
||||
if (!have_next) {
|
||||
break;
|
||||
}
|
||||
*((char **)def->ptr) = nexttk;
|
||||
CONSUME_TK();
|
||||
break;
|
||||
case ARG_BOOL:
|
||||
*((bool *)def->ptr) = string_strcmp(argv[i+1], "yes") == 0;
|
||||
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;
|
||||
case ARG_INT: {
|
||||
char *end;
|
||||
*((int32_t *)def->ptr) = string_conv_strtol(argv[i+1], &end, 10);
|
||||
} break;
|
||||
}
|
||||
i++;
|
||||
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;
|
||||
}
|
||||
|
@ -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_
|
||||
|
15
ulib/assert.h
Normal file
15
ulib/assert.h
Normal file
@ -0,0 +1,15 @@
|
||||
#ifndef ULIB_ASSERT_H_
|
||||
#define ULIB_ASSERT_H_
|
||||
|
||||
#include <util/util.h>
|
||||
#include <uprintf.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_
|
9
ulib/devids.h
Normal file
9
ulib/devids.h
Normal file
@ -0,0 +1,9 @@
|
||||
#ifndef ULIB_DEVIDS_H_
|
||||
#define ULIB_DEVIDS_H_
|
||||
|
||||
enum {
|
||||
DEV_TERMDEV = 0x10,
|
||||
DEV_PS2KBDEV = 0x11,
|
||||
};
|
||||
|
||||
#endif // ULIB_DEVIDS_H_
|
@ -1,82 +0,0 @@
|
||||
// Config
|
||||
|
||||
#include <stddef.h>
|
||||
#include <dlmalloc/malloc.h>
|
||||
#include <uprintf.h>
|
||||
#include <errors.h>
|
||||
#include <sync/spinlock.h>
|
||||
#include <string/string.h>
|
||||
#include <sysdefs/mman.h>
|
||||
#include <system/system.h>
|
||||
|
||||
#define USE_DL_PREFIX 1
|
||||
#define LACKS_SYS_TYPES_H 1
|
||||
#define NO_MALLOC_STATS 1
|
||||
#define LACKS_ERRNO_H 1
|
||||
#define LACKS_TIME_H 1
|
||||
#define LACKS_STDLIB_H 1
|
||||
#define LACKS_SYS_MMAN_H 1
|
||||
#define LACKS_FCNTL_H 1
|
||||
#define LACKS_UNISTD_H 1
|
||||
#define LACKS_SYS_PARAM_H 1
|
||||
#define LACKS_STRINGS_H 1
|
||||
#define LACKS_SCHED_H 1
|
||||
#define HAVE_MMAP 0
|
||||
#define MORECORE_CONTIGUOUS 0
|
||||
#define ABORT \
|
||||
do { \
|
||||
uprintf("dlmalloc: Aborting...\n"); \
|
||||
} while(0)
|
||||
#define MALLOC_FAILURE_ACTION
|
||||
#define HAVE_MORECORE 1
|
||||
#define USE_LOCKS 2
|
||||
#define malloc_getpagesize 0x1000
|
||||
#define EINVAL E_INVALIDARGUMENT
|
||||
#define ENOMEM E_NOMEMORY
|
||||
|
||||
#define MLOCK_T SpinLock
|
||||
|
||||
int ACQUIRE_LOCK(SpinLock *sl) {
|
||||
spinlock_acquire(sl);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int RELEASE_LOCK(SpinLock *sl) {
|
||||
spinlock_release(sl);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int INITIAL_LOCK(SpinLock *sl) {
|
||||
spinlock_init(sl);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static MLOCK_T malloc_global_mutex = { 0 };
|
||||
|
||||
#define PAGE_SIZE 0x1000
|
||||
|
||||
static size_t _roundpage(size_t sz) {
|
||||
return (sz + PAGE_SIZE - 1) & ~(PAGE_SIZE - 1);
|
||||
}
|
||||
|
||||
void *_last = 0;
|
||||
|
||||
void *sbrk(ptrdiff_t inc) {
|
||||
if (inc < 0) {
|
||||
return 0;
|
||||
}
|
||||
if (!inc) {
|
||||
return _last;
|
||||
}
|
||||
|
||||
uint64_t pages = _roundpage(inc);
|
||||
uint8_t *maddr = NULL;
|
||||
int32_t ret = mman_map(NULL, pages, MMAN_MAP_PF_RW, 0, &maddr);
|
||||
if (ret != E_OK) {
|
||||
return 0;
|
||||
}
|
||||
string_memset(maddr, 0, pages);
|
||||
_last = (void *)(maddr + inc);
|
||||
return maddr;
|
||||
}
|
||||
|
@ -1 +0,0 @@
|
||||
../../dlmalloc/malloc.c
|
@ -1 +0,0 @@
|
||||
../../dlmalloc/malloc.h
|
@ -3,6 +3,7 @@
|
||||
|
||||
#define LL_APPEND(head, new) \
|
||||
do { \
|
||||
if ((new) != NULL) { \
|
||||
if ((head) != NULL) { \
|
||||
typeof((head)) __tmp; \
|
||||
(new)->next = NULL; \
|
||||
@ -15,23 +16,32 @@
|
||||
(new)->next = NULL; \
|
||||
(head) = (new); \
|
||||
} \
|
||||
} \
|
||||
} while(0)
|
||||
|
||||
#define LL_REMOVE(head, ele) \
|
||||
do { \
|
||||
if ((head) != NULL && (ele) != NULL) { \
|
||||
typeof((head)) __cur = (head); \
|
||||
typeof((head)) __prev = NULL; \
|
||||
while (__cur != (ele)) { \
|
||||
while (__cur != NULL && __cur != (ele)) { \
|
||||
__prev = __cur; \
|
||||
__cur = __cur->next; \
|
||||
} \
|
||||
if (__cur == (ele)) { \
|
||||
if (__prev != NULL) { \
|
||||
__prev->next = __cur->next; \
|
||||
} else { \
|
||||
(head) = __cur->next; \
|
||||
} \
|
||||
(ele)->next = NULL; \
|
||||
} \
|
||||
} \
|
||||
} while(0)
|
||||
|
||||
#define LL_FINDPROP(head, out, propname, propvalue) \
|
||||
do { \
|
||||
(out) = NULL; \
|
||||
typeof((head)) __tmp = (head); \
|
||||
while (__tmp) { \
|
||||
if (__tmp->propname == (propvalue)) { \
|
||||
@ -42,4 +52,20 @@
|
||||
} \
|
||||
} while(0)
|
||||
|
||||
#define LL_FOREACH_SAFE(head, var, tmp) \
|
||||
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 ((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) \
|
||||
for ((idx) = 0, var = (head), tmp = (var ? var->next : NULL); \
|
||||
var != NULL && (idx) < (max); \
|
||||
var = tmp, tmp = (var ? var->next : NULL), (idx)++)
|
||||
|
||||
#endif // ULIB_LINKLIST_H_
|
||||
|
@ -1,9 +1,11 @@
|
||||
#include <stdint.h>
|
||||
#include <system/system.h>
|
||||
#include <sysdefs/ipcpipe.h>
|
||||
#include <sysdefs/devctl.h>
|
||||
#include <printf/printf.h>
|
||||
|
||||
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);
|
||||
}
|
||||
|
@ -1,5 +1,6 @@
|
||||
#include <stddef.h>
|
||||
#include <string/string.h>
|
||||
#include <umalloc/umalloc.h>
|
||||
|
||||
size_t string_len(const char *s) {
|
||||
size_t l = 0;
|
||||
@ -130,3 +131,44 @@ 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 char *saved = NULL;
|
||||
|
||||
if (s) {
|
||||
saved = s;
|
||||
}
|
||||
|
||||
if (!delim || !saved) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
while (*saved && string_strchr(delim, *saved)) {
|
||||
saved++;
|
||||
}
|
||||
|
||||
if (!*saved) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
char *w = (char *)umalloc(sizeof(char) * STRING_TOKENIZEALLOC_TOK_SIZE);
|
||||
string_memset(w, 0, sizeof(char) * STRING_TOKENIZEALLOC_TOK_SIZE);
|
||||
|
||||
int k = 0;
|
||||
while (*saved && !string_strchr(delim, *saved)) {
|
||||
if (k >= STRING_TOKENIZEALLOC_TOK_SIZE - 1) {
|
||||
break;
|
||||
}
|
||||
w[k++] = *saved++;
|
||||
}
|
||||
|
||||
w[k] = '\0';
|
||||
|
||||
if (*saved) {
|
||||
saved++;
|
||||
}
|
||||
|
||||
return w;
|
||||
}
|
||||
|
@ -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
|
||||
|
||||
|
@ -1,27 +1,18 @@
|
||||
#include <stdint.h>
|
||||
#include <uprintf.h>
|
||||
|
||||
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 ret = 0;
|
||||
uint64_t ret;
|
||||
asm volatile(
|
||||
"mov %[SYSNUM], %%rax\n"
|
||||
"mov %[ARG1], %%rdi\n"
|
||||
"mov %[ARG2], %%rsi\n"
|
||||
"mov %[ARG3], %%rdx\n"
|
||||
"mov %[ARG4], %%r10\n"
|
||||
"mov %[ARG5], %%r8\n"
|
||||
"mov %[ARG6], %%r9\n"
|
||||
"mov %[a4], %%r10\n"
|
||||
"mov %[a5], %%r8\n"
|
||||
"mov %[a6], %%r9\n"
|
||||
"int $0x80\n"
|
||||
"mov %%rax, %[RESULT]\n"
|
||||
: [RESULT]"=r"(ret)
|
||||
: [SYSNUM]"r"(num),
|
||||
[ARG1]"r"(arg1),
|
||||
[ARG2]"r"(arg2),
|
||||
[ARG3]"r"(arg3),
|
||||
[ARG4]"r"(arg4),
|
||||
[ARG5]"r"(arg5),
|
||||
[ARG6]"r"(arg6)
|
||||
: "rax", "rdi", "rsi", "rdx", "r10", "r8", "r9", "memory"
|
||||
: "=a"(ret)
|
||||
: "a"(num), "D"(arg1), "S"(arg2), "d"(arg3),
|
||||
[a4]"r"(arg4), [a5]"r"(arg5), [a6]"r"(arg6)
|
||||
: "r10", "r8", "r9", "memory", "cc"
|
||||
);
|
||||
return ret;
|
||||
}
|
||||
|
@ -5,6 +5,7 @@
|
||||
#include <sysdefs/ioctl.h>
|
||||
#include <sysdefs/processctl.h>
|
||||
#include <sysdefs/ipcpipe.h>
|
||||
#include <sysdefs/devctl.h>
|
||||
#include <uprintf.h>
|
||||
|
||||
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);
|
||||
}
|
||||
|
@ -3,6 +3,7 @@
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
#include <sysdefs/devctl.h>
|
||||
|
||||
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_
|
||||
|
224
ulib/ubsan/ubsan.c
Normal file
224
ulib/ubsan/ubsan.c
Normal 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");
|
||||
}
|
||||
|
@ -3,7 +3,6 @@
|
||||
|
||||
#include <ansiq/all.h>
|
||||
#include <args/args.h>
|
||||
#include <dlmalloc/malloc.h>
|
||||
#include <string/string.h>
|
||||
#include <string/char.h>
|
||||
#include <sync/spinlock.h>
|
||||
@ -13,6 +12,9 @@
|
||||
#include <uprintf.h>
|
||||
#include <linklist.h>
|
||||
#include <log.h>
|
||||
#include <assert.h>
|
||||
#include <umalloc/umalloc.h>
|
||||
#include <devids.h>
|
||||
|
||||
#include <errors.h>
|
||||
#include <sysdefs/ioctl.h>
|
||||
|
120
ulib/umalloc/umalloc.c
Normal file
120
ulib/umalloc/umalloc.c
Normal file
@ -0,0 +1,120 @@
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
#include <umalloc/umalloc.h>
|
||||
#include <sysdefs/mman.h>
|
||||
#include <system/system.h>
|
||||
#include <errors.h>
|
||||
#include <linklist.h>
|
||||
#include <string/string.h>
|
||||
#include <util/util.h>
|
||||
#include <assert.h>
|
||||
|
||||
#define ARENA_SIZE (1<<20)
|
||||
#define BLOCK_MAGIC 0xDEADBEEF
|
||||
|
||||
typedef struct UmArena {
|
||||
struct UmArena *next;
|
||||
uintptr_t mem;
|
||||
uintptr_t base;
|
||||
size_t cursor;
|
||||
int64_t balance;
|
||||
} __attribute__((aligned(16))) UmArena;
|
||||
|
||||
typedef struct {
|
||||
uint32_t magic;
|
||||
size_t size;
|
||||
uint8_t data[];
|
||||
} __attribute__((aligned(16))) UmBlock;
|
||||
|
||||
static UmArena *ARENAS = NULL;
|
||||
|
||||
UmArena *um_newarena(void) {
|
||||
size_t arenasize = ARENA_SIZE;
|
||||
|
||||
uint8_t *mem = NULL;
|
||||
int32_t err = mman_map(NULL, arenasize, MMAN_MAP_PF_RW, 0, &mem);
|
||||
if (mem == NULL || err != E_OK) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
UmArena *arena = (UmArena *)mem;
|
||||
arena->base = (uintptr_t)mem;
|
||||
arena->mem = ((uintptr_t)mem + sizeof(UmArena) + 15) & ~0xF;
|
||||
arena->cursor = 0;
|
||||
arena->balance = 0;
|
||||
LL_APPEND(ARENAS, arena);
|
||||
|
||||
return arena;
|
||||
}
|
||||
|
||||
void *umalloc(size_t size) {
|
||||
UmArena *usable = NULL;
|
||||
|
||||
size = (size + 15) & ~(size_t)0xF;
|
||||
|
||||
UmArena *arena, *arenatmp;
|
||||
LL_FOREACH_SAFE(ARENAS, arena, arenatmp) {
|
||||
if (arena->cursor + sizeof(UmBlock) + size <= ARENA_SIZE - ((uintptr_t)arena->mem - arena->base)) {
|
||||
usable = arena;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (usable == NULL) {
|
||||
usable = um_newarena();
|
||||
}
|
||||
|
||||
if (usable == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
uintptr_t addr = usable->mem + usable->cursor;
|
||||
UmBlock *block = (UmBlock *)addr;
|
||||
block->size = size;
|
||||
block->magic = BLOCK_MAGIC;
|
||||
|
||||
usable->cursor += sizeof(UmBlock) + size;
|
||||
usable->balance += size;
|
||||
|
||||
string_memset(block->data, 0, size);
|
||||
return block->data;
|
||||
}
|
||||
|
||||
void ufree(void *ptr_) {
|
||||
if (ptr_ == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
uintptr_t ptr = (uintptr_t)ptr_;
|
||||
|
||||
UmArena *freeable = NULL;
|
||||
size_t size = 0;
|
||||
|
||||
UmArena *arena, *arenatmp;
|
||||
LL_FOREACH_SAFE(ARENAS, arena, arenatmp) {
|
||||
if (ptr >= arena->mem && ptr < arena->mem + arena->cursor) {
|
||||
UmBlock *block = (UmBlock *)(ptr - sizeof(UmBlock));
|
||||
|
||||
if (((uintptr_t)block->data != ptr)
|
||||
|| (block->magic != BLOCK_MAGIC)
|
||||
|| (block->size == 0)
|
||||
|| (block->size > ARENA_SIZE)) {
|
||||
return;
|
||||
}
|
||||
|
||||
string_memset(block->data, 0xDD, block->size);
|
||||
block->magic = 0;
|
||||
|
||||
arena->balance -= block->size;
|
||||
ASSERT(arena->balance >= 0, "umalloc: imbalance after free\n");
|
||||
|
||||
if (arena->balance == 0) {
|
||||
LL_REMOVE(ARENAS, arena);
|
||||
mman_unmap((void *)arena->base);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
10
ulib/umalloc/umalloc.h
Normal file
10
ulib/umalloc/umalloc.h
Normal file
@ -0,0 +1,10 @@
|
||||
#ifndef ULIB_UMALLOC_UMALLOC_H_
|
||||
#define ULIB_UMALLOC_UMALLOC_H_
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
|
||||
void *umalloc(size_t size);
|
||||
void ufree(void *ptr_);
|
||||
|
||||
#endif // ULIB_UMALLOC_UMALLOC_H_
|
@ -5,11 +5,21 @@
|
||||
|
||||
#define ARRLEN(X) (sizeof((X))/sizeof((X)[0]))
|
||||
|
||||
#define ZERO(X) \
|
||||
#define ZERO(X) string_memset((X), 0, sizeof(*(X)))
|
||||
|
||||
#define MIN(a, b) \
|
||||
({ \
|
||||
string_memset((X), 0, sizeof(*(X))); \
|
||||
*(X); \
|
||||
}) \
|
||||
typeof(a) _a = (a); \
|
||||
typeof(b) _b = (b); \
|
||||
(_a < _b ? _a : _b); \
|
||||
})
|
||||
|
||||
#define MAX(a, b) \
|
||||
({ \
|
||||
typeof(a) _a = (a); \
|
||||
typeof(b) _b = (b); \
|
||||
(_a > _b ? _a : _b); \
|
||||
})
|
||||
|
||||
void quit(void);
|
||||
|
||||
|
@ -22,6 +22,7 @@ SECTIONS {
|
||||
{
|
||||
_bss_start = .;
|
||||
*(.bss .bss*)
|
||||
. = ALIGN(4K);
|
||||
_bss_end = .;
|
||||
}
|
||||
}
|
||||
|
@ -2,22 +2,26 @@
|
||||
#include <ulib.h>
|
||||
|
||||
uint64_t PID;
|
||||
Dev_t ps2kbdev;
|
||||
|
||||
void tb_runinitscript(void) {
|
||||
char *tbargs[] = { "-m", "runfile", "-f", "base:/scripts/init.tb", "-logcmds", "yes" };
|
||||
int32_t tb = processctl(-1, PCTL_SPAWN, (uint64_t)"base:/bin/tb", (uint64_t)&tbargs, ARRLEN(tbargs));
|
||||
|
||||
ipcpipe(tb, IPCPIPE_IN, IPCPIPE_ADD_BCAST, NULL, 1);
|
||||
|
||||
processctl(tb, PCTL_RUN, 0, 0, 0);
|
||||
|
||||
while(processctl(tb, PCTL_POLLSTATE, 0, 0, 0) != 4) {
|
||||
schedrelease();
|
||||
int32_t r = devctl(&ps2kbdev, 0x00, NULL, 0, 0);
|
||||
if (r != E_NOTYET) {
|
||||
uint8_t b = r;
|
||||
ipcpipe(tb, IPCPIPE_IN, IPCPIPE_WRITE, &b, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void main(void) {
|
||||
PID = (uint64_t)processctl(-1, PCTL_GETPID, 0, 0, 0);
|
||||
devctl(&ps2kbdev, DEVCTL_GET_HANDLE, (uint8_t *)DEV_PS2KBDEV, 0, 0);
|
||||
|
||||
tb_runinitscript();
|
||||
|
||||
@ -25,4 +29,3 @@ void main(void) {
|
||||
|
||||
for(;;);
|
||||
}
|
||||
|
||||
|
@ -61,12 +61,12 @@ void pctl_ls(void) {
|
||||
|
||||
uint64_t procslen = processctl(-1, PCTL_PLS_SZ, 0, 0, 0);
|
||||
|
||||
char *namebuf = dlmalloc(34);
|
||||
char *membuf = dlmalloc(20);
|
||||
char *namebuf = umalloc(34);
|
||||
char *membuf = umalloc(20);
|
||||
|
||||
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);
|
||||
|
234
user/tb/interp.c
234
user/tb/interp.c
@ -9,184 +9,110 @@ 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) {
|
||||
ufree(tk->str);
|
||||
ufree(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;
|
||||
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 = umalloc(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++];
|
||||
}
|
||||
|
||||
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;
|
||||
Token *tk = umalloc(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++;
|
||||
char *tkstr = umalloc(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 {
|
||||
while (tz->pos < tz->len && !string_chr_isspace(tz->str[tz->pos])) {
|
||||
tz->pos++;
|
||||
Token *tk = umalloc(sizeof(*tk));
|
||||
tk->str = tkstr;
|
||||
tk->next = NULL;
|
||||
LL_APPEND(tz->tokens, tk);
|
||||
}
|
||||
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] == '"') {
|
||||
Token *tk, *tktmp;
|
||||
LL_FOREACH_SAFE(tz->tokens, tk, tktmp) {
|
||||
if (tk->str[0] == '"') {
|
||||
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) {
|
||||
} else if (tk->str[0] == '%') {
|
||||
RtCmd *cmd, *cmdtmp;
|
||||
LL_FOREACH_SAFE(RTCMDS, cmd, cmdtmp) {
|
||||
if (string_strcmp(tk->str, cmd->cmdname) == 0) {
|
||||
tk->type = TOK_CMD;
|
||||
tk->cmd = cmd;
|
||||
break;
|
||||
}
|
||||
cmd = cmd->next;
|
||||
}
|
||||
} else {
|
||||
tk->type = TOK_MISC;
|
||||
}
|
||||
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);
|
||||
Token *tk, *tktmp;
|
||||
LL_FOREACH_SAFE(tz->tokens, tk, tktmp) {
|
||||
if (tk->str[0] == '$' && string_len(tk->str) > 1) {
|
||||
RtAlias *alias, *aliastmp;
|
||||
LL_FOREACH_SAFE(RTALIASES, alias, aliastmp) {
|
||||
if (string_strcmp(alias->namebuf, tk->str+1) == 0) {
|
||||
ufree(tk->str);
|
||||
size_t len = string_len(alias->valbuf)+1;
|
||||
tk->str = umalloc(len);
|
||||
string_memset(tk->str, 0, len);
|
||||
string_memcpy(tk->str, alias->valbuf, 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;
|
||||
}
|
||||
#define LINE_MAX 1024
|
||||
|
||||
if (*nextstart == '\0') {
|
||||
return false;
|
||||
}
|
||||
*bgptr = nextstart;
|
||||
const char *scn = nextstart;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
*endptr = scn - 1;
|
||||
|
||||
while (string_chr_isspace(**bgptr) && *bgptr < *endptr) {
|
||||
(*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) {
|
||||
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);
|
||||
uprintf("+%s\n", line);
|
||||
}
|
||||
|
||||
Tokenizer tz = {0};
|
||||
tz_init(&tz, bg, linelen);
|
||||
Tokenizer tz; ZERO(&tz);
|
||||
tz_init(&tz, line);
|
||||
|
||||
Token toktmp = {0};
|
||||
while (tz_next(&tz, &toktmp)) {
|
||||
Token *tok = dlmalloc(sizeof(*tok));
|
||||
tok->ptr = toktmp.ptr;
|
||||
tok->len = toktmp.len;
|
||||
LL_APPEND(tz.tokens, tok);
|
||||
}
|
||||
tz_tokenize(&tz);
|
||||
|
||||
tz_classify(&tz);
|
||||
tz_expandspecial(&tz);
|
||||
@ -195,36 +121,25 @@ bool interp_runstring(const char *string, InterpResult **res, bool logcmds, bool
|
||||
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;
|
||||
usprintf(RES.errmsg, "cmd %s failed", cmdtk->str);
|
||||
goto next;
|
||||
}
|
||||
} else if (cmdtk->type == TOK_MISC) {
|
||||
char *appname = dlmalloc(1024);
|
||||
usprintf(appname, "%.*s", (int)cmdtk->len, cmdtk->ptr);
|
||||
size_t argslen1;
|
||||
Token *argtk, *argtktmp;
|
||||
LL_FOREACH_SAFE_IDX(cmdtk->next, argtk, argtktmp, argslen1);
|
||||
|
||||
size_t argslen1 = 0;
|
||||
Token *argtk = cmdtk->next;
|
||||
while (argtk) {
|
||||
argslen1++;
|
||||
argtk = argtk->next;
|
||||
}
|
||||
|
||||
char **args1 = (char **)dlmalloc(sizeof(char *) * argslen1);
|
||||
argtk = cmdtk->next;
|
||||
size_t i = 0;
|
||||
while (argtk) {
|
||||
args1[i] = (char *)dlmalloc(PROC_ARG_MAX);
|
||||
size_t i;
|
||||
char **args1 = (char **)umalloc(sizeof(char *) * argslen1);
|
||||
LL_FOREACH_SAFE_IDX(cmdtk->next, argtk, argtktmp, i) {
|
||||
args1[i] = (char *)umalloc(PROC_ARG_MAX);
|
||||
string_memset(args1[i], 0, PROC_ARG_MAX);
|
||||
string_memcpy(args1[i], argtk->ptr, argtk->len);
|
||||
i++;
|
||||
argtk = argtk->next;
|
||||
string_memcpy(args1[i], argtk->str, MIN(string_len(argtk->str), PROC_ARG_MAX));
|
||||
}
|
||||
|
||||
int32_t app = processctl(-1, PCTL_SPAWN, (uint64_t)appname, (uint64_t)args1, argslen1);
|
||||
int32_t app = processctl(-1, PCTL_SPAWN, (uint64_t)cmdtk->str, (uint64_t)args1, argslen1);
|
||||
if (app < 0) {
|
||||
usprintf(RES.errmsg, "Could not run %s: %s\n", appname, ERRSTRING(app));
|
||||
usprintf(RES.errmsg, "Could not run %s: %s\n", cmdtk->str, ERRSTRING(app));
|
||||
ok = false;
|
||||
goto cleanup;
|
||||
}
|
||||
@ -244,16 +159,17 @@ bool interp_runstring(const char *string, InterpResult **res, bool logcmds, bool
|
||||
}
|
||||
|
||||
cleanup: {
|
||||
for (size_t j = 0; j < argslen1; j++) {
|
||||
dlfree(args1[j]);
|
||||
}
|
||||
dlfree(args1);
|
||||
dlfree(appname);
|
||||
for (size_t j = 0; j < argslen1; j++) ufree(args1[j]);
|
||||
ufree(args1);
|
||||
}
|
||||
}
|
||||
|
||||
next:
|
||||
tz_free(&tz);
|
||||
ufree(line);
|
||||
line = string_tokenizealloc(NULL, "\n");
|
||||
}
|
||||
|
||||
done:
|
||||
return ok;
|
||||
}
|
||||
|
@ -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_
|
||||
|
@ -57,14 +57,14 @@ void do_file(char *filepath) {
|
||||
return;
|
||||
}
|
||||
|
||||
IoctlStat statbuf = {0};
|
||||
IoctlStat statbuf; ZERO(&statbuf);
|
||||
|
||||
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);
|
||||
return;
|
||||
}
|
||||
uint8_t *buf = dlmalloc(statbuf.size+1);
|
||||
uint8_t *buf = umalloc(statbuf.size+1);
|
||||
string_memset(buf, 0, statbuf.size+1);
|
||||
|
||||
if ((ret = ioctl(ioh, IOCTL_READ, (uint64_t)buf, statbuf.size, 0)) < 0) {
|
||||
@ -73,7 +73,7 @@ void do_file(char *filepath) {
|
||||
}
|
||||
|
||||
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);
|
||||
@ -81,7 +81,7 @@ void do_file(char *filepath) {
|
||||
}
|
||||
|
||||
done:
|
||||
dlfree(buf);
|
||||
ufree(buf);
|
||||
ioctl(ioh, IOCTL_CLOSEF, 0, 0, 0);
|
||||
}
|
||||
|
||||
|
@ -9,39 +9,38 @@ RtAlias *RTALIASES = NULL;
|
||||
|
||||
#define RTCMD(name, _fn) \
|
||||
do { \
|
||||
RtCmd *_cmd = dlmalloc(sizeof(*_cmd)); \
|
||||
RtCmd *_cmd = umalloc(sizeof(*_cmd)); \
|
||||
_cmd->cmdname = (name); \
|
||||
_cmd->fn = (_fn); \
|
||||
LL_APPEND(RTCMDS, _cmd); \
|
||||
} 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) {
|
||||
uprintf("%s", tk->str);
|
||||
if (tk->next != NULL) {
|
||||
uprintf(" ");
|
||||
}
|
||||
tk = tk->next;
|
||||
}
|
||||
uprintf("\n");
|
||||
return true;
|
||||
}
|
||||
|
||||
bool rt_mkalias(Token *tks) {
|
||||
RtAlias *alias = dlmalloc(sizeof(*alias));
|
||||
RtAlias *alias = umalloc(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;
|
||||
}
|
||||
|
Reference in New Issue
Block a user