diff --git a/Makefile b/Makefile index a4cbee1..07c0dbe 100644 --- a/Makefile +++ b/Makefile @@ -1,4 +1,5 @@ MAKE := make +MAKEFLAGS += -j 8 ARCH := aarch64 GNU := $(ARCH)-linux-gnu @@ -14,6 +15,7 @@ CCFLAGS += -Wall -Wextra -O0 \ LD := $(GNU)-ld LDFLAGS += -g -nostdlib -no-pie OBJCOPY := $(GNU)-objcopy +OBJDUMP := $(GNU)-objdump MISC_DIR := misc QEMUFLAGS += -dtb $(MISC_DIR)/bcm2710-rpi-3-b-plus.dtb @@ -43,15 +45,17 @@ TARGET_OBJS := $(TARGET_SRCS:%=%.o) SRCS := $(shell find $(LIB_DIR) -name '*.c') OBJS := $(SRCS:%=%.o) -.PHONY: all build clean clean_target run kernel debug gdb +.PHONY: all build clean clean_target run \ + kernel bootloader userprog debug gdb objdump all: $(CPIO) - $(MAKE) build TARGET_DIR=./kernel TARGET=kernel8 - $(MAKE) build TARGET_DIR=./bootloader TARGET=bootloader + $(MAKE) $(MAKEFLAGS) build TARGET_DIR=kernel TARGET=kernel8 + $(MAKE) $(MAKEFLAGS) build TARGET_DIR=bootloader TARGET=bootloader build: $(IMG) -$(CPIO): $(shell find $(ROOTFS_DIR)) +$(CPIO): $(shell find $(ROOTFS_DIR)) userprog + cp userprog.img $(ROOTFS_DIR)/userprog cd $(ROOTFS_DIR) && find . | cpio -o -H newc > ../$@ $(IMG): $(ELF) @@ -69,9 +73,10 @@ $(ELF): $(LD_SCRIPT) $(TARGET_OBJS) $(OBJS) $(CC) -c $< -o $@ $(INCLUDE) $(CCFLAGS) clean: - -rm $(OBJS) $(CPIO) - $(MAKE) clean_target TARGET_DIR=./kernel TARGET=kernel8 - $(MAKE) clean_target TARGET_DIR=./bootloader TARGET=bootloader + -rm $(OBJS) $(CPIO) $(ROOTFS_DIR)/userprog + $(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) @@ -80,15 +85,23 @@ run: all $(CPIO) $(QEMU) -kernel bootloader.img $(QEMUFLAGS) -serial pty kernel: $(CPIO) - $(MAKE) build TARGET_DIR=kernel TARGET=kernel8 + $(MAKE) $(MAKEFLAGS) build TARGET_DIR=kernel TARGET=kernel8 $(QEMU) -kernel kernel8.img $(QEMUFLAGS) -serial stdio bootloader: $(CPIO) - $(MAKE) build TARGET_DIR=./bootloader TARGET=bootloader + $(MAKE) $(MAKEFLAGS) build TARGET_DIR=bootloader TARGET=bootloader $(QEMU) -kernel bootloader.img $(QEMUFLAGS) -debug: all $(CPIO) +userprog: + $(MAKE) $(MAKEFLAGS) build TARGET_DIR=userprog TARGET=userprog + +debug: $(CPIO) + $(MAKE) $(MAKEFLAGS) build TARGET_DIR=kernel TARGET=kernel8 $(QEMU) -kernel kernel8.img $(QEMUFLAGS) -serial stdio -S -s gdb: $(GDB) + +objdump: + $(MAKE) $(MAKEFLAGS) build TARGET_DIR=kernel TARGET=kernel8 + $(OBJDUMP) -D kernel8.elf diff --git a/include/errcode.h b/include/errcode.h index 2e4d916..239d04e 100644 --- a/include/errcode.h +++ b/include/errcode.h @@ -6,3 +6,5 @@ #define ERR_OUT_OF_BOUND 0x00000004 #define ERR_INVALID_OP 0x00000005 #define ERR_INVALID_MEM 0x00000006 +#define ERR_NOT_EXIST 0x00000007 +#define ERR_ADMINKILL 0x00114514 diff --git a/include/logger.h b/include/logger.h index eaa15ce..72e3b87 100644 --- a/include/logger.h +++ b/include/logger.h @@ -70,7 +70,7 @@ logger_cur = _Generic((msg), \ FLUSH("[ERROR]: "); \ } #else -#define ERROR(val) +#define ERROR(val) CLEAN #endif #if LOGLEVEL >= 1 @@ -79,7 +79,7 @@ logger_cur = _Generic((msg), \ FLUSH("[INFOR]: "); \ } #else -#define INFOR(val) +#define INFOR(val) CLEAN #endif #if LOGLEVEL >= 2 @@ -87,14 +87,21 @@ logger_cur = _Generic((msg), \ LOG(val); \ FLUSH("[DEBUG]: "); \ } -#define DEBUG_DTB(val) DEBUG(val) +#else // #if LOGLEVEL >= 2 +#define DEBUG(val) CLEAN +#endif // #if LOGLEVEL >= 2 + +// #define DEBUG_DTB(val) DEBUG(val) +#define DEBUG_DTB(val) CLEAN + +#define DEBUG_EXCEP(val) DEBUG(val) +// #define DEBUG_EXCEP(val) CLEAN + // #define DEBUG_MEM(val) DEBUG(val) #define DEBUG_MEM(val) CLEAN -#else // #if LOGLEVEL >= 2 -#define DEBUG(val) -#define DEBUG_DTB(val) -#define DEBUG_MEM(val) -#endif // #if LOGLEVEL >= 2 + +// #define DEBUG_INITRD(val) DEBUG(val) +#define DEBUG_INITRD(val) CLEAN extern char logger_buf[LOGGER_BUFLEN]; extern char *logger_cur; diff --git a/kernel/exception_handler.S b/kernel/exception_table.S similarity index 86% rename from kernel/exception_handler.S rename to kernel/exception_table.S index 5b87f70..76f153f 100644 --- a/kernel/exception_handler.S +++ b/kernel/exception_table.S @@ -44,10 +44,22 @@ _null_handler: save_all - bl not_implemented_interrupt + bl not_implemented_handler load_all eret +_synchronous_handler: + save_all + bl synchronous_handler + load_all + eret + +_irq_handler: + save_all + bl irq_handler + load_all + eret + .align 11 .global exception_vector_table exception_vector_table: @@ -60,18 +72,18 @@ exception_vector_table: b _null_handler .align 7 + b _synchronous_handler + .align 7 + b _irq_handler + .align 7 b _null_handler .align 7 b _null_handler - .align 7 - b _null_handler - .align 7 - b _null_handler - .align 7 - - b _null_handler - .align 7 - b _null_handler + .align 7 + + b _synchronous_handler + .align 7 + b _irq_handler .align 7 b _null_handler .align 7 diff --git a/kernel/include/exception.h b/kernel/include/exception.h new file mode 100644 index 0000000..253088a --- /dev/null +++ b/kernel/include/exception.h @@ -0,0 +1,5 @@ +#pragma once + +void init_exception(void); +void not_implemented_handler(void); +void synchronous_handler(void); diff --git a/kernel/include/exec.h b/kernel/include/exec.h new file mode 100644 index 0000000..5e9d58e --- /dev/null +++ b/kernel/include/exec.h @@ -0,0 +1,3 @@ +#pragma once + +void user_exec(void *text, void *sp); diff --git a/kernel/include/interrupt.h b/kernel/include/interrupt.h new file mode 100644 index 0000000..c667eea --- /dev/null +++ b/kernel/include/interrupt.h @@ -0,0 +1,17 @@ +#pragma once + +#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/shell.h b/kernel/include/shell.h index 3c6ccc8..b5014b7 100644 --- a/kernel/include/shell.h +++ b/kernel/include/shell.h @@ -1,15 +1,7 @@ #pragma once -#include #include - -void help(void); -void hello(void); -void hwinfo(void); -void memalloc(size_t size); -void ls(file_node_t *root); -void cat(file_node_t *root, const char *filename); -void reboot(void); +#include int // is continue shell(file_node_t *); diff --git a/kernel/include/utils.h b/kernel/include/utils.h index 8b975f9..e79a44b 100644 --- a/kernel/include/utils.h +++ b/kernel/include/utils.h @@ -43,8 +43,14 @@ void exit(int); : [a] "=r" (ret) \ ) -#define W_SYSREG(val, reg) \ +#define W_SYSREG(reg, val) \ asm volatile( \ "msr " #reg ", %[a]" \ - : [a] "r" (val) \ + :: [a] "r" (val) \ + ) + +#define R_REG(ret, reg) \ + asm volatile( \ + "mov %[a], " #reg \ + : [a] "=r" (ret) \ ) diff --git a/kernel/lib/dtb.c b/kernel/lib/dtb.c index 7f5554d..0b888b4 100644 --- a/kernel/lib/dtb.c +++ b/kernel/lib/dtb.c @@ -28,8 +28,8 @@ void _memory_traverse() { dtb_reserved_entries = make_vector(0); while (fdt_memory_cur->address != 0 || fdt_memory_cur->size != 0) { - DEBUG(ntoh64(fdt_memory_cur->address)); - DEBUG(ntoh64(fdt_memory_cur->size)); + DEBUG_DTB(ntoh64(fdt_memory_cur->address)); + DEBUG_DTB(ntoh64(fdt_memory_cur->size)); VEC_PUSH(dtb_reserved_entries, fdt_memory_cur++); } @@ -101,8 +101,8 @@ void fdt_traverse(const vector_t *struct_cbs) dtb_end = dtb_start + ntoh32(((fdt_header_t *)dtb_start)->totalsize); - DEBUG(fdt_memory_cur); - DEBUG(fdt_struct_cur); + DEBUG_DTB(fdt_memory_cur); + DEBUG_DTB(fdt_struct_cur); _memory_traverse(); DEBUG_DTB("memory traverse done"); _struct_traverse("", struct_cbs); diff --git a/kernel/lib/exception.c b/kernel/lib/exception.c new file mode 100644 index 0000000..780a55d --- /dev/null +++ b/kernel/lib/exception.c @@ -0,0 +1,42 @@ +#include +#include +#include +#include +#include + +void init_exception() +{ + asm volatile( + "adr x0, exception_vector_table" ENDL + "msr vbar_el1, x0" ENDL + ::: "x0" + ); +} + +void not_implemented_handler() +{ + DEBUG_EXCEP("not implemented caught"); +} + +void synchronous_handler() +{ + static int count = 0; + if (count++ > 5) + exit(ERR_ADMINKILL); + DEBUG_EXCEP("synchronous caught"); + uint64_t x0 = 0x0; + R_REG(x0, x0); + LOG(x0); + + uint64_t spsr_el1 = 0x0; + R_SYSREG(spsr_el1, spsr_el1); + LOG(spsr_el1); + + uint64_t elr_el1 = 0x0; + R_SYSREG(elr_el1, elr_el1); + LOG(elr_el1); + + uint64_t esr_el1 = 0x0; + R_SYSREG(esr_el1, esr_el1); + DEBUG_EXCEP(esr_el1); +} diff --git a/kernel/lib/exec.c b/kernel/lib/exec.c new file mode 100644 index 0000000..0cb24a2 --- /dev/null +++ b/kernel/lib/exec.c @@ -0,0 +1,16 @@ +#include +#include + +void user_exec(void *text, void *sp) +{ + // enable core timer + uint64_t cntkctl_el1 = 0x0; + R_SYSREG(cntkctl_el1, cntkctl_el1); + W_SYSREG(cntkctl_el1, cntkctl_el1 | 1); + W_SYSREG(cntp_ctl_el0, 1); + + W_SYSREG(spsr_el1, 0); + W_SYSREG(elr_el1, text); + W_SYSREG(sp_el0, sp); + asm volatile("eret"); +} diff --git a/kernel/lib/interrupt.c b/kernel/lib/interrupt.c new file mode 100644 index 0000000..74a3ee7 --- /dev/null +++ b/kernel/lib/interrupt.c @@ -0,0 +1,58 @@ +#include +#include +#include +#include + +void init_interrupt(void) +{ + uint64_t cntfrq_el0; + 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); +} + +void irq_handler(void) +{ + LOG("irq caught"); + uint64_t irq_source = *CORE0_IRQ_SOURCE; + DEBUG_EXCEP(irq_source); + + *CORE0_TIMER_IRQ_CTRL = 0x0; + if (irq_source & GPU_INT) + _uart_irq_handler(); + if (irq_source & CNTPNSIRQ_INT) + _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"); +} diff --git a/kernel/lib/shell.c b/kernel/lib/shell.c index 63e36aa..362f261 100644 --- a/kernel/lib/shell.c +++ b/kernel/lib/shell.c @@ -1,10 +1,13 @@ #include +#include #include #include #include #include #include #include +#include +#include #define INPUT_BUFLEN 1000 @@ -13,25 +16,29 @@ #define PM_RSTC 0x3F10001c #define PM_WDOG 0x3F100024 -void help (void) +static inline +void _help (void) { uart_puts( - "help : print this help menu" ENDL - "hello : print Hello World!" ENDL - "hwinfo : print hardware info" ENDL - "memalloc : alloate memory and print" ENDL - "ls : list directory contents" ENDL - "cat : concatenate files and print" ENDL - "reboot : reboot the device" ENDL + "help : print this help menu" ENDL + "hello : print Hello World!" ENDL + "hwinfo : print hardware info" ENDL + "memalloc : alloate memory and print" ENDL + "ls : list directory contents" ENDL + "cat : concatenate files and print" ENDL + "exec : execute file in usermode" ENDL + "reboot : reboot the device" ENDL ); } -void hello (void) +static inline +void _hello (void) { uart_puts("hello, world" ENDL); } -void hwinfo (void) +static inline +void _hwinfo (void) { uart_puts( "hwinfo: " ENDL @@ -51,7 +58,8 @@ void hwinfo (void) uart_puts(ENDL); } -void memalloc(size_t size) +static inline +void _memalloc(size_t size) { void *addr = kmalloc(size); uart_puts("size: "); @@ -63,40 +71,60 @@ void memalloc(size_t size) uart_puts(ENDL); } -void ls_initrd_callback(file_node_t *tr) +static inline +void _ls_initrd_callback(file_node_t *tr) { uart_puts(tr->filename); uart_puts(ENDL); } -void ls(file_node_t *root) +static inline +void _ls(file_node_t *root) { - initrd_traverse(root, ls_initrd_callback); + initrd_traverse(root, _ls_initrd_callback); } -void cat(file_node_t *root, const char *filename) +static inline +void _cat(file_node_t *root, const char *filename) { file_node_t *tr = initrd_get(root, filename); if (tr) { uart_puts((char *)tr->filecontent); } else { - uart_puts("FILE NOT EXIST!" ENDL); + exit(ERR_NOT_EXIST); } } -void set(long addr, unsigned int value) { - volatile unsigned int* point = (unsigned int*)addr; - *point = value; -} - -void reset(int tick) { // reboot after watchdog timer expire - set(PM_RSTC, PM_PASSWORD | 0x20); // full reset - set(PM_WDOG, PM_PASSWORD | tick); // number of watchdog tick -} - -void reboot(void) +static inline +void _exec(file_node_t *root, const char *filename) { - reset(1 << 16); + file_node_t *tr = initrd_get(root, filename); + if (tr) { + void *userspace = allocate_page(1 << 6); + memcpy(userspace, tr->filecontent, tr->filesize); + user_exec(userspace, userspace + (1 << (12 + 6)) - 8); + kfree(userspace); + } else { + exit(ERR_NOT_EXIST); + } +} + +static inline +void _set(long addr, unsigned int value) { + volatile unsigned int* point = (unsigned int*)addr; + *point = value; +} + +static inline +void _reset(int tick) { // reboot after watchdog timer expire + _set(PM_RSTC, PM_PASSWORD | 0x20); // full reset + _set(PM_WDOG, PM_PASSWORD | tick); // number of watchdog tick +} + +static inline +void _reboot(void) +{ + _reset(1 << 16); } int shell(file_node_t *initrd_root) @@ -127,19 +155,21 @@ int shell(file_node_t *initrd_root) *j = '\0'; if (!strcmp(bin, "help")) { - help(); + _help(); } else if (!strcmp(bin, "hello")) { - hello(); + _hello(); } else if (!strcmp(bin, "hwinfo")) { - hwinfo(); + _hwinfo(); } else if (!strcmp(bin, "memalloc")){ - memalloc((size_t)atoi32(param)); + _memalloc((size_t)atoi32(param)); } else if (!strcmp(bin, "ls")) { - ls(initrd_root); + _ls(initrd_root); } else if (!strcmp(bin, "cat")) { - cat(initrd_root, param); + _cat(initrd_root, param); + } else if (!strcmp(bin, "exec")) { + _exec(initrd_root, param); } else if (!strcmp(bin, "reboot")) { - reboot(); + _reboot(); } return true; diff --git a/kernel/main.c b/kernel/main.c index 705b973..e99d8dd 100644 --- a/kernel/main.c +++ b/kernel/main.c @@ -7,23 +7,28 @@ #include #include #include +#include +#include void init(void *dtb, file_node_t **initrd_root) { + init_exception(); + init_interrupt(); + // UART uart_init(); // Device tree - INFOR(dtb); + DEBUG_DTB(dtb); dtb_start = dtb; vector_t *dtb_struct_cbs = make_vector(0); VEC_PUSH(dtb_struct_cbs, &initrd_dtb_cb); VEC_PUSH(dtb_struct_cbs, &mman_dtb_memory_cb); fdt_traverse(dtb_struct_cbs); - DEBUG("device tree parse done"); + DEBUG_DTB("device tree parse done"); // Initramfs - INFOR(initrd_start); + DEBUG_INITRD(initrd_start); *initrd_root = initrd_init(); // Memory (Buddy system) diff --git a/lib/uart.c b/lib/uart.c index e128186..770657a 100644 --- a/lib/uart.c +++ b/lib/uart.c @@ -3,18 +3,20 @@ #include /* Auxilary mini UART registers */ -#define AUX_ENABLE ((volatile unsigned int*)(MMIO_BASE+0x00215004)) -#define AUX_MU_IO ((volatile unsigned int*)(MMIO_BASE+0x00215040)) -#define AUX_MU_IER ((volatile unsigned int*)(MMIO_BASE+0x00215044)) -#define AUX_MU_IIR ((volatile unsigned int*)(MMIO_BASE+0x00215048)) -#define AUX_MU_LCR ((volatile unsigned int*)(MMIO_BASE+0x0021504C)) -#define AUX_MU_MCR ((volatile unsigned int*)(MMIO_BASE+0x00215050)) -#define AUX_MU_LSR ((volatile unsigned int*)(MMIO_BASE+0x00215054)) -#define AUX_MU_MSR ((volatile unsigned int*)(MMIO_BASE+0x00215058)) -#define AUX_MU_SCRATCH ((volatile unsigned int*)(MMIO_BASE+0x0021505C)) -#define AUX_MU_CNTL ((volatile unsigned int*)(MMIO_BASE+0x00215060)) -#define AUX_MU_STAT ((volatile unsigned int*)(MMIO_BASE+0x00215064)) -#define AUX_MU_BAUD ((volatile unsigned int*)(MMIO_BASE+0x00215068)) +#define AUX_ENABLE ((volatile unsigned int*)(MMIO_BASE + 0x00215004)) +#define AUX_MU_IO ((volatile unsigned int*)(MMIO_BASE + 0x00215040)) +#define AUX_MU_IER ((volatile unsigned int*)(MMIO_BASE + 0x00215044)) +#define AUX_MU_IIR ((volatile unsigned int*)(MMIO_BASE + 0x00215048)) +#define AUX_MU_LCR ((volatile unsigned int*)(MMIO_BASE + 0x0021504C)) +#define AUX_MU_MCR ((volatile unsigned int*)(MMIO_BASE + 0x00215050)) +#define AUX_MU_LSR ((volatile unsigned int*)(MMIO_BASE + 0x00215054)) +#define AUX_MU_MSR ((volatile unsigned int*)(MMIO_BASE + 0x00215058)) +#define AUX_MU_SCRATCH ((volatile unsigned int*)(MMIO_BASE + 0x0021505C)) +#define AUX_MU_CNTL ((volatile unsigned int*)(MMIO_BASE + 0x00215060)) +#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; @@ -23,49 +25,52 @@ int is_uart_init = 0; */ void uart_init() { - register unsigned int r; - - /* initialize UART */ - *AUX_ENABLE |=1; // enable UART1, AUX mini uart - *AUX_MU_IER = 0; - *AUX_MU_CNTL = 0; - *AUX_MU_LCR = 3; // 8 bits - *AUX_MU_MCR = 0; - *AUX_MU_IER = 0; - *AUX_MU_IIR = 0xc6; // disable interrupts - *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 + register unsigned int r; - is_uart_init = 1; + /* 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; + *AUX_MU_IER = 0; + *AUX_MU_IIR = 0xc6; // disable interrupts + *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 + + *ARMINT_En_IRQs1 |= (1 << 29); + + is_uart_init = 1; } /** * Send a character */ -void uart_send(unsigned int c) { - /* wait until we can send */ - do{asm volatile("nop");}while(!(*AUX_MU_LSR&0x20)); - /* write the character to the buffer */ - *AUX_MU_IO=c; +void uart_send(unsigned int c) +{ + /* wait until we can send */ + do { asm volatile("nop"); } while (!(*AUX_MU_LSR & 0x20)); + /* write the character to the buffer */ + *AUX_MU_IO = c; } uint8_t uart_getb() { uint8_t r; /* wait until something is in the buffer */ - do{asm volatile("nop");}while(!(*AUX_MU_LSR&0x01)); + do { asm volatile("nop"); } while (!(*AUX_MU_LSR & 0x01)); /* read it and return */ - r=(uint8_t)(*AUX_MU_IO); + r = (uint8_t)(*AUX_MU_IO); return r; } @@ -73,38 +78,40 @@ uint8_t uart_getb() /** * Receive a character */ -char uart_getc() { +char uart_getc() +{ char r = (char)uart_getb(); /* convert carrige return to newline */ - return r=='\r'?'\n':r; + return r == '\r' ? '\n' : r; } /** * Display a string */ -void uart_puts(const char *s) { - while(*s) { - /* convert newline to carrige return + newline */ - if(*s=='\n') - uart_send('\r'); - uart_send(*s++); - } +void uart_puts(const char *s) +{ + while (*s) { + /* convert newline to carrige return + newline */ + if(*s == '\n') + uart_send('\r'); + uart_send(*s++); + } } /** * Display a binary value in hexadecimal */ -void uart_hex(uint64_t d) { - unsigned int n; - int c; - for(c=28;c>=0;c-=4) { - // get highest tetrad - n=(d>>c)&0xF; - // 0-9 => '0'-'9', 10-15 => 'A'-'F' - n+=n>9?0x37:0x30; - uart_send(n); - } +void uart_hex(uint64_t d) +{ + unsigned int n; + for (int c = 28; c >= 0; c -= 4) { + // get highest tetrad + n = (d >> c) & 0xF; + // 0-9 => '0'-'9', 10-15 => 'A'-'F' + n += n > 9 ? 0x37 : 0x30; + uart_send(n); + } } void uart_int(int d) diff --git a/rootfs/userprog b/rootfs/userprog new file mode 100755 index 0000000..f3fc31e Binary files /dev/null and b/rootfs/userprog differ diff --git a/userprog/Start.S b/userprog/Start.S new file mode 100644 index 0000000..8c8a87a --- /dev/null +++ b/userprog/Start.S @@ -0,0 +1,11 @@ +.section ".text" +.global _start +_start: + mov x0, 0 +loop: + add x0, x0, 1 + svc 0 + cmp x0, 5 + blt loop +wait: + b wait diff --git a/userprog/linker.ld b/userprog/linker.ld new file mode 100644 index 0000000..503ba5a --- /dev/null +++ b/userprog/linker.ld @@ -0,0 +1,18 @@ +ENTRY(_start) + +SECTIONS +{ + .text : { + *(.text.start) + *(.text) + } + .rodata : { + *(.rodata) + } + .data : { + *(.data) + } + .bss : { + *(.bss) + } +}