commit e906741ee9e8af1abc27b3c4b0a9969bd222aa5d Author: Yi-Ting Shih Date: Tue Mar 11 05:17:34 2025 +0800 initial commit diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..ff069fe --- /dev/null +++ b/Makefile @@ -0,0 +1,72 @@ +MAKE := make + +ARCH := aarch64 +GNU := $(ARCH)-linux-gnu + +QEMU := qemu-system-$(ARCH) +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 +LD := $(GNU)-ld +LDFLAGS += -g -nostdlib +OBJCOPY := $(GNU)-objcopy + +#TARGET := kernel8 +#TARGET_DIR := ./kernel +ELF := $(TARGET).elf +IMG := $(TARGET).img + +LD_SCRIPT := $(TARGET_DIR)/linker.ld +INCLUDE += -Iinclude +LIB_DIR := ./lib +MISC_DIR := ./misc +#QEMUFLAGS += -dtb $(MISC_DIR)/bcm2710-rpi-3-b-plus.dtb + +BOOTLOADER_DIR := ./bootloader +ROOTFS_DIR := ./rootfs + +CPIO := initramfs.cpio +QEMUFLAGS += -initrd $(CPIO) + +SRCS := $(shell find $(TARGET_DIR) -name '*.[cS]') \ + $(shell find $(LIB_DIR) -name '*.c') +OBJS := $(SRCS:%=%.o) + +.PHONY: all build clean clean_target run + +all: + $(MAKE) build TARGET_DIR=./kernel TARGET=kernel8 + $(MAKE) build TARGET_DIR=./bootloader TARGET=bootloader + +build: $(IMG) + +$(CPIO): $(shell find $(ROOTFS_DIR)) + cd $(ROOTFS_DIR) && find . | cpio -o -H newc > ../$@ + +$(IMG): $(ELF) + $(OBJCOPY) -O binary $< $@ + +$(ELF): $(LD_SCRIPT) $(OBJS) + $(LD) -o $@ -T $^ $(LDFLAGS) + +%.S.o: %.S + mkdir -p $(dir $@) + $(CC) -c $< -o $@ $(INCLUDE) $(CCFLAGS) + +%.c.o: %.c + mkdir -p $(dir $@) + $(CC) -c $< -o $@ $(INCLUDE) $(CCFLAGS) + +clean: + $(MAKE) clean_target TARGET_DIR=./kernel TARGET=kernel8 + $(MAKE) clean_target TARGET_DIR=./bootloader TARGET=bootloader + +clean_target: + -rm $(OBJS) $(ELF) $(IMG) $(CPIO) + +run: all $(CPIO) + $(QEMU) -kernel bootloader.img $(QEMUFLAGS) + #$(QEMU) -kernel kernel8.img $(QEMUFLAGS) diff --git a/bootloader/Start.S b/bootloader/Start.S new file mode 100644 index 0000000..10dfa07 --- /dev/null +++ b/bootloader/Start.S @@ -0,0 +1,56 @@ +.section ".text.boot" + +.global _start + +_start: + mrs x1, mpidr_el1 + and x1, x1, #3 + cbz x1, run + +wait: + wfe + b wait + +run: + mov x20, x0 + adr x0, _start + mov sp, x0 + + adr x0, __text_start + ldr x1, =__new_text_start + cmp x0, x1 + b.gt relocate + + adr x0, __bss_start + adr x1, __bss_end + bl memzero + + mov x0, x20 + bl main + b wait + +relocate: + // move text section + ldr x0, =__new_text_start + adr x1, __text_start + adr x2, __text_end + sub x2, x2, x1 + bl memcpy + mov x19, x0 + + // move rodata section + ldr x0, =__new_ro_start + adr x1, __rodata_start + adr x2, __rodata_end + sub x2, x2, x1 + bl memcpy + + // move data section + ldr x0, =__new_data_start + adr x1, __data_start + adr x2, __data_end + sub x2, x2, x1 + bl memcpy + + br x19 + b wait diff --git a/bootloader/linker.ld b/bootloader/linker.ld new file mode 100644 index 0000000..190396a --- /dev/null +++ b/bootloader/linker.ld @@ -0,0 +1,50 @@ +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 + + 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 +} + +SECTIONS +{ + .text : { + __text_start = .; + KEEP(*(.text.boot)) + *(.text) + __text_end = .; + } >TEXT + .rodata : { + __rodata_start = .; + *(.rodata) + __rodata_end = .; + } >RO + .data : { + __data_start = .; + *(.data) + __data_end = .; + } >DATA + .bss : { + __bss_start = .; + *(.bss) + __bss_end = .; + } >BSS + __stack_end = ORIGIN(RAM) + LENGTH(RAM); + + __new_text_start = ORIGIN(NEWTEXT); + __new_ro_start = ORIGIN(NEWRO); + __new_data_start = ORIGIN(NEWDATA); + __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 new file mode 100644 index 0000000..ba3441b --- /dev/null +++ b/bootloader/main.c @@ -0,0 +1,21 @@ +#include +#include +#include + +extern byte_t __kernel[]; +byte_t *kernel = __kernel; + +void main() +{ + uart_init(); + + uart_getc(); + uart_puts("loaded addr: "); + uart_hex((unsigned int)(unsigned long)main); + uart_puts(ENDL); + + int shell_cont = 1; + while (shell_cont) { + shell_cont = shell(); + } +} diff --git a/include/gpio.h b/include/gpio.h new file mode 100644 index 0000000..2f528ba --- /dev/null +++ b/include/gpio.h @@ -0,0 +1,46 @@ +#pragma once +/* + * Copyright (C) 2018 bzt (bztsrc@github) + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + */ + +#define MMIO_BASE 0x3F000000 + +#define GPFSEL0 ((volatile unsigned int*)(MMIO_BASE+0x00200000)) +#define GPFSEL1 ((volatile unsigned int*)(MMIO_BASE+0x00200004)) +#define GPFSEL2 ((volatile unsigned int*)(MMIO_BASE+0x00200008)) +#define GPFSEL3 ((volatile unsigned int*)(MMIO_BASE+0x0020000C)) +#define GPFSEL4 ((volatile unsigned int*)(MMIO_BASE+0x00200010)) +#define GPFSEL5 ((volatile unsigned int*)(MMIO_BASE+0x00200014)) +#define GPSET0 ((volatile unsigned int*)(MMIO_BASE+0x0020001C)) +#define GPSET1 ((volatile unsigned int*)(MMIO_BASE+0x00200020)) +#define GPCLR0 ((volatile unsigned int*)(MMIO_BASE+0x00200028)) +#define GPLEV0 ((volatile unsigned int*)(MMIO_BASE+0x00200034)) +#define GPLEV1 ((volatile unsigned int*)(MMIO_BASE+0x00200038)) +#define GPEDS0 ((volatile unsigned int*)(MMIO_BASE+0x00200040)) +#define GPEDS1 ((volatile unsigned int*)(MMIO_BASE+0x00200044)) +#define GPHEN0 ((volatile unsigned int*)(MMIO_BASE+0x00200064)) +#define GPHEN1 ((volatile unsigned int*)(MMIO_BASE+0x00200068)) +#define GPPUD ((volatile unsigned int*)(MMIO_BASE+0x00200094)) +#define GPPUDCLK0 ((volatile unsigned int*)(MMIO_BASE+0x00200098)) +#define GPPUDCLK1 ((volatile unsigned int*)(MMIO_BASE+0x0020009C)) diff --git a/include/initrd.h b/include/initrd.h new file mode 100644 index 0000000..c72bf0d --- /dev/null +++ b/include/initrd.h @@ -0,0 +1,46 @@ +#pragma once + +#include + +typedef struct { + char c_magic[6]; + char c_ino[8]; + char c_mode[8]; + char c_uid[8]; + char c_gid[8]; + char c_nlink[8]; + char c_mtime[8]; + char c_filesize[8]; + char c_devmajor[8]; + char c_devminor[8]; + char c_rdevmajor[8]; + char c_rdevminor[8]; + char c_namesize[8]; + char c_check[8]; +}__attribute__((packed)) cpio_newc_header_t; + +typedef struct file_node { + struct file_node *l, *r; + int rand; + int node_size; + + int ino; + int mode; + int uid; + int gid; + int nlink; + int mtime; + int filesize; + int devmajor; + int devminor; + int rdevmajor; + int rdevminor; + int namesize; + + char *filename; + byte_t *filecontent; +} file_node_t; + +file_node_t *initrd_init(void); +int initrd_ls(void); +file_node_t *initrd_get(file_node_t *root, const char *filename); diff --git a/include/kmalloc.h b/include/kmalloc.h new file mode 100644 index 0000000..feb86fa --- /dev/null +++ b/include/kmalloc.h @@ -0,0 +1,7 @@ +#pragma once + +#include + +void *simple_alloc(size_t size); +void *kmalloc(size_t size); +void kfree(void *ptr); diff --git a/include/mbox.h b/include/mbox.h new file mode 100644 index 0000000..563c2d9 --- /dev/null +++ b/include/mbox.h @@ -0,0 +1,48 @@ +/* + * Copyright (C) 2018 bzt (bztsrc@github) + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + */ + +/* a properly aligned buffer */ +extern volatile unsigned int mbox[36]; + +#define MBOX_REQUEST 0 + +/* channels */ +#define MBOX_CH_POWER 0 +#define MBOX_CH_FB 1 +#define MBOX_CH_VUART 2 +#define MBOX_CH_VCHIQ 3 +#define MBOX_CH_LEDS 4 +#define MBOX_CH_BTNS 5 +#define MBOX_CH_TOUCH 6 +#define MBOX_CH_COUNT 7 +#define MBOX_CH_PROP 8 + +/* tags */ +#define MBOX_TAG_GETSERIAL 0x10004 +#define MBOX_TAG_LAST 0 +#define MBOX_TAG_BOARD_REVISION 0x00010002 + +int mbox_call(unsigned char ch); +unsigned int get_board_revision(void); diff --git a/include/random.h b/include/random.h new file mode 100644 index 0000000..42c88c1 --- /dev/null +++ b/include/random.h @@ -0,0 +1,8 @@ +#pragma once + +extern const int _random_a; +extern const int _random_c; +extern const int _random_m; +extern int seed; + +int random(void); diff --git a/include/shell.h b/include/shell.h new file mode 100644 index 0000000..d24f816 --- /dev/null +++ b/include/shell.h @@ -0,0 +1,9 @@ +#pragma once + +void help(void); +void hello(void); +void hwinfo(void); +void reboot(void); + +int // is continue +shell(void); diff --git a/include/stddef.h b/include/stddef.h new file mode 100644 index 0000000..868939b --- /dev/null +++ b/include/stddef.h @@ -0,0 +1,9 @@ +#pragma once + +#define true 1 +#define false 0 +#define ENDL "\r\n" + +typedef long unsigned int size_t; +typedef unsigned char byte_t; +typedef unsigned long long int uint64_t; diff --git a/include/string.h b/include/string.h new file mode 100644 index 0000000..98addf6 --- /dev/null +++ b/include/string.h @@ -0,0 +1,7 @@ +#pragma once + +#include + +int strcmp(const char *lhs, const char *rhs); +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 new file mode 100644 index 0000000..d2d64ee --- /dev/null +++ b/include/uart.h @@ -0,0 +1,10 @@ +#pragma once + +#include + +void uart_init(); +void uart_send(unsigned int c); +byte_t uart_getb(); +char uart_getc(); +void uart_puts(char *s); +void uart_hex(unsigned int d); diff --git a/kernel/Start.S b/kernel/Start.S new file mode 100644 index 0000000..df2cb8f --- /dev/null +++ b/kernel/Start.S @@ -0,0 +1,32 @@ +.section ".text.boot" + +.global _start + +_start: + // read cpu id, stop slave cores + mrs x1, mpidr_el1 + and x1, x1, #3 + cbz x1, 2f + // cpu id > 0, stop +1: + 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 + + // clear bss + ldr x1, =__bss_start + ldr w2, =__bss_size +3: + cbz w2, 4f + str xzr, [x1], #8 + sub w2, w2, #1 + cbnz w2, 3b + +4: + // jump to C code, should not return + bl main + // for failsafe, halt this core too + b 1b diff --git a/kernel/linker.ld b/kernel/linker.ld new file mode 100644 index 0000000..b9c3c02 --- /dev/null +++ b/kernel/linker.ld @@ -0,0 +1,33 @@ +ENTRY(_start) +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 +} + +SECTIONS +{ + .text : { + KEEP(*(.text.boot)) + *(.text) + } >TEXT + .rodata : { + *(.rodata) + } >RO + .data : { + *(.data) + } >DATA + .bss : { + __bss_start = .; + *(.bss) + __bss_end = .; + } >DATA + __stack_end = ORIGIN(RAM) + LENGTH(RAM); +} + +__kernel = 0x80000; +__heap_start = ORIGIN(RAM); +__heap_end = ORIGIN(RAM) + LENGTH(RAM) - 2M; +__bss_size = (__bss_end - __bss_start)>>3; diff --git a/kernel/main.c b/kernel/main.c new file mode 100644 index 0000000..dbb6e4e --- /dev/null +++ b/kernel/main.c @@ -0,0 +1,12 @@ +#include +#include + +void main() +{ + uart_init(); + + int shell_cont = 1; + while (shell_cont) { + shell_cont = shell(); + } +} diff --git a/lib/initrd.c b/lib/initrd.c new file mode 100644 index 0000000..5568ab1 --- /dev/null +++ b/lib/initrd.c @@ -0,0 +1,88 @@ +#include +#include +#include +#include +#include + +#define nullnode ((file_node_t *)0) + +void _init_node(file_node_t *node) { + node->l = nullnode; + node->r = nullnode; + node->rand = random(); + node->node_size = 1; +} + +void _pull_from(file_node_t *to, file_node_t *from) +{ + if (!from) + return; + + to->node_size += from->node_size; +} + +void _pull(file_node_t *node) +{ + node->node_size = 1; + _pull_from(node, node->l); + _pull_from(node, node->r); +} + +file_node_t *_merge(file_node_t *a, file_node_t *b) +{ + if (!a || !b) + return a ?: b; + + if (a->rand < b->rand) { + a->r = _merge(a->r, b); + _pull(a); + return a; + } + b->l = _merge(a, b->l); + _pull(b); + return b; +} + +void _split(file_node_t *rt, const char *s, file_node_t **a, file_node_t **b) +{ + if (!rt) { + *a = *b = nullnode; + return; + } + + if (strcmp(s, rt->filename) < 0) { + *a = rt; + _split((*a)->r, s, &(*a)->r, b); + _pull(*a); + } else { + *b = rt; + _split((*b)->l, s, a, &(*b)->l); + _pull(*b); + } +} + + +file_node_t *initrd_init(void) +{ + // TODO + + return nullnode; +} + +file_node_t *_node_bs(file_node_t *cur, const char *s) +{ + if (!cur) + return nullnode; + + int cmp = strcmp(s, cur->filename); + if (cmp < 0) + return _node_bs(cur->r, s); + if (cmp > 0) + return _node_bs(cur->l, s); + return cur; // cmp == 0 +} + +file_node_t *initrd_get(file_node_t *root, const char *filename) +{ + return _node_bs(root, filename); +} diff --git a/lib/kmalloc.c b/lib/kmalloc.c new file mode 100644 index 0000000..3d697b5 --- /dev/null +++ b/lib/kmalloc.c @@ -0,0 +1,37 @@ +#include +#include + +extern void *__heap_start; +extern void *__heap_end; + +void *_heap_top = (void *)0; + +// simple 8-byte aligned linear allocation +void *simple_alloc(size_t size) +{ + if (!_heap_top) { + _heap_top = __heap_start; + } + + if (size & 0xff) + size = (size & ~0xff) + 0x100; + + if ((uint64_t)_heap_top + size >= (uint64_t)__heap_end) + return (void *)0; + + void *ret = _heap_top; + _heap_top = (void *)((uint64_t)_heap_top + size); + + return ret; +} + +void *kmalloc(size_t size) +{ + return simple_alloc(size); +} + +void kfree(void *ptr) +{ + // not implemented for now + return; +} diff --git a/lib/mbox.c b/lib/mbox.c new file mode 100644 index 0000000..ac3f4fd --- /dev/null +++ b/lib/mbox.c @@ -0,0 +1,89 @@ +/* + * Copyright (C) 2018 bzt (bztsrc@github) + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + */ + +#include +#include + +/* mailbox message buffer */ +volatile unsigned int __attribute__((aligned(16))) mbox[36]; + +#define VIDEOCORE_MBOX (MMIO_BASE+0x0000B880) +#define MBOX_READ ((volatile unsigned int*)(VIDEOCORE_MBOX+0x0)) +#define MBOX_POLL ((volatile unsigned int*)(VIDEOCORE_MBOX+0x10)) +#define MBOX_SENDER ((volatile unsigned int*)(VIDEOCORE_MBOX+0x14)) +#define MBOX_STATUS ((volatile unsigned int*)(VIDEOCORE_MBOX+0x18)) +#define MBOX_CONFIG ((volatile unsigned int*)(VIDEOCORE_MBOX+0x1C)) +#define MBOX_WRITE ((volatile unsigned int*)(VIDEOCORE_MBOX+0x20)) +#define MBOX_RESPONSE 0x80000000 +#define MBOX_FULL 0x80000000 +#define MBOX_EMPTY 0x40000000 + +#define MAILBOX_BASE MMIO_BASE + 0xb880 + +#define REQUEST_CODE 0x00000000 +#define REQUEST_SUCCEED 0x80000000 +#define REQUEST_FAILED 0x80000001 +#define TAG_REQUEST_CODE 0x00000000 +#define END_TAG 0x00000000 + +/** + * Make a mailbox call. Returns 0 on failure, non-zero on success + */ +int mbox_call(unsigned char ch) +{ + unsigned int r = (((unsigned int)((unsigned long)&mbox)&~0xF) | (ch&0xF)); + /* wait until we can write to the mailbox */ + do{asm volatile("nop");}while(*MBOX_STATUS & MBOX_FULL); + /* write the address of our message to the mailbox with channel identifier */ + *MBOX_WRITE = r; + /* now wait for the response */ + while(1) { + /* is there a response? */ + do{asm volatile("nop");}while(*MBOX_STATUS & MBOX_EMPTY); + /* is it a response to our message? */ + if(r == *MBOX_READ) + /* is it a valid successful response? */ + return mbox[1]==MBOX_RESPONSE; + } + return 0; +} + +unsigned int get_board_revision(void) +{ + mbox[0] = 36 * 4; + mbox[1] = REQUEST_CODE; + + // tags + mbox[2] = MBOX_TAG_BOARD_REVISION; + mbox[3] = 4; + mbox[4] = TAG_REQUEST_CODE; + mbox[5] = 0; // value buffer + + mbox[6] = END_TAG; + + mbox_call(MBOX_CH_PROP); + + return mbox[5]; +} diff --git a/lib/random.c b/lib/random.c new file mode 100644 index 0000000..0192542 --- /dev/null +++ b/lib/random.c @@ -0,0 +1,12 @@ +#include + +const int _random_a = 100003; +const int _random_c = 114514 + 33; +const int _random_m = 1000000007; +int seed = 0; + +int random(void) +{ + seed = _random_a * (seed + _random_c) % _random_m; + return seed; +} diff --git a/lib/shell.c b/lib/shell.c new file mode 100644 index 0000000..ab7a4d9 --- /dev/null +++ b/lib/shell.c @@ -0,0 +1,75 @@ +#include +#include +#include +#include +#include + +#define INPUT_BUFLEN 1000 + +void help (void) +{ + uart_puts( + "help : print this help menu" ENDL + "hello : print Hello World!" ENDL + "hwinfo: print hardware info" ENDL + "reboot: reboot the device" ENDL + ); +} + +void hello (void) +{ + uart_puts("hello, world" ENDL); +} + +void hwinfo (void) +{ + unsigned int val = get_board_revision(); + uart_puts("hwinfo: "); + uart_hex(val); + uart_puts(ENDL); +} + +#define PM_PASSWORD 0x5a000000 +#define PM_RSTC 0x3F10001c +#define PM_WDOG 0x3F100024 + +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) +{ + reset(1 << 16); +} + +int shell (void) +{ + uart_puts("# "); + + char buf[INPUT_BUFLEN], ch; + int sz = 0; + while ((ch = uart_getc()) != '\n') { + buf[sz++] = ch; + uart_send(ch); + } + uart_puts(ENDL); + buf[sz] = '\0'; + + if (strcmp(buf, "help") == 0) { + help(); + } else if (strcmp(buf, "hello") == 0) { + hello(); + } else if (strcmp(buf, "hwinfo") == 0) { + hwinfo(); + } else if (strcmp(buf, "reboot") == 0) { + reboot(); + } + + return true; +} diff --git a/lib/string.c b/lib/string.c new file mode 100644 index 0000000..6f2fedc --- /dev/null +++ b/lib/string.c @@ -0,0 +1,35 @@ +#include +#include + +int strcmp(const char *a, const char *b) +{ + while (*a != '\0' && *b != '\0') { + if (*a != *b) + return (*a > *b) - (*a < *b); + a++, b++; + } + if (*a == '\0' && *b == '\0') + return 0; + + if (*a == '\0') + return -1; + return 1; +} + +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; + + return ret; +} + +void *memzero(void *start, void *end) +{ + void *ret = start; + for (byte_t *p = start; p < (byte_t *)end; ++p) + *p = 0; + + return ret; +} diff --git a/lib/uart.c b/lib/uart.c new file mode 100644 index 0000000..f103162 --- /dev/null +++ b/lib/uart.c @@ -0,0 +1,103 @@ +#include +#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)) + +/** + * Set baud rate and characteristics (115200 8N1) and map to GPIO + */ +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 +} + +/** + * 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; +} + +byte_t uart_getb() +{ + byte_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); + + return r; +} + +/** + * Receive a character + */ +char uart_getc() { + char r = (char)uart_getb(); + + /* convert carrige return to newline */ + return r=='\r'?'\n':r; +} + +/** + * Display a string + */ +void uart_puts(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(unsigned int 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); + } +} diff --git a/misc/bcm2710-rpi-3-b-plus.dtb b/misc/bcm2710-rpi-3-b-plus.dtb new file mode 100644 index 0000000..ffc07cc Binary files /dev/null and b/misc/bcm2710-rpi-3-b-plus.dtb differ diff --git a/misc/config.txt b/misc/config.txt new file mode 100644 index 0000000..a348083 --- /dev/null +++ b/misc/config.txt @@ -0,0 +1,3 @@ +initramfs initramfs.cpio 0x20000000 +kernel=bootloader.img +arm_64bit=1 diff --git a/rootfs/poop.txt b/rootfs/poop.txt new file mode 100644 index 0000000..a491c26 --- /dev/null +++ b/rootfs/poop.txt @@ -0,0 +1 @@ +poop diff --git a/scripts/upload.py b/scripts/upload.py new file mode 100644 index 0000000..5dc3e59 --- /dev/null +++ b/scripts/upload.py @@ -0,0 +1,15 @@ +from pwn import * + +kernel = open("kernel8.img", "rb").read() +r = serialtube("/dev/ttyS5", convert_newlines=False) + + +input("@") +r.send(str(len(kernel))+"\n") +#print(r.recv()) +#r.interactive() +print(r.recvuntil(b") : ")) +r.send(kernel) + + +r.interactive()