diff --git a/.gdbinit b/.gdbinit new file mode 100644 index 0000000..a59fc53 --- /dev/null +++ b/.gdbinit @@ -0,0 +1,2 @@ +file kernel8.elf +target remote :1234 diff --git a/Makefile b/Makefile index ff069fe..145cdf7 100644 --- a/Makefile +++ b/Makefile @@ -2,6 +2,7 @@ MAKE := make ARCH := aarch64 GNU := $(ARCH)-linux-gnu +GDB := $(GNU)-gdb QEMU := qemu-system-$(ARCH) QEMUFLAGS += -M raspi3b -display none -serial null -serial pty @@ -9,9 +10,9 @@ QEMUFLAGS += -M raspi3b -display none -serial null -serial pty CC := $(GNU)-gcc CCFLAGS += -Wall -Wextra -O0 \ -nostdinc -nostdlib -nostartfiles -nodefaultlibs \ - -Wno-unused-parameter -Wno-main -g + -Wno-unused-parameter -Wno-unused-value -Wno-main -g LD := $(GNU)-ld -LDFLAGS += -g -nostdlib +LDFLAGS += -g -nostdlib -no-pie OBJCOPY := $(GNU)-objcopy #TARGET := kernel8 @@ -23,7 +24,7 @@ LD_SCRIPT := $(TARGET_DIR)/linker.ld INCLUDE += -Iinclude LIB_DIR := ./lib MISC_DIR := ./misc -#QEMUFLAGS += -dtb $(MISC_DIR)/bcm2710-rpi-3-b-plus.dtb +QEMUFLAGS += -dtb $(MISC_DIR)/bcm2710-rpi-3-b-plus.dtb BOOTLOADER_DIR := ./bootloader ROOTFS_DIR := ./rootfs @@ -35,7 +36,7 @@ SRCS := $(shell find $(TARGET_DIR) -name '*.[cS]') \ $(shell find $(LIB_DIR) -name '*.c') OBJS := $(SRCS:%=%.o) -.PHONY: all build clean clean_target run +.PHONY: all build clean clean_target run kernel debug gdb all: $(MAKE) build TARGET_DIR=./kernel TARGET=kernel8 @@ -69,4 +70,14 @@ clean_target: run: all $(CPIO) $(QEMU) -kernel bootloader.img $(QEMUFLAGS) - #$(QEMU) -kernel kernel8.img $(QEMUFLAGS) + +kernel: all $(CPIO) + -killall screen + $(QEMU) -kernel kernel8.img $(QEMUFLAGS) + +debug: all $(CPIO) + -killall screen + $(QEMU) -kernel kernel8.img $(QEMUFLAGS) -S -s + +gdb: + $(GDB) diff --git a/bootloader/Start.S b/bootloader/Start.S index 10dfa07..90b2efd 100644 --- a/bootloader/Start.S +++ b/bootloader/Start.S @@ -12,8 +12,9 @@ wait: b wait run: + // move dtb to x20 mov x20, x0 - adr x0, _start + adrp x0, __stack_end mov sp, x0 adr x0, __text_start @@ -25,6 +26,7 @@ run: adr x1, __bss_end bl memzero + // move dtb back to x0 mov x0, x20 bl main b wait @@ -36,7 +38,8 @@ relocate: adr x2, __text_end sub x2, x2, x1 bl memcpy - mov x19, x0 + + mov x19, x0 // save return pointer // move rodata section ldr x0, =__new_ro_start @@ -52,5 +55,6 @@ relocate: sub x2, x2, x1 bl memcpy + mov x0, x20 br x19 b wait diff --git a/bootloader/linker.ld b/bootloader/linker.ld index 190396a..c9895b4 100644 --- a/bootloader/linker.ld +++ b/bootloader/linker.ld @@ -1,16 +1,16 @@ ENTRY(_start) MEMORY { - NEWTEXT (rx) : ORIGIN = 0x10000, LENGTH = 128K - NEWRO (r) : ORIGIN = 0x30000, LENGTH = 128K - NEWDATA (rw) : ORIGIN = 0x50000, LENGTH = 64K - NEWBSS (rw) : ORIGIN = 0x60000, LENGTH = 64K + NEWTEXT (rx) : ORIGIN = 0x10000, LENGTH = 64K + NEWRO (r) : ORIGIN = 0x20000, LENGTH = 16K + NEWDATA (rw) : ORIGIN = 0x24000, LENGTH = 16K + NEWBSS (rw) : ORIGIN = 0x28000, LENGTH = 16K - TEXT (rx) : ORIGIN = 0x80000, LENGTH = 128K - RO (r) : ORIGIN = 0xa0000, LENGTH = 128K - DATA (rw) : ORIGIN = 0xc0000, LENGTH = 64K - BSS (rw) : ORIGIN = 0xd0000, LENGTH = 64K - RAM (rw) : ORIGIN = 0xf0000, LENGTH = 8M + TEXT (rx) : ORIGIN = 0x80000, LENGTH = 64K + RO (r) : ORIGIN = 0x90000, LENGTH = 16K + DATA (rw) : ORIGIN = 0x94000, LENGTH = 16K + BSS (rw) : ORIGIN = 0x98000, LENGTH = 16K + RAM (rw) : ORIGIN = 0x9c000, LENGTH = 4M } SECTIONS @@ -36,6 +36,7 @@ SECTIONS *(.bss) __bss_end = .; } >BSS + __stack_end = ORIGIN(RAM) + LENGTH(RAM); __new_text_start = ORIGIN(NEWTEXT); @@ -44,7 +45,6 @@ SECTIONS __new_bss_start = ORIGIN(NEWBSS); } -__kernel = 0x80000; __heap_start = ORIGIN(RAM); __heap_end = ORIGIN(RAM) + LENGTH(RAM) - 2M; __bss_size = (__bss_end - __bss_start)>>3; diff --git a/bootloader/main.c b/bootloader/main.c index ba3441b..dd7d1de 100644 --- a/bootloader/main.c +++ b/bootloader/main.c @@ -2,20 +2,44 @@ #include #include -extern byte_t __kernel[]; -byte_t *kernel = __kernel; +// extern uint64_t __kernel; +uint64_t __kernel = 0x80000; -void main() +typedef void (*main_func_t)(void *); + +void main(void *dtb) { uart_init(); - uart_getc(); + uart_puts("waiting for kernel to be sent ..." ENDL); + + union { + int size; + uint8_t buf[4]; + } kernel_header; + kernel_header.size = 0; + for (int i = 0; i < (int)sizeof(kernel_header); ++i) + kernel_header.buf[i] = uart_getb(); + + uart_puts("received kernel size: "); + uart_int(kernel_header.size); + uart_puts(ENDL); + uart_puts("loaded addr: "); uart_hex((unsigned int)(unsigned long)main); uart_puts(ENDL); - - int shell_cont = 1; - while (shell_cont) { - shell_cont = shell(); - } + + uart_puts("dtb addr: "); + uart_hex((unsigned int)(unsigned long)dtb); + uart_puts(ENDL); + + uint8_t *kernel = (void *)__kernel; + uart_puts("kernel addr: "); + uart_hex((unsigned int)(unsigned long)kernel); + uart_puts("$" ENDL); + + for (int i = 0; i < kernel_header.size; ++i) + kernel[i] = uart_getb(); + + ((main_func_t)kernel)(dtb); } diff --git a/include/dtb.h b/include/dtb.h new file mode 100644 index 0000000..7e24bdd --- /dev/null +++ b/include/dtb.h @@ -0,0 +1,52 @@ +#pragma once + +#include +#include + +typedef struct { + uint32_t magic; + uint32_t totalsize; + uint32_t off_dt_struct; + uint32_t off_dt_strings; + uint32_t off_mem_rsvmap; + uint32_t version; + uint32_t last_comp_version; + uint32_t boot_cpuid_phys; + uint32_t size_dt_strings; + uint32_t size_dt_struct; +}__attribute__((packed)) fdt_header_t; + +typedef struct { + uint64_t address; + uint64_t size; +}__attribute__((packed)) fdt_reserve_entry_t; + +typedef struct { + uint32_t len; + uint32_t nameoff; +}__attribute__((packed)) fdt_prop_header_t; + +typedef struct { + uint32_t len; + const char *name; + void *value; +} fdt_prop_t; + +#define FDT_BEGIN_NODE 0x00000001 +#define FDT_END_NODE 0x00000002 +#define FDT_PROP 0x00000003 +#define FDT_NOP 0x00000004 +#define FDT_END 0x00000009 + +#define FDT_PATH_BUFFER_LEN 0x10 + +typedef void (*fdt_callback_func_t)(const vector_t *props); +typedef struct { + const char *name; + const fdt_callback_func_t func; +} fdt_callback_t; + +void fdt_callback(const char *path, const vector_t *cbs, const vector_t *props); +void fdt_traverse(const vector_t *cbs); + +extern void *dtb_addr; diff --git a/include/errcode.h b/include/errcode.h new file mode 100644 index 0000000..5d6cccc --- /dev/null +++ b/include/errcode.h @@ -0,0 +1,6 @@ +#pragma once + +#define ERR_NO_MEM 0x00000001 +#define ERR_UNREACHABLE 0x00000002 +#define ERR_CONVERSION 0x00000003 +#define ERR_VECTOR_OOR 0x00000101 diff --git a/include/initrd.h b/include/initrd.h index c72bf0d..5ae1c2e 100644 --- a/include/initrd.h +++ b/include/initrd.h @@ -1,6 +1,8 @@ #pragma once #include +#include +#include typedef struct { char c_magic[6]; @@ -38,9 +40,16 @@ typedef struct file_node { int namesize; char *filename; - byte_t *filecontent; + uint8_t *filecontent; } file_node_t; +typedef void (*initrd_callback_func_t)(file_node_t *); + file_node_t *initrd_init(void); -int initrd_ls(void); +void initrd_fdt_callback(const vector_t *props); file_node_t *initrd_get(file_node_t *root, const char *filename); +void initrd_traverse(file_node_t *tr, initrd_callback_func_t func); + +extern fdt_callback_t initrd_dtb_cb; +extern void *initrd_start; +extern void *initrd_end; diff --git a/include/shell.h b/include/shell.h index d24f816..18739d4 100644 --- a/include/shell.h +++ b/include/shell.h @@ -1,9 +1,14 @@ #pragma once +#include +#include + void help(void); void hello(void); void hwinfo(void); +void ls(file_node_t *root); +void cat(file_node_t *root, const char *filename); void reboot(void); int // is continue -shell(void); +shell(file_node_t *); diff --git a/include/stddef.h b/include/stddef.h index 868939b..22829f8 100644 --- a/include/stddef.h +++ b/include/stddef.h @@ -3,7 +3,12 @@ #define true 1 #define false 0 #define ENDL "\r\n" +#define NAME_MAX 255 +#define PATH_MAX 4096 typedef long unsigned int size_t; -typedef unsigned char byte_t; +typedef unsigned char uint8_t; +typedef int int32_t; +typedef unsigned int uint32_t; +typedef long long int int64_t; typedef unsigned long long int uint64_t; diff --git a/include/string.h b/include/string.h index 98addf6..b3013df 100644 --- a/include/string.h +++ b/include/string.h @@ -3,5 +3,8 @@ #include int strcmp(const char *lhs, const char *rhs); +char *strcpy(char *destination, const char *source); +size_t strlen(const char *str); + void *memcpy(void *dest, const void *src, size_t count); void *memzero(void *start, void *end); diff --git a/include/uart.h b/include/uart.h index d2d64ee..5b81019 100644 --- a/include/uart.h +++ b/include/uart.h @@ -2,9 +2,24 @@ #include +#define DEBUG(x) { \ + uart_puts(#x " = "); \ + uart_hex((unsigned int)(unsigned long)x); \ + uart_puts(ENDL); \ +} + +#define DEBUG_s(x) { \ + uart_puts(#x " = "); \ + uart_puts(x); \ + uart_puts(ENDL); \ +} + void uart_init(); void uart_send(unsigned int c); -byte_t uart_getb(); +uint8_t uart_getb(); char uart_getc(); -void uart_puts(char *s); +void uart_puts(const char *s); void uart_hex(unsigned int d); +void uart_int(int d); + +extern int is_uart_init; diff --git a/include/utils.h b/include/utils.h new file mode 100644 index 0000000..222e077 --- /dev/null +++ b/include/utils.h @@ -0,0 +1,31 @@ +#pragma once + +#include +#include + +uint32_t msb32(uint32_t); + +uint32_t hton32(const uint32_t); +uint32_t ntoh32(const uint32_t); + +uint64_t hton64(const uint64_t); +uint64_t ntoh64(const uint64_t); + +int isdigit(int); +int isxdigit(int); +int isupper(int); +int isspace(int); + +int32_t atoi32(const char *); +uint32_t atoh32(const char *); + +void exit(int); + +#define MIN(x, y) (((x) < (y)) ? (x) : (y)) +#define MAX(x, y) (((x) < (y)) ? (y) : (x)) +#define ALIGN4(ptr) (void *)(((((uint64_t)(ptr) - 1) >> 2) + 1) << 2) +#define ALIGN8(ptr) (void *)(((((uint64_t)(ptr) - 1) >> 3) + 1) << 3) +#define BUMP(orig_type, bump_type, ptr) ( \ + (ptr = (orig_type *)((bump_type *)ptr + 1)), \ + ((bump_type *)ptr - 1) \ +) diff --git a/include/vector.h b/include/vector.h new file mode 100644 index 0000000..167a0fd --- /dev/null +++ b/include/vector.h @@ -0,0 +1,18 @@ +#pragma once + +#include + +typedef struct { + size_t size; + size_t cap; + + uint64_t *data; +} vector_t; + +vector_t *make_vector(size_t size); + +uint64_t vec_at(const vector_t *vec, size_t idx); +vector_t *vec_push(vector_t *vec, uint64_t val); + +#define VEC_AT(type, vec, idx) ((type *)vec_at((vec), (idx))) +#define VEC_PUSH(vec, val) vec = vec_push(vec, (uint64_t)val) diff --git a/kernel/Start.S b/kernel/Start.S index 4d2b7f0..21d8f65 100644 --- a/kernel/Start.S +++ b/kernel/Start.S @@ -4,25 +4,24 @@ _start: // read cpu id, stop slave cores - mrs x1, mpidr_el1 - and x1, x1, #3 - cbz x1, 2f + mrs x1, mpidr_el1 + and x1, x1, #3 + cbz x1, run // cpu id > 0, stop -1: +wait: wfe - b 1b -2:// cpu id == 0 - // set top of stack just before our code (stack grows to a lower address per AAPCS64) - ldr x1, =_start - mov sp, x1 + b wait + +run: // cpu id == 0 + mov x20, x0 + adrp x0, __stack_end + mov sp, x0 // clear bss adr x0, __bss_start adr x1, __bss_end bl memzero -4: - // jump to C code, should not return - bl main - // for failsafe, halt this core too - b 1b + mov x0, x20 + bl main + b wait diff --git a/kernel/linker.ld b/kernel/linker.ld index b9c3c02..c70588a 100644 --- a/kernel/linker.ld +++ b/kernel/linker.ld @@ -4,7 +4,7 @@ MEMORY TEXT (rx) : ORIGIN = 0x80000, LENGTH = 128K RO (r) : ORIGIN = 0xa0000, LENGTH = 128K DATA (rw) : ORIGIN = 0x100000, LENGTH = 512K - RAM (rw) : ORIGIN = 0x180000, LENGTH = 8M + RAM (rw) : ORIGIN = 0x180000, LENGTH = 64M } SECTIONS @@ -24,10 +24,10 @@ SECTIONS *(.bss) __bss_end = .; } >DATA + __stack_end = ORIGIN(RAM) + LENGTH(RAM); } -__kernel = 0x80000; __heap_start = ORIGIN(RAM); -__heap_end = ORIGIN(RAM) + LENGTH(RAM) - 2M; +__heap_end = ORIGIN(RAM) + 32M; __bss_size = (__bss_end - __bss_start)>>3; diff --git a/kernel/main.c b/kernel/main.c index dbb6e4e..a853e99 100644 --- a/kernel/main.c +++ b/kernel/main.c @@ -1,12 +1,28 @@ #include +#include +#include #include +#include -void main() +void main(void *dtb) { uart_init(); + uart_getc(); + + DEBUG(dtb); + + dtb_addr = dtb; + vector_t *dtb_cbs = make_vector(0); + VEC_PUSH(dtb_cbs, &initrd_dtb_cb); + fdt_traverse(dtb_cbs); + + DEBUG(initrd_start); + DEBUG(initrd_end); + + file_node_t *initrd_root = initrd_init(); int shell_cont = 1; while (shell_cont) { - shell_cont = shell(); + shell_cont = shell(initrd_root); } } diff --git a/lib/dtb.c b/lib/dtb.c new file mode 100644 index 0000000..afd93d7 --- /dev/null +++ b/lib/dtb.c @@ -0,0 +1,81 @@ +#include +#include +#include +#include +#include +#include +#include + +void *dtb_addr; + +void fdt_callback(const char *path, const vector_t *cbs, const vector_t *props) +{ + for (int i = 0; i < (int)cbs->size; ++i) + if (!strcmp(path, VEC_AT(fdt_callback_t, cbs, i)->name)) + VEC_AT(fdt_callback_t, cbs, i)->func(props); +} + +uint32_t *fdt_struct_cur; + +#define nextnode(ptr) (void *)((((uint64_t)(ptr) >> 2) + 1) << 2) +void traverse(const char *path, const vector_t *cbs) +{ + vector_t *props = make_vector(0); + + fdt_prop_t *prop; + const fdt_prop_header_t *prop_header; + const char *fdt_node_path = 0x0; + + for (;;) { + fdt_struct_cur = ALIGN4(fdt_struct_cur); + + switch (ntoh32(*fdt_struct_cur)) { + case FDT_BEGIN_NODE: + BUMP(uint32_t, uint32_t, fdt_struct_cur); + fdt_node_path = (void *)fdt_struct_cur; + do { + BUMP(uint32_t, char, fdt_struct_cur); + } while (*(char *)fdt_struct_cur != '\0'); + BUMP(uint32_t, char, fdt_struct_cur); // '\0' + + fdt_struct_cur = ALIGN4(fdt_struct_cur); + traverse(fdt_node_path, cbs); + break; + case FDT_END_NODE: + fdt_struct_cur = nextnode(fdt_struct_cur); + goto traverse_callback; + case FDT_PROP: + BUMP(uint32_t, uint32_t, fdt_struct_cur); + prop_header = BUMP(uint32_t, fdt_prop_header_t, fdt_struct_cur); + + prop = kmalloc(sizeof(fdt_prop_t)); + prop->len = ntoh32(prop_header->len); + prop->name = dtb_addr + + ntoh32(((fdt_header_t *)dtb_addr)->off_dt_strings) + + ntoh32(prop_header->nameoff); + prop->value = (void *)fdt_struct_cur; + VEC_PUSH(props, prop); + + fdt_struct_cur = (void *)((uint64_t)fdt_struct_cur + + ntoh32(prop_header->len)); + fdt_struct_cur = ALIGN4(fdt_struct_cur); + break; + case FDT_NOP: + fdt_struct_cur = nextnode(fdt_struct_cur); + break; + case FDT_END: + return; + default: + exit(ERR_UNREACHABLE); + } + } +traverse_callback: + fdt_callback(path, cbs, props); +} + +void fdt_traverse(const vector_t *cbs) +{ + fdt_struct_cur = dtb_addr + ntoh32(((fdt_header_t *)dtb_addr)->off_dt_struct); + + traverse("", cbs); +} diff --git a/lib/initrd.c b/lib/initrd.c index 5568ab1..e1cafd7 100644 --- a/lib/initrd.c +++ b/lib/initrd.c @@ -1,11 +1,34 @@ -#include #include +#include +#include +#include #include #include #include +#include #define nullnode ((file_node_t *)0) +fdt_callback_t initrd_dtb_cb = { + .name = "chosen", + .func = initrd_fdt_callback, +}; + +void *initrd_start = 0x0; +void *initrd_end = 0x0; + +void initrd_fdt_callback(const vector_t *props) +{ + for (int i = 0; i < (int)props->size; ++i) { + if (!strcmp(VEC_AT(fdt_prop_t, props, i)->name, "linux,initrd-start")) + initrd_start = (void *)(uint64_t)ntoh32( + *(uint32_t *)VEC_AT(fdt_prop_t, props, i)->value); + if (!strcmp(VEC_AT(fdt_prop_t, props, i)->name, "linux,initrd-end")) + initrd_end = (void *)(uint64_t)ntoh32( + *(uint32_t *)VEC_AT(fdt_prop_t, props, i)->value); + } +} + void _init_node(file_node_t *node) { node->l = nullnode; node->r = nullnode; @@ -50,7 +73,7 @@ void _split(file_node_t *rt, const char *s, file_node_t **a, file_node_t **b) return; } - if (strcmp(s, rt->filename) < 0) { + if (strcmp(rt->filename, s) < 0) { *a = rt; _split((*a)->r, s, &(*a)->r, b); _pull(*a); @@ -61,12 +84,53 @@ void _split(file_node_t *rt, const char *s, file_node_t **a, file_node_t **b) } } +cpio_newc_header_t *initrd_cur; file_node_t *initrd_init(void) { - // TODO + cpio_newc_header_t *header; + char *filename; + uint8_t *filecontent; + + initrd_cur = (void *)initrd_start; + + file_node_t *root = nullnode, *ltr, *rtr; + for (;;) { + header = BUMP(cpio_newc_header_t, cpio_newc_header_t, initrd_cur); + + filename = (void *)initrd_cur; + if (!strcmp(filename, "TRAILER!!!")) + break; + initrd_cur = ALIGN4((uint64_t)initrd_cur + atoh32(header->c_namesize)); + + filecontent = (void *)initrd_cur; + initrd_cur = ALIGN4((uint64_t)initrd_cur + atoh32(header->c_filesize)); + + file_node_t *newnode = kmalloc(sizeof(file_node_t)); + _init_node(newnode); + newnode->ino = atoh32(header->c_ino); + newnode->mode = atoh32(header->c_mode); + newnode->uid = atoh32(header->c_uid); + newnode->gid = atoh32(header->c_gid); + newnode->nlink = atoh32(header->c_nlink); + newnode->mtime = atoh32(header->c_mtime); + newnode->filesize = atoh32(header->c_filesize); + newnode->devmajor = atoh32(header->c_devmajor); + newnode->devminor = atoh32(header->c_devminor); + newnode->rdevmajor = atoh32(header->c_rdevmajor); + newnode->rdevminor = atoh32(header->c_rdevminor); + newnode->namesize = atoh32(header->c_namesize); + + newnode->filename = filename; + newnode->filecontent = filecontent; + + DEBUG_s(filename); + + _split(root, filename, <r, &rtr); + root = _merge(ltr, _merge(newnode, rtr)); + } - return nullnode; + return root; } file_node_t *_node_bs(file_node_t *cur, const char *s) @@ -74,7 +138,7 @@ file_node_t *_node_bs(file_node_t *cur, const char *s) if (!cur) return nullnode; - int cmp = strcmp(s, cur->filename); + int cmp = strcmp(cur->filename, s); if (cmp < 0) return _node_bs(cur->r, s); if (cmp > 0) @@ -82,7 +146,17 @@ file_node_t *_node_bs(file_node_t *cur, const char *s) return cur; // cmp == 0 } -file_node_t *initrd_get(file_node_t *root, const char *filename) +file_node_t *initrd_get(file_node_t *tr, const char *filename) { - return _node_bs(root, filename); + return _node_bs(tr, filename); +} + +void initrd_traverse(file_node_t *tr, initrd_callback_func_t func) +{ + if (!tr) + return; + + initrd_traverse(tr->l, func); + func(tr); + initrd_traverse(tr->r, func); } diff --git a/lib/kmalloc.c b/lib/kmalloc.c index 3d697b5..3455b60 100644 --- a/lib/kmalloc.c +++ b/lib/kmalloc.c @@ -1,8 +1,11 @@ +#include +#include +#include #include #include -extern void *__heap_start; -extern void *__heap_end; +extern uint64_t __heap_start; +extern uint64_t __heap_end; void *_heap_top = (void *)0; @@ -10,14 +13,14 @@ void *_heap_top = (void *)0; void *simple_alloc(size_t size) { if (!_heap_top) { - _heap_top = __heap_start; + _heap_top = (void *)&__heap_start; } if (size & 0xff) size = (size & ~0xff) + 0x100; - if ((uint64_t)_heap_top + size >= (uint64_t)__heap_end) - return (void *)0; + if ((uint64_t)_heap_top + size >= (uint64_t)&__heap_end) + exit(ERR_NO_MEM); void *ret = _heap_top; _heap_top = (void *)((uint64_t)_heap_top + size); diff --git a/lib/shell.c b/lib/shell.c index bd951ce..a008e48 100644 --- a/lib/shell.c +++ b/lib/shell.c @@ -1,4 +1,5 @@ #include +#include #include #include #include @@ -17,6 +18,8 @@ void help (void) "help : print this help menu" ENDL "hello : print Hello World!" ENDL "hwinfo: print hardware info" ENDL + "ls : list directory contents" ENDL + "cat : concatenate files and print" ENDL "reboot: reboot the device" ENDL ); } @@ -46,6 +49,27 @@ void hwinfo (void) uart_puts(ENDL); } +void ls_initrd_callback(file_node_t *tr) +{ + uart_puts(tr->filename); + uart_puts(ENDL); +} + +void ls(file_node_t *root) +{ + initrd_traverse(root, ls_initrd_callback); +} + +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); + } +} + void set(long addr, unsigned int value) { volatile unsigned int* point = (unsigned int*)addr; *point = value; @@ -61,7 +85,7 @@ void reboot(void) reset(1 << 16); } -int shell (void) +int shell(file_node_t *initrd_root) { uart_puts("# "); @@ -74,13 +98,31 @@ int shell (void) uart_puts(ENDL); buf[sz] = '\0'; - if (strcmp(buf, "help") == 0) { + const char *i = buf; + + char bin[INPUT_BUFLEN], *j; + for (j = bin; *i != '\0' && !isspace(*i); ++i, ++j) + *j = *i; + *j = '\0'; + + 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")) { help(); - } else if (strcmp(buf, "hello") == 0) { + } else if (!strcmp(bin, "hello")) { hello(); - } else if (strcmp(buf, "hwinfo") == 0) { + } else if (!strcmp(bin, "hwinfo")) { hwinfo(); - } else if (strcmp(buf, "reboot") == 0) { + } else if (!strcmp(bin, "ls")) { + ls(initrd_root); + } else if (!strcmp(bin, "cat")) { + cat(initrd_root, param); + } else if (!strcmp(bin, "reboot")) { reboot(); } diff --git a/lib/string.c b/lib/string.c index 6f2fedc..67d8e74 100644 --- a/lib/string.c +++ b/lib/string.c @@ -16,11 +16,30 @@ int strcmp(const char *a, const char *b) return 1; } +char *strcpy(char *destination, const char *source) +{ + char *ret = destination; + while (*source != '\0') + *destination++ = *source++; + *destination = '\0'; + + return ret; +} + +size_t strlen(const char *str) +{ + size_t ret = 0; + while (*str != '\0') + ++ret, ++str; + + return ret; +} + void *memcpy(void *dest, const void *src, size_t count) { void *ret = dest; - for (const byte_t *p = src; count > 0; --count, ++p, ++dest) - *(byte_t *)dest = *p; + for (const uint8_t *p = src; count > 0; --count, ++p, ++dest) + *(uint8_t *)dest = *p; return ret; } @@ -28,7 +47,7 @@ void *memcpy(void *dest, const void *src, size_t count) void *memzero(void *start, void *end) { void *ret = start; - for (byte_t *p = start; p < (byte_t *)end; ++p) + for (uint8_t *p = start; p < (uint8_t *)end; ++p) *p = 0; return ret; diff --git a/lib/uart.c b/lib/uart.c index f103162..0636103 100644 --- a/lib/uart.c +++ b/lib/uart.c @@ -1,5 +1,6 @@ #include #include +#include /* Auxilary mini UART registers */ #define AUX_ENABLE ((volatile unsigned int*)(MMIO_BASE+0x00215004)) @@ -15,6 +16,8 @@ #define AUX_MU_STAT ((volatile unsigned int*)(MMIO_BASE+0x00215064)) #define AUX_MU_BAUD ((volatile unsigned int*)(MMIO_BASE+0x00215068)) +int is_uart_init = 0; + /** * Set baud rate and characteristics (115200 8N1) and map to GPIO */ @@ -42,6 +45,8 @@ void uart_init() r=150; while(r--) { asm volatile("nop"); } *GPPUDCLK0 = 0; // flush GPIO setup *AUX_MU_CNTL = 3; // enable Tx, Rx + + is_uart_init = 1; } /** @@ -54,13 +59,13 @@ void uart_send(unsigned int c) { *AUX_MU_IO=c; } -byte_t uart_getb() +uint8_t uart_getb() { - byte_t r; + uint8_t r; /* wait until something is in the buffer */ do{asm volatile("nop");}while(!(*AUX_MU_LSR&0x01)); /* read it and return */ - r=(byte_t)(*AUX_MU_IO); + r=(uint8_t)(*AUX_MU_IO); return r; } @@ -78,7 +83,7 @@ char uart_getc() { /** * Display a string */ -void uart_puts(char *s) { +void uart_puts(const char *s) { while(*s) { /* convert newline to carrige return + newline */ if(*s=='\n') @@ -90,7 +95,7 @@ void uart_puts(char *s) { /** * Display a binary value in hexadecimal */ -void uart_hex(unsigned int d) { +void uart_hex(const unsigned int d) { unsigned int n; int c; for(c=28;c>=0;c-=4) { @@ -101,3 +106,26 @@ void uart_hex(unsigned int d) { uart_send(n); } } + +void uart_int(int d) +{ + unsigned int buf[11]; + int size = 0; + + if (d == 0) { + uart_send((unsigned int)'0'); + return; + } + + int is_neg = (d < 0); + + while (d != 0) { + buf[size++] = '0' + d % 10; + d /= 10; + } + + if (is_neg) + uart_send((unsigned int)'-'); + while (size--) + uart_send(buf[size]); +} diff --git a/lib/utils.c b/lib/utils.c new file mode 100644 index 0000000..a887bed --- /dev/null +++ b/lib/utils.c @@ -0,0 +1,132 @@ +#include +#include +#include + +uint32_t msb32(uint32_t x) +{ + static const int msb[32] = { + 0, 9, 1, 10, 13, 21, 2, 29, 11, 14, 16, 18, 22, 25, 3, 30, + 8, 12, 20, 28, 15, 17, 24, 7, 19, 27, 23, 6, 26, 5, 4, 31 + }; + + x |= x >> 1; + x |= x >> 2; + x |= x >> 4; + x |= x >> 8; + x |= x >> 16; + + return msb[(uint32_t)(x * 0x07c4acddu) >> 27]; +} + +uint32_t hton32(const uint32_t h) +{ + const uint8_t *p = (const void *)&h; + + return (uint32_t)p[0] << 24 | + (uint32_t)p[1] << 16 | + (uint32_t)p[2] << 8 | + (uint32_t)p[3]; +} + +uint32_t ntoh32(const uint32_t h) +{ + return hton32(h); +} + +uint64_t hton64(const uint64_t h) +{ + return (uint64_t)hton32(h & 0xffffffff) << 32 | + (uint64_t)hton32(h >> 32); +} + +uint64_t ntoh64(const uint64_t h) +{ + return hton64(h); +} + +int isspace(int c) +{ + switch (c) { + case ' ': + case '\t': + case '\n': + case '\v': + case '\f': + case '\r': + return true; + } + return false; +} + +int isdigit(int c) +{ + return ('0' <= c && c <= '9'); +} + +int isxdigit(int c) +{ + return ('0' <= c && c <= '9') || + ('a' <= c && c <= 'f') || + ('A' <= c && c <= 'F'); +} + +int isupper(int c) +{ + return ('A' <= c && c <= 'F'); +} + +int32_t atoi32(const char *s) +{ + if (!s) + exit(ERR_CONVERSION); + + int is_neg = 0; + if (*s != '\0' && *s == '-') + is_neg = 1, s++; + + int32_t ret = 0; + for (; *s != '\0'; ++s) { + if (!isdigit(*s)) + exit(ERR_CONVERSION); + ret *= 10, ret += *s - '0'; + } + + return is_neg ? -ret : ret; +} + +uint32_t atoh32(const char *s) +{ + if (!s) + exit(ERR_CONVERSION); + + uint32_t ret = 0; + for (int i = 8; i--; ++s) { + if (!isxdigit(*s)) + exit(ERR_CONVERSION); + ret <<= 4, ret |= (isdigit(*s) ? *s - '0' : + (isupper(*s) ? *s - 'A' + 10 : + *s - 'a' + 10)); + } + + return ret; +} + +void exit(int exit_code) +{ + static int print = 0; + if (!print) { + uart_puts( + "OOPS! YOUR KERNEL DEAD" ENDL + "ERROR CODE: " + ); + uart_hex(exit_code); + uart_puts(ENDL); + print = 1; + } + + asm volatile( + "wfe\n" + "b exit" + ); + __builtin_unreachable(); +} diff --git a/lib/vector.c b/lib/vector.c new file mode 100644 index 0000000..9ffd914 --- /dev/null +++ b/lib/vector.c @@ -0,0 +1,39 @@ +#include +#include +#include +#include +#include +#include + +vector_t *make_vector(size_t size) +{ + vector_t *ret = kmalloc(sizeof(vector_t)); + ret->size = size; + uint32_t msb = msb32(size); + ret->cap = (msb == size) ? size : (msb << 1); + ret->cap = MAX(ret->cap, 4); + ret->data = kmalloc(ret->cap * sizeof(uint64_t)); + memzero(ret->data, ret->data + ret->cap); + + return ret; +} + +uint64_t vec_at(const vector_t *vec, size_t idx) +{ + if (idx >= vec->size) + exit(ERR_VECTOR_OOR); + + return vec->data[idx]; +} + +vector_t *vec_push(vector_t *vec, uint64_t val) +{ + if (vec->size == vec->cap) { + uint64_t *old = vec->data; + vec->data = kmalloc((vec->cap <<= 1) * sizeof(uint64_t)); + memcpy(vec->data, old, vec->size * sizeof(uint64_t)); + } + + vec->data[vec->size++] = val; + return vec; +} diff --git a/rootfs/poop/poop/poop.txt b/rootfs/poop/poop/poop.txt new file mode 100644 index 0000000..ea9da5f --- /dev/null +++ b/rootfs/poop/poop/poop.txt @@ -0,0 +1 @@ +pooppooppoop diff --git a/test.py b/test.py new file mode 100755 index 0000000..3366d15 --- /dev/null +++ b/test.py @@ -0,0 +1,13 @@ +#!/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/upload.py b/upload.py new file mode 100755 index 0000000..4a2cd00 --- /dev/null +++ b/upload.py @@ -0,0 +1,30 @@ +#!/usr/bin/env -S python3 +from pwn import * +from struct import pack +from tqdm import tqdm + +if len(sys.argv) < 2: + print("no args for serial device") + exit() + +while True: + kernel = open("kernel8.img", "rb").read() + r = serialtube(sys.argv[1], convert_newlines=False) + + # send size + sz = len(kernel) + print("size:", sz) + r.send(pack("