From dca3cff9f4ee1f2430969936d4f0fe7073afa557 Mon Sep 17 00:00:00 2001 From: Pin-Shao Chen Date: Mon, 26 Jun 2023 13:04:31 +0800 Subject: [PATCH 1/2] feat: lab3 --- lab3/.gitignore | 5 + lab3/Makefile | 66 +++++++++++ lab3/README.md | 15 +++ lab3/raspi3b/bcm2710-rpi-3-b-plus.dtb | Bin 0 -> 33106 bytes lab3/raspi3b/config.txt | 3 + lab3/raspi3b/initramfs.cpio | Bin 0 -> 1024 bytes lab3/rootfs/file1 | 1 + lab3/rootfs/file2.txt | 1 + lab3/rootfs/test_el0_exception | Bin 0 -> 24 bytes lab3/src/bootloader/bootloader.c | 40 +++++++ lab3/src/bootloader/include/bootloader.h | 6 + lab3/src/bootloader/linker.ld | 41 +++++++ lab3/src/bootloader/start.s | 20 ++++ lab3/src/exec/Makefile | 18 +++ lab3/src/exec/linker.ld | 18 +++ lab3/src/exec/main.s | 11 ++ lab3/src/exec/test_el0_exception | Bin 0 -> 24 bytes lab3/src/exec/test_el0_exception.s.o | Bin 0 -> 840 bytes lab3/src/kernel/include/kernel.h | 10 ++ lab3/src/kernel/kernel.c | 145 +++++++++++++++++++++++ lab3/src/kernel/linker.ld | 42 +++++++ lab3/src/kernel/start.s | 25 ++++ lab3/src/lib/allocator.c | 26 ++++ lab3/src/lib/command.c | 129 ++++++++++++++++++++ lab3/src/lib/coretimer.c | 103 ++++++++++++++++ lab3/src/lib/devicetree.c | 88 ++++++++++++++ lab3/src/lib/exception.c | 33 ++++++ lab3/src/lib/exception_table.s | 101 ++++++++++++++++ lab3/src/lib/include/allocator.h | 6 + lab3/src/lib/include/command.h | 10 ++ lab3/src/lib/include/coretimer.h | 20 ++++ lab3/src/lib/include/devicetree.h | 39 ++++++ lab3/src/lib/include/exception.h | 9 ++ lab3/src/lib/include/interrupt.h | 18 +++ lab3/src/lib/include/mailbox.h | 25 ++++ lab3/src/lib/include/ramdisk.h | 46 +++++++ lab3/src/lib/include/reboot.h | 9 ++ lab3/src/lib/include/ringbuffer.h | 23 ++++ lab3/src/lib/include/shell.h | 5 + lab3/src/lib/include/string.h | 10 ++ lab3/src/lib/include/uart.h | 36 ++++++ lab3/src/lib/include/utils.h | 16 +++ lab3/src/lib/interrupt.c | 40 +++++++ lab3/src/lib/mailbox.c | 56 +++++++++ lab3/src/lib/ramdisk.c | 81 +++++++++++++ lab3/src/lib/reboot.c | 20 ++++ lab3/src/lib/ringbuffer.c | 40 +++++++ lab3/src/lib/shell.c | 35 ++++++ lab3/src/lib/string.c | 59 +++++++++ lab3/src/lib/uart.c | 115 ++++++++++++++++++ lab3/src/lib/utils.c | 38 ++++++ lab3/upload.py | 12 ++ 52 files changed, 1715 insertions(+) create mode 100644 lab3/.gitignore create mode 100644 lab3/Makefile create mode 100644 lab3/README.md create mode 100644 lab3/raspi3b/bcm2710-rpi-3-b-plus.dtb create mode 100644 lab3/raspi3b/config.txt create mode 100644 lab3/raspi3b/initramfs.cpio create mode 100644 lab3/rootfs/file1 create mode 100644 lab3/rootfs/file2.txt create mode 100644 lab3/rootfs/test_el0_exception create mode 100644 lab3/src/bootloader/bootloader.c create mode 100644 lab3/src/bootloader/include/bootloader.h create mode 100644 lab3/src/bootloader/linker.ld create mode 100644 lab3/src/bootloader/start.s create mode 100644 lab3/src/exec/Makefile create mode 100644 lab3/src/exec/linker.ld create mode 100644 lab3/src/exec/main.s create mode 100644 lab3/src/exec/test_el0_exception create mode 100644 lab3/src/exec/test_el0_exception.s.o create mode 100644 lab3/src/kernel/include/kernel.h create mode 100644 lab3/src/kernel/kernel.c create mode 100644 lab3/src/kernel/linker.ld create mode 100644 lab3/src/kernel/start.s create mode 100644 lab3/src/lib/allocator.c create mode 100644 lab3/src/lib/command.c create mode 100644 lab3/src/lib/coretimer.c create mode 100644 lab3/src/lib/devicetree.c create mode 100644 lab3/src/lib/exception.c create mode 100644 lab3/src/lib/exception_table.s create mode 100644 lab3/src/lib/include/allocator.h create mode 100644 lab3/src/lib/include/command.h create mode 100644 lab3/src/lib/include/coretimer.h create mode 100644 lab3/src/lib/include/devicetree.h create mode 100644 lab3/src/lib/include/exception.h create mode 100644 lab3/src/lib/include/interrupt.h create mode 100644 lab3/src/lib/include/mailbox.h create mode 100644 lab3/src/lib/include/ramdisk.h create mode 100644 lab3/src/lib/include/reboot.h create mode 100644 lab3/src/lib/include/ringbuffer.h create mode 100644 lab3/src/lib/include/shell.h create mode 100644 lab3/src/lib/include/string.h create mode 100644 lab3/src/lib/include/uart.h create mode 100644 lab3/src/lib/include/utils.h create mode 100644 lab3/src/lib/interrupt.c create mode 100644 lab3/src/lib/mailbox.c create mode 100644 lab3/src/lib/ramdisk.c create mode 100644 lab3/src/lib/reboot.c create mode 100644 lab3/src/lib/ringbuffer.c create mode 100644 lab3/src/lib/shell.c create mode 100644 lab3/src/lib/string.c create mode 100644 lab3/src/lib/uart.c create mode 100644 lab3/src/lib/utils.c create mode 100644 lab3/upload.py diff --git a/lab3/.gitignore b/lab3/.gitignore new file mode 100644 index 000000000..05792799d --- /dev/null +++ b/lab3/.gitignore @@ -0,0 +1,5 @@ +tmp +book +build +*.elf +*.img diff --git a/lab3/Makefile b/lab3/Makefile new file mode 100644 index 000000000..e0c273646 --- /dev/null +++ b/lab3/Makefile @@ -0,0 +1,66 @@ +shell = /bin/bash +CROSS_COMPILER := aarch64-linux-gnu- +CC := $(CROSS_COMPILER)gcc +LD := $(CROSS_COMPILER)ld +OC := $(CROSS_COMPILER)objcopy +BUILD_DIR := build +SRC_DIR := src +LIB_DIR := $(SRC_DIR)/lib +KERNEL_DIR := $(SRC_DIR)/kernel +BOOTLOADER_DIR := $(SRC_DIR)/bootloader +KERNEL_SRCS := $(shell cd src; find kernel lib -name '*.[cs]') +KERNEL_OBJS := $(KERNEL_SRCS:%=$(BUILD_DIR)/%.o) +BOOTLOADER_SRCS := $(shell cd src; find bootloader lib -name '*.[cs]') +BOOTLOADER_OBJS := $(BOOTLOADER_SRCS:%=$(BUILD_DIR)/%.o) + +KERNEL_CFLAGS := -I $(KERNEL_DIR)/include +BOOTLOADER_CFLAGS := -I $(BOOTLOADER_DIR)/include +CFLAGS := -O0 -I $(LIB_DIR)/include -fno-stack-protector -ffreestanding -fdata-sections -ffunction-sections -g + +.PHONY : all clean rootfs test debug + +all: kernel8.img + +clean: + rm -rf build kernel8.img kernel8.elf + +rootfs: + cd rootfs && find . | cpio -o -H newc > ../raspi3b/initramfs.cpio + +test: + qemu-system-aarch64 -M raspi3b -kernel bootloader.img -initrd raspi3b/initramfs.cpio -dtb raspi3b/bcm2710-rpi-3-b-plus.dtb -serial null -serial pty -display none + +debug: + qemu-system-aarch64 -M raspi3b -kernel bootloader.img -initrd raspi3b/initramfs.cpio -dtb raspi3b/bcm2710-rpi-3-b-plus.dtb -serial null -serial pty -display none -S -s + +kernel8.img: $(KERNEL_OBJS) + $(LD) -T $(KERNEL_DIR)/linker.ld -o kernel8.elf $^ + $(OC) -O binary kernel8.elf kernel8.img + +bootloader.img: $(BOOTLOADER_OBJS) + $(LD) -T $(BOOTLOADER_DIR)/linker.ld -o bootloader.elf $^ --gc-sections + $(OC) -O binary bootloader.elf bootloader.img + +$(BUILD_DIR)/kernel/%.c.o: $(KERNEL_DIR)/%.c + mkdir -p $(dir $@) + $(CC) $(KERNEL_CFLAGS) $(CFLAGS) -c $< -o $@ + +$(BUILD_DIR)/kernel/%.s.o: $(KERNEL_DIR)/%.s + mkdir -p $(dir $@) + $(CC) $(KERNEL_CFLAGS) $(CFLAGS) -c $< -o $@ + +$(BUILD_DIR)/bootloader/%.c.o: $(BOOTLOADER_DIR)/%.c + mkdir -p $(dir $@) + $(CC) $(BOOTLOADER_CFLAGS) $(CFLAGS) -c $< -o $@ + +$(BUILD_DIR)/bootloader/%.s.o: $(BOOTLOADER_DIR)/%.s + mkdir -p $(dir $@) + $(CC) $(BOOTLOADER_CFLAGS) $(CFLAGS) -c $< -o $@ + +$(BUILD_DIR)/lib/%.c.o: $(LIB_DIR)/%.c + mkdir -p $(dir $@) + $(CC) $(CFLAGS) -c $< -o $@ + +$(BUILD_DIR)/lib/%.s.o: $(LIB_DIR)/%.s + mkdir -p $(dir $@) + $(CC) $(CFLAGS) -c $< -o $@ diff --git a/lab3/README.md b/lab3/README.md new file mode 100644 index 000000000..432991252 --- /dev/null +++ b/lab3/README.md @@ -0,0 +1,15 @@ +# OS + +Physical Environment: Raspberry Pi 3b+ + +Simulate Environment: QEMU + +Build Command: +``` +make +``` + +Simulate Command: +``` +qemu-system-aarch64 -M raspi3b -kernel kernel8.img -serial null -serial stdio -display none +``` diff --git a/lab3/raspi3b/bcm2710-rpi-3-b-plus.dtb b/lab3/raspi3b/bcm2710-rpi-3-b-plus.dtb new file mode 100644 index 0000000000000000000000000000000000000000..ddd8af88c45aa20caada0403fbd069383a1a1015 GIT binary patch literal 33106 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�!{|ADA4XD>wp8k##gUzLJ7OVy;H|%WGCBm9 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 G{{I6vS%S&{ literal 0 HcmV?d00001 diff --git a/lab3/raspi3b/config.txt b/lab3/raspi3b/config.txt new file mode 100644 index 000000000..933de3548 --- /dev/null +++ b/lab3/raspi3b/config.txt @@ -0,0 +1,3 @@ +kernel=bootloader.img +arm_64bit=1 +initramfs initramfs.cpio 0x20000000 \ No newline at end of file diff --git a/lab3/raspi3b/initramfs.cpio b/lab3/raspi3b/initramfs.cpio new file mode 100644 index 0000000000000000000000000000000000000000..580694561a91767c52f0ec5d840772bcab5f8a19 GIT binary patch literal 1024 zcmXpoH!wFaGynn<16MaNZRiH34UAnaKzulDU|?uwVrk)MX$cVrOCl2{j>tSDwh@f2 z#{jeqW}lm>6G+?wuYD$#uIA2A?OA}~*nmkY%W zmLRo6xWO1=CedzyhXu%1BfXM}5)^kBp}51?$r&7`_}yV?;c8$Cb}uk0(Bc4BSQtXx zZD3H6T3iyJnqv^3T9KSuP?DLS#{dQmml#+WCNeTGT#*-H__+H2{}7k literal 0 HcmV?d00001 diff --git a/lab3/rootfs/file1 b/lab3/rootfs/file1 new file mode 100644 index 000000000..9bc8d9ca0 --- /dev/null +++ b/lab3/rootfs/file1 @@ -0,0 +1 @@ +this is file1. diff --git a/lab3/rootfs/file2.txt b/lab3/rootfs/file2.txt new file mode 100644 index 000000000..221d4764a --- /dev/null +++ b/lab3/rootfs/file2.txt @@ -0,0 +1 @@ +this is file2. diff --git a/lab3/rootfs/test_el0_exception b/lab3/rootfs/test_el0_exception new file mode 100644 index 0000000000000000000000000000000000000000..1adf648a4c1b9d2d1b5e9fa08b84e52ef2fafc78 GIT binary patch literal 24 gcmZQzXt>0{!Z4AMf#Hh02*bzK|Nn + +#include +#include + +#include +#include +#include + +extern uint32_t _bss_begin; +extern uint32_t _bss_end; +extern uint32_t _stack_top; + +void _init(void){ + for(uint32_t*addr = &_bss_begin; addr != &_bss_end; addr++){ + *addr = 0; + } + uart_init(); + load_kernel(); +} + +void load_kernel(){ + char *kernel_addr = (char *)0x80000; + uart_print("Input Size: "); + char buf[BUF_SIZE]; + size_t recvlen = uart_readline(buf); + buf[recvlen] = '\0'; + uint32_t imagesize = atoi(buf); + uart_print("Input Kernel Image (Size: "); + uart_print_hex(imagesize, 32); + uart_print("): "); + uart_read(kernel_addr, imagesize); + uart_print("Go to kernel!"); + newline(); + asm volatile( + "mov x0, x10\n" + "ldr x1, =0x80000\n" + "br x1\n" + ); +} \ No newline at end of file diff --git a/lab3/src/bootloader/include/bootloader.h b/lab3/src/bootloader/include/bootloader.h new file mode 100644 index 000000000..ec7cd9762 --- /dev/null +++ b/lab3/src/bootloader/include/bootloader.h @@ -0,0 +1,6 @@ +#ifndef __KERNEL__ +#define __KERNEL__ +#define BUF_SIZE 0x20 +void load_kernel(); +void _init(); +#endif diff --git a/lab3/src/bootloader/linker.ld b/lab3/src/bootloader/linker.ld new file mode 100644 index 000000000..dda0fcb48 --- /dev/null +++ b/lab3/src/bootloader/linker.ld @@ -0,0 +1,41 @@ +ENTRY(_start) +MEMORY +{ + BOOTLOADER (rx) : ORIGIN = 0x20000, LENGTH = 128K + CODE (rx) : ORIGIN = 0x80000, LENGTH = 128K + ROM (r) : ORIGIN = 0xa0000, LENGTH = 128K + RAM (rw) : ORIGIN = 0xc0000, LENGTH = 512K +} +SECTIONS +{ + .text : + { + _loader_begin = .; + *(.text.start) + *(.text.loader) + *(.text) + } >CODE + .rodata : + { + _rodata_begin = .; + *(.rodata) + _rodata_end = .; + } >ROM + .data : + { + _data_begin = .; + *(.data) + _data_end = .; + } >RAM + .bss : { + . = ALIGN(0x8); + _bss_begin = .; + *(.bss) + _bss_end = .; + _loader_end = .; + } >RAM + _stack_top = ORIGIN(RAM) + LENGTH(RAM); + _bootloader_begin = ORIGIN(BOOTLOADER); + _loader_size = _loader_end - _loader_begin; + _kernel_begin = ORIGIN(CODE); +} \ No newline at end of file diff --git a/lab3/src/bootloader/start.s b/lab3/src/bootloader/start.s new file mode 100644 index 000000000..116e617f2 --- /dev/null +++ b/lab3/src/bootloader/start.s @@ -0,0 +1,20 @@ +.section ".text.start" +.extern _stack_top +.extern _bootloader_begin +.extern _kernel_begin +.extern _loader_size +.extern _init +.global _start +_start: + mov x10, x0 + adrp x0, _stack_top + mov sp, x0 + adrp x0, _kernel_begin + adrp x1, _bootloader_begin + adrp x2, _loader_size + _loop: + ldr x4, [x0], #8 + str x4, [x1], #8 + subs x2, x2, #8 + b.gt _loop + b #(_init - 0x60000) diff --git a/lab3/src/exec/Makefile b/lab3/src/exec/Makefile new file mode 100644 index 000000000..7fb284d7b --- /dev/null +++ b/lab3/src/exec/Makefile @@ -0,0 +1,18 @@ +CROSS_COMPILE = aarch64-linux-gnu- +CC := $(CROSS_COMPILE)gcc +LD := $(CROSS_COMPILE)ld + +.PHONY: clean + +CFLAGS := -O0 -fno-stack-protector -ffreestanding -fdata-sections -ffunction-sections + +test_el0_exception: test_el0_exception.s.o + $(LD) -T linker.ld $^ -o test_el0_exception.elf + $(CROSS_COMPILE)objcopy -O binary test_el0_exception.elf test_el0_exception + cp $@ ../../rootfs + +test_el0_exception.s.o: main.s + $(CC) $(CFLAGS) -c $< -o $@ + +clean: + rm test_el0_exception.elf test_el0_exception test_el0_exception.s.o \ No newline at end of file diff --git a/lab3/src/exec/linker.ld b/lab3/src/exec/linker.ld new file mode 100644 index 000000000..b2ebef1ea --- /dev/null +++ b/lab3/src/exec/linker.ld @@ -0,0 +1,18 @@ +ENTRY(_start) + +SECTIONS +{ + .text : { + *(.text.start) + *(.text) + } + .rodata : { + *(.rodata) + } + .data : { + *(.data) + } + .bss : { + *(.bss) + } +} \ No newline at end of file diff --git a/lab3/src/exec/main.s b/lab3/src/exec/main.s new file mode 100644 index 000000000..596352f0e --- /dev/null +++ b/lab3/src/exec/main.s @@ -0,0 +1,11 @@ +.section ".text.start" +.global _start +_start: + mov x0, 0 +1: + add x0, x0, 1 + svc 0 + cmp x0, 5 + blt 1b +1: + b 1b \ No newline at end of file diff --git a/lab3/src/exec/test_el0_exception b/lab3/src/exec/test_el0_exception new file mode 100644 index 0000000000000000000000000000000000000000..1adf648a4c1b9d2d1b5e9fa08b84e52ef2fafc78 GIT binary patch literal 24 gcmZQzXt>0{!Z4AMf#Hh02*bzK|NnJfjWMqH=MuzPS2p&w7fx!bw&;cy$z`()44rDc4VqjsI2$a4eFT(I~_5c4N zKtU0(5*!3GRvQ=?m>HO`>R<-SU<1rRi_rnZnV8}r5dkdf8B{75;)_cXi%J+6^olEU zOA?cSbV(6}&VaE>QY%Ur^imQ_5*hT8ii;WaKmtH@V14LrAcrpv)C6)n8=7VZG(L=r z6dhn8MIZ?hLk}qjuq-Blu3sIfgae4l)vp883o;Xz`z3&K$N)WtKzgyoegst03MdUS qAA~_}1p%13oIp0Z+rbK;9_0pe5Cppa1##%-hAOl`Xa%#-^#cHHG$T3y literal 0 HcmV?d00001 diff --git a/lab3/src/kernel/include/kernel.h b/lab3/src/kernel/include/kernel.h new file mode 100644 index 000000000..72de3cc4f --- /dev/null +++ b/lab3/src/kernel/include/kernel.h @@ -0,0 +1,10 @@ +#ifndef __KERNEL__ +#define __KERNEL__ +#define BUF_SIZE 256 +void _init(); +void boot_message(); +void allocator_test(); +void devicetree_check(); +void spsr_el1_check(); +void boottimer(); +#endif diff --git a/lab3/src/kernel/kernel.c b/lab3/src/kernel/kernel.c new file mode 100644 index 000000000..5eb2f4e18 --- /dev/null +++ b/lab3/src/kernel/kernel.c @@ -0,0 +1,145 @@ +#include +// C +#include +#include +// tool +#include +#include +#include +// lab1 +#include +#include +#include +// lab2 +#include +#include +#include +// lab3 +#include +#include +#include + +extern uint32_t _rodata_begin; +extern uint32_t _rodata_end; +extern uint32_t _data_begin; +extern uint32_t _data_end; +extern uint32_t _bss_begin; +extern uint32_t _bss_end; +extern uint32_t _heap_begin; +extern uint32_t _heap_end; +extern uint32_t _stack_top; +extern void *_devicetree_begin; + +extern uint32_t _user_begin; +extern uint32_t _user_end; + +void _init(void){ + for(uint32_t*addr = &_bss_begin; addr != &_bss_end; addr++){ + *addr = 0; + } + uart_init(); + boot_message(); + allocator_test(); + devicetree_check(); + exception_init(); + coretimer_el0_enable(); + interrupt_enable(); + spsr_el1_check(); + add_timer(8, &boottimer, 0); + shell(); +} + +void boot_message(){ + char buf[BUF_SIZE]; + uart_print("Boot Success!"); + newline(); + uint32_t board_revision; + uint32_t arm_memory_base_addr; + uint32_t arm_memory_size; + get_board_revision(&board_revision); + get_ARM_memory_base_address_and_size(&arm_memory_base_addr, &arm_memory_size); + + uart_print("board_revision: "); + uart_print_hex(board_revision, 32); + newline(); + + uart_print("arm_memory_base_addr: "); + uart_print_hex(arm_memory_base_addr, 32); + newline(); + + uart_print("arm_memory_size: "); + uart_print_hex(arm_memory_size, 32); + newline(); + + uart_print("&_rodata_begin="); + uart_print_hex((uint64_t) &_rodata_begin, 64); + newline(); + uart_print("&_rodata_end="); + uart_print_hex((uint64_t) &_rodata_end, 64); + newline(); + uart_print("&_data_begin="); + uart_print_hex((uint64_t) &_data_begin, 64); + newline(); + uart_print("&_data_end="); + uart_print_hex((uint64_t) &_data_end, 64); + newline(); + uart_print("&_bss_begin="); + uart_print_hex((uint64_t) &_bss_begin, 64); + newline(); + uart_print("&_bss_end="); + uart_print_hex((uint64_t) &_bss_end, 64); + newline(); + uart_print("&_heap_begin="); + uart_print_hex((uint64_t) &_heap_begin, 64); + newline(); + uart_print("&_heap_end="); + uart_print_hex((uint64_t) &_heap_end, 64); + newline(); +} + +void allocator_test(){ + void *test1 = simple_malloc(1); + if(test1 == NULL){ + uart_print("Error: Get NULL Pointer!"); + newline(); + return; + } + void *test2 = simple_malloc(16); + if(test2 == NULL){ + uart_print("Error: Get NULL Pointer!"); + newline(); + return; + } + uart_print("Test Simple Allocator 1: "); + uart_print_hex((uint64_t)test1, 64); + newline(); + + uart_print("Test Simple Allocator 2: "); + uart_print_hex((uint64_t)test2, 64); + newline(); +} + +void devicetree_check(){ + uart_print("Devicetree address: "); + uart_print_hex((uint64_t)_devicetree_begin, 64); + newline(); +} + +void spsr_el1_check(){ + uint64_t spsr_el1 = 0; + asm("mrs %0, spsr_el1":"=r"(spsr_el1)); + uart_print("spsr_el1: "); + uart_print_hex(spsr_el1, 32); + newline(); +} + +void boottimer(){ + uint32_t cntfrq_el0; + uint64_t cntpct_el0; + asm("mrs %0, cntfrq_el0":"=r"(cntfrq_el0)); + asm("mrs %0, cntpct_el0":"=r"(cntpct_el0)); + uart_print("Seconds after booting: "); + uart_print_hex(cntpct_el0 / cntfrq_el0, 64); + newline(); + add_timer(8, &boottimer, 0); +} diff --git a/lab3/src/kernel/linker.ld b/lab3/src/kernel/linker.ld new file mode 100644 index 000000000..9b40b95af --- /dev/null +++ b/lab3/src/kernel/linker.ld @@ -0,0 +1,42 @@ +ENTRY(_start) +MEMORY +{ + CODE (rx) : ORIGIN = 0x80000, LENGTH = 128K + ROM (r) : ORIGIN = 0xa0000, LENGTH = 128K + RAM (rw) : ORIGIN = 0xc0000, LENGTH = 5M + USER (rwx) : ORIGIN = 0x680000, LENGTH = 5M +} +SECTIONS +{ + .text : + { + *(.text.start) + *(.text) + } >CODE + .rodata : + { + _rodata_begin = .; + *(.rodata) + _rodata_end = .; + } >ROM + .data : + { + . = ALIGN(0x8); + _data_begin = .; + *(.data) + . = ALIGN(0x8); + _data_end = .; + } >RAM + .bss : { + . = ALIGN(0x8); + _bss_begin = .; + *(.bss .bss.*) + . = ALIGN(0x8); + _bss_end = .; + } >RAM + _heap_begin = ORIGIN(RAM) + 1M; + _heap_end = ORIGIN(RAM) + 4M; + _stack_top = ORIGIN(RAM) + LENGTH(RAM); + _user_begin = ORIGIN(USER); + _user_end = ORIGIN(USER) + LENGTH(USER) - 8; +} diff --git a/lab3/src/kernel/start.s b/lab3/src/kernel/start.s new file mode 100644 index 000000000..e69e63867 --- /dev/null +++ b/lab3/src/kernel/start.s @@ -0,0 +1,25 @@ +.section ".text.start" +.extern _stack_top +.extern _devicetree_begin +.extern _init +.global _start +_start: + adr x1, _devicetree_begin + str x0, [x1] + adrp x0, _stack_top + //ldr x0, =_stack_top + mov sp, x0 + bl from_el2_to_el1 + adrp x0, _stack_top + mov sp, x0 + bl _init +from_el2_to_el1: + mov x0, (1 << 31) // EL1 uses aarch64 + msr hcr_el2, x0 + mov x0, 0x3c5 // EL1h (SPSel = 1) with interrupt disabled + msr spsr_el2, x0 + msr elr_el2, lr + eret // return to EL1 +_hang: + wfe + b _hang diff --git a/lab3/src/lib/allocator.c b/lab3/src/lib/allocator.c new file mode 100644 index 000000000..a5621cd21 --- /dev/null +++ b/lab3/src/lib/allocator.c @@ -0,0 +1,26 @@ +#include + +//#include + +extern uint32_t _heap_begin; +extern uint32_t _heap_end; + +void *mem_chunk_begin; +void *mem_chunk_end; + +int check; + +void *simple_malloc(size_t size){ + if(check != 1){ + check = 1; + mem_chunk_begin = (void *) &_heap_begin; + mem_chunk_end = (void *) &_heap_end; + } + size = (((size - 1) >> 4) + 1) << 4; + if((uint64_t) mem_chunk_begin + size >= (uint64_t) mem_chunk_end){ + return NULL; + } + void *chunk = mem_chunk_begin; + mem_chunk_begin = (void *)((uint64_t) mem_chunk_begin + size); + return chunk; +} \ No newline at end of file diff --git a/lab3/src/lib/command.c b/lab3/src/lib/command.c new file mode 100644 index 000000000..2abf17417 --- /dev/null +++ b/lab3/src/lib/command.c @@ -0,0 +1,129 @@ +#include +// C +#include +#include +// tool +#include +#include +// lab1 +#include +#include +#include +// lab2 +#include +#include +#include +// lab3 +#include +#include +#include + +extern uint32_t _user_begin; +extern uint32_t _user_end; + +void help(){ + uart_print("help\t : print this help menu"); + newline(); + uart_print("hello\t : print Hello World!"); + newline(); + uart_print("reboot\t : reboot the device"); + newline(); + uart_print("ls\t : list directory contents"); + newline(); + uart_print("cat\t : concatenate files and print on the standard output"); + newline(); + uart_print("exec\t : execute a file"); + newline(); + uart_print("setTimeout\t: set a timer"); + newline(); +} + +void hello(){ + uart_print("Hello World!"); + newline(); +} + +void reboot(){ + uart_print("Reboot system now!"); + newline(); + reset(1<<16); +} + +void ls(){ + cpio_file* file_ptr = cpio_parse(); + for(cpio_file* cur = file_ptr; cur != NULL; cur = cur->next){ + uart_print(cur->name); + newline(); + } +} + +void cat(char *filename){ + cpio_file* file_ptr = cpio_parse(); + if(file_ptr == NULL){ + uart_print("Error: cpio"); + return; + } + int isfound = 0; + for(cpio_file* cur = file_ptr; cur != NULL; cur = cur->next){ + if(strcmp(filename, cur->name) == 0){ + uart_write(cur->content, cur->filesize); + isfound = 1; + break; + } + } + if(!isfound){ + uart_print("Not Found!"); + newline(); + } +} + +void exec(char *filename){ + cpio_file* file_ptr = cpio_parse(); + if(file_ptr == NULL){ + uart_print("Error: cpio"); + return; + } + int isfound = 0; + for(cpio_file* cur = file_ptr; cur != NULL; cur = cur->next){ + if(strcmp(filename, cur->name) == 0){ + isfound = 1; + memcpy(&_user_begin, cur->content, cur->filesize); + coretimer_el0_enable(); + /* + uart_print("&_user_begin="); + uart_print_hex((uint64_t) &_user_begin, 64); + newline(); + uart_print("&_user_end="); + uart_print_hex((uint64_t) &_user_end, 64); + newline(); + */ + asm("msr spsr_el1, %0"::"r"((uint64_t)0x0)); // 0x0 enable all interrupt + asm("msr elr_el1, %0"::"r"(&_user_begin)); + asm("msr sp_el0, %0"::"r"(&_user_end)); + asm("eret"); + break; + } + } + if(!isfound){ + uart_print("Not Found!"); + newline(); + } +} + +void timeout(void *arg){ + uart_print("Timeout: "); + uart_print((char *)arg); + newline(); +} + +void setTimeout(){ + int time; + char *msg = (char *)simple_malloc(0x20); + char time_inp[0x20]; + uart_print("Time (secs): "); + uart_readline(time_inp); + time = atoi(time_inp); + uart_print("Msg: "); + uart_readline(msg); + add_timer(time, &timeout, (void *)msg); +} \ No newline at end of file diff --git a/lab3/src/lib/coretimer.c b/lab3/src/lib/coretimer.c new file mode 100644 index 000000000..7b773c766 --- /dev/null +++ b/lab3/src/lib/coretimer.c @@ -0,0 +1,103 @@ +#include + +#include + +#include +#include +#include +#include + +TIMER* timer_queue; + +void coretimer_el0_enable(){ + asm("msr cntp_ctl_el0, %0"::"r"((uint64_t)1)); +} + +void timer_queue_push(TIMER* new_timer){ + interrupt_disable(); + if(!timer_queue){ + timer_queue = new_timer; + goto ret; + } + TIMER* head = timer_queue; + TIMER* prev = 0; + if(head->time > new_timer->time){ + new_timer->next = head; + timer_queue = new_timer; + goto ret; + } + while(head->next){ + prev = head; + head = head->next; + if(head->time > new_timer->time){ + new_timer->next = head; + prev->next = new_timer; + goto ret; + } + } + head->next = new_timer; +ret: + interrupt_enable(); +} + +TIMER* timer_queue_pop(){ + if(!timer_queue) return 0; + interrupt_disable(); + TIMER* timer = timer_queue; + timer_queue = timer_queue->next; + interrupt_enable(); + return timer; +} + +TIMER* timer_queue_top(){ + if(!timer_queue) return 0; + return timer_queue; +} + +void timer_sched(){ + TIMER* timer = timer_queue_top(); + if(!timer) return ; + uint64_t cntpct_el0; + asm("mrs %0, cntpct_el0":"=r"(cntpct_el0)); + asm("msr cntp_tval_el0, %0"::"r"((uint32_t)timer->time-cntpct_el0)); + memory_write(CORE0_TIMER_IRQ_CTRL, 2); +} + +void add_timer(uint64_t time_wait, void (*func)(void *), void *arg){ + uint32_t cntfrq_el0; + uint64_t cntpct_el0; + asm("mrs %0, cntfrq_el0":"=r"(cntfrq_el0)); + asm("mrs %0, cntpct_el0":"=r"(cntpct_el0)); + + uint64_t time = cntpct_el0 + time_wait * cntfrq_el0; + + TIMER* new_timer = (TIMER*)simple_malloc(sizeof(TIMER)); + new_timer->time = time; + new_timer->func = func; + new_timer->arg = arg; + new_timer->next = 0; + + timer_queue_push(new_timer); + timer_sched(); +} + +void coretimer_el0_handler(){ + memory_write(CORE0_TIMER_IRQ_CTRL, 0); + uint64_t cntpct_el0; + asm("mrs %0, cntpct_el0":"=r"(cntpct_el0)); + + TIMER* timer; + while(1){ + interrupt_disable(); + timer = timer_queue_top(); + if(!timer){ + interrupt_enable(); + break; + } + if(timer->time > cntpct_el0) break; + timer_queue_pop(); + interrupt_enable(); + timer->func(timer->arg); + } + timer_sched(); +} \ No newline at end of file diff --git a/lab3/src/lib/devicetree.c b/lab3/src/lib/devicetree.c new file mode 100644 index 000000000..4feaedac8 --- /dev/null +++ b/lab3/src/lib/devicetree.c @@ -0,0 +1,88 @@ +#include + +#include +#include +#include +#include + +void *_devicetree_begin = (void *) 0xffffffff; + +void fdt_traverse(initramfs_callback f, void *data){ + char *fdt = (char *) _devicetree_begin; + if((uint64_t)fdt == 0xffffffff) return; + + fdt_header *header = (fdt_header *) fdt; + + char *fdt_struct_begin = fdt + ntohl(header->off_dt_struct); + char *fdt_string_begin = fdt + ntohl(header->off_dt_strings); + char *fdt_struct_end = fdt_struct_begin + ntohl(header->size_dt_struct); + + int isend = 0; + char *node_name; + char *prop_name; + for(char *node = fdt_nextnode(fdt_struct_begin-1, fdt_struct_end); node && !isend; node = fdt_nextnode(node, fdt_struct_end)){ + f(node, node + 4, data); + } +} + +char *fdt_nextnode(char *fdt_addr, char *fdt_struct_end){ + fdt_addr = (char *) align((uint64_t) fdt_addr); + int isend = 0; + while((uint64_t)fdt_addr < (uint64_t)fdt_struct_end && !isend) { + switch (ntohl(*(uint32_t*)fdt_addr)){ + case FDT_BEGIN_NODE: { + return fdt_addr; + }case FDT_PROP: { + fdt_addr += (uint64_t)ntohl(*(uint32_t*)(fdt_addr + 4)) + 8; + break; + }case FDT_END: { + isend = 1; + break; + }case FDT_END_NODE: { + }case FDT_NOP: { + break; + } + } + fdt_addr = (char *) align((uint64_t) fdt_addr); + } + return 0; +} + +fdt_prop *fdt_nextprop(char *fdt_addr, char **nexttok){ + char *fdt = (char *)_devicetree_begin; + if((uint64_t)fdt == 0xffffffff) return 0; + + fdt_header *header = (fdt_header *) fdt; + + char *fdt_string_begin = fdt + ntohl(header->off_dt_strings); + + fdt_addr = (char *) align((uint64_t) fdt_addr - 1); + int isend = 0; + fdt_prop *prop; + while(!isend) { + switch (ntohl(*(uint32_t*)fdt_addr)){ + case FDT_PROP: + prop = (fdt_prop*) simple_malloc(sizeof(fdt_prop)); + if(prop == NULL){ + uart_print("Error: fdt_nuxtprop"); + newline(); + return NULL; + } + prop->len = ntohl(*(uint32_t*)(fdt_addr+4)); + prop->name = fdt_string_begin + ntohl(*(uint32_t *) (fdt_addr + 8)); + prop->value = fdt_addr + 12; + *nexttok = (void *) fdt_addr + 8 + ntohl(*(uint32_t*) (fdt_addr + 4)); + return prop; + case FDT_END: + case FDT_BEGIN_NODE: + case FDT_END_NODE: + isend = 1; + break; + case FDT_NOP: + break; + } + fdt_addr = (char *) align((uint64_t) fdt_addr); + } + return 0; +} + diff --git a/lab3/src/lib/exception.c b/lab3/src/lib/exception.c new file mode 100644 index 000000000..f611b1552 --- /dev/null +++ b/lab3/src/lib/exception.c @@ -0,0 +1,33 @@ +#include + +#include +#include + +#include + +void exception_init(){ + asm("msr vbar_el1, %0"::"r"((void*)&exception_vector_table)); +} + +void exception_handler(){ + uint64_t spsr_el1; + uint64_t elr_el1; + uint64_t esr_el1; + uint64_t x0; + asm("mov %0, x0":"=r"(x0)); + asm("mrs %0, spsr_el1":"=r"(spsr_el1)); + asm("mrs %0, elr_el1":"=r"(elr_el1)); + asm("mrs %0, esr_el1":"=r"(esr_el1)); + uart_print("x0: "); + uart_print_hex(x0, 64); + newline(); + uart_print("spsr_el1: "); + uart_print_hex(spsr_el1, 64); + newline(); + uart_print("elr_el1: "); + uart_print_hex(elr_el1, 64); + newline(); + uart_print("esr_el1: "); + uart_print_hex(esr_el1, 64); + newline(); +} \ No newline at end of file diff --git a/lab3/src/lib/exception_table.s b/lab3/src/lib/exception_table.s new file mode 100644 index 000000000..aae7e1d54 --- /dev/null +++ b/lab3/src/lib/exception_table.s @@ -0,0 +1,101 @@ +.section ".text.exception" +.extern "exception_handler" + +// save general registers to stack +.macro save_all + sub sp, sp, 32 * 8 + stp x0, x1, [sp ,16 * 0] + stp x2, x3, [sp ,16 * 1] + stp x4, x5, [sp ,16 * 2] + stp x6, x7, [sp ,16 * 3] + stp x8, x9, [sp ,16 * 4] + stp x10, x11, [sp ,16 * 5] + stp x12, x13, [sp ,16 * 6] + stp x14, x15, [sp ,16 * 7] + stp x16, x17, [sp ,16 * 8] + stp x18, x19, [sp ,16 * 9] + stp x20, x21, [sp ,16 * 10] + stp x22, x23, [sp ,16 * 11] + stp x24, x25, [sp ,16 * 12] + stp x26, x27, [sp ,16 * 13] + stp x28, x29, [sp ,16 * 14] + str x30, [sp, 16 * 15] +.endm + +// load general registers from stack +.macro load_all + ldp x0, x1, [sp ,16 * 0] + ldp x2, x3, [sp ,16 * 1] + ldp x4, x5, [sp ,16 * 2] + ldp x6, x7, [sp ,16 * 3] + ldp x8, x9, [sp ,16 * 4] + ldp x10, x11, [sp ,16 * 5] + ldp x12, x13, [sp ,16 * 6] + ldp x14, x15, [sp ,16 * 7] + ldp x16, x17, [sp ,16 * 8] + ldp x18, x19, [sp ,16 * 9] + ldp x20, x21, [sp ,16 * 10] + ldp x22, x23, [sp ,16 * 11] + ldp x24, x25, [sp ,16 * 12] + ldp x26, x27, [sp ,16 * 13] + ldp x28, x29, [sp ,16 * 14] + ldr x30, [sp, 16 * 15] + add sp, sp, 32 * 8 +.endm + + +_exception_handler: + save_all + bl exception_handler + load_all + eret +_irq_handler: + save_all + bl interrupt_irq_handler + load_all + eret +_not_implement: + save_all + bl not_implemented_interrupt + load_all + eret + + +.align 11 // vector table should be aligned to 0x800 +.global exception_vector_table +exception_vector_table: + b _not_implement // branch to a handler function. + .align 7 // entry size is 0x80, .align will pad 0 + b _not_implement + .align 7 + b _not_implement + .align 7 + b _not_implement + .align 7 + + b _exception_handler + .align 7 + b _irq_handler + .align 7 + b _not_implement + .align 7 + b _not_implement + .align 7 + + b _exception_handler + .align 7 + b _irq_handler + .align 7 + b _not_implement + .align 7 + b _not_implement + .align 7 + + b _not_implement + .align 7 + b _not_implement + .align 7 + b _not_implement + .align 7 + b _not_implement + .align 7 diff --git a/lab3/src/lib/include/allocator.h b/lab3/src/lib/include/allocator.h new file mode 100644 index 000000000..8a0c3092c --- /dev/null +++ b/lab3/src/lib/include/allocator.h @@ -0,0 +1,6 @@ +#ifndef __ALLOCATOR__ +#define __ALLOCATOR__ +#include +#include +void *simple_malloc(size_t size); +#endif \ No newline at end of file diff --git a/lab3/src/lib/include/command.h b/lab3/src/lib/include/command.h new file mode 100644 index 000000000..ba8170349 --- /dev/null +++ b/lab3/src/lib/include/command.h @@ -0,0 +1,10 @@ +#ifndef __COMMAND__ +#define __COMMAND__ +void help(); +void hello(); +void reboot(); +void ls(); +void cat(char *filename); +void exec(char *filename); +void setTimeout(); +#endif \ No newline at end of file diff --git a/lab3/src/lib/include/coretimer.h b/lab3/src/lib/include/coretimer.h new file mode 100644 index 000000000..a431e9b76 --- /dev/null +++ b/lab3/src/lib/include/coretimer.h @@ -0,0 +1,20 @@ +#ifndef __CORETIMER__ +#define __CORETIMER__ + +#include + +#define CORE0_TIMER_IRQ_CTRL 0x40000040 + +void coretimer_el0_enable(); +void coretimer_el0_handler(); +void coretimer_el0_set(uint32_t t); + +typedef struct TIMER_{ + uint64_t time; + void (*func)(void *); + void *arg; + struct TIMER_* next; +} TIMER; + +void add_timer(uint64_t time_wait, void (*func)(void *), void *arg); +#endif \ No newline at end of file diff --git a/lab3/src/lib/include/devicetree.h b/lab3/src/lib/include/devicetree.h new file mode 100644 index 000000000..b01dde5e0 --- /dev/null +++ b/lab3/src/lib/include/devicetree.h @@ -0,0 +1,39 @@ + +#ifndef __DEVICETREE__ +#define __DEVICETREE__ +#include +#include + +#define FDT_BEGIN_NODE 0x00000001 +#define FDT_END_NODE 0x00000002 +#define FDT_PROP 0x00000003 +#define FDT_NOP 0x00000004 +#define FDT_END 0x00000009 + +extern void *_devicetree_begin; + +typedef struct _fdt_header { // 5.2 big-endian + uint32_t magic; // 0xd00dfeed + uint32_t totalsize; // + uint32_t off_dt_struct; // offset in bytes of the devicetree struct + uint32_t off_dt_strings; // offset in bytes of the strings block + uint32_t off_mem_rsvmap; + uint32_t version; + uint32_t last_comp_version; + uint32_t boot_cpuid_phys; + uint32_t size_dt_strings; // the length in bytes of the strings block + uint32_t size_dt_struct; // the length in bytes of the structure block +} fdt_header; + +typedef struct _fdt_prop{ // 5.4 FDT_PROP (0x00000003) + uint32_t len; + //uint32_t nameoff; + const char *name; + const char *value; +} fdt_prop; + +typedef int (*initramfs_callback)(char* node, const char *name, void *data); +void fdt_traverse(initramfs_callback f, void *data); +char *fdt_nextnode(char *fdt_addr, char *fdt_struct_end); +fdt_prop *fdt_nextprop(char *fdt_addr, char **nexttok); +#endif \ No newline at end of file diff --git a/lab3/src/lib/include/exception.h b/lab3/src/lib/include/exception.h new file mode 100644 index 000000000..a6464c967 --- /dev/null +++ b/lab3/src/lib/include/exception.h @@ -0,0 +1,9 @@ +#ifndef __EXCEPTION__ +#define __EXCEPTION__ +#include +#include + +extern uint64_t exception_vector_table; + +void exception_init(); +#endif \ No newline at end of file diff --git a/lab3/src/lib/include/interrupt.h b/lab3/src/lib/include/interrupt.h new file mode 100644 index 000000000..bb6f6cbbf --- /dev/null +++ b/lab3/src/lib/include/interrupt.h @@ -0,0 +1,18 @@ +#ifndef __INTERRUPT__ +#define __INTERRUPT__ + +#include +#include + +#define MMIO_BASE 0x3f000000 +#define ARMINTERRUPT_BASE MMIO_BASE + 0xB000 +#define ARMINT_IRQ_PEND_BASE_REG ARMINTERRUPT_BASE + 0x200 +#define ARMINT_IRQ_PEND1_REG ARMINTERRUPT_BASE + 0x204 +#define ARMINT_IRQ_PEND2_REG ARMINTERRUPT_BASE + 0x208 +#define ARMINT_En_IRQs1_REG ARMINTERRUPT_BASE + 0x210 +#define CORE0_INTERRUPT_SOURCE 0x40000060 + +void interrupt_enable(); +void interrupt_disable(); +void interrupt_irq_handler(); +#endif \ No newline at end of file diff --git a/lab3/src/lib/include/mailbox.h b/lab3/src/lib/include/mailbox.h new file mode 100644 index 000000000..a249d01af --- /dev/null +++ b/lab3/src/lib/include/mailbox.h @@ -0,0 +1,25 @@ +#ifndef __MAILBOX__ +#define __MAILBOX__ +#include +#define MMIO_BASE 0x3f000000 +#define MAILBOX_BASE MMIO_BASE + 0xb880 + +#define MAILBOX_READ MAILBOX_BASE +#define MAILBOX_STATUS MAILBOX_BASE + 0x18 +#define MAILBOX_WRITE MAILBOX_BASE + 0x20 + +#define MAILBOX_EMPTY 0x40000000 +#define MAILBOX_FULL 0x80000000 + +#define GET_BOARD_REVISION 0x00010002 +#define GET_ARM_MEMORY 0x00010005 +#define REQUEST_CODE 0x00000000 +#define REQUEST_SUCCEED 0x80000000 +#define REQUEST_FAILED 0x80000001 +#define TAG_REQUEST_CODE 0x00000000 +#define END_TAG 0x00000000 + +void mailbox_call(uint32_t* mailbox); +void get_board_revision(uint32_t*revision); +void get_ARM_memory_base_address_and_size(uint32_t*addr_base, uint32_t*size); +#endif \ No newline at end of file diff --git a/lab3/src/lib/include/ramdisk.h b/lab3/src/lib/include/ramdisk.h new file mode 100644 index 000000000..56fc76f1c --- /dev/null +++ b/lab3/src/lib/include/ramdisk.h @@ -0,0 +1,46 @@ +#ifndef __RAMDISK__ +#define __RAMDISK__ +#include +#include + +struct cpio_newc_header { + char c_magic[6]; // 070702 + char c_ino[8]; // inode numbers + char c_mode[8]; // mode + char c_uid[8]; // uid + char c_gid[8]; // gid + char c_nlink[8]; // link number + char c_mtime[8]; + char c_filesize[8]; // content size + char c_devmajor[8]; + char c_devminor[8]; + char c_rdevmajor[8]; + char c_rdevminor[8]; + char c_namesize[8]; // file name length + char c_check[8]; // sum of all bytes +}; + +typedef struct _cpio_file{ + char *header; + uint32_t ino; + uint32_t mode; + uint32_t uid; + uint32_t gid; + uint32_t nlink; + uint32_t mtime; + uint32_t filesize; + uint32_t devmajor; + uint32_t devminor; + uint32_t rdevmajor; + uint32_t rdevminor; + uint32_t namesize; + uint32_t check; + char *name; + char *content; + struct _cpio_file *next; +} cpio_file; + +int ramdisk_get_addr(); +cpio_file* cpio_parse(); + +#endif \ No newline at end of file diff --git a/lab3/src/lib/include/reboot.h b/lab3/src/lib/include/reboot.h new file mode 100644 index 000000000..dbe0d77da --- /dev/null +++ b/lab3/src/lib/include/reboot.h @@ -0,0 +1,9 @@ +#ifndef __REBOOT__ +#define __REBOOT__ +#define PM_PASSWORD 0x5a000000 +#define PM_RSTC 0x3F10001c +#define PM_WDOG 0x3F100024 +void set(long addr, unsigned int value); +void reset(int tick); +void cancel_reset(); +#endif \ No newline at end of file diff --git a/lab3/src/lib/include/ringbuffer.h b/lab3/src/lib/include/ringbuffer.h new file mode 100644 index 000000000..f2d11bfd6 --- /dev/null +++ b/lab3/src/lib/include/ringbuffer.h @@ -0,0 +1,23 @@ +#ifndef __RINGBUFFER__ +#define __RINGBUFFER__ + +#include +#include + +typedef struct{ + uint32_t flags; + char *buf; + uint32_t lbound,rbound; + size_t size, len; +} RingBuffer; + +#define RingBuffer_flag_Empty 0b1 +#define RingBuffer_flag_Full 0b10 +#define RingBuffer_Empty(buf) (buf->flags&RingBuffer_flag_Empty) +#define RingBuffer_Full(buf) (buf->flags&RingBuffer_flag_Full) + +RingBuffer *RingBuffer_new(size_t bufsize); +size_t RingBuffer_writeb(RingBuffer *rbuf, char b); +size_t RingBuffer_readb(RingBuffer *rbuf, char* b); + +#endif \ No newline at end of file diff --git a/lab3/src/lib/include/shell.h b/lab3/src/lib/include/shell.h new file mode 100644 index 000000000..f0f75eb16 --- /dev/null +++ b/lab3/src/lib/include/shell.h @@ -0,0 +1,5 @@ +#ifndef __SHELL__ +#define __SHELL__ +#define BUF_SIZE 256 +void shell(); +#endif \ No newline at end of file diff --git a/lab3/src/lib/include/string.h b/lab3/src/lib/include/string.h new file mode 100644 index 000000000..e7c0a07a5 --- /dev/null +++ b/lab3/src/lib/include/string.h @@ -0,0 +1,10 @@ +#ifndef __STRING__ +#define __STRING__ +#include +#include +int atoi(const char* str); +int strcmp(const char* x, const char* y); +int strncmp(const char*x, const char*y, int len); +size_t strlen(const char *str); +void *memcpy(void *dst, const void *src, size_t n); +#endif \ No newline at end of file diff --git a/lab3/src/lib/include/uart.h b/lab3/src/lib/include/uart.h new file mode 100644 index 000000000..2d94739f7 --- /dev/null +++ b/lab3/src/lib/include/uart.h @@ -0,0 +1,36 @@ +#ifndef __UART__ +#define __UART__ +#include +#include + +#define BASE_ADDR 0x3f000000 +#define AUX_ENABLES BASE_ADDR + 0x215004 +#define AUX_MU_CNTL_REG BASE_ADDR + 0x215060 +#define AUX_MU_IER_REG BASE_ADDR + 0x215044 +#define AUX_MU_LCR_REG BASE_ADDR + 0x21504c +#define AUX_MU_MCR_REG BASE_ADDR + 0x215050 +#define AUX_MU_BAUD_REG BASE_ADDR + 0x215068 +#define AUX_MU_IIR_REG BASE_ADDR + 0x215048 +#define AUX_MU_LSR_REG BASE_ADDR + 0x215054 +#define AUX_MU_IO_REG BASE_ADDR + 0x215040 +#define GPFSEL0 BASE_ADDR + 0x200000 +#define GPFSEL1 BASE_ADDR + 0x200004 +#define GPPUD BASE_ADDR + 0x200094 +#define GPPUDCLK0 BASE_ADDR + 0x200098 +#define GPPUDCLK1 BASE_ADDR + 0x20009c + +void uart_init(); + +size_t uart_write_1c(char*buf); +size_t uart_write(char* buf, size_t len); +size_t uart_readline(char* buf); +void uart_print(char* buf); +void uart_print_hex(uint64_t num, int len); +void newline(); + +void uart_interrupt_handler(); +size_t uart_read_sync(char* buf, size_t len); +size_t uart_read_async(char* buf, size_t len); + +#endif +#define uart_read uart_read_async \ No newline at end of file diff --git a/lab3/src/lib/include/utils.h b/lab3/src/lib/include/utils.h new file mode 100644 index 000000000..ba9128b99 --- /dev/null +++ b/lab3/src/lib/include/utils.h @@ -0,0 +1,16 @@ +#ifndef __UTILS__ +#define __UTILS__ +#include +#include +#define memory_read(addr) *(uint32_t *)(addr) +#define memory_write(addr,val) *(uint32_t *)(addr) = (uint32_t)(val) +#define align(tmp) (void*)((tmp >> 2) + 1 << 2) +void wait_cycles(uint32_t times); +uint32_t hex2u32_8(char *buf); +uint16_t ntohs(uint16_t tmp); +uint32_t ntohl(uint32_t tmp); +uint64_t ntohll(uint64_t tmp); +uint16_t htons(uint16_t tmp); +uint32_t htonl(uint32_t tmp); +uint64_t htonll(uint64_t tmp); +#endif \ No newline at end of file diff --git a/lab3/src/lib/interrupt.c b/lab3/src/lib/interrupt.c new file mode 100644 index 000000000..1fa201fdd --- /dev/null +++ b/lab3/src/lib/interrupt.c @@ -0,0 +1,40 @@ +#include + +#include +#include + +#include +#include +#include + +uint32_t interrupt_depth; + +void interrupt_enable(){ + if(interrupt_depth==0) asm("msr DAIFClr, 0xf"); + interrupt_depth++; +} + +void interrupt_disable(){ + interrupt_depth--; + if(interrupt_depth == 0) asm("msr DAIFSet, 0xf"); +} + +void interrupt_irq_handler(){ + uint32_t irq_pend_base_reg = memory_read(ARMINT_IRQ_PEND_BASE_REG); + uint32_t irq_pend1_reg = memory_read(ARMINT_IRQ_PEND1_REG); + uint32_t irq_pend2_reg = memory_read(ARMINT_IRQ_PEND2_REG); + uint32_t core0_int_src = memory_read(CORE0_INTERRUPT_SOURCE); + uint32_t aux_mu_iir_reg = memory_read(AUX_MU_IIR_REG); + + if(core0_int_src & 0b10){ + coretimer_el0_handler(); + } + if(aux_mu_iir_reg&0b100){ + uart_interrupt_handler(); + } +} + +void not_implemented_interrupt(){ + uart_print("Not implemented!!!"); + newline(); +} diff --git a/lab3/src/lib/mailbox.c b/lab3/src/lib/mailbox.c new file mode 100644 index 000000000..c7b3fad2f --- /dev/null +++ b/lab3/src/lib/mailbox.c @@ -0,0 +1,56 @@ +#include + +#include + +#include +#include + +void mailbox_call(uint32_t* mailbox){ + uint32_t mailbox_addr = (uint32_t)((uint64_t)mailbox & 0xfffffff0); + mailbox_addr |= 8; + while((memory_read(MAILBOX_STATUS) & MAILBOX_FULL) != 0); + memory_write(MAILBOX_WRITE, mailbox_addr); + while(1){ + while((memory_read(MAILBOX_STATUS) & MAILBOX_EMPTY) != 0); + uint32_t data = memory_read(MAILBOX_READ); + if((data & 0xf) == 8) break; + } +} + +void get_board_revision(uint32_t*revision){ + unsigned int mailbox[7]; + mailbox[0] = 7 * 4; // buffer size in bytes + mailbox[1] = REQUEST_CODE; + // tags begin + mailbox[2] = GET_BOARD_REVISION; // tag identifier + mailbox[3] = 4; // maximum of request and response value buffer's length. + mailbox[4] = TAG_REQUEST_CODE; + mailbox[5] = 0; // value buffer + // tags end + mailbox[6] = END_TAG; + + mailbox_call(mailbox); // message passing procedure call, you should implement it following the 6 steps provided above. + + //printf("0x%x\n", mailbox[5]); // it should be 0xa020d3 for rpi3 b+ + *revision = mailbox[5]; +} + +void get_ARM_memory_base_address_and_size(uint32_t*addr_base, uint32_t*size){ + unsigned int mailbox[8]; + mailbox[0] = 8 * 4; // buffer size in bytes + mailbox[1] = REQUEST_CODE; + // tags begin + mailbox[2] = GET_ARM_MEMORY; // tag identifier + mailbox[3] = 8; // maximum of request and response value buffer's length. + mailbox[4] = TAG_REQUEST_CODE; + mailbox[5] = 0; // value buffer + mailbox[6] = 0; // value buffer + // tags end + mailbox[7] = END_TAG; + + mailbox_call(mailbox); // message passing procedure call, you should implement it following the 6 steps provided above. + + //printf("0x%x\n", mailbox[5]); // it should be 0xa020d3 for rpi3 b+ + *addr_base = mailbox[5]; + *size = mailbox[6]; +} \ No newline at end of file diff --git a/lab3/src/lib/ramdisk.c b/lab3/src/lib/ramdisk.c new file mode 100644 index 000000000..15c9da707 --- /dev/null +++ b/lab3/src/lib/ramdisk.c @@ -0,0 +1,81 @@ +#include + +#include + +#include +#include +#include +#include + +int isinit; +void *_randisk_begin; + +typedef struct{ + int found; + char *initrd_start; +} ramdisk_data; + +int ramdisk_fdt_callback(char* node, const char *name, void *data){ + if(strcmp(name, "chosen")) return 0; + ramdisk_data* _data = (ramdisk_data*) data; + fdt_prop *prop; + while(prop = fdt_nextprop(node + 1, &node)){ + if(!strcmp(prop->name,"linux,initrd-start")){ + _data->initrd_start = (char *)(uint64_t)ntohl(*(uint32_t*)prop->value); + } + } + _data->found = 1; + return 1; +} + +int ramdisk_get_addr(){ + ramdisk_data data; + data.initrd_start = 0; + data.found = 0; + fdt_traverse(ramdisk_fdt_callback, (void *)&data); + if(data.found){ + /* + uart_print("/chosen linux,initrd-start: "); + uart_print_hex((uint64_t)data.initrd_start, 64); + newline(); + */ + _randisk_begin = data.initrd_start; + return 0; + } + return -1; +} + +cpio_file* cpio_parse(){ + if(isinit != 1){ + int initres = ramdisk_get_addr(); + if(!initres) isinit = 1; + else return 0; + } + char *ptr = (char *) _randisk_begin; + char *name = ptr + sizeof(struct cpio_newc_header); + struct cpio_newc_header* cur_cpio_header; + cpio_file *head = NULL; + cpio_file *prev = NULL; + cpio_file *cur = NULL; + while(1){ + cur_cpio_header = (struct cpio_newc_header*) ptr; + name = ptr + sizeof(struct cpio_newc_header); + if(strcmp("TRAILER!!!", name) == 0) break; + cur = (cpio_file*) simple_malloc (sizeof(cpio_file)); + if(cur == NULL){ + uart_print("Error: Get NULL Pointer!"); + return NULL; + } + if(head == NULL) head = cur; + cur->header = ptr; + cur->namesize = hex2u32_8(cur_cpio_header->c_namesize); + cur->filesize = hex2u32_8(cur_cpio_header->c_filesize); + cur->name = name; + cur->content = (char*) align((uint64_t) name + cur->namesize - 1); + cur->next = 0; + ptr = (char *) align((uint64_t) cur->content + cur->filesize - 1); + if(prev != NULL) prev->next = cur; + prev = cur; + } + return head; +} \ No newline at end of file diff --git a/lab3/src/lib/reboot.c b/lab3/src/lib/reboot.c new file mode 100644 index 000000000..cd53ecacb --- /dev/null +++ b/lab3/src/lib/reboot.c @@ -0,0 +1,20 @@ +#include + +#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 cancel_reset() { + set(PM_RSTC, PM_PASSWORD | 0); // full reset + set(PM_WDOG, PM_PASSWORD | 0); // number of watchdog tick +} \ No newline at end of file diff --git a/lab3/src/lib/ringbuffer.c b/lab3/src/lib/ringbuffer.c new file mode 100644 index 000000000..6e28b0387 --- /dev/null +++ b/lab3/src/lib/ringbuffer.c @@ -0,0 +1,40 @@ +#include + +#include +#include + +RingBuffer *RingBuffer_new(size_t bufsize){ + RingBuffer* newbuf = (RingBuffer*)simple_malloc(sizeof(RingBuffer)); + newbuf->flags = 0; + newbuf->flags |= RingBuffer_flag_Empty; + newbuf->buf = (char *)simple_malloc(bufsize); + newbuf->lbound = 0; + newbuf->rbound = 0; + newbuf->len = 0; + newbuf->size = bufsize; + return newbuf; +} + +size_t RingBuffer_writeb(RingBuffer *rbuf, char b){ + interrupt_disable(); + if(RingBuffer_Full(rbuf)) return 0; + rbuf->buf[rbuf->rbound++] = b; + rbuf->rbound %= rbuf->size; + rbuf->len++; + if(rbuf->len >= rbuf->size) rbuf->flags |= RingBuffer_flag_Full; + rbuf->flags &= ~RingBuffer_flag_Empty; + interrupt_enable(); + return 1; +} + +size_t RingBuffer_readb(RingBuffer *rbuf, char* b){ + interrupt_disable(); + if(RingBuffer_Empty(rbuf)) return 0; + *b = rbuf->buf[rbuf->lbound++]; + rbuf->lbound %= rbuf->size; + rbuf->len--; + if(rbuf->len <= 0) rbuf->flags |= RingBuffer_flag_Empty; + if(rbuf->len < rbuf->size)rbuf->flags &= ~RingBuffer_flag_Full; + interrupt_enable(); + return 1; +} \ No newline at end of file diff --git a/lab3/src/lib/shell.c b/lab3/src/lib/shell.c new file mode 100644 index 000000000..2cb2e9d0c --- /dev/null +++ b/lab3/src/lib/shell.c @@ -0,0 +1,35 @@ +#include + +#include +#include +#include + +void shell(){ + char buf[BUF_SIZE]; + while(1){ + uart_print("# "); + uart_readline(buf); + if(strncmp(buf, "help", 4) == 0){ + help(); + }else if(strncmp(buf, "hello", 5) == 0){ + hello(); + }else if(strncmp(buf, "reboot", 6) == 0){ + reboot(); + }else if(strncmp(buf, "ls", 2) == 0){ + ls(); + }else if(strncmp(buf, "cat", 2) == 0){ + uart_print("Filename: "); + uart_readline(buf); + cat(buf); + }else if(strncmp(buf, "exec", 4) == 0){ + exec(&buf[5]); + }else if(strncmp(buf, "setTimeout", 10) == 0){ + setTimeout(); + }else{ + uart_print("Unknown command: ["); + uart_print(buf); + uart_print("]."); + newline(); + } + } +} diff --git a/lab3/src/lib/string.c b/lab3/src/lib/string.c new file mode 100644 index 000000000..9dae9bb38 --- /dev/null +++ b/lab3/src/lib/string.c @@ -0,0 +1,59 @@ +#include + +#include +#include + +int atoi(const char* str){ + int num = 0; + int i = 0; + while(str[i]){ + num *= 10; + num += str[i] - '0'; + i++; + } + return num; +} + +int strcmp(const char* x, const char* y){ + int i = 0; + for(; x[i] && y[i]; i++){ + if(x[i] < y[i]) return -1; + else if(x[i] > y[i]) return 1; + } + if(x[i]) return 1; + else if(y[i]) return -1; + return 0; +} + +int strncmp(const char*x, const char*y, int len){ + int i = 0; + for(; x[i] && y[i] && i < len; i++){ + if(x[i] < y[i]) return -1; + else if(x[i] > y[i]) return 1; + } + if(i == len) return 0; + else if(x[i]) return 1; + else if(y[i]) return -1; + return 0; +} + +size_t strlen(const char *str){ + int i = 0; + while(*str){ + i++; + str++; + } + return i; +} + +void *memcpy(void *dst, const void *src, size_t n){ + size_t npage = n / sizeof(uint64_t); + size_t noff = n % sizeof(uint64_t); + for(int i=0;i + +#include +#include + +#include +#include +#include + +#define UART_BUF_LEN 0x200 +RingBuffer *uart_buffer; + +void uart_init(){ + //12-14, 15-17 + // get oringin val, reset gpio14-15, set alt5 0b010 + memory_write(GPFSEL1, (memory_read(GPFSEL1) & 0xfffc0fff) | (0b010010 << 12)); + //gpio page 101 1 ~ 4, 6 + memory_write(GPPUD, 0b00); + wait_cycles(150u); + memory_write(GPPUDCLK0, (1 << 14) | (1 << 15)); + wait_cycles(150u); + memory_write(GPPUDCLK0, 0u); + // Initialization 1 ~ 8 + memory_write(AUX_ENABLES, 0b001); + memory_write(AUX_MU_CNTL_REG, 0u); + + memory_write(AUX_MU_LCR_REG, 3u); + memory_write(AUX_MU_MCR_REG, 0u); + memory_write(AUX_MU_BAUD_REG, 270u); + memory_write(AUX_MU_IIR_REG, 6u); + memory_write(AUX_MU_CNTL_REG, 3u); + // interrupt + memory_write(AUX_MU_IER_REG, 0b01); + memory_write(ARMINT_En_IRQs1_REG, memory_read(ARMINT_En_IRQs1_REG) | (1<<29)); + uart_buffer = RingBuffer_new(UART_BUF_LEN); +} + +void uart_interrupt_handler(){ + interrupt_disable(); + while((memory_read(AUX_MU_LSR_REG) & 1) && !RingBuffer_Full(uart_buffer)){ + RingBuffer_writeb(uart_buffer, memory_read(AUX_MU_IO_REG)&0xff); + } + interrupt_enable(); +} + +size_t uart_read_sync(char* buf, size_t len){ + size_t recvlen = 0; + while(recvlen < len){ + while(!(memory_read(AUX_MU_LSR_REG) & 1)); + buf[recvlen++] = (char)(memory_read(AUX_MU_IO_REG) & 0xff); + } + return recvlen; +} + +size_t uart_read_async(char* buf, size_t len) +{ + size_t recvlen = 0; + while(recvlen < len){ + while(RingBuffer_Empty(uart_buffer)); + if(RingBuffer_readb(uart_buffer, &buf[recvlen]) == 1) recvlen++; + } + return recvlen; +} + +size_t uart_write_1c(char*buf){ + if(buf[0] == '\r') return 0; + while(!(memory_read(AUX_MU_LSR_REG) & 0b100000)); + memory_write(AUX_MU_IO_REG, (memory_read(AUX_MU_IO_REG) & 0xffffff00) | buf[0]); + return 1; +} + +size_t uart_write(char* buf, size_t len){ + size_t writelen = 0; + while(writelen < len){ + uart_write_1c(&buf[writelen++]); + } + return writelen; +} + +size_t uart_readline(char* buf){ + int i = 0; + while(uart_read(&buf[i], 1)){ + if(buf[i] == '\r' || buf[i] == '\n'){ + buf[i] = '\0'; + break; + } + i++; + } + return i; +} + +void uart_print(char* buf){ + int i=0; + while(buf[i]){ + uart_write_1c(&buf[i]); + i++; + } +} + +void uart_print_hex(uint64_t num, int len){ + uint64_t tmp; + char hex[20] = {}; + uart_print("0x"); + for(int i = len - 4; i >= 0; i -= 4){ + tmp = (num >> i) & 0xF; + // 0-9 a-f + hex[(len / 4 - 1) - i / 4] = (char) tmp + (tmp > 9 ? 'a' - 10 : '0'); + } + uart_print(hex); +} + +void newline(){ + uart_print("\r\n"); +} + diff --git a/lab3/src/lib/utils.c b/lab3/src/lib/utils.c new file mode 100644 index 000000000..8dc23498f --- /dev/null +++ b/lab3/src/lib/utils.c @@ -0,0 +1,38 @@ +#include + +void wait_cycles(uint32_t times){ + while(times--) asm volatile("nop"); +} + +uint32_t hex2u32_8(char *buf){ + uint32_t num = 0; + for(int i = 0; i < 8; i++){ + num <<= 4; + num += (buf[i] >= 'A' ? buf[i] - 'A' + 10 : buf[i] - '0'); + } + return num; +} + +uint16_t ntohs(uint16_t tmp){ + return (tmp << 8) | (tmp >> 8); +} + +uint32_t ntohl(uint32_t tmp){ + return ((uint32_t)(ntohs(tmp & 0xffffLL)) << 16) | (ntohs((tmp >> 16) & 0xffffLL)); +} + +uint64_t ntohll(uint64_t tmp){ + return ((uint64_t)(ntohl(tmp & 0xffffffffLL)) << 32) | (ntohl((tmp >> 32) & 0xffffffffLL)); +} + +uint16_t htons(uint16_t tmp){ + return (tmp >> 8) | (tmp << 8); +} + +uint32_t htonl(uint32_t tmp){ + return (ntohs((tmp >> 16) & 0xffffLL)) | ((uint32_t)(ntohs(tmp & 0xffffLL)) << 16); +} + +uint64_t htonll(uint64_t tmp){ + return (ntohl((tmp >> 32) & 0xffffffffLL)) | ((uint64_t)(ntohl(tmp & 0xffffffffLL)) << 32); +} \ No newline at end of file diff --git a/lab3/upload.py b/lab3/upload.py new file mode 100644 index 000000000..b3523f946 --- /dev/null +++ b/lab3/upload.py @@ -0,0 +1,12 @@ +from pwn import * + +kernel = open("kernel8.img", "rb").read() +r = serialtube("/dev/pts/13", convert_newlines=False) +#r = serialtube("/dev/ttyS0", convert_newlines=False) +#r = remote('127.0.0.1',10001) +size = (str(len(kernel)) + "\n" ).encode() +print(size) +r.sendline(size) +print(r.recvuntil(b"): ").decode()) +r.send(kernel) +r.interactive() \ No newline at end of file From 59b06e4aa872320240352af487138e505dfd25ec Mon Sep 17 00:00:00 2001 From: Pin-Shao Chen Date: Tue, 27 Jun 2023 14:15:16 +0800 Subject: [PATCH 2/2] feat: lab4 --- lab4/.gitignore | 5 + lab4/Makefile | 66 ++++ lab4/README.md | 15 + lab4/raspi3b/bcm2710-rpi-3-b-plus.dtb | Bin 0 -> 33106 bytes lab4/raspi3b/config.txt | 3 + lab4/raspi3b/initramfs.cpio | Bin 0 -> 1024 bytes lab4/rootfs/file1 | 1 + lab4/rootfs/file2.txt | 1 + lab4/rootfs/lab3 | Bin 0 -> 24 bytes lab4/src/bootloader/bootloader.c | 40 +++ lab4/src/bootloader/include/bootloader.h | 6 + lab4/src/bootloader/linker.ld | 41 +++ lab4/src/bootloader/start.s | 20 ++ lab4/src/exec/Makefile | 18 + lab4/src/exec/linker.ld | 18 + lab4/src/exec/main.s | 11 + lab4/src/exec/test_el0_exception | Bin 0 -> 24 bytes lab4/src/exec/test_el0_exception.s.o | Bin 0 -> 840 bytes lab4/src/kernel/include/kernel.h | 11 + lab4/src/kernel/kernel.c | 256 ++++++++++++++ lab4/src/kernel/linker.ld | 44 +++ lab4/src/kernel/start.s | 25 ++ lab4/src/lib/allocator.c | 414 +++++++++++++++++++++++ lab4/src/lib/command.c | 129 +++++++ lab4/src/lib/coretimer.c | 103 ++++++ lab4/src/lib/devicetree.c | 88 +++++ lab4/src/lib/exception_table.s | 101 ++++++ lab4/src/lib/include/allocator.h | 12 + lab4/src/lib/include/command.h | 10 + lab4/src/lib/include/coretimer.h | 19 ++ lab4/src/lib/include/devicetree.h | 39 +++ lab4/src/lib/include/interrupt.h | 18 + lab4/src/lib/include/mailbox.h | 25 ++ lab4/src/lib/include/ramdisk.h | 46 +++ lab4/src/lib/include/reboot.h | 9 + lab4/src/lib/include/shell.h | 5 + lab4/src/lib/include/string.h | 10 + lab4/src/lib/include/uart.h | 52 +++ lab4/src/lib/include/utils.h | 16 + lab4/src/lib/interrupt.c | 64 ++++ lab4/src/lib/mailbox.c | 56 +++ lab4/src/lib/ramdisk.c | 81 +++++ lab4/src/lib/reboot.c | 20 ++ lab4/src/lib/shell.c | 35 ++ lab4/src/lib/string.c | 59 ++++ lab4/src/lib/uart.c | 150 ++++++++ lab4/src/lib/utils.c | 38 +++ lab4/upload.py | 12 + 48 files changed, 2192 insertions(+) create mode 100644 lab4/.gitignore create mode 100644 lab4/Makefile create mode 100644 lab4/README.md create mode 100644 lab4/raspi3b/bcm2710-rpi-3-b-plus.dtb create mode 100644 lab4/raspi3b/config.txt create mode 100644 lab4/raspi3b/initramfs.cpio create mode 100644 lab4/rootfs/file1 create mode 100644 lab4/rootfs/file2.txt create mode 100644 lab4/rootfs/lab3 create mode 100644 lab4/src/bootloader/bootloader.c create mode 100644 lab4/src/bootloader/include/bootloader.h create mode 100644 lab4/src/bootloader/linker.ld create mode 100644 lab4/src/bootloader/start.s create mode 100644 lab4/src/exec/Makefile create mode 100644 lab4/src/exec/linker.ld create mode 100644 lab4/src/exec/main.s create mode 100644 lab4/src/exec/test_el0_exception create mode 100644 lab4/src/exec/test_el0_exception.s.o create mode 100644 lab4/src/kernel/include/kernel.h create mode 100644 lab4/src/kernel/kernel.c create mode 100644 lab4/src/kernel/linker.ld create mode 100644 lab4/src/kernel/start.s create mode 100644 lab4/src/lib/allocator.c create mode 100644 lab4/src/lib/command.c create mode 100644 lab4/src/lib/coretimer.c create mode 100644 lab4/src/lib/devicetree.c create mode 100644 lab4/src/lib/exception_table.s create mode 100644 lab4/src/lib/include/allocator.h create mode 100644 lab4/src/lib/include/command.h create mode 100644 lab4/src/lib/include/coretimer.h create mode 100644 lab4/src/lib/include/devicetree.h create mode 100644 lab4/src/lib/include/interrupt.h create mode 100644 lab4/src/lib/include/mailbox.h create mode 100644 lab4/src/lib/include/ramdisk.h create mode 100644 lab4/src/lib/include/reboot.h create mode 100644 lab4/src/lib/include/shell.h create mode 100644 lab4/src/lib/include/string.h create mode 100644 lab4/src/lib/include/uart.h create mode 100644 lab4/src/lib/include/utils.h create mode 100644 lab4/src/lib/interrupt.c create mode 100644 lab4/src/lib/mailbox.c create mode 100644 lab4/src/lib/ramdisk.c create mode 100644 lab4/src/lib/reboot.c create mode 100644 lab4/src/lib/shell.c create mode 100644 lab4/src/lib/string.c create mode 100644 lab4/src/lib/uart.c create mode 100644 lab4/src/lib/utils.c create mode 100644 lab4/upload.py diff --git a/lab4/.gitignore b/lab4/.gitignore new file mode 100644 index 000000000..05792799d --- /dev/null +++ b/lab4/.gitignore @@ -0,0 +1,5 @@ +tmp +book +build +*.elf +*.img diff --git a/lab4/Makefile b/lab4/Makefile new file mode 100644 index 000000000..e0c273646 --- /dev/null +++ b/lab4/Makefile @@ -0,0 +1,66 @@ +shell = /bin/bash +CROSS_COMPILER := aarch64-linux-gnu- +CC := $(CROSS_COMPILER)gcc +LD := $(CROSS_COMPILER)ld +OC := $(CROSS_COMPILER)objcopy +BUILD_DIR := build +SRC_DIR := src +LIB_DIR := $(SRC_DIR)/lib +KERNEL_DIR := $(SRC_DIR)/kernel +BOOTLOADER_DIR := $(SRC_DIR)/bootloader +KERNEL_SRCS := $(shell cd src; find kernel lib -name '*.[cs]') +KERNEL_OBJS := $(KERNEL_SRCS:%=$(BUILD_DIR)/%.o) +BOOTLOADER_SRCS := $(shell cd src; find bootloader lib -name '*.[cs]') +BOOTLOADER_OBJS := $(BOOTLOADER_SRCS:%=$(BUILD_DIR)/%.o) + +KERNEL_CFLAGS := -I $(KERNEL_DIR)/include +BOOTLOADER_CFLAGS := -I $(BOOTLOADER_DIR)/include +CFLAGS := -O0 -I $(LIB_DIR)/include -fno-stack-protector -ffreestanding -fdata-sections -ffunction-sections -g + +.PHONY : all clean rootfs test debug + +all: kernel8.img + +clean: + rm -rf build kernel8.img kernel8.elf + +rootfs: + cd rootfs && find . | cpio -o -H newc > ../raspi3b/initramfs.cpio + +test: + qemu-system-aarch64 -M raspi3b -kernel bootloader.img -initrd raspi3b/initramfs.cpio -dtb raspi3b/bcm2710-rpi-3-b-plus.dtb -serial null -serial pty -display none + +debug: + qemu-system-aarch64 -M raspi3b -kernel bootloader.img -initrd raspi3b/initramfs.cpio -dtb raspi3b/bcm2710-rpi-3-b-plus.dtb -serial null -serial pty -display none -S -s + +kernel8.img: $(KERNEL_OBJS) + $(LD) -T $(KERNEL_DIR)/linker.ld -o kernel8.elf $^ + $(OC) -O binary kernel8.elf kernel8.img + +bootloader.img: $(BOOTLOADER_OBJS) + $(LD) -T $(BOOTLOADER_DIR)/linker.ld -o bootloader.elf $^ --gc-sections + $(OC) -O binary bootloader.elf bootloader.img + +$(BUILD_DIR)/kernel/%.c.o: $(KERNEL_DIR)/%.c + mkdir -p $(dir $@) + $(CC) $(KERNEL_CFLAGS) $(CFLAGS) -c $< -o $@ + +$(BUILD_DIR)/kernel/%.s.o: $(KERNEL_DIR)/%.s + mkdir -p $(dir $@) + $(CC) $(KERNEL_CFLAGS) $(CFLAGS) -c $< -o $@ + +$(BUILD_DIR)/bootloader/%.c.o: $(BOOTLOADER_DIR)/%.c + mkdir -p $(dir $@) + $(CC) $(BOOTLOADER_CFLAGS) $(CFLAGS) -c $< -o $@ + +$(BUILD_DIR)/bootloader/%.s.o: $(BOOTLOADER_DIR)/%.s + mkdir -p $(dir $@) + $(CC) $(BOOTLOADER_CFLAGS) $(CFLAGS) -c $< -o $@ + +$(BUILD_DIR)/lib/%.c.o: $(LIB_DIR)/%.c + mkdir -p $(dir $@) + $(CC) $(CFLAGS) -c $< -o $@ + +$(BUILD_DIR)/lib/%.s.o: $(LIB_DIR)/%.s + mkdir -p $(dir $@) + $(CC) $(CFLAGS) -c $< -o $@ diff --git a/lab4/README.md b/lab4/README.md new file mode 100644 index 000000000..432991252 --- /dev/null +++ b/lab4/README.md @@ -0,0 +1,15 @@ +# OS + +Physical Environment: Raspberry Pi 3b+ + +Simulate Environment: QEMU + +Build Command: +``` +make +``` + +Simulate Command: +``` +qemu-system-aarch64 -M raspi3b -kernel kernel8.img -serial null -serial stdio -display none +``` diff --git a/lab4/raspi3b/bcm2710-rpi-3-b-plus.dtb b/lab4/raspi3b/bcm2710-rpi-3-b-plus.dtb new file mode 100644 index 0000000000000000000000000000000000000000..ddd8af88c45aa20caada0403fbd069383a1a1015 GIT binary patch literal 33106 zcmc&-3y>T~d7eF;POo#2AAoS|c;%BV+1B{>aVMR?3MWg(RxDYvBxCbj?d{IpE!vlN z_fC=lArsyK;t+*0DM%F0|Ni^$zk9lSdj9&d|NXw_J$%gbyt_QFm&J1juFG+4#szm- z!SlLbH-5d_C=Hrt#s=5mNg7_K+-=VVozB^IZD-MMw5mbfpYz-GrLH&EsWf)ZRT_nv z;%=fc%@$mnj%k|g(OR~cJ$P$>=prb%&&6}^ zWVcnB>;|1$xjwr)DCDPeQ#m5QksfjGNZ{o1xtxo01#k`vPI>8!C87wVu?g3`hDK|t zSw+auUW@1bgbT#LNb41XTWyp_TyAb=#tMP? zT#4&-g0s-BwSWL7lnCP~$A=|8l66v!#CdB1Cs`ll^<9RSMn$q=MgYPwAI4vB;)@X* z5`PuqAJzCK1r}jw`VVOQ0Qw)2_*$VW@k|e*a4Lt7*!W7Wv2gb5@RKIvp*NY6Kl|BF|H&IWc+$eOj4wnu)9cjQj-F}U zix|iJE1g;oemc#s;blJYNhd6Vw&4v(_9mvORmvh5z{4_DAgo$*!Ecl`OQk9Gc$g8kGNqbCRoK)fiAz^XU`)%>%b^SIxQFY z%zVLsVmw?2n8>fcYaNh35e=b8UReQr8h64VybSXvUFrd!EC=J@GJlJkl|$wq;AgzX z{V<9fQQ0yMG)LHnufwHo7d(uE97ncRgZc7OU793dtkaRng9l2-5A5^!*nh}_H}Aod z_wGD;@JQ*-{fF)r-?ZF!dB=|)EbYG|U%JQoa@KeF;PE2@I(+2#LGgfyNt!Q6+I-PF z@xXz+cZ@d@&+jsi-R3c49(&|b$eD-1EEo!fq5)2shheE;s1$a4cO5u;4oTX4Mq7yG7P#$|aMIS7BU9g`pOkqH`&iZF~? zg<~4f5q?)gmwdZ2m_;~Fw+K@dr+YoZ6S%hFx&haXxVGbR`Bl2)<$lD`k#6#G^WJCU zqcTm+FdcEUOstkXE*7?ki_A^qO3Pd8m2#FcEwn53Q#p~A6v|0Qc@p2H`nCyaJsAX>@GCG=I|J7)8Tr{M-?vQ;>4e z&e3T)(s6W9bTV14mjEX!m!UJoN`iCg+~R~2{Dit<@kQ=;0$=E2Xl!cFG*05s4wE-J zr{78C?^@u*=@df!QaaZFhj_|wfLCL(7jvfwkr)Gn-{T5nP3y8{;mLyYZHf+ z_fV3asm2&Rtw+lEI$SQjWVsJ3y>1mRNj+iFSRRw^QfyDMP0;>J-Qe}r=$MakV{b-)nhFwF}4Mv?{$W z-hPduhB8okDg&3E_H~pg#}UT|(kq5#S9)pssq~1$zLVvovw2D$ClF4Qzi7LVSoyQS z+Zv^n@+avdT4=fS@3XK>B;TUjCn*1_W3D`s?dzp+T8?~+efIZ8;BLn?jGoFwc(cm7 z+PbIA+;TqP@|G_-yhZx2WlgL5B)yl#>2V~v>Uv4idU>3d!`tfgC`s=XaeCw}HaD#0 z+yOkcN4E}=v|bsfg_l#+U#MxmJm;QWZI`2*7Qiz(=;59kdB7a#t^(n!jK^0M(_iz@vzIGv_AQWo~@N|Ssf z%Tl#4%G8cwILr^zkdLHJCiw{ZX@vcv%G7sgrpaSoY4ANTKQmYBl`8FWb>YY&aO8XD_91 z8z!ey={$vUx@(ns^=$A`@8>18eO`*3E=Avm$*D1vx2PSiMqbYrPfg{CTGU$VAsDl% zu5F<`bl#z*jd0pk+Hbku%P}z=Wq|i9v46C|v>~qj(0X=dm9*7uq!GIEUevBNy8ys3 z4azRGX^U1vi*suctxC5PkrR5bYeElC;nU?SS>DY`i*pU|(-B{3FzlpBeV=#`IKmHT zNGFD{OM`I?yL=?&^W2DrNQSuJP0Dcv{OnJ)?-)jh{f&`LwbpV3!!%ngz3bthz_kt6 z4Y+Q^wH=pBm-VY@Ry&`^IZVlW4l9hdhLtA!bH3|on7Zf4Ahn;PE(ksIPNF1*hSpCO zI9qYKbd`7FxV&2&(R1orNIM_0D|8q|eu)n!b*_HWbLp^Ngid)WCUD{?k2~PMDN2{r zp^!(HZWj2YE3{L#91s`v>3QW&V`sab%jb=+Q)>j3piZ+Xe1Zq8fn`RXXytaMPgMG<7);d)_3qPIBL+XvXnwhIF1-(|Qwf~j~c1{QMBvcK>`xy9Gh%tRBx%mZ>@on+yq zX$fIkC#+Y+Bad!fq{)VIeG+)%*=XzzJ3sQJ&KazTA_C6JaO5fY-FEjaiH+j_6=BET zWj=>6XemE^^#@ubk0IW9XOMcj6)@4={%s~gi@Fk*5fBN3)3QTGVv@HxFqOx37B;B9 zXgftFz#|{*UrCpj$OeMx#AU-MaW?;fWu=WJ4&})CpB=cQto>V71h2oWKtvikn-}$A z7D18;VX6<$b6{G2ZJXqQ^qo5MvIx_W_G;wA`lWo-Zl=kHI+j@f4BM`*bumBa?i%t# zTGU(eML#c>N6PIc!XS!juxxi28J>yj8904X4wN%>NfM0yfID?yAf^qkus8QvQ1P7gLCxcD1xba!ZC#6JzILh z^6d07Z~365jj+g(^X*a=yn{+vxQ_}jI`Yt879dJOY6JVEco#WZNMVIM^OrvB`- zaj?@PGf2Oc&mQm$pIyV}o;aTzTg7Ew?bd8TRF>fL5u(vtC`{WX z^C67S74#yu2L$aTENd2NS=LGW%;QO#pf^%(FP`;+Zl&CIOK#$?#p5=zTbeuD3q0{v ztDQpV0}VRT8YCy=yXFYu$vZDC3)?5lB(m$@7OMOuWCui~p|f;iWkz1Gb6bxxp5-MD zVQIR`{8=}We>DCHw^K4L?P9#{kiXA?3L_%=%ySlDUYaNCk8K(<3}NI$^ufZ?`dUPd z3>(itX3`&WTxew=?PWW{Pk-F9j^Yw}u+vX#+_Hr9l%q(J#-mzG~~y z^FW=&wHkS@)^-lkQR*S}VHsC~|JXa*rSN|dv}SRwhJWU%b;&m3mM4oa9phKx|1@xf zf6RG`&8)<25oyQe4@AP?luy{Aiwy5@VA_7Twq)_vyb69Qjlv+qH4X34_nx;n48IY6 zE!#@Gvt0}CX3QIHI=1w-;Th*0h;aZ0!Ic`(qOypgr8q+v+a>c+zFqskK4+Mmfg6tb zIIbtIjAc^B!S1-1>5^j`$Vb{S`ytX{_$l+$u;?Uhw#a31ncJzkS$Tzi5Qs=a7s+9k z!IQixOy!`uwo?7@T}k*rF91Hc=|0AX*fr-Pg=rs%dFB}9dEs1J!rC8G_R0tBPFU_? zZ2)qL+59aCtA0*^255S$bv_HYSYFUuRX>*x`?-8c`#JG}1|4Y)k`wX^`#H*jxZqXl z5O&_k&Wy|4E$zx*Lbrj4G<2jxIbAq+eiq)%xI&o9j&@1$R2Gh2Nx!T0OrEm1=$K|m zc?RmN<_B7-W4BvCS9HbQTFwmNm}lG$?as~kK$KV$k3yonEFHK$=beNnEH~q940)G) z@DREz+e*4a`RMx&@JGt6-hz{U&ASkIJ}xVpHSYmy1)qZ?;}rgWvfORW+o6EqyE?#k z9^#TG_AL+L${>y1U5}87r`~&jPZg$i7N*UX1Dj6XN8EZFRJNZR-Ne3s^5yco8)I^^ zKZswJ`?a_-4NP4T5l&??uq>JvTefX)D z$^-e^ZDE8buT1|ZMv^wJzcWSHI{l15;!S(yHc#26DX{a7-cp|L_f?MNhrOFp;Q=L_tU`#TBe{OGW!_HQMK;Qe4Z=i!#;4MX}yxyaiTZ_~W(;%zr? zGraBLEpL)Y8tfY;L{dR-;rH#g6J;|!sB#|VdoTI2avw!`-!L78rF~GZDF4jLpKS>p z%E0aZclns8tn@l{zgA%s^Ro5uIJ_h+Fg!9pw0^dKwogW?PV9uAv^D*s@Pm%DW5uD~ zusp(V`e$R3ej9LH9;f|wBN_HjSH*-_+M_!xZ4KY%glYROoTK)5nXAruAEbwQ5En8Y zJqYq;Ye@;q0+05N{8N|syw*OcOAM+!2`=Q%P>o(Fv^{D$uD7=pKswAc}-s~*Ovns z>h7|`5#q94B;?F@dO^-H4o>sIc=sfNtj-Xod0%E>gZfD2>2<&p86S7fn1lO%YzCVyI`pD5YYf2kl{rFAcl~KaICF$>GGv86g{)zGf zEW&imN9C7;KXbY^UmNlc5VH$Y#ljwczEQT7>C$>5Xt6G&KIUtk#%X-wd#b_t6k6+8 z8{v2(b`C?QUGp`Kk3@`zBYl(~ZRR9{p{@|7_J$3~@-g~2{Hn7nwU=K9uJGCwbJ)jY zf7<~f($HNBU*uK$@tdQx;oP3WP$z2|&RQ4i{Yl_+%+C5^o+w-2dhkl+d=t`1IV&=! zBwxz2-swn_eRjN!EH&}zaf4vSL%xvzc?Q?R?q}&ye%yLcxf5T@>jRheUGZU4N6PiK zw`@$5$}#LmSytvr{1x;!Hb1qJ3~0||GDw`Au}T?G)kFs5Ps`-WK*s^D47i4VDKgN$ z@L80>=tc0r@~dor3jbRyEaMz&!1$#7p7tFCOT*}d$0nHZ&VBp5JZ&8Kj_o&Csc!N} zCv}5yDvz2#Q1#C90P_L!v1^F0of@|a*^GV_$oeimhzID{$X4ddj7n%ACCsNX6F4g? znLnnzvf)wAIqSSO`JgP>hBF|c3*Z*_QrEhL)>}bK<)I7PE-rFoap{X_& zFgnuRL63VTjy*aew8wgAKx4j2RLe_h`*e64{b%4_XYujKyxmDlnbBTkDi}zdGS;4S zSzj?;lwUtWR9SqK>2WDPq{((B2vHFOCR#3 zSOyPR1HW0H0qM!xPn3?_EV0z5V+Rm-t`aSy+H_LB zsEM#$o$_1V3VEiy*spr?n4YPchQuJ@F6(hJV`<>{hCyP(~g0H{_@GAFmihN&miQPh`=3nZT&HgP&_ zP;`YvaV=vKNMqCJWi36B6MD3B)Mv#deGSw5-?&MhIB&)sI}>MEAAz{FYeW5=Dem&S zjW*KIXoBRcqH`OG4A{@wk={4{}_~K7;P- zxGWEAbDnpeFb(g8f7S^ff&aV{eq{o`hPYWL{N2D6j{1!Y_t@)(PKhNQUxzAL3LOXp?AD z*xm?}yz#!7FLi>2rFyy7GDeg6Z^q??V2nu7gAv3y*xI!pW;!1T1i}#xxAxPx(Vy1m zvM+ocF6boV#SvHedN=$LPw_qStL;Zu>bE(!rg`L^X1Q}i%DqzlkHqr-`IPauoIFa^ zrAFf{3ko0{w8%G+ns;bWXXN#Y}~ zF}}|Y%ZoS@#7UKo;fFYR(q93GHfSZBL#x1f)e8JjJ~To*Q{=;!3qJwJ7;%j7TV_1Nn63Y${6e4&_Ik|uQh5tL%`x-{55tV#Hj{z zOQx}rKGb#W19(mj;2}2vuJ!&+q|GPF1v!j;9PmO4{8NBmoq)3*+4im;Qjeth6mV`$ zq`eYwjt6gTwwka8jn*=UjUpbA57T`I@x??sw1KgIA-qvO<9FLZP>p1cG40rYA#Q38 z-yoGc3*FbYntQhoKRYx1Y)vea?agoB*_xkUDSa;WY)+=nZGSy@p`*;v&#a?=ny;kY z7f#Wy@XI3jjKVQLvFSQDEJj&CL zBFLBaNxuz$hMboxJ)+vUb&u`af5Hv_A@oPX7?-Sj0!vkBx8iKwk6c8EiUB!_bMu)7 zMEUdEr)3Zo=7qT?CeW~(7uwFcCsbov&5$m1Me;+up&O-_@!Kv7mpo-;77o-(#bq;q zW`2<6z%d+R)_oZ_{32kMIOV2;hz*JLRd>TB(l(Q�!{|ADA4XD>wp8k##gUzLJ7OVy;H|%WGCBm9 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 G{{I6vS%S&{ literal 0 HcmV?d00001 diff --git a/lab4/raspi3b/config.txt b/lab4/raspi3b/config.txt new file mode 100644 index 000000000..933de3548 --- /dev/null +++ b/lab4/raspi3b/config.txt @@ -0,0 +1,3 @@ +kernel=bootloader.img +arm_64bit=1 +initramfs initramfs.cpio 0x20000000 \ No newline at end of file diff --git a/lab4/raspi3b/initramfs.cpio b/lab4/raspi3b/initramfs.cpio new file mode 100644 index 0000000000000000000000000000000000000000..d4dfe3f1eaf1cda48cf91458aafb161db4aa230c GIT binary patch literal 1024 zcmXpoH!wFaGynn<16MaNZRiH34UAnaKzulDU|?uwVrgmUVrB*w#~@4`F@zujMlf+b z2B2*)``k>OK;jm7?K81-HFt(;2RjpH6p+SgAKZOunK`M33?&(v#R@V`I0kYLducV>`#T`Z{?l5+828T6%cUW4u8kmCJ3yca#+&~-!Byom? zDNIRDVv;cf5Hwt3U}2cZ$iQ$#UWDP}>i_>kfPx~3FoCJZL!$=*9;GN!;P?iKgakQy R`nU!uDk_3pGztbT1OS~Gg^vIL literal 0 HcmV?d00001 diff --git a/lab4/rootfs/file1 b/lab4/rootfs/file1 new file mode 100644 index 000000000..9bc8d9ca0 --- /dev/null +++ b/lab4/rootfs/file1 @@ -0,0 +1 @@ +this is file1. diff --git a/lab4/rootfs/file2.txt b/lab4/rootfs/file2.txt new file mode 100644 index 000000000..221d4764a --- /dev/null +++ b/lab4/rootfs/file2.txt @@ -0,0 +1 @@ +this is file2. diff --git a/lab4/rootfs/lab3 b/lab4/rootfs/lab3 new file mode 100644 index 0000000000000000000000000000000000000000..1adf648a4c1b9d2d1b5e9fa08b84e52ef2fafc78 GIT binary patch literal 24 gcmZQzXt>0{!Z4AMf#Hh02*bzK|Nn + +#include +#include + +#include +#include +#include + +extern uint32_t _bss_begin; +extern uint32_t _bss_end; +extern uint32_t _stack_top; + +void _init(void){ + for(uint32_t*addr = &_bss_begin; addr != &_bss_end; addr++){ + *addr = 0; + } + uart_init(); + load_kernel(); +} + +void load_kernel(){ + char *kernel_addr = (char *)0x80000; + uart_print("Input Size: "); + char buf[BUF_SIZE]; + size_t recvlen = uart_readline(buf); + buf[recvlen] = '\0'; + uint32_t imagesize = atoi(buf); + uart_print("Input Kernel Image (Size: "); + uart_print_hex(imagesize, 32); + uart_print("): "); + uart_read(kernel_addr, imagesize); + uart_print("Go to kernel!"); + newline(); + asm volatile( + "mov x0, x10\n" + "ldr x1, =0x80000\n" + "br x1\n" + ); +} \ No newline at end of file diff --git a/lab4/src/bootloader/include/bootloader.h b/lab4/src/bootloader/include/bootloader.h new file mode 100644 index 000000000..ec7cd9762 --- /dev/null +++ b/lab4/src/bootloader/include/bootloader.h @@ -0,0 +1,6 @@ +#ifndef __KERNEL__ +#define __KERNEL__ +#define BUF_SIZE 0x20 +void load_kernel(); +void _init(); +#endif diff --git a/lab4/src/bootloader/linker.ld b/lab4/src/bootloader/linker.ld new file mode 100644 index 000000000..dda0fcb48 --- /dev/null +++ b/lab4/src/bootloader/linker.ld @@ -0,0 +1,41 @@ +ENTRY(_start) +MEMORY +{ + BOOTLOADER (rx) : ORIGIN = 0x20000, LENGTH = 128K + CODE (rx) : ORIGIN = 0x80000, LENGTH = 128K + ROM (r) : ORIGIN = 0xa0000, LENGTH = 128K + RAM (rw) : ORIGIN = 0xc0000, LENGTH = 512K +} +SECTIONS +{ + .text : + { + _loader_begin = .; + *(.text.start) + *(.text.loader) + *(.text) + } >CODE + .rodata : + { + _rodata_begin = .; + *(.rodata) + _rodata_end = .; + } >ROM + .data : + { + _data_begin = .; + *(.data) + _data_end = .; + } >RAM + .bss : { + . = ALIGN(0x8); + _bss_begin = .; + *(.bss) + _bss_end = .; + _loader_end = .; + } >RAM + _stack_top = ORIGIN(RAM) + LENGTH(RAM); + _bootloader_begin = ORIGIN(BOOTLOADER); + _loader_size = _loader_end - _loader_begin; + _kernel_begin = ORIGIN(CODE); +} \ No newline at end of file diff --git a/lab4/src/bootloader/start.s b/lab4/src/bootloader/start.s new file mode 100644 index 000000000..116e617f2 --- /dev/null +++ b/lab4/src/bootloader/start.s @@ -0,0 +1,20 @@ +.section ".text.start" +.extern _stack_top +.extern _bootloader_begin +.extern _kernel_begin +.extern _loader_size +.extern _init +.global _start +_start: + mov x10, x0 + adrp x0, _stack_top + mov sp, x0 + adrp x0, _kernel_begin + adrp x1, _bootloader_begin + adrp x2, _loader_size + _loop: + ldr x4, [x0], #8 + str x4, [x1], #8 + subs x2, x2, #8 + b.gt _loop + b #(_init - 0x60000) diff --git a/lab4/src/exec/Makefile b/lab4/src/exec/Makefile new file mode 100644 index 000000000..7fb284d7b --- /dev/null +++ b/lab4/src/exec/Makefile @@ -0,0 +1,18 @@ +CROSS_COMPILE = aarch64-linux-gnu- +CC := $(CROSS_COMPILE)gcc +LD := $(CROSS_COMPILE)ld + +.PHONY: clean + +CFLAGS := -O0 -fno-stack-protector -ffreestanding -fdata-sections -ffunction-sections + +test_el0_exception: test_el0_exception.s.o + $(LD) -T linker.ld $^ -o test_el0_exception.elf + $(CROSS_COMPILE)objcopy -O binary test_el0_exception.elf test_el0_exception + cp $@ ../../rootfs + +test_el0_exception.s.o: main.s + $(CC) $(CFLAGS) -c $< -o $@ + +clean: + rm test_el0_exception.elf test_el0_exception test_el0_exception.s.o \ No newline at end of file diff --git a/lab4/src/exec/linker.ld b/lab4/src/exec/linker.ld new file mode 100644 index 000000000..b2ebef1ea --- /dev/null +++ b/lab4/src/exec/linker.ld @@ -0,0 +1,18 @@ +ENTRY(_start) + +SECTIONS +{ + .text : { + *(.text.start) + *(.text) + } + .rodata : { + *(.rodata) + } + .data : { + *(.data) + } + .bss : { + *(.bss) + } +} \ No newline at end of file diff --git a/lab4/src/exec/main.s b/lab4/src/exec/main.s new file mode 100644 index 000000000..596352f0e --- /dev/null +++ b/lab4/src/exec/main.s @@ -0,0 +1,11 @@ +.section ".text.start" +.global _start +_start: + mov x0, 0 +1: + add x0, x0, 1 + svc 0 + cmp x0, 5 + blt 1b +1: + b 1b \ No newline at end of file diff --git a/lab4/src/exec/test_el0_exception b/lab4/src/exec/test_el0_exception new file mode 100644 index 0000000000000000000000000000000000000000..1adf648a4c1b9d2d1b5e9fa08b84e52ef2fafc78 GIT binary patch literal 24 gcmZQzXt>0{!Z4AMf#Hh02*bzK|NnJfjWMqH=MuzPS2p&w7fx!bw&;cy$z`()44rDc4VqjsI2$a4eFT(I~_5c4N zKtU0(5*!3GRvQ=?m>HO`>R<-SU<1rRi_rnZnV8}r5dkdf8B{75;)_cXi%J+6^olEU zOA?cSbV(6}&VaE>QY%Ur^imQ_5*hT8ii;WaKmtH@V14LrAcrpv)C6)n8=7VZG(L=r z6dhn8MIZ?hLk}qjuq-Blu3sIfgae4l)vp883o;Xz`z3&K$N)WtKzgyoegst03MdUS qAA~_}1p%13oIp0Z+rbK;9_0pe5Cppa1##%-hAOl`Xa%#-^#cHHG$T3y literal 0 HcmV?d00001 diff --git a/lab4/src/kernel/include/kernel.h b/lab4/src/kernel/include/kernel.h new file mode 100644 index 000000000..19c78e2d4 --- /dev/null +++ b/lab4/src/kernel/include/kernel.h @@ -0,0 +1,11 @@ +#ifndef __KERNEL__ +#define __KERNEL__ +#define BUF_SIZE 256 +void _init(); +void boot_message(); +void allocator_test(); +void devicetree_check(); +void spsr_el1_check(); +void boottimer(); +void allocator_test2(); +#endif diff --git a/lab4/src/kernel/kernel.c b/lab4/src/kernel/kernel.c new file mode 100644 index 000000000..2535cc1f5 --- /dev/null +++ b/lab4/src/kernel/kernel.c @@ -0,0 +1,256 @@ +#include +// C +#include +#include +// tool +#include +#include +#include +// lab1 +#include +#include +#include +// lab2 +#include +#include +// lab3 +#include +#include +// lab4 +#include + +extern uint32_t _rodata_begin; +extern uint32_t _rodata_end; +extern uint32_t _data_begin; +extern uint32_t _data_end; +extern uint32_t _bss_begin; +extern uint32_t _bss_end; +extern uint32_t _heap_begin; +extern uint32_t _heap_end; +extern uint32_t _stack_top; +extern void *_devicetree_begin; + +extern uint32_t _image_memory_begin; +extern uint32_t _image_memory_end; + +extern uint32_t _user_begin; +extern uint32_t _user_end; +extern uint64_t exception_vector_table; + +void _init(void){ + for(uint32_t*addr = &_bss_begin; addr != &_bss_end; addr++){ + *addr = 0; + } + uart_init(); + boot_message(); + allocator_test(); + devicetree_check(); + asm("msr vbar_el1, %0"::"r"((void*)&exception_vector_table));//exception + coretimer_el0_enable(); + interrupt_enable(); + spsr_el1_check(); + add_timer(8, &boottimer, 0); + malloc_init(); + allocator_test2(); + shell(); +} + +void boot_message(){ + char buf[BUF_SIZE]; + uart_print("Boot Success!"); + newline(); + uint32_t board_revision; + uint32_t arm_memory_base_addr; + uint32_t arm_memory_size; + get_board_revision(&board_revision); + get_ARM_memory_base_address_and_size(&arm_memory_base_addr, &arm_memory_size); + + uart_print("board_revision: "); + uart_print_hex(board_revision, 32); + newline(); + + uart_print("arm_memory_base_addr: "); + uart_print_hex(arm_memory_base_addr, 32); + newline(); + + uart_print("arm_memory_size: "); + uart_print_hex(arm_memory_size, 32); + newline(); + + uart_print("&_rodata_begin="); + uart_print_hex((uint64_t) &_rodata_begin, 64); + newline(); + uart_print("&_rodata_end="); + uart_print_hex((uint64_t) &_rodata_end, 64); + newline(); + uart_print("&_data_begin="); + uart_print_hex((uint64_t) &_data_begin, 64); + newline(); + uart_print("&_data_end="); + uart_print_hex((uint64_t) &_data_end, 64); + newline(); + uart_print("&_bss_begin="); + uart_print_hex((uint64_t) &_bss_begin, 64); + newline(); + uart_print("&_bss_end="); + uart_print_hex((uint64_t) &_bss_end, 64); + newline(); + uart_print("&_heap_begin="); + uart_print_hex((uint64_t) &_heap_begin, 64); + newline(); + uart_print("&_heap_end="); + uart_print_hex((uint64_t) &_heap_end, 64); + newline(); + uart_print("&_image_memory_begin="); + uart_print_hex((uint64_t) &_image_memory_begin, 64); + newline(); + uart_print("&_image_memory_end="); + uart_print_hex((uint64_t) &_image_memory_end, 64); + newline(); +} + +void allocator_test(){ + void *test1 = simple_malloc(1); + if(test1 == NULL){ + uart_print("Error: Get NULL Pointer!"); + newline(); + return; + } + void *test2 = simple_malloc(16); + if(test2 == NULL){ + uart_print("Error: Get NULL Pointer!"); + newline(); + return; + } + uart_print("Test Simple Allocator 1: "); + uart_print_hex((uint64_t)test1, 64); + newline(); + + uart_print("Test Simple Allocator 2: "); + uart_print_hex((uint64_t)test2, 64); + newline(); +} + +void devicetree_check(){ + uart_print("Devicetree address: "); + uart_print_hex((uint64_t)_devicetree_begin, 64); + newline(); +} + +void spsr_el1_check(){ + uint64_t spsr_el1 = 0; + asm("mrs %0, spsr_el1":"=r"(spsr_el1)); + uart_print("spsr_el1: "); + uart_print_hex(spsr_el1, 32); + newline(); +} + +void boottimer(){ + uint32_t cntfrq_el0; + uint64_t cntpct_el0; + asm("mrs %0, cntfrq_el0":"=r"(cntfrq_el0)); + asm("mrs %0, cntpct_el0":"=r"(cntpct_el0)); + uart_print("Seconds after booting: "); + uart_print_hex(cntpct_el0 / cntfrq_el0, 64); + newline(); + add_timer(8, &boottimer, 0); +} + + +void allocator_test2(){ + void *test_malloc1 = buddy_system_malloc(0x3000); + void *test_malloc2 = buddy_system_malloc(0x5000); + void *test_malloc3 = buddy_system_malloc(0x2000); + void *test_malloc4 = buddy_system_malloc(0x7000); + void *test_malloc5 = buddy_system_malloc(0x1000); + buddy_system_free(test_malloc1); + buddy_system_free(test_malloc2); + buddy_system_free(test_malloc3); + buddy_system_free(test_malloc4); + buddy_system_free(test_malloc5); + + test_malloc1 = buddy_system_malloc(0x3000); + test_malloc2 = buddy_system_malloc(0x1000); + test_malloc3 = buddy_system_malloc(0x5000); + test_malloc4 = buddy_system_malloc(0x2000); + test_malloc5 = buddy_system_malloc(0x1000); + + test_malloc1 = buddy_system_malloc(0x1800); + test_malloc2 = buddy_system_malloc(0x2300); + test_malloc3 = buddy_system_malloc(0x12800); + test_malloc4 = buddy_system_malloc(0x22000); + test_malloc5 = buddy_system_malloc(0x3000); + + buddy_system_free(test_malloc1); + test_malloc1 = buddy_system_malloc(0x1f00); + buddy_system_free(test_malloc4); + test_malloc4 = buddy_system_malloc(0x1300); + buddy_system_free(test_malloc4); + buddy_system_free(test_malloc3); + test_malloc3 = buddy_system_malloc(0x1500); + test_malloc4 = buddy_system_malloc(0x20010); + + buddy_system_free(test_malloc1); + buddy_system_free(test_malloc2); + buddy_system_free(test_malloc3); + buddy_system_free(test_malloc4); + buddy_system_free(test_malloc5); + + test_malloc1 = buddy_system_malloc(0x1000); + test_malloc2 = buddy_system_malloc(0x1000); + test_malloc3 = buddy_system_malloc(0x1000); + test_malloc4 = buddy_system_malloc(0x1000); + test_malloc5 = buddy_system_malloc(0x1000); + + test_malloc1 = buddy_system_malloc(0x1000); + test_malloc2 = buddy_system_malloc(0x1000); + test_malloc3 = buddy_system_malloc(0x1000); + test_malloc4 = buddy_system_malloc(0x1000); + test_malloc5 = buddy_system_malloc(0x1000); + + test_malloc1 = buddy_system_malloc(0x1000); + test_malloc2 = buddy_system_malloc(0x1000); + test_malloc3 = buddy_system_malloc(0x1000); + test_malloc4 = buddy_system_malloc(0x1000); + test_malloc5 = buddy_system_malloc(0x1000); + + test_malloc1 = buddy_system_malloc(0x1000); + test_malloc2 = buddy_system_malloc(0x1000); + test_malloc3 = buddy_system_malloc(0x1000); + test_malloc4 = buddy_system_malloc(0x1000); + test_malloc5 = buddy_system_malloc(0x1000); + + buddy_system_free(test_malloc1); + buddy_system_free(test_malloc2); + buddy_system_free(test_malloc3); + buddy_system_free(test_malloc4); + buddy_system_free(test_malloc5); + + uart_print("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n"); + + void * test_k1 = kmalloc(0x16); + void * test_k2 = kmalloc(0x16); + void * test_k3 = kmalloc(0x16); + void * test_k4 = kmalloc(0x256); + + kfree(test_k1); + kfree(test_k2); + kfree(test_k3); + kfree(test_k4); + + test_k1 = kmalloc(0x16); + test_k2 = kmalloc(0x16); + test_k3 = kmalloc(0x16); + test_k4 = kmalloc(0x256); + + kfree(test_k1); + kfree(test_k2); + kfree(test_k3); + kfree(test_k4); + + int * test = kmalloc(sizeof(int)); + *test = 0x1234; + uart_print_hex(*test, 32); + newline(); + kfree(test); +} \ No newline at end of file diff --git a/lab4/src/kernel/linker.ld b/lab4/src/kernel/linker.ld new file mode 100644 index 000000000..9e5a9d42f --- /dev/null +++ b/lab4/src/kernel/linker.ld @@ -0,0 +1,44 @@ +ENTRY(_start) +MEMORY +{ + CODE (rx) : ORIGIN = 0x80000, LENGTH = 128K + ROM (r) : ORIGIN = 0xa0000, LENGTH = 128K + RAM (rw) : ORIGIN = 0xc0000, LENGTH = 40M + USER (rwx) : ORIGIN = 0x40c0000, LENGTH = 5M +} +SECTIONS +{ + .text : + { + *(.text.start) + *(.text) + } >CODE + .rodata : + { + _rodata_begin = .; + *(.rodata) + _rodata_end = .; + } >ROM + .data : + { + . = ALIGN(0x8); + _data_begin = .; + *(.data) + . = ALIGN(0x8); + _data_end = .; + } >RAM + .bss : { + . = ALIGN(0x8); + _bss_begin = .; + *(.bss .bss.*) + . = ALIGN(0x8); + _bss_end = .; + } >RAM + _heap_begin = ORIGIN(RAM) + 20M; + _heap_end = ORIGIN(RAM) + 35M; + _stack_top = ORIGIN(RAM) + LENGTH(RAM); + _user_begin = ORIGIN(USER); + _user_end = ORIGIN(USER) + LENGTH(USER) - 8; + _image_memory_begin = ORIGIN(CODE); + _image_memory_end = ORIGIN(USER) + LENGTH(USER); +} diff --git a/lab4/src/kernel/start.s b/lab4/src/kernel/start.s new file mode 100644 index 000000000..e69e63867 --- /dev/null +++ b/lab4/src/kernel/start.s @@ -0,0 +1,25 @@ +.section ".text.start" +.extern _stack_top +.extern _devicetree_begin +.extern _init +.global _start +_start: + adr x1, _devicetree_begin + str x0, [x1] + adrp x0, _stack_top + //ldr x0, =_stack_top + mov sp, x0 + bl from_el2_to_el1 + adrp x0, _stack_top + mov sp, x0 + bl _init +from_el2_to_el1: + mov x0, (1 << 31) // EL1 uses aarch64 + msr hcr_el2, x0 + mov x0, 0x3c5 // EL1h (SPSel = 1) with interrupt disabled + msr spsr_el2, x0 + msr elr_el2, lr + eret // return to EL1 +_hang: + wfe + b _hang diff --git a/lab4/src/lib/allocator.c b/lab4/src/lib/allocator.c new file mode 100644 index 000000000..dcf671de5 --- /dev/null +++ b/lab4/src/lib/allocator.c @@ -0,0 +1,414 @@ +#include + +#include +#include +#include + +#include +#include +#include + +#define FRAME_SIZE 0x1000 +#define LIST_SIZE 17 +#define PAGE_NUM 0x3c000000 / FRAME_SIZE +#define F -1 +#define X 3 + +typedef struct NODE_{ + struct NODE_ *next; + struct NODE_ *prev; + int index; + int val; +} NODE; + +NODE* free_lists[LIST_SIZE + 1]; + +NODE node[PAGE_NUM + 1]; + +extern uint32_t _heap_begin; +extern uint32_t _heap_end; + +extern uint32_t _image_memory_begin; +extern uint32_t _image_memory_end; + +void *mem_chunk_begin; +void *mem_chunk_end; + +int check; + +void *simple_malloc(size_t size){ + if(check != 1){ + check = 1; + mem_chunk_begin = (void *) &_heap_begin; + mem_chunk_end = (void *) &_heap_end; + } + size = (((size - 1) >> 4) + 1) << 4; + if((uint64_t) mem_chunk_begin + size >= (uint64_t) mem_chunk_end){ + return NULL; + } + void *tmp = mem_chunk_begin; + mem_chunk_begin = (void *)((uint64_t) mem_chunk_begin + size); + return tmp; +} +/// +typedef struct{ + int found; + char *initrd_start; + char *initrd_end; +} ramdisk_data; + +int malloc_ramdisk_fdt_callback(char* node, const char *name, void *data){ + if(strcmp(name, "chosen")) return 0; + ramdisk_data* _data = (ramdisk_data*) data; + fdt_prop *prop; + while(prop = fdt_nextprop(node + 1, &node)){ + if(!strcmp(prop->name,"linux,initrd-start")){ + _data->initrd_start = (char *)(uint64_t)ntohl(*(uint32_t*)prop->value); + } + if(!strcmp(prop->name,"linux,initrd-end")){ + _data->initrd_end = (char *)(uint64_t)ntohl(*(uint32_t*)prop->value); + } + } + _data->found = 1; + return 1; +} + +int ramdisk_reserve(){ + ramdisk_data data; + data.initrd_start = 0; + data.initrd_end = 0; + data.found = 0; + fdt_traverse(malloc_ramdisk_fdt_callback, (void *)&data); + if(data.found){ + memory_reserve((uint64_t)data.initrd_start, (uint64_t)data.initrd_end); + return 0; + } + return -1; +} +/// + +int log_2(uint64_t num){ + int count = 0; + uint64_t tmp = 1; + while(tmp < num){ + count++; + tmp <<= 1; + } + return count; +} + +uint64_t phy_addr(NODE* tmp){ + return (uint64_t) (tmp->index * FRAME_SIZE); +} + +uint64_t block_size(NODE* tmp){ + return (uint64_t) (FRAME_SIZE * (1 << tmp->val)); +} + +void show_node_info(NODE* tmp){ + int i = tmp->index; + uart_print("Node["); + uart_print_hex(i, 32); + uart_print("]: addr("); + uart_print_hex(phy_addr(&node[i]), 64); + uart_print("), size("); + uart_print_hex(block_size(&node[i]), 64); + uart_print(")"); + newline(); +} + +void list_erase(int i){ + uart_print("Erase node:\n"); + show_node_info(&node[i]); + int k = node[i].val; + if(free_lists[k] && free_lists[k]->index == i){ + free_lists[k] = free_lists[k]->next; + if(free_lists[k]) free_lists[k]->prev = NULL; + node[i].prev = NULL; + node[i].next = NULL; + node[i].val = -2; + return; + }else{ + NODE *now = &node[i]; + now->prev->next = now->next; + if(now->next) now->next->prev = now->prev; + node[i].prev = NULL; + node[i].next = NULL; + node[i].val = -2; + return; + } + uart_print("Erase error!!!\n"); +} + +void list_insert(int i, NODE* tmp){ + if(free_lists[i] == NULL){ + free_lists[i] = tmp; + }else{ + tmp->next = free_lists[i]; + free_lists[i]->prev = tmp; + free_lists[i] = tmp; + } + uart_print("list insert "); + uart_print_hex(i, 32); + newline(); + show_node_info(tmp); +} + +NODE *list_top(int i){ + return free_lists[i]; +} + +void buddy_system_init() { + uart_print("Allocator init\n"); + for(int i = 0; i <= PAGE_NUM; i++){ + node[i].next = NULL; + node[i].prev = NULL; + node[i].index = i; + if(i == 0x00){ + node[i].val = log_2(0x20000); + list_insert(node[i].val, &node[i]); + }else if(i == 0x20000){ + node[i].val = log_2(0x10000); + list_insert(node[i].val, &node[i]); + }else if(i == 0x30000){ + node[i].val = log_2(0x8000); + list_insert(node[i].val, &node[i]); + }else if(i == 0x38000){ + node[i].val = log_2(0x4000); + list_insert(node[i].val, &node[i]); + }else{ + node[i].val = F; + } + } +} + +void malloc_init(){ + for(int i = 0; i < LIST_SIZE + 1; i++){ + free_lists[i] = NULL; + } + + buddy_system_init(); + memory_reserve(0x0000, 0x1000); // 1 + memory_reserve((uint64_t) &_image_memory_begin, (uint64_t) &_image_memory_end);// 2, 5 + ramdisk_reserve(); // 3 + if((uint64_t) _devicetree_begin != 0xffffffff){ // 4 + fdt_header *header = (fdt_header *) _devicetree_begin; + uint64_t _devicetree_end = (uint64_t) _devicetree_begin + ntohl(header->totalsize); + memory_reserve((uint64_t)_devicetree_begin, (uint64_t) _devicetree_end); + } +} + +int node_split(NODE* tmp, int power_size){ + if(power_size <= 0) return -1; + int r = tmp->index ^ (1 << (power_size - 1)); + list_erase(tmp->index); + tmp->val = power_size - 1; + node[r].val = power_size - 1; + uart_print("Split buddy: \n"); + uart_print("1: \n"); + show_node_info(tmp); + uart_print("2: \n"); + show_node_info(&node[r]); + list_insert(power_size - 1, &node[r]); + list_insert(power_size - 1, tmp); + return r; +} + +void *buddy_system_malloc(size_t size){ + uart_print("-------------\n"); + uart_print("Request size: "); + uart_print_hex(size, 32); + newline(); + size = size / FRAME_SIZE + (size % FRAME_SIZE != 0); + const int o_power_size = log_2(size); + int power_size = o_power_size; + while(power_size <= LIST_SIZE){ + if(free_lists[power_size] == NULL){ + power_size++; + continue; + } + if(free_lists[power_size]->val < 0){ + uart_print_hex(free_lists[power_size]->val, 32); + uart_print("alloc error!!!\n"); + } + NODE *tmp = list_top(power_size); + while(o_power_size < power_size){ + node_split(tmp, power_size); + power_size--; + } + uart_print("Found node: "); + show_node_info(tmp); + int tmp_val = tmp->val; + list_erase(tmp->index); + uart_print("-------------\n"); + + uint64_t addr_tmp = phy_addr(tmp); + tmp->val = -1 * tmp_val - X; + return (void *) addr_tmp; + } + uart_print("No enough space!!!\n"); + uart_print("-------------\n"); + return NULL; +} + + + +void node_merge(NODE* tmp){ + if(tmp->index == 0x0 && tmp->val == log_2(0x20000)) return; + if(tmp->index == 0x20000 && tmp->val == log_2(0x10000)) return; + if(tmp->index == 0x30000 && tmp->val == log_2(0x8000)) return; + if(tmp->index == 0x38000 && tmp->val == log_2(0x4000)) return; + int r = tmp->index ^ (1 << tmp->val); + if(node[r].val == tmp->val){ + uart_print("Merge node: \n"); + uart_print("1: \n"); + show_node_info(tmp); + uart_print("2: \n"); + show_node_info(&node[r]); + int tmp_val = tmp->val; + list_erase(tmp->index); + list_erase(r); + if(tmp->index > r){ + node[r].val = tmp_val + 1; + tmp->val = -1; + list_insert(node[r].val, &node[r]); + node_merge(&node[r]); + }else{ + node[r].val = -1; + tmp->val = tmp_val + 1; + list_insert(tmp->val, tmp); + node_merge(tmp); + } + } +} + +void buddy_system_free(void *tmp){ + uart_print("-------------\n"); + uart_print("Free node: "); + uart_print_hex((uint64_t) tmp, 64); + newline(); + uint64_t i = (uint64_t) tmp / FRAME_SIZE; + if(node[i].val > -1 * X){ + uart_print("free error!\n"); + }else{ + node[i].val = (node[i].val + X) * -1; + list_insert(node[i].val, &node[i]); + node_merge(&node[i]); + } + uart_print("-------------\n"); +} + +void __memory_reserve(int i, uint64_t begin, uint64_t end){ + uart_print("Check "); + uart_print_hex(i, 64); + newline(); + int lbound = phy_addr(&node[i]); + int rbound = phy_addr(&node[i + (1 << node[i].val)]); + if(begin <= lbound && end >= rbound){ + list_erase(i); + }else if(end <= lbound || begin >= rbound){ + return; + }else{ + int j = node_split(&node[i], node[i].val); + if(j == -1) { + list_erase(i); + return; + } + __memory_reserve(i, begin, end); + __memory_reserve(j, begin, end); + } +} + +void memory_reserve(uint64_t begin, uint64_t end) { + uart_print("Reserve "); + uart_print_hex(begin, 64); + uart_print(" - "); + uart_print_hex(end, 64); + newline(); + for(int i = 0; i <= LIST_SIZE; i++){ + for(NODE * now = free_lists[i]; now != NULL; now = now->next){ + __memory_reserve(now->index, begin, end); + } + } +} + +typedef struct per_chunk_{ + struct per_chunk_ *next; + uint64_t addr; +} per_chunk; + +typedef struct chunk_{ + struct chunk_ *t_next; + per_chunk * next; + uint64_t begin; + uint64_t end; +} chunk; + +chunk *chunk_table = NULL; + +void *kmalloc(size_t size){ + if(chunk_table == NULL){ + chunk_table = simple_malloc(sizeof(chunk)); + chunk_table->begin = (uint64_t) buddy_system_malloc(0x1000); + chunk_table->end = chunk_table->begin + 0x1000; + chunk_table->t_next = NULL; + chunk_table->next = NULL; + } + chunk *now = chunk_table; + size = (((size - 1) >> 4) + 1) << 4; + while((uint64_t) now->begin + size >= (uint64_t) now->end){ + if(now->t_next){ + now = now->t_next; + continue; + }else{ + chunk* chunk_tmp = now->t_next; + now->t_next = simple_malloc(sizeof(chunk)); + now = now->t_next; + now->begin = (uint64_t) buddy_system_malloc(0x1000); + now->end = now->begin + 0x1000; + now->t_next = chunk_tmp; + now->next = NULL; + } + } + uint64_t tmp = now->begin; + now->begin = ((uint64_t) now->begin + size); + if(now->next == NULL){ + now->next = simple_malloc(sizeof(per_chunk)); + now->next->addr = tmp; + now->next->next = NULL; + }else{ + per_chunk *per_chunk_tmp = now->next; + now->next = simple_malloc(sizeof(per_chunk)); + now->next->addr = tmp; + now->next->next = per_chunk_tmp; + now->next->next = NULL; + } + + return (void *)tmp; +} + +void kfree(void * tmp){ + chunk *now = chunk_table; + chunk *prev = chunk_table; + for(; now != NULL; now = now->t_next){ + if(now->next->addr == (uint64_t) tmp){ + now->next = now->next->next; + if(now->next == NULL){ + buddy_system_free((void * )now->begin); + if(chunk_table == now){ + chunk_table = NULL; + }else{ + prev->t_next = now->t_next; + } + } + return; + } + for(per_chunk* cur = now->next; cur != NULL; cur = cur->next){ + if((uint64_t) tmp == cur->next->addr){ + cur->next = cur->next->next; + return; + } + } + prev = now; + } +} \ No newline at end of file diff --git a/lab4/src/lib/command.c b/lab4/src/lib/command.c new file mode 100644 index 000000000..4852168e7 --- /dev/null +++ b/lab4/src/lib/command.c @@ -0,0 +1,129 @@ +#include +// C +#include +#include +// tool +#include +#include +// lab1 +#include +#include +#include +// lab2 +#include +#include +#include +// lab3 +#include +#include + + +extern uint32_t _user_begin; +extern uint32_t _user_end; + +void help(){ + uart_print("help\t : print this help menu"); + newline(); + uart_print("hello\t : print Hello World!"); + newline(); + uart_print("reboot\t : reboot the device"); + newline(); + uart_print("ls\t : list directory contents"); + newline(); + uart_print("cat\t : concatenate files and print on the standard output"); + newline(); + uart_print("exec\t : execute a file"); + newline(); + uart_print("setTimeout\t: set a timer"); + newline(); +} + +void hello(){ + uart_print("Hello World!"); + newline(); +} + +void reboot(){ + uart_print("Reboot system now!"); + newline(); + reset(1<<16); +} + +void ls(){ + cpio_file* file_ptr = cpio_parse(); + for(cpio_file* cur = file_ptr; cur != NULL; cur = cur->next){ + uart_print(cur->name); + newline(); + } +} + +void cat(char *filename){ + cpio_file* file_ptr = cpio_parse(); + if(file_ptr == NULL){ + uart_print("Error: cpio"); + return; + } + int isfound = 0; + for(cpio_file* cur = file_ptr; cur != NULL; cur = cur->next){ + if(strcmp(filename, cur->name) == 0){ + uart_write(cur->content, cur->filesize); + isfound = 1; + break; + } + } + if(!isfound){ + uart_print("Not Found!"); + newline(); + } +} + +void exec(char *filename){ + cpio_file* file_ptr = cpio_parse(); + if(file_ptr == NULL){ + uart_print("Error: cpio"); + return; + } + int isfound = 0; + for(cpio_file* cur = file_ptr; cur != NULL; cur = cur->next){ + if(strcmp(filename, cur->name) == 0){ + isfound = 1; + memcpy(&_user_begin, cur->content, cur->filesize); + coretimer_el0_enable(); + /* + uart_print("&_user_begin="); + uart_print_hex((uint64_t) &_user_begin, 64); + newline(); + uart_print("&_user_end="); + uart_print_hex((uint64_t) &_user_end, 64); + newline(); + */ + asm("msr spsr_el1, %0"::"r"((uint64_t)0x0)); // 0x0 enable all interrupt + asm("msr elr_el1, %0"::"r"(&_user_begin)); + asm("msr sp_el0, %0"::"r"(&_user_end)); + asm("eret"); + break; + } + } + if(!isfound){ + uart_print("Not Found!"); + newline(); + } +} + +void timeout(void *arg){ + uart_print("Timeout: "); + uart_print((char *)arg); + newline(); +} + +void setTimeout(){ + int time; + char *msg = (char *)simple_malloc(0x20); + char time_inp[0x20]; + uart_print("Time (secs): "); + uart_readline(time_inp); + time = atoi(time_inp); + uart_print("Msg: "); + uart_readline(msg); + add_timer(time, &timeout, (void *)msg); +} \ No newline at end of file diff --git a/lab4/src/lib/coretimer.c b/lab4/src/lib/coretimer.c new file mode 100644 index 000000000..aafd6bbde --- /dev/null +++ b/lab4/src/lib/coretimer.c @@ -0,0 +1,103 @@ +#include + +#include + +#include +#include +#include +#include + +TIMER* timer_queue; + +void timer_queue_push(TIMER* new_timer){ + interrupt_disable(); + if(!timer_queue){ + timer_queue = new_timer; + goto ret; + } + TIMER* head = timer_queue; + TIMER* prev = 0; + if(head->time > new_timer->time){ + new_timer->next = head; + timer_queue = new_timer; + goto ret; + } + while(head->next){ + prev = head; + head = head->next; + if(head->time > new_timer->time){ + new_timer->next = head; + prev->next = new_timer; + goto ret; + } + } + head->next = new_timer; +ret: + interrupt_enable(); +} + +TIMER* timer_queue_pop(){ + if(!timer_queue) return 0; + interrupt_disable(); + TIMER* timer = timer_queue; + timer_queue = timer_queue->next; + interrupt_enable(); + return timer; +} + +TIMER* timer_queue_top(){ + if(!timer_queue) return 0; + return timer_queue; +} + +void timer_sched(){ + TIMER* timer = timer_queue_top(); + if(!timer) return ; + uint64_t cntpct_el0; + asm("mrs %0, cntpct_el0":"=r"(cntpct_el0)); + asm("msr cntp_tval_el0, %0"::"r"((uint32_t)timer->time-cntpct_el0)); + memory_write(CORE0_TIMER_IRQ_CTRL, 2); +} + +void coretimer_el0_enable(){ + asm("msr cntp_ctl_el0, %0"::"r"((uint64_t)1)); +} + +void coretimer_el0_handler(){ + memory_write(CORE0_TIMER_IRQ_CTRL, 0); + uint64_t cntpct_el0; + asm("mrs %0, cntpct_el0":"=r"(cntpct_el0)); + + TIMER* timer; + while(1){ + interrupt_disable(); + timer = timer_queue_top(); + if(!timer){ + interrupt_enable(); + break; + } + if(timer->time > cntpct_el0) break; + timer_queue_pop(); + interrupt_enable(); + timer->func(timer->arg); + } + timer_sched(); +} + +void add_timer(uint64_t time_wait, void (*func)(void *), void *arg){ + uint32_t cntfrq_el0; + uint64_t cntpct_el0; + asm("mrs %0, cntfrq_el0":"=r"(cntfrq_el0)); + asm("mrs %0, cntpct_el0":"=r"(cntpct_el0)); + + uint64_t time = cntpct_el0 + time_wait * cntfrq_el0; + + TIMER* new_timer = (TIMER*)simple_malloc(sizeof(TIMER)); + new_timer->time = time; + new_timer->func = func; + new_timer->arg = arg; + new_timer->next = 0; + + timer_queue_push(new_timer); + timer_sched(); +} \ No newline at end of file diff --git a/lab4/src/lib/devicetree.c b/lab4/src/lib/devicetree.c new file mode 100644 index 000000000..4feaedac8 --- /dev/null +++ b/lab4/src/lib/devicetree.c @@ -0,0 +1,88 @@ +#include + +#include +#include +#include +#include + +void *_devicetree_begin = (void *) 0xffffffff; + +void fdt_traverse(initramfs_callback f, void *data){ + char *fdt = (char *) _devicetree_begin; + if((uint64_t)fdt == 0xffffffff) return; + + fdt_header *header = (fdt_header *) fdt; + + char *fdt_struct_begin = fdt + ntohl(header->off_dt_struct); + char *fdt_string_begin = fdt + ntohl(header->off_dt_strings); + char *fdt_struct_end = fdt_struct_begin + ntohl(header->size_dt_struct); + + int isend = 0; + char *node_name; + char *prop_name; + for(char *node = fdt_nextnode(fdt_struct_begin-1, fdt_struct_end); node && !isend; node = fdt_nextnode(node, fdt_struct_end)){ + f(node, node + 4, data); + } +} + +char *fdt_nextnode(char *fdt_addr, char *fdt_struct_end){ + fdt_addr = (char *) align((uint64_t) fdt_addr); + int isend = 0; + while((uint64_t)fdt_addr < (uint64_t)fdt_struct_end && !isend) { + switch (ntohl(*(uint32_t*)fdt_addr)){ + case FDT_BEGIN_NODE: { + return fdt_addr; + }case FDT_PROP: { + fdt_addr += (uint64_t)ntohl(*(uint32_t*)(fdt_addr + 4)) + 8; + break; + }case FDT_END: { + isend = 1; + break; + }case FDT_END_NODE: { + }case FDT_NOP: { + break; + } + } + fdt_addr = (char *) align((uint64_t) fdt_addr); + } + return 0; +} + +fdt_prop *fdt_nextprop(char *fdt_addr, char **nexttok){ + char *fdt = (char *)_devicetree_begin; + if((uint64_t)fdt == 0xffffffff) return 0; + + fdt_header *header = (fdt_header *) fdt; + + char *fdt_string_begin = fdt + ntohl(header->off_dt_strings); + + fdt_addr = (char *) align((uint64_t) fdt_addr - 1); + int isend = 0; + fdt_prop *prop; + while(!isend) { + switch (ntohl(*(uint32_t*)fdt_addr)){ + case FDT_PROP: + prop = (fdt_prop*) simple_malloc(sizeof(fdt_prop)); + if(prop == NULL){ + uart_print("Error: fdt_nuxtprop"); + newline(); + return NULL; + } + prop->len = ntohl(*(uint32_t*)(fdt_addr+4)); + prop->name = fdt_string_begin + ntohl(*(uint32_t *) (fdt_addr + 8)); + prop->value = fdt_addr + 12; + *nexttok = (void *) fdt_addr + 8 + ntohl(*(uint32_t*) (fdt_addr + 4)); + return prop; + case FDT_END: + case FDT_BEGIN_NODE: + case FDT_END_NODE: + isend = 1; + break; + case FDT_NOP: + break; + } + fdt_addr = (char *) align((uint64_t) fdt_addr); + } + return 0; +} + diff --git a/lab4/src/lib/exception_table.s b/lab4/src/lib/exception_table.s new file mode 100644 index 000000000..09ac8ad90 --- /dev/null +++ b/lab4/src/lib/exception_table.s @@ -0,0 +1,101 @@ +.section ".text.exception" +.extern "exception_handler" + +// save general registers to stack +.macro save_all + sub sp, sp, 32 * 8 + stp x0, x1, [sp ,16 * 0] + stp x2, x3, [sp ,16 * 1] + stp x4, x5, [sp ,16 * 2] + stp x6, x7, [sp ,16 * 3] + stp x8, x9, [sp ,16 * 4] + stp x10, x11, [sp ,16 * 5] + stp x12, x13, [sp ,16 * 6] + stp x14, x15, [sp ,16 * 7] + stp x16, x17, [sp ,16 * 8] + stp x18, x19, [sp ,16 * 9] + stp x20, x21, [sp ,16 * 10] + stp x22, x23, [sp ,16 * 11] + stp x24, x25, [sp ,16 * 12] + stp x26, x27, [sp ,16 * 13] + stp x28, x29, [sp ,16 * 14] + str x30, [sp, 16 * 15] +.endm + +// load general registers from stack +.macro load_all + ldp x0, x1, [sp ,16 * 0] + ldp x2, x3, [sp ,16 * 1] + ldp x4, x5, [sp ,16 * 2] + ldp x6, x7, [sp ,16 * 3] + ldp x8, x9, [sp ,16 * 4] + ldp x10, x11, [sp ,16 * 5] + ldp x12, x13, [sp ,16 * 6] + ldp x14, x15, [sp ,16 * 7] + ldp x16, x17, [sp ,16 * 8] + ldp x18, x19, [sp ,16 * 9] + ldp x20, x21, [sp ,16 * 10] + ldp x22, x23, [sp ,16 * 11] + ldp x24, x25, [sp ,16 * 12] + ldp x26, x27, [sp ,16 * 13] + ldp x28, x29, [sp ,16 * 14] + ldr x30, [sp, 16 * 15] + add sp, sp, 32 * 8 +.endm + + +_exception_handler: + save_all + bl exception_handler + load_all + eret +_irq_handler: + save_all + bl interrupt_irq_handler + load_all + eret +_not_implement: + save_all + bl not_implemented_interrupt + load_all + eret + + +.align 11 // vector table should be aligned to 0x800 +.global exception_vector_table +exception_vector_table: + b _not_implement // branch to a handler function. + .align 7 // entry size is 0x80, .align will pad 0 + b _not_implement + .align 7 + b _not_implement + .align 7 + b _not_implement + .align 7 + + b _exception_handler + .align 7 + b _irq_handler + .align 7 + b _not_implement + .align 7 + b _not_implement + .align 7 + + b _exception_handler + .align 7 + b _irq_handler + .align 7 + b _not_implement + .align 7 + b _not_implement + .align 7 + + b _not_implement + .align 7 + b _not_implement + .align 7 + b _not_implement + .align 7 + b _not_implement + .align 7 \ No newline at end of file diff --git a/lab4/src/lib/include/allocator.h b/lab4/src/lib/include/allocator.h new file mode 100644 index 000000000..424c194df --- /dev/null +++ b/lab4/src/lib/include/allocator.h @@ -0,0 +1,12 @@ +#ifndef __ALLOCATOR__ +#define __ALLOCATOR__ +#include +#include +void *simple_malloc(size_t size); +void malloc_init(); +void *buddy_system_malloc(size_t size); +void buddy_system_free(void *tmp); +void memory_reserve(uint64_t begin, uint64_t end); +void *kmalloc(size_t size); +void kfree(void * tmp); +#endif \ No newline at end of file diff --git a/lab4/src/lib/include/command.h b/lab4/src/lib/include/command.h new file mode 100644 index 000000000..ba8170349 --- /dev/null +++ b/lab4/src/lib/include/command.h @@ -0,0 +1,10 @@ +#ifndef __COMMAND__ +#define __COMMAND__ +void help(); +void hello(); +void reboot(); +void ls(); +void cat(char *filename); +void exec(char *filename); +void setTimeout(); +#endif \ No newline at end of file diff --git a/lab4/src/lib/include/coretimer.h b/lab4/src/lib/include/coretimer.h new file mode 100644 index 000000000..404c7785f --- /dev/null +++ b/lab4/src/lib/include/coretimer.h @@ -0,0 +1,19 @@ +#ifndef __CORETIMER__ +#define __CORETIMER__ + +#include + +#define CORE0_TIMER_IRQ_CTRL 0x40000040 + +typedef struct TIMER_{ + uint64_t time; + void (*func)(void *); + void *arg; + struct TIMER_* next; +} TIMER; + +void coretimer_el0_enable(); +void coretimer_el0_handler(); +void add_timer(uint64_t time_wait, void (*func)(void *), void *arg); + +#endif \ No newline at end of file diff --git a/lab4/src/lib/include/devicetree.h b/lab4/src/lib/include/devicetree.h new file mode 100644 index 000000000..b01dde5e0 --- /dev/null +++ b/lab4/src/lib/include/devicetree.h @@ -0,0 +1,39 @@ + +#ifndef __DEVICETREE__ +#define __DEVICETREE__ +#include +#include + +#define FDT_BEGIN_NODE 0x00000001 +#define FDT_END_NODE 0x00000002 +#define FDT_PROP 0x00000003 +#define FDT_NOP 0x00000004 +#define FDT_END 0x00000009 + +extern void *_devicetree_begin; + +typedef struct _fdt_header { // 5.2 big-endian + uint32_t magic; // 0xd00dfeed + uint32_t totalsize; // + uint32_t off_dt_struct; // offset in bytes of the devicetree struct + uint32_t off_dt_strings; // offset in bytes of the strings block + uint32_t off_mem_rsvmap; + uint32_t version; + uint32_t last_comp_version; + uint32_t boot_cpuid_phys; + uint32_t size_dt_strings; // the length in bytes of the strings block + uint32_t size_dt_struct; // the length in bytes of the structure block +} fdt_header; + +typedef struct _fdt_prop{ // 5.4 FDT_PROP (0x00000003) + uint32_t len; + //uint32_t nameoff; + const char *name; + const char *value; +} fdt_prop; + +typedef int (*initramfs_callback)(char* node, const char *name, void *data); +void fdt_traverse(initramfs_callback f, void *data); +char *fdt_nextnode(char *fdt_addr, char *fdt_struct_end); +fdt_prop *fdt_nextprop(char *fdt_addr, char **nexttok); +#endif \ No newline at end of file diff --git a/lab4/src/lib/include/interrupt.h b/lab4/src/lib/include/interrupt.h new file mode 100644 index 000000000..bb6f6cbbf --- /dev/null +++ b/lab4/src/lib/include/interrupt.h @@ -0,0 +1,18 @@ +#ifndef __INTERRUPT__ +#define __INTERRUPT__ + +#include +#include + +#define MMIO_BASE 0x3f000000 +#define ARMINTERRUPT_BASE MMIO_BASE + 0xB000 +#define ARMINT_IRQ_PEND_BASE_REG ARMINTERRUPT_BASE + 0x200 +#define ARMINT_IRQ_PEND1_REG ARMINTERRUPT_BASE + 0x204 +#define ARMINT_IRQ_PEND2_REG ARMINTERRUPT_BASE + 0x208 +#define ARMINT_En_IRQs1_REG ARMINTERRUPT_BASE + 0x210 +#define CORE0_INTERRUPT_SOURCE 0x40000060 + +void interrupt_enable(); +void interrupt_disable(); +void interrupt_irq_handler(); +#endif \ No newline at end of file diff --git a/lab4/src/lib/include/mailbox.h b/lab4/src/lib/include/mailbox.h new file mode 100644 index 000000000..a249d01af --- /dev/null +++ b/lab4/src/lib/include/mailbox.h @@ -0,0 +1,25 @@ +#ifndef __MAILBOX__ +#define __MAILBOX__ +#include +#define MMIO_BASE 0x3f000000 +#define MAILBOX_BASE MMIO_BASE + 0xb880 + +#define MAILBOX_READ MAILBOX_BASE +#define MAILBOX_STATUS MAILBOX_BASE + 0x18 +#define MAILBOX_WRITE MAILBOX_BASE + 0x20 + +#define MAILBOX_EMPTY 0x40000000 +#define MAILBOX_FULL 0x80000000 + +#define GET_BOARD_REVISION 0x00010002 +#define GET_ARM_MEMORY 0x00010005 +#define REQUEST_CODE 0x00000000 +#define REQUEST_SUCCEED 0x80000000 +#define REQUEST_FAILED 0x80000001 +#define TAG_REQUEST_CODE 0x00000000 +#define END_TAG 0x00000000 + +void mailbox_call(uint32_t* mailbox); +void get_board_revision(uint32_t*revision); +void get_ARM_memory_base_address_and_size(uint32_t*addr_base, uint32_t*size); +#endif \ No newline at end of file diff --git a/lab4/src/lib/include/ramdisk.h b/lab4/src/lib/include/ramdisk.h new file mode 100644 index 000000000..56fc76f1c --- /dev/null +++ b/lab4/src/lib/include/ramdisk.h @@ -0,0 +1,46 @@ +#ifndef __RAMDISK__ +#define __RAMDISK__ +#include +#include + +struct cpio_newc_header { + char c_magic[6]; // 070702 + char c_ino[8]; // inode numbers + char c_mode[8]; // mode + char c_uid[8]; // uid + char c_gid[8]; // gid + char c_nlink[8]; // link number + char c_mtime[8]; + char c_filesize[8]; // content size + char c_devmajor[8]; + char c_devminor[8]; + char c_rdevmajor[8]; + char c_rdevminor[8]; + char c_namesize[8]; // file name length + char c_check[8]; // sum of all bytes +}; + +typedef struct _cpio_file{ + char *header; + uint32_t ino; + uint32_t mode; + uint32_t uid; + uint32_t gid; + uint32_t nlink; + uint32_t mtime; + uint32_t filesize; + uint32_t devmajor; + uint32_t devminor; + uint32_t rdevmajor; + uint32_t rdevminor; + uint32_t namesize; + uint32_t check; + char *name; + char *content; + struct _cpio_file *next; +} cpio_file; + +int ramdisk_get_addr(); +cpio_file* cpio_parse(); + +#endif \ No newline at end of file diff --git a/lab4/src/lib/include/reboot.h b/lab4/src/lib/include/reboot.h new file mode 100644 index 000000000..dbe0d77da --- /dev/null +++ b/lab4/src/lib/include/reboot.h @@ -0,0 +1,9 @@ +#ifndef __REBOOT__ +#define __REBOOT__ +#define PM_PASSWORD 0x5a000000 +#define PM_RSTC 0x3F10001c +#define PM_WDOG 0x3F100024 +void set(long addr, unsigned int value); +void reset(int tick); +void cancel_reset(); +#endif \ No newline at end of file diff --git a/lab4/src/lib/include/shell.h b/lab4/src/lib/include/shell.h new file mode 100644 index 000000000..f0f75eb16 --- /dev/null +++ b/lab4/src/lib/include/shell.h @@ -0,0 +1,5 @@ +#ifndef __SHELL__ +#define __SHELL__ +#define BUF_SIZE 256 +void shell(); +#endif \ No newline at end of file diff --git a/lab4/src/lib/include/string.h b/lab4/src/lib/include/string.h new file mode 100644 index 000000000..e7c0a07a5 --- /dev/null +++ b/lab4/src/lib/include/string.h @@ -0,0 +1,10 @@ +#ifndef __STRING__ +#define __STRING__ +#include +#include +int atoi(const char* str); +int strcmp(const char* x, const char* y); +int strncmp(const char*x, const char*y, int len); +size_t strlen(const char *str); +void *memcpy(void *dst, const void *src, size_t n); +#endif \ No newline at end of file diff --git a/lab4/src/lib/include/uart.h b/lab4/src/lib/include/uart.h new file mode 100644 index 000000000..370b47b8f --- /dev/null +++ b/lab4/src/lib/include/uart.h @@ -0,0 +1,52 @@ +#ifndef __UART__ +#define __UART__ +#include +#include + +#define RingBuffer_flag_Empty 0b1 +#define RingBuffer_flag_Full 0b10 +#define RingBuffer_Empty(buf) (buf->flags&RingBuffer_flag_Empty) +#define RingBuffer_Full(buf) (buf->flags&RingBuffer_flag_Full) + +#define BASE_ADDR 0x3f000000 +#define AUX_ENABLES BASE_ADDR + 0x215004 +#define AUX_MU_CNTL_REG BASE_ADDR + 0x215060 +#define AUX_MU_IER_REG BASE_ADDR + 0x215044 +#define AUX_MU_LCR_REG BASE_ADDR + 0x21504c +#define AUX_MU_MCR_REG BASE_ADDR + 0x215050 +#define AUX_MU_BAUD_REG BASE_ADDR + 0x215068 +#define AUX_MU_IIR_REG BASE_ADDR + 0x215048 +#define AUX_MU_LSR_REG BASE_ADDR + 0x215054 +#define AUX_MU_IO_REG BASE_ADDR + 0x215040 +#define GPFSEL0 BASE_ADDR + 0x200000 +#define GPFSEL1 BASE_ADDR + 0x200004 +#define GPPUD BASE_ADDR + 0x200094 +#define GPPUDCLK0 BASE_ADDR + 0x200098 +#define GPPUDCLK1 BASE_ADDR + 0x20009c + +typedef struct{ + uint32_t flags; + char *buf; + uint32_t lbound,rbound; + size_t size, len; +} RingBuffer; + +void uart_init(); + +size_t uart_write_1c(char*buf); +size_t uart_write(char* buf, size_t len); +size_t uart_readline(char* buf); +void uart_print(char* buf); +void uart_print_hex(uint64_t num, int len); +void newline(); + +void uart_interrupt_handler(); +size_t uart_read_sync(char* buf, size_t len); +size_t uart_read_async(char* buf, size_t len); + +RingBuffer *RingBuffer_new(size_t bufsize); +size_t RingBuffer_writeb(RingBuffer *rbuf, char b); +size_t RingBuffer_readb(RingBuffer *rbuf, char* b); + +#endif +#define uart_read uart_read_async \ No newline at end of file diff --git a/lab4/src/lib/include/utils.h b/lab4/src/lib/include/utils.h new file mode 100644 index 000000000..ba9128b99 --- /dev/null +++ b/lab4/src/lib/include/utils.h @@ -0,0 +1,16 @@ +#ifndef __UTILS__ +#define __UTILS__ +#include +#include +#define memory_read(addr) *(uint32_t *)(addr) +#define memory_write(addr,val) *(uint32_t *)(addr) = (uint32_t)(val) +#define align(tmp) (void*)((tmp >> 2) + 1 << 2) +void wait_cycles(uint32_t times); +uint32_t hex2u32_8(char *buf); +uint16_t ntohs(uint16_t tmp); +uint32_t ntohl(uint32_t tmp); +uint64_t ntohll(uint64_t tmp); +uint16_t htons(uint16_t tmp); +uint32_t htonl(uint32_t tmp); +uint64_t htonll(uint64_t tmp); +#endif \ No newline at end of file diff --git a/lab4/src/lib/interrupt.c b/lab4/src/lib/interrupt.c new file mode 100644 index 000000000..8cbd1326c --- /dev/null +++ b/lab4/src/lib/interrupt.c @@ -0,0 +1,64 @@ +#include + +#include +#include + +#include +#include +#include + +uint32_t interrupt_depth; + +void interrupt_enable(){ + if(interrupt_depth==0) asm("msr DAIFClr, 0xf"); + interrupt_depth++; +} + +void interrupt_disable(){ + interrupt_depth--; + if(interrupt_depth == 0) asm("msr DAIFSet, 0xf"); +} +#include +void exception_handler(){ + uint64_t spsr_el1; + uint64_t elr_el1; + uint64_t esr_el1; + uint64_t x0; + asm("mov %0, x0":"=r"(x0)); + asm("mrs %0, spsr_el1":"=r"(spsr_el1)); + asm("mrs %0, elr_el1":"=r"(elr_el1)); + asm("mrs %0, esr_el1":"=r"(esr_el1)); + uart_print("x0: "); + uart_print_hex(x0, 64); + newline(); + uart_print("spsr_el1: "); + uart_print_hex(spsr_el1, 64); + newline(); + uart_print("elr_el1: "); + uart_print_hex(elr_el1, 64); + newline(); + uart_print("esr_el1: "); + uart_print_hex(esr_el1, 64); + newline(); + reboot(); +} + +void interrupt_irq_handler(){ + uint32_t irq_pend_base_reg = memory_read(ARMINT_IRQ_PEND_BASE_REG); + uint32_t irq_pend1_reg = memory_read(ARMINT_IRQ_PEND1_REG); + uint32_t irq_pend2_reg = memory_read(ARMINT_IRQ_PEND2_REG); + uint32_t core0_int_src = memory_read(CORE0_INTERRUPT_SOURCE); + uint32_t aux_mu_iir_reg = memory_read(AUX_MU_IIR_REG); + + if(core0_int_src & 0b10){ + coretimer_el0_handler(); + } + if(aux_mu_iir_reg&0b100){ + uart_interrupt_handler(); + } +} + +void not_implemented_interrupt(){ + uart_print("Not implemented!!!"); + newline(); +} diff --git a/lab4/src/lib/mailbox.c b/lab4/src/lib/mailbox.c new file mode 100644 index 000000000..c7b3fad2f --- /dev/null +++ b/lab4/src/lib/mailbox.c @@ -0,0 +1,56 @@ +#include + +#include + +#include +#include + +void mailbox_call(uint32_t* mailbox){ + uint32_t mailbox_addr = (uint32_t)((uint64_t)mailbox & 0xfffffff0); + mailbox_addr |= 8; + while((memory_read(MAILBOX_STATUS) & MAILBOX_FULL) != 0); + memory_write(MAILBOX_WRITE, mailbox_addr); + while(1){ + while((memory_read(MAILBOX_STATUS) & MAILBOX_EMPTY) != 0); + uint32_t data = memory_read(MAILBOX_READ); + if((data & 0xf) == 8) break; + } +} + +void get_board_revision(uint32_t*revision){ + unsigned int mailbox[7]; + mailbox[0] = 7 * 4; // buffer size in bytes + mailbox[1] = REQUEST_CODE; + // tags begin + mailbox[2] = GET_BOARD_REVISION; // tag identifier + mailbox[3] = 4; // maximum of request and response value buffer's length. + mailbox[4] = TAG_REQUEST_CODE; + mailbox[5] = 0; // value buffer + // tags end + mailbox[6] = END_TAG; + + mailbox_call(mailbox); // message passing procedure call, you should implement it following the 6 steps provided above. + + //printf("0x%x\n", mailbox[5]); // it should be 0xa020d3 for rpi3 b+ + *revision = mailbox[5]; +} + +void get_ARM_memory_base_address_and_size(uint32_t*addr_base, uint32_t*size){ + unsigned int mailbox[8]; + mailbox[0] = 8 * 4; // buffer size in bytes + mailbox[1] = REQUEST_CODE; + // tags begin + mailbox[2] = GET_ARM_MEMORY; // tag identifier + mailbox[3] = 8; // maximum of request and response value buffer's length. + mailbox[4] = TAG_REQUEST_CODE; + mailbox[5] = 0; // value buffer + mailbox[6] = 0; // value buffer + // tags end + mailbox[7] = END_TAG; + + mailbox_call(mailbox); // message passing procedure call, you should implement it following the 6 steps provided above. + + //printf("0x%x\n", mailbox[5]); // it should be 0xa020d3 for rpi3 b+ + *addr_base = mailbox[5]; + *size = mailbox[6]; +} \ No newline at end of file diff --git a/lab4/src/lib/ramdisk.c b/lab4/src/lib/ramdisk.c new file mode 100644 index 000000000..15c9da707 --- /dev/null +++ b/lab4/src/lib/ramdisk.c @@ -0,0 +1,81 @@ +#include + +#include + +#include +#include +#include +#include + +int isinit; +void *_randisk_begin; + +typedef struct{ + int found; + char *initrd_start; +} ramdisk_data; + +int ramdisk_fdt_callback(char* node, const char *name, void *data){ + if(strcmp(name, "chosen")) return 0; + ramdisk_data* _data = (ramdisk_data*) data; + fdt_prop *prop; + while(prop = fdt_nextprop(node + 1, &node)){ + if(!strcmp(prop->name,"linux,initrd-start")){ + _data->initrd_start = (char *)(uint64_t)ntohl(*(uint32_t*)prop->value); + } + } + _data->found = 1; + return 1; +} + +int ramdisk_get_addr(){ + ramdisk_data data; + data.initrd_start = 0; + data.found = 0; + fdt_traverse(ramdisk_fdt_callback, (void *)&data); + if(data.found){ + /* + uart_print("/chosen linux,initrd-start: "); + uart_print_hex((uint64_t)data.initrd_start, 64); + newline(); + */ + _randisk_begin = data.initrd_start; + return 0; + } + return -1; +} + +cpio_file* cpio_parse(){ + if(isinit != 1){ + int initres = ramdisk_get_addr(); + if(!initres) isinit = 1; + else return 0; + } + char *ptr = (char *) _randisk_begin; + char *name = ptr + sizeof(struct cpio_newc_header); + struct cpio_newc_header* cur_cpio_header; + cpio_file *head = NULL; + cpio_file *prev = NULL; + cpio_file *cur = NULL; + while(1){ + cur_cpio_header = (struct cpio_newc_header*) ptr; + name = ptr + sizeof(struct cpio_newc_header); + if(strcmp("TRAILER!!!", name) == 0) break; + cur = (cpio_file*) simple_malloc (sizeof(cpio_file)); + if(cur == NULL){ + uart_print("Error: Get NULL Pointer!"); + return NULL; + } + if(head == NULL) head = cur; + cur->header = ptr; + cur->namesize = hex2u32_8(cur_cpio_header->c_namesize); + cur->filesize = hex2u32_8(cur_cpio_header->c_filesize); + cur->name = name; + cur->content = (char*) align((uint64_t) name + cur->namesize - 1); + cur->next = 0; + ptr = (char *) align((uint64_t) cur->content + cur->filesize - 1); + if(prev != NULL) prev->next = cur; + prev = cur; + } + return head; +} \ No newline at end of file diff --git a/lab4/src/lib/reboot.c b/lab4/src/lib/reboot.c new file mode 100644 index 000000000..cd53ecacb --- /dev/null +++ b/lab4/src/lib/reboot.c @@ -0,0 +1,20 @@ +#include + +#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 cancel_reset() { + set(PM_RSTC, PM_PASSWORD | 0); // full reset + set(PM_WDOG, PM_PASSWORD | 0); // number of watchdog tick +} \ No newline at end of file diff --git a/lab4/src/lib/shell.c b/lab4/src/lib/shell.c new file mode 100644 index 000000000..2cb2e9d0c --- /dev/null +++ b/lab4/src/lib/shell.c @@ -0,0 +1,35 @@ +#include + +#include +#include +#include + +void shell(){ + char buf[BUF_SIZE]; + while(1){ + uart_print("# "); + uart_readline(buf); + if(strncmp(buf, "help", 4) == 0){ + help(); + }else if(strncmp(buf, "hello", 5) == 0){ + hello(); + }else if(strncmp(buf, "reboot", 6) == 0){ + reboot(); + }else if(strncmp(buf, "ls", 2) == 0){ + ls(); + }else if(strncmp(buf, "cat", 2) == 0){ + uart_print("Filename: "); + uart_readline(buf); + cat(buf); + }else if(strncmp(buf, "exec", 4) == 0){ + exec(&buf[5]); + }else if(strncmp(buf, "setTimeout", 10) == 0){ + setTimeout(); + }else{ + uart_print("Unknown command: ["); + uart_print(buf); + uart_print("]."); + newline(); + } + } +} diff --git a/lab4/src/lib/string.c b/lab4/src/lib/string.c new file mode 100644 index 000000000..9dae9bb38 --- /dev/null +++ b/lab4/src/lib/string.c @@ -0,0 +1,59 @@ +#include + +#include +#include + +int atoi(const char* str){ + int num = 0; + int i = 0; + while(str[i]){ + num *= 10; + num += str[i] - '0'; + i++; + } + return num; +} + +int strcmp(const char* x, const char* y){ + int i = 0; + for(; x[i] && y[i]; i++){ + if(x[i] < y[i]) return -1; + else if(x[i] > y[i]) return 1; + } + if(x[i]) return 1; + else if(y[i]) return -1; + return 0; +} + +int strncmp(const char*x, const char*y, int len){ + int i = 0; + for(; x[i] && y[i] && i < len; i++){ + if(x[i] < y[i]) return -1; + else if(x[i] > y[i]) return 1; + } + if(i == len) return 0; + else if(x[i]) return 1; + else if(y[i]) return -1; + return 0; +} + +size_t strlen(const char *str){ + int i = 0; + while(*str){ + i++; + str++; + } + return i; +} + +void *memcpy(void *dst, const void *src, size_t n){ + size_t npage = n / sizeof(uint64_t); + size_t noff = n % sizeof(uint64_t); + for(int i=0;i + +#include +#include + +#include +#include +#include + +#define UART_BUF_LEN 0x200 +RingBuffer *uart_buffer; + +void uart_init(){ + //12-14, 15-17 + // get oringin val, reset gpio14-15, set alt5 0b010 + memory_write(GPFSEL1, (memory_read(GPFSEL1) & 0xfffc0fff) | (0b010010 << 12)); + //gpio page 101 1 ~ 4, 6 + memory_write(GPPUD, 0b00); + wait_cycles(150u); + memory_write(GPPUDCLK0, (1 << 14) | (1 << 15)); + wait_cycles(150u); + memory_write(GPPUDCLK0, 0u); + // Initialization 1 ~ 8 + memory_write(AUX_ENABLES, 0b001); + memory_write(AUX_MU_CNTL_REG, 0u); + + memory_write(AUX_MU_LCR_REG, 3u); + memory_write(AUX_MU_MCR_REG, 0u); + memory_write(AUX_MU_BAUD_REG, 270u); + memory_write(AUX_MU_IIR_REG, 6u); + memory_write(AUX_MU_CNTL_REG, 3u); + // interrupt + memory_write(AUX_MU_IER_REG, 0b01); + memory_write(ARMINT_En_IRQs1_REG, memory_read(ARMINT_En_IRQs1_REG) | (1<<29)); + uart_buffer = RingBuffer_new(UART_BUF_LEN); +} + +void uart_interrupt_handler(){ + interrupt_disable(); + while((memory_read(AUX_MU_LSR_REG) & 1) && !RingBuffer_Full(uart_buffer)){ + RingBuffer_writeb(uart_buffer, memory_read(AUX_MU_IO_REG)&0xff); + } + interrupt_enable(); +} + +size_t uart_read_sync(char* buf, size_t len){ + size_t recvlen = 0; + while(recvlen < len){ + while(!(memory_read(AUX_MU_LSR_REG) & 1)); + buf[recvlen++] = (char)(memory_read(AUX_MU_IO_REG) & 0xff); + } + return recvlen; +} + +size_t uart_read_async(char* buf, size_t len) +{ + size_t recvlen = 0; + while(recvlen < len){ + while(RingBuffer_Empty(uart_buffer)); + if(RingBuffer_readb(uart_buffer, &buf[recvlen]) == 1) recvlen++; + } + return recvlen; +} + +size_t uart_write_1c(char*buf){ + if(buf[0] == '\r') return 0; + while(!(memory_read(AUX_MU_LSR_REG) & 0b100000)); + memory_write(AUX_MU_IO_REG, (memory_read(AUX_MU_IO_REG) & 0xffffff00) | buf[0]); + return 1; +} + +size_t uart_write(char* buf, size_t len){ + size_t writelen = 0; + while(writelen < len){ + uart_write_1c(&buf[writelen++]); + } + return writelen; +} + +size_t uart_readline(char* buf){ + int i = 0; + while(uart_read(&buf[i], 1)){ + if(buf[i] == '\r' || buf[i] == '\n'){ + buf[i] = '\0'; + break; + } + i++; + } + return i; +} + +void uart_print(char* buf){ + int i=0; + while(buf[i]){ + uart_write_1c(&buf[i]); + i++; + } +} + +void uart_print_hex(uint64_t num, int len){ + uint64_t tmp; + char hex[20] = {}; + uart_print("0x"); + for(int i = len - 4; i >= 0; i -= 4){ + tmp = (num >> i) & 0xF; + // 0-9 a-f + hex[(len / 4 - 1) - i / 4] = (char) tmp + (tmp > 9 ? 'a' - 10 : '0'); + } + uart_print(hex); +} + +void newline(){ + uart_print("\r\n"); +} + +RingBuffer *RingBuffer_new(size_t bufsize){ + RingBuffer* newbuf = (RingBuffer*)simple_malloc(sizeof(RingBuffer)); + newbuf->flags = 0; + newbuf->flags |= RingBuffer_flag_Empty; + newbuf->buf = (char *)simple_malloc(bufsize); + newbuf->lbound = 0; + newbuf->rbound = 0; + newbuf->len = 0; + newbuf->size = bufsize; + return newbuf; +} + +size_t RingBuffer_writeb(RingBuffer *rbuf, char b){ + interrupt_disable(); + if(RingBuffer_Full(rbuf)) return 0; + rbuf->buf[rbuf->rbound++] = b; + rbuf->rbound %= rbuf->size; + rbuf->len++; + if(rbuf->len >= rbuf->size) rbuf->flags |= RingBuffer_flag_Full; + rbuf->flags &= ~RingBuffer_flag_Empty; + interrupt_enable(); + return 1; +} + +size_t RingBuffer_readb(RingBuffer *rbuf, char* b){ + interrupt_disable(); + if(RingBuffer_Empty(rbuf)) return 0; + *b = rbuf->buf[rbuf->lbound++]; + rbuf->lbound %= rbuf->size; + rbuf->len--; + if(rbuf->len <= 0) rbuf->flags |= RingBuffer_flag_Empty; + if(rbuf->len < rbuf->size)rbuf->flags &= ~RingBuffer_flag_Full; + interrupt_enable(); + return 1; +} \ No newline at end of file diff --git a/lab4/src/lib/utils.c b/lab4/src/lib/utils.c new file mode 100644 index 000000000..8dc23498f --- /dev/null +++ b/lab4/src/lib/utils.c @@ -0,0 +1,38 @@ +#include + +void wait_cycles(uint32_t times){ + while(times--) asm volatile("nop"); +} + +uint32_t hex2u32_8(char *buf){ + uint32_t num = 0; + for(int i = 0; i < 8; i++){ + num <<= 4; + num += (buf[i] >= 'A' ? buf[i] - 'A' + 10 : buf[i] - '0'); + } + return num; +} + +uint16_t ntohs(uint16_t tmp){ + return (tmp << 8) | (tmp >> 8); +} + +uint32_t ntohl(uint32_t tmp){ + return ((uint32_t)(ntohs(tmp & 0xffffLL)) << 16) | (ntohs((tmp >> 16) & 0xffffLL)); +} + +uint64_t ntohll(uint64_t tmp){ + return ((uint64_t)(ntohl(tmp & 0xffffffffLL)) << 32) | (ntohl((tmp >> 32) & 0xffffffffLL)); +} + +uint16_t htons(uint16_t tmp){ + return (tmp >> 8) | (tmp << 8); +} + +uint32_t htonl(uint32_t tmp){ + return (ntohs((tmp >> 16) & 0xffffLL)) | ((uint32_t)(ntohs(tmp & 0xffffLL)) << 16); +} + +uint64_t htonll(uint64_t tmp){ + return (ntohl((tmp >> 32) & 0xffffffffLL)) | ((uint64_t)(ntohl(tmp & 0xffffffffLL)) << 32); +} \ No newline at end of file diff --git a/lab4/upload.py b/lab4/upload.py new file mode 100644 index 000000000..015c17fa7 --- /dev/null +++ b/lab4/upload.py @@ -0,0 +1,12 @@ +from pwn import * + +kernel = open("kernel8.img", "rb").read() +r = serialtube("/dev/pts/3", convert_newlines=False) +#r = serialtube("/dev/ttyS0", convert_newlines=False) +#r = remote('127.0.0.1',10001) +size = (str(len(kernel)) + "\n" ).encode() +print(size) +r.sendline(size) +print(r.recvuntil(b"): ").decode()) +r.send(kernel) +r.interactive() \ No newline at end of file