From e2ebb6cc34cf7bc6d9e9380bfe24e13c3f2c0a15 Mon Sep 17 00:00:00 2001 From: Yi-Ting Shih Date: Wed, 26 Mar 2025 15:30:57 +0800 Subject: [PATCH] Feat: lab 3 w/o adv 2 --- .gitignore | 1 + Makefile | 9 +- {include => bootloader/include}/uart.h | 4 +- {lib => bootloader/lib}/uart.c | 9 +- include/errcode.h | 2 + include/logger.h | 13 +- include/stddef.h | 6 +- include/string.h | 1 + kernel/Start.S | 2 +- kernel/include/interrupt.h | 11 -- kernel/include/ringbuffer.h | 14 ++ kernel/include/timer.h | 27 ++++ kernel/include/uart.h | 25 ++++ kernel/include/utils.h | 24 +++- kernel/lib/exception.c | 4 +- kernel/lib/interrupt.c | 67 ++++----- kernel/lib/ringbuffer.c | 47 +++++++ kernel/lib/shell.c | 87 ++++++++---- kernel/lib/timer.c | 95 +++++++++++++ kernel/lib/uart.c | 188 +++++++++++++++++++++++++ kernel/main.c | 28 ++++ lib/string.c | 15 ++ rootfs/userprog | Bin 1944 -> 0 bytes test.py | 13 -- userprog/Makefile | 39 +++++ 25 files changed, 618 insertions(+), 113 deletions(-) rename {include => bootloader/include}/uart.h (72%) rename {lib => bootloader/lib}/uart.c (94%) create mode 100644 kernel/include/ringbuffer.h create mode 100644 kernel/include/timer.h create mode 100644 kernel/include/uart.h create mode 100644 kernel/lib/ringbuffer.c create mode 100644 kernel/lib/timer.c create mode 100644 kernel/lib/uart.c delete mode 100755 rootfs/userprog delete mode 100755 test.py create mode 100644 userprog/Makefile diff --git a/.gitignore b/.gitignore index 7ab3923..724759f 100644 --- a/.gitignore +++ b/.gitignore @@ -3,3 +3,4 @@ **.elf **.cpio .gdb_history +userprog/userprog diff --git a/Makefile b/Makefile index 07c0dbe..b685978 100644 --- a/Makefile +++ b/Makefile @@ -10,6 +10,7 @@ QEMUFLAGS += -M raspi3b -display none -serial null CC := $(GNU)-gcc CCFLAGS += -Wall -Wextra -O0 \ + -mcpu=cortex-a53+nofp+nosimd \ -nostdinc -nostdlib -nostartfiles -nodefaultlibs \ -Wno-unused-parameter -Wno-unused-value -Wno-main -g LD := $(GNU)-ld @@ -55,7 +56,7 @@ all: $(CPIO) build: $(IMG) $(CPIO): $(shell find $(ROOTFS_DIR)) userprog - cp userprog.img $(ROOTFS_DIR)/userprog + cp userprog/userprog $(ROOTFS_DIR)/userprog cd $(ROOTFS_DIR) && find . | cpio -o -H newc > ../$@ $(IMG): $(ELF) @@ -74,9 +75,9 @@ $(ELF): $(LD_SCRIPT) $(TARGET_OBJS) $(OBJS) clean: -rm $(OBJS) $(CPIO) $(ROOTFS_DIR)/userprog + $(MAKE) $(MAKEFLAGS) -C userprog clean $(MAKE) $(MAKEFLAGS) clean_target TARGET_DIR=kernel TARGET=kernel8 $(MAKE) $(MAKEFLAGS) clean_target TARGET_DIR=bootloader TARGET=bootloader - $(MAKE) $(MAKEFLAGS) clean_target TARGET_DIR=userprog TARGET=userprog clean_target: -rm $(TARGET_OBJS) $(ELF) $(IMG) @@ -90,10 +91,10 @@ kernel: $(CPIO) bootloader: $(CPIO) $(MAKE) $(MAKEFLAGS) build TARGET_DIR=bootloader TARGET=bootloader - $(QEMU) -kernel bootloader.img $(QEMUFLAGS) + $(QEMU) -kernel bootloader.img $(QEMUFLAGS) -serial stdio userprog: - $(MAKE) $(MAKEFLAGS) build TARGET_DIR=userprog TARGET=userprog + $(MAKE) $(MAKEFLAGS) -C userprog debug: $(CPIO) $(MAKE) $(MAKEFLAGS) build TARGET_DIR=kernel TARGET=kernel8 diff --git a/include/uart.h b/bootloader/include/uart.h similarity index 72% rename from include/uart.h rename to bootloader/include/uart.h index 2bf4a0d..970ed88 100644 --- a/include/uart.h +++ b/bootloader/include/uart.h @@ -3,10 +3,10 @@ #include void uart_init(); -void uart_send(unsigned int c); +void uart_send(uint32_t c); uint8_t uart_getb(); char uart_getc(); void uart_puts(const char *s); void uart_hex(uint64_t d); -extern int is_uart_init; +extern int is_uart_inited; diff --git a/lib/uart.c b/bootloader/lib/uart.c similarity index 94% rename from lib/uart.c rename to bootloader/lib/uart.c index 770657a..e982278 100644 --- a/lib/uart.c +++ b/bootloader/lib/uart.c @@ -16,9 +16,7 @@ #define AUX_MU_STAT ((volatile unsigned int*)(MMIO_BASE + 0x00215064)) #define AUX_MU_BAUD ((volatile unsigned int*)(MMIO_BASE + 0x00215068)) -#define ARMINT_En_IRQs1 ((volatile unsigned int*)(MMIO_BASE + 0x0000b210)) - -int is_uart_init = 0; +int is_uart_inited = 0; /** * Set baud rate and characteristics (115200 8N1) and map to GPIO @@ -29,7 +27,6 @@ void uart_init() /* initialize UART */ *AUX_ENABLE |= 1; // enable UART1, AUX mini uart - *AUX_MU_IER = 1; *AUX_MU_CNTL = 0; *AUX_MU_LCR = 3; // 8 bits *AUX_MU_MCR = 0; @@ -48,9 +45,7 @@ void uart_init() *GPPUDCLK0 = 0; // flush GPIO setup *AUX_MU_CNTL = 3; // enable Tx, Rx - *ARMINT_En_IRQs1 |= (1 << 29); - - is_uart_init = 1; + is_uart_inited = 1; } /** diff --git a/include/errcode.h b/include/errcode.h index 239d04e..ef9686f 100644 --- a/include/errcode.h +++ b/include/errcode.h @@ -1,5 +1,6 @@ #pragma once +#define NO_ERROR 0x00000000 #define ERR_NO_MEM 0x00000001 #define ERR_UNREACHABLE 0x00000002 #define ERR_CONVERSION 0x00000003 @@ -7,4 +8,5 @@ #define ERR_INVALID_OP 0x00000005 #define ERR_INVALID_MEM 0x00000006 #define ERR_NOT_EXIST 0x00000007 +#define ERR_IO_FAILED 0x00000008 #define ERR_ADMINKILL 0x00114514 diff --git a/include/logger.h b/include/logger.h index 72e3b87..f9ed13f 100644 --- a/include/logger.h +++ b/include/logger.h @@ -34,6 +34,13 @@ static inline char *_logger_pointer(char *dest, void *x) return _logger_hex(dest, (uint64_t)x); } +static inline +void _uart_puts_sync(const char *s) +{ + while (*s != '\0') + uart_putb_sync((const uint8_t *)s++, 1); +} + #define _I_HATE_C_LANG(msg) \ logger_cur = _Generic((msg), \ char * : _do_nothing, \ @@ -54,9 +61,9 @@ logger_cur = _Generic((msg), \ } #define FLUSH(prefix) { \ - uart_puts(prefix); \ - uart_puts(logger_buf); \ - uart_puts(ENDL); \ + _uart_puts_sync(prefix); \ + _uart_puts_sync(logger_buf); \ + _uart_puts_sync(ENDL); \ logger_cur = logger_buf; \ } diff --git a/include/stddef.h b/include/stddef.h index 22829f8..9ec82a0 100644 --- a/include/stddef.h +++ b/include/stddef.h @@ -1,8 +1,10 @@ #pragma once -#define true 1 -#define false 0 +#define true 0x1 +#define false 0x0 + #define ENDL "\r\n" + #define NAME_MAX 255 #define PATH_MAX 4096 diff --git a/include/string.h b/include/string.h index b3013df..4bdfce7 100644 --- a/include/string.h +++ b/include/string.h @@ -5,6 +5,7 @@ int strcmp(const char *lhs, const char *rhs); char *strcpy(char *destination, const char *source); size_t strlen(const char *str); +char *strtok_r(char *str, const char *delimiters, char **saveptr); void *memcpy(void *dest, const void *src, size_t count); void *memzero(void *start, void *end); diff --git a/kernel/Start.S b/kernel/Start.S index fafdd77..71e2118 100644 --- a/kernel/Start.S +++ b/kernel/Start.S @@ -7,7 +7,7 @@ _start: mrs x1, mpidr_el1 and x1, x1, #3 cbz x1, run - // cpu id > 0, stop + // cpu id > 0, fallback to wait wait: wfe b wait diff --git a/kernel/include/interrupt.h b/kernel/include/interrupt.h index c667eea..47de170 100644 --- a/kernel/include/interrupt.h +++ b/kernel/include/interrupt.h @@ -2,16 +2,5 @@ #include -#define CORE0_TIMER_IRQ_CTRL ((volatile uint32_t *)0x40000040) -#define CORE0_IRQ_SOURCE ((volatile uint32_t *)0x40000060) - -enum :uint32_t { - CNTPNSIRQ_INT = ((uint32_t)1 << 1), - GPU_INT = ((uint32_t)1 << 8) -}; - void init_interrupt(void); void irq_handler(void); - -void enable_interrupt(void); -void disable_interrupt(void); diff --git a/kernel/include/ringbuffer.h b/kernel/include/ringbuffer.h new file mode 100644 index 0000000..02bfa6b --- /dev/null +++ b/kernel/include/ringbuffer.h @@ -0,0 +1,14 @@ +#pragma once + +#include + +typedef struct { + size_t size; + size_t cap; + uint8_t *data; + uint8_t *read, *write; +} ringbuffer_t; + +ringbuffer_t *make_ringbuffer(size_t size); +int ringbuffer_push(ringbuffer_t *buf, uint8_t val); +uint8_t ringbuffer_bump(ringbuffer_t *buf); diff --git a/kernel/include/timer.h b/kernel/include/timer.h new file mode 100644 index 0000000..e370931 --- /dev/null +++ b/kernel/include/timer.h @@ -0,0 +1,27 @@ +#pragma once + +#include + +typedef void (*task_callback_func_t)(uint64_t); + +typedef struct { + uint64_t firing_tick; + uint64_t interval; + uint64_t repeat; + + task_callback_func_t func; + uint64_t param; +} task_t; + +typedef struct timer { + struct timer *_l, *_r; + uint32_t _d; + + task_t data; +} timer_t; + +void add_task(task_t task); + +void timer_irq_handler(void); + +extern timer_t *global_timer; diff --git a/kernel/include/uart.h b/kernel/include/uart.h new file mode 100644 index 0000000..2a2d5ca --- /dev/null +++ b/kernel/include/uart.h @@ -0,0 +1,25 @@ +#pragma once + +#include +#include + +#define UART_BUFLEN 0x800 + +void uart_init(void); +char uart_getc(void); +void uart_puts(const char *s); +void uart_hex(uint64_t d); + +void uart_irq_handler(void); + +size_t uart_putb_sync(const uint8_t *bytes, size_t len); +size_t uart_getb_sync(uint8_t *bytes, size_t len); + +size_t uart_putb_async(const uint8_t *bytes, size_t len); +size_t uart_getb_async(uint8_t *bytes, size_t len); + +extern size_t (*uart_putb)(const uint8_t *bytes, size_t len); +extern size_t (*uart_getb)(uint8_t *bytes, size_t len); +extern int is_uart_inited; + +extern ringbuffer_t *uart_readbuf; diff --git a/kernel/include/utils.h b/kernel/include/utils.h index e79a44b..361eb20 100644 --- a/kernel/include/utils.h +++ b/kernel/include/utils.h @@ -45,8 +45,16 @@ void exit(int); #define W_SYSREG(reg, val) \ asm volatile( \ - "msr " #reg ", %[a]" \ + "mov x0, %[a]" ENDL \ + "msr " #reg ", x0" ENDL \ :: [a] "r" (val) \ + : "x0" \ + ) + +#define W_SYSREG_IMM(reg, val) \ + asm volatile( \ + "msr " #reg ", %[a]" \ + :: [a] "i" (val) \ ) #define R_REG(ret, reg) \ @@ -54,3 +62,17 @@ void exit(int); "mov %[a], " #reg \ : [a] "=r" (ret) \ ) + +#define W_REG(reg, val) \ + asm volatile( \ + "mov " #reg ", %[a]" \ + :: [a] "r" (val) \ + ) + +#define MMIO_W_HELPER(name, reg, mask, offset) \ + static inline void name(uint64_t state) \ + { *reg = (*reg & ~((mask) << (offset))) | ((state & (mask)) << (offset)); } + +#define MMIO_R_HELPER(name, reg, mask, offset) \ + static inline uint64_t name(void) \ + { return (*reg >> (offset)) & (mask); } diff --git a/kernel/lib/exception.c b/kernel/lib/exception.c index 780a55d..390528e 100644 --- a/kernel/lib/exception.c +++ b/kernel/lib/exception.c @@ -20,8 +20,8 @@ void not_implemented_handler() void synchronous_handler() { - static int count = 0; - if (count++ > 5) + static int poop = 0; + if (poop++ > 5) exit(ERR_ADMINKILL); DEBUG_EXCEP("synchronous caught"); uint64_t x0 = 0x0; diff --git a/kernel/lib/interrupt.c b/kernel/lib/interrupt.c index 74a3ee7..b44b551 100644 --- a/kernel/lib/interrupt.c +++ b/kernel/lib/interrupt.c @@ -1,58 +1,45 @@ #include +#include +#include #include #include #include +#define CORE0_TIMER_IRQ_CTRL ((volatile uint32_t *)0x40000040) +#define CORE0_IRQ_SOURCE ((volatile uint32_t *)0x40000060) + +static inline +void _enable_interrupt(void) +{ W_SYSREG_IMM(DAIFClr, 0xf); } + +static inline +void _disable_interrupt(void) +{ W_SYSREG_IMM(DAIFSet, 0xf); } + +MMIO_W_HELPER(_enable_timer_irq, CORE0_TIMER_IRQ_CTRL, 0x1, 1); + +MMIO_R_HELPER(_irq_source_timer, CORE0_IRQ_SOURCE, 0x1, 1); +MMIO_R_HELPER(_irq_source_uart, CORE0_IRQ_SOURCE, 0x1, 8); + void init_interrupt(void) { uint64_t cntfrq_el0; + W_SYSREG(cntp_ctl_el0, 1); R_SYSREG(cntfrq_el0, cntfrq_el0); W_SYSREG(cntp_tval_el0, cntfrq_el0); - *CORE0_TIMER_IRQ_CTRL = 0x2; -} - -static inline -void _uart_irq_handler(void) -{ - DEBUG_EXCEP("uart irq"); -} - -static inline -void _timer_irq_handler(void) -{ - LOG("timer irq"); - - uint64_t cntpct_el0; - R_SYSREG(cntpct_el0, cntpct_el0); - DEBUG_EXCEP(cntpct_el0); - - uint64_t cntfrq_el0; - R_SYSREG(cntfrq_el0, cntfrq_el0); - W_SYSREG(cntp_tval_el0, cntfrq_el0); + _enable_timer_irq(true); + _enable_interrupt(); } void irq_handler(void) { - LOG("irq caught"); - uint64_t irq_source = *CORE0_IRQ_SOURCE; - DEBUG_EXCEP(irq_source); + // uint64_t core0_irq_source = *CORE0_IRQ_SOURCE; + // DEBUG_EXCEP(core0_irq_source); - *CORE0_TIMER_IRQ_CTRL = 0x0; - if (irq_source & GPU_INT) - _uart_irq_handler(); - if (irq_source & CNTPNSIRQ_INT) - _timer_irq_handler(); + if (_irq_source_timer()) + timer_irq_handler(); - *CORE0_TIMER_IRQ_CTRL = 0x2; -} - -void enable_interrupt(void) -{ - asm volatile("msr DAIFClr, 0xf"); -} - -void disable_interrupt(void) -{ - asm volatile("msr DAIFSet, 0xf"); + if (_irq_source_uart()) + uart_irq_handler(); } diff --git a/kernel/lib/ringbuffer.c b/kernel/lib/ringbuffer.c new file mode 100644 index 0000000..9cd6009 --- /dev/null +++ b/kernel/lib/ringbuffer.c @@ -0,0 +1,47 @@ +#include +#include +#include +#include +#include + +ringbuffer_t *make_ringbuffer(size_t size) +{ + ringbuffer_t *ret = kmalloc(sizeof(ringbuffer_t)); + uint8_t *data = kmalloc(size * sizeof(uint8_t)); + *ret = (ringbuffer_t){ + .size = 0, + .cap = size, + .data = data, + .read = data, + .write = data, + }; + return ret; +} + +int ringbuffer_push(ringbuffer_t *buf, uint8_t val) +{ + if (buf->size == buf->cap) + return ERR_OUT_OF_BOUND; + + *buf->write++ = val; + ++buf->size; + + if (buf->write == buf->data + buf->cap) + buf->write = buf->data; + + return NO_ERROR; +} + +uint8_t ringbuffer_bump(ringbuffer_t *buf) +{ + if (buf->size == 0) + exit(ERR_INVALID_OP); + + uint8_t ret = *buf->read++; + --buf->size; + + if (buf->read == buf->data + buf->cap) + buf->read = buf->data; + + return ret; +} diff --git a/kernel/lib/shell.c b/kernel/lib/shell.c index 362f261..d3dfaf9 100644 --- a/kernel/lib/shell.c +++ b/kernel/lib/shell.c @@ -1,4 +1,6 @@ #include +#include +#include #include #include #include @@ -109,6 +111,35 @@ void _exec(file_node_t *root, const char *filename) } } +static inline +void _settimeout_cb_func(uint64_t args) +{ + vector_t *v = (void *)args; + for (int i = 2; i < (int)v->size; ++i) { + uart_puts(VEC_AT(char, v, i)); + uart_puts(" "); + } + uart_puts(ENDL); +} + +static inline +void _settimeout(int32_t sec, vector_t *args) +{ + uint64_t cntpct_el0, cntfrq_el0; + R_SYSREG(cntpct_el0, cntpct_el0); + R_SYSREG(cntfrq_el0, cntfrq_el0); + + task_t task = (task_t){ + .firing_tick = cntpct_el0 + sec * cntfrq_el0, + .interval = sec * cntfrq_el0, + .repeat = 1, + + .func = _settimeout_cb_func, + .param = (uint64_t)args, + }; + add_task(task); +} + static inline void _set(long addr, unsigned int value) { volatile unsigned int* point = (unsigned int*)addr; @@ -130,45 +161,47 @@ void _reboot(void) int shell(file_node_t *initrd_root) { uart_puts("# "); - - char buf[INPUT_BUFLEN], ch; + char *buf = kmalloc(INPUT_BUFLEN * sizeof(char)), ch; int sz = 0; while ((ch = uart_getc()) != '\n') { buf[sz++] = ch; - uart_send(ch); + uart_putb((const uint8_t *)&ch, 1); } uart_puts(ENDL); - buf[sz] = '\0'; + buf[sz] = ' '; - const char *i = buf; + vector_t *args = make_vector(0); + for (char *saveptr = 0x0, *tok = strtok_r(buf, " ", &saveptr); + tok; tok = strtok_r((char *)0x0, " ", &saveptr)) { + VEC_PUSH(args, tok); + LOG(tok); + } - char bin[INPUT_BUFLEN], *j; - for (j = bin; *i != '\0' && !isspace(*i); ++i, ++j) - *j = *i; - *j = '\0'; + // DEBUG("ENDL"); + CLEAN; - for (; *i != '\0' && isspace(*i); ++i); - - char param[INPUT_BUFLEN]; - for (j = param; *i != '\0' && !isspace(*i); ++i, ++j) - *j = *i; - *j = '\0'; - - if (!strcmp(bin, "help")) { + char *cmd = args->size ? VEC_AT(char, args, 0) : (char *)0x0; + if (!strcmp(cmd, "help")) { _help(); - } else if (!strcmp(bin, "hello")) { + } else if (!strcmp(cmd, "hello")) { _hello(); - } else if (!strcmp(bin, "hwinfo")) { + } else if (!strcmp(cmd, "hwinfo")) { _hwinfo(); - } else if (!strcmp(bin, "memalloc")){ - _memalloc((size_t)atoi32(param)); - } else if (!strcmp(bin, "ls")) { + } else if (!strcmp(cmd, "memalloc") && args->size >= 2){ + char *p1 = VEC_AT(char, args, 1); + _memalloc((size_t)atoi32(p1)); + } else if (!strcmp(cmd, "ls")) { _ls(initrd_root); - } else if (!strcmp(bin, "cat")) { - _cat(initrd_root, param); - } else if (!strcmp(bin, "exec")) { - _exec(initrd_root, param); - } else if (!strcmp(bin, "reboot")) { + } else if (!strcmp(cmd, "cat") && args->size >= 2) { + char *p1 = VEC_AT(char, args, 1); + _cat(initrd_root, p1); + } else if (!strcmp(cmd, "exec") && args->size >= 2) { + char *p1 = VEC_AT(char, args, 1); + _exec(initrd_root, p1); + } else if (!strcmp(cmd, "settimeout") && args->size >= 2) { + char *p1 = VEC_AT(char, args, 1); + _settimeout(atoi32(p1), args); + } else if (!strcmp(cmd, "reboot")) { _reboot(); } diff --git a/kernel/lib/timer.c b/kernel/lib/timer.c new file mode 100644 index 0000000..ef418a3 --- /dev/null +++ b/kernel/lib/timer.c @@ -0,0 +1,95 @@ +#include +#include +#include +#include + +#define CORE0_TIMER_IRQ_CTRL ((volatile uint32_t *)0x40000040) + +timer_t *global_timer = (timer_t *)0x0; + +MMIO_W_HELPER(_enable_timer_irq, CORE0_TIMER_IRQ_CTRL, 0x1, 1); + +static inline +uint32_t _d(timer_t *t) +{ return t ? t->_d : 0; } + +static inline +void _swap(timer_t *a, timer_t *b) +{ + timer_t *tmp = a; + a = b, b = tmp; +} + +static inline +timer_t *_merge(timer_t *a, timer_t *b) +{ + if (!a || !b) + return a ?: b; + + if (a->data.firing_tick > b->data.firing_tick) + _swap(a, b); + a->_r = _merge(a->_r, b); + + if (_d(a->_l) < _d(a->_r)) + _swap(a->_l, a->_r); + + a->_d = _d(a->_r) + 1; + return a; +} + +static inline +timer_t *_pop(timer_t *t) +{ + if (!t || (!t->_l && !t->_r)) + return (timer_t *)0x0; + return _merge(t->_l, t->_r); +} + +static inline +void _set_timer_interrrupt() +{ + if (global_timer) { + uint64_t cntpct_el0; + R_SYSREG(cntpct_el0, cntpct_el0); + DEBUG_EXCEP(cntpct_el0); + + uint64_t firing_tick = MAX(global_timer->data.firing_tick, cntpct_el0); + W_SYSREG(cntp_cval_el0, firing_tick); + + _enable_timer_irq(true); + } +} + +void add_task(task_t task) +{ + DEBUG_EXCEP("add task"); + timer_t *newtimer = kmalloc(sizeof(timer_t)); + *newtimer = (timer_t){ + ._l = (timer_t *)0x0, + ._r = (timer_t *)0x0, + ._d = 0, + + .data = task, + }; + + global_timer = _merge(global_timer, newtimer); + _set_timer_interrrupt(); +} + +void timer_irq_handler(void) +{ + _enable_timer_irq(false); + + LOG("timer irq"); + + uint64_t cntpct_el0; + R_SYSREG(cntpct_el0, cntpct_el0); + DEBUG_EXCEP(cntpct_el0); + + if (global_timer) { + global_timer->data.func(global_timer->data.param); + global_timer = _pop(global_timer); + } + + _set_timer_interrrupt(); +} diff --git a/kernel/lib/uart.c b/kernel/lib/uart.c new file mode 100644 index 0000000..9435a31 --- /dev/null +++ b/kernel/lib/uart.c @@ -0,0 +1,188 @@ +#include +#include +#include +#include +#include +#include +#include +#include + +/* Auxilary mini UART registers */ +#define AUX_ENABLE ((volatile uint32_t*)(MMIO_BASE + 0x00215004)) +#define AUX_MU_IO ((volatile uint32_t*)(MMIO_BASE + 0x00215040)) +#define AUX_MU_IER ((volatile uint32_t*)(MMIO_BASE + 0x00215044)) +#define AUX_MU_IIR ((volatile uint32_t*)(MMIO_BASE + 0x00215048)) +#define AUX_MU_LCR ((volatile uint32_t*)(MMIO_BASE + 0x0021504C)) +#define AUX_MU_MCR ((volatile uint32_t*)(MMIO_BASE + 0x00215050)) +#define AUX_MU_LSR ((volatile uint32_t*)(MMIO_BASE + 0x00215054)) +#define AUX_MU_MSR ((volatile uint32_t*)(MMIO_BASE + 0x00215058)) +#define AUX_MU_SCRATCH ((volatile uint32_t*)(MMIO_BASE + 0x0021505C)) +#define AUX_MU_CNTL ((volatile uint32_t*)(MMIO_BASE + 0x00215060)) +#define AUX_MU_STAT ((volatile uint32_t*)(MMIO_BASE + 0x00215064)) +#define AUX_MU_BAUD ((volatile uint32_t*)(MMIO_BASE + 0x00215068)) + +#define ARMINT_En_IRQs1 ((volatile uint32_t*)(MMIO_BASE + 0x0000b210)) + +size_t (*uart_putb)(const uint8_t *bytes, size_t len) = uart_putb_sync; +size_t (*uart_getb)(uint8_t *bytes, size_t len) = uart_getb_sync; +int is_uart_inited = false; + +ringbuffer_t *uart_readbuf; +ringbuffer_t *uart_writebuf; + +MMIO_W_HELPER(_uart_enable_receive_interrupt, AUX_MU_IER, 0x1, 0); +MMIO_W_HELPER(_uart_enable_transmit_interrupt, AUX_MU_IER, 0x1, 1); +MMIO_W_HELPER(_uart_clear_receive_fifo, AUX_MU_IIR, 0x1, 1); +MMIO_W_HELPER(_uart_clear_transmit_fifo, AUX_MU_IIR, 0x1, 2); +MMIO_W_HELPER(_uart_write_data, AUX_MU_IO, 0xff, 0); +MMIO_W_HELPER(_uart_interrupt_controller, ARMINT_En_IRQs1, 0x1, 29); + +MMIO_R_HELPER(_uart_interrupt_pending, AUX_MU_IIR, 0x1, 0); +MMIO_R_HELPER(_uart_transmit_interrupt, AUX_MU_IIR, 0x1, 1); +MMIO_R_HELPER(_uart_receive_interrupt, AUX_MU_IIR, 0x1, 2); +MMIO_R_HELPER(_uart_transmitter_idle, AUX_MU_LSR, 0x1, 5); +MMIO_R_HELPER(_uart_data_ready, AUX_MU_LSR, 0x1, 0); +MMIO_R_HELPER(_uart_read_data, AUX_MU_IO, 0xff, 0); + +void uart_init(void) +{ + register uint32_t r; + + /* initialize UART */ + *AUX_ENABLE |= 1; // enable UART1, AUX mini uart + *AUX_MU_CNTL = 0; // disable Tx, Rx + *AUX_MU_LCR = 3; // set 8 bits + *AUX_MU_MCR = 0; + *AUX_MU_IER = 0; // disable interrupt by default + *AUX_MU_IIR = 0x6; // clear tx, rx FIFO + *AUX_MU_BAUD = 270; // 115200 baud + /* map UART1 to GPIO pins */ + r = *GPFSEL1; + r &= ~((7 << 12) | (7 << 15)); // gpio14, gpio15 + r |= (2 << 12) | (2 << 15); // alt5 + *GPFSEL1 = r; + *GPPUD = 0; // enable pins 14 and 15 + r = 150; while (r--) { asm volatile("nop"); } + *GPPUDCLK0 = (1 << 14) | (1 << 15); + r = 150; while (r--) { asm volatile("nop"); } + *GPPUDCLK0 = 0; // flush GPIO setup + *AUX_MU_CNTL = 3; // enable Tx, Rx + _uart_interrupt_controller(true); + + uart_readbuf = make_ringbuffer(UART_BUFLEN); + uart_writebuf = make_ringbuffer(UART_BUFLEN); + + _uart_enable_receive_interrupt(true); + //uint64_t ier = *AUX_MU_IER; + + uart_getb = uart_getb_async; + uart_putb = uart_putb_async; + + is_uart_inited = true; +} + +void uart_transmit_interrupt_handler() +{ + if (uart_writebuf->size > 0) + _uart_write_data(ringbuffer_bump(uart_writebuf)); +} + +void uart_receive_interrupt_handler() +{ + if (uart_readbuf->size < uart_readbuf->cap) { + uint8_t b = _uart_read_data(); + ringbuffer_push(uart_readbuf, b); + } +} + +void uart_irq_handler(void) +{ + _uart_enable_receive_interrupt(false); + _uart_enable_transmit_interrupt(false); + if (_uart_receive_interrupt()) + uart_receive_interrupt_handler(); + if (_uart_transmit_interrupt()) + uart_transmit_interrupt_handler(); + + _uart_enable_receive_interrupt(true); + if (uart_writebuf->size > 0) + _uart_enable_transmit_interrupt(true); +} + +size_t uart_putb_async(const uint8_t *bytes, size_t len) +{ + size_t sentlen = 0; + for (; sentlen < len; ++bytes, ++sentlen) + ringbuffer_push(uart_writebuf, *bytes); + + if (uart_writebuf->size > 0) + _uart_enable_transmit_interrupt(true); + + return sentlen; +} + +size_t uart_putb_sync(const uint8_t *bytes, size_t len) +{ + size_t sentlen = 0; + for (; sentlen < len; ++bytes, ++sentlen) { + do asm volatile("nop"); // busy waiting + while (!_uart_transmitter_idle()); + + _uart_write_data(*bytes); + } + + return sentlen; +} + +size_t uart_getb_async(uint8_t *bytes, size_t len) +{ + size_t recvlen = 0; + for (; recvlen < len; ++bytes, ++recvlen) { + while (!uart_readbuf->size) + asm volatile("wfe"); // wait for interrupt + *bytes = ringbuffer_bump(uart_readbuf); + } + + return recvlen; +} + +size_t uart_getb_sync(uint8_t *bytes, size_t len) +{ + size_t recvlen = 0; + for (; recvlen < len; ++bytes, ++recvlen) { + do asm volatile("nop"); + while (!_uart_data_ready()); + + *bytes = _uart_read_data(); + } + + return recvlen; +} + +char uart_getc(void) +{ + char r; + uart_getb((uint8_t *)&r, 1); + return r == '\r' ? '\n' : r; +} + +void uart_puts(const char *s) +{ + size_t len = strlen(s); + size_t ret = uart_putb((const uint8_t *)s, len); + if (ret != len) + exit(ERR_IO_FAILED); +} + +void uart_hex(uint64_t d) +{ + char buf[0x11], *p = buf; + uint64_t n; + for (int c = 28; c >= 0; c -= 4) { + n = (d >> c) & 0xf; + n += n > 9 ? (char)'A' : (char)'0'; + *p++ = n; + } + *p = '\0'; + uart_puts(buf); +} diff --git a/kernel/main.c b/kernel/main.c index e99d8dd..d181853 100644 --- a/kernel/main.c +++ b/kernel/main.c @@ -1,4 +1,5 @@ #include +#include #include #include #include @@ -35,11 +36,38 @@ void init(void *dtb, file_node_t **initrd_root) mman_init(); } +static inline +void _print_time(uint64_t) +{ + uint64_t cntpct_el0, cntfrq_el0; + R_SYSREG(cntpct_el0, cntpct_el0); + R_SYSREG(cntfrq_el0, cntfrq_el0); + DEBUG_EXCEP(cntpct_el0 / cntpct_el0); +} + void main(void *dtb) { file_node_t *initrd_root = 0x0; init(dtb, &initrd_root); + LOG("system booting in"); + _print_time(0x0); + + uint64_t cntpct_el0, cntfrq_el0; + R_SYSREG(cntpct_el0, cntpct_el0); + R_SYSREG(cntfrq_el0, cntfrq_el0); + + task_t task = { + .firing_tick = cntpct_el0 + 2 * cntfrq_el0, + .interval = 2 * cntfrq_el0, + .repeat = 1, + + .func = _print_time, + .param = 0x0, + }; + + add_task(task); + uint64_t el; R_SYSREG(el, CurrentEL); INFOR(el); diff --git a/lib/string.c b/lib/string.c index 67d8e74..4472c7e 100644 --- a/lib/string.c +++ b/lib/string.c @@ -35,6 +35,21 @@ size_t strlen(const char *str) return ret; } +char *strtok_r(char *restrict str, const char *restrict delimiters, + char **restrict saveptr) +{ + if (str) + *saveptr = str; + for (char *ret = *saveptr; **saveptr != '\0'; ++(*saveptr)) { + for (int i = 0; delimiters[i] != '\0'; i++) + if (**saveptr == delimiters[i]) { + *(*saveptr)++ = '\0'; + return ret; + } + } + return 0x0; +} + void *memcpy(void *dest, const void *src, size_t count) { void *ret = dest; diff --git a/rootfs/userprog b/rootfs/userprog deleted file mode 100755 index f3fc31e66a3366be7a7eda9bd4b013f7b45dfcfc..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1944 zcmZQzXt>0{!Z4AMf#Hh02*bzK|Nn59}Q*VS4{o?_2qonPKAl|No~ysAsTzQ14(VZ^BTR zz`zg!VuQlWfw3XzZ}p)SAiH4dAMi8$4_f z{0=`ESr{fhYt2IhvK2l@;4wJM4VO z@9=lWGb z`TgO){~>>?kAeLRPJ8SOKOZtP{FDRfXLtC?$lzf4fEg06_6!W!4onOo53qF%0qxJe!)&hPN^e={^6Le2iq&+wBSFhBrfRS*M9g&dFfcGg{Qmzx1|;Cf2bK>-l3&8Wz%b?a z|NjjTd4suZ^H}4M>v&U0|30~pw|EZ diff --git a/test.py b/test.py deleted file mode 100755 index 3366d15..0000000 --- a/test.py +++ /dev/null @@ -1,13 +0,0 @@ -#!/usr/bin/env -S python3 -from pwn import * -from struct import pack - -print(sys.argv) - -if len(sys.argv) < 2: - print("no args for serial device") - exit() - -tube = serialtube(sys.argv[1], convert_newlines=False) - -tube.interactive() diff --git a/userprog/Makefile b/userprog/Makefile new file mode 100644 index 0000000..e5dd716 --- /dev/null +++ b/userprog/Makefile @@ -0,0 +1,39 @@ +MAKE := make +MAKEFLAGS += -j 8 + +ARCH := aarch64 +GNU := $(ARCH)-linux-gnu + +CC := $(GNU)-gcc +CCFLAGS += -Wall -Wextra -O0 \ + -nostdinc -nostdlib -nostartfiles -nodefaultlibs \ + -Wno-unused-parameter -Wno-unused-value -Wno-main -g + +LD := $(GNU)-ld +LDFLAGS += -g -nostdlib -no-pie +OBJCOPY := $(GNU)-objcopy + +LD_SCRIPT := linker.ld +SRCS := $(shell find . -name '*.[cS]') +OBJS := $(SRCS:%=%.o) + +.PHONY: all + +all: userprog + +userprog: userprog.elf + $(OBJCOPY) -O binary $< $@ + +userprog.elf: $(LD_SCRIPT) $(OBJS) + $(LD) -o $@ -T $(LD_SCRIPT) $(OBJS) $(LDFLAGS) + +%.S.o: %.S + mkdir -p $(dir $@) + $(CC) -c $< -o $@ $(CCFLAGS) + +%.c.o: %.c + mkdir -p $(dir $@) + $(CC) -c $< -o $@ $(CCFLAGS) + +clean: + -rm $(OBJS) userprog userprog.elf