diff options
| -rw-r--r-- | .gitignore | 1 | ||||
| -rw-r--r-- | Makefile | 53 | ||||
| -rwxr-xr-x | run.sh | 10 | ||||
| -rw-r--r-- | src/boot.s | 44 | ||||
| -rw-r--r-- | src/kernel.c | 4 | ||||
| -rw-r--r-- | src/link.ld | 20 |
6 files changed, 132 insertions, 0 deletions
diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..567609b --- /dev/null +++ b/.gitignore | |||
| @@ -0,0 +1 @@ | |||
| build/ | |||
diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..7478d63 --- /dev/null +++ b/Makefile | |||
| @@ -0,0 +1,53 @@ | |||
| 1 | SRC_DIR := src | ||
| 2 | BUILD_DIR := build | ||
| 3 | OBJ_DIR := $(BUILD_DIR) | ||
| 4 | BIN_DIR := $(BUILD_DIR)/bin | ||
| 5 | |||
| 6 | IMG := $(BIN_DIR)/kernel8.img | ||
| 7 | ELF := $(BIN_DIR)/kernel8.elf | ||
| 8 | |||
| 9 | SRC := $(wildcard $(SRC_DIR)/*.c) | ||
| 10 | OBJ := $(SRC:$(SRC_DIR)/%.c=$(OBJ_DIR)/%.o) | ||
| 11 | ASM_SRC := $(wildcard $(SRC_DIR)/*.s) | ||
| 12 | ASM_OBJ := $(ASM_SRC:$(SRC_DIR)/%.s=$(OBJ_DIR)/%.o) | ||
| 13 | LINK := $(SRC_DIR)/link.ld | ||
| 14 | |||
| 15 | CPPFLAGS := -I$(SRC_DIR) -MMD -MP | ||
| 16 | CFLAGS := -Wall -Wextra -O2 -ffreestanding -nostdinc -nostdlib -nostartfiles | ||
| 17 | LDFLAGS := -nostdlib | ||
| 18 | |||
| 19 | TOOLCHAIN := $(HOME)/bin/arm-gnu-toolchain-14.2.rel1-x86_64-aarch64-none-elf/bin | ||
| 20 | AS := $(TOOLCHAIN)/aarch64-none-elf-as | ||
| 21 | CC := $(TOOLCHAIN)/aarch64-none-elf-gcc | ||
| 22 | LD := $(TOOLCHAIN)/aarch64-none-elf-ld | ||
| 23 | OBJCOPY := $(TOOLCHAIN)/aarch64-none-elf-objcopy | ||
| 24 | |||
| 25 | .PHONY: all clean | ||
| 26 | |||
| 27 | all: $(IMG) | ||
| 28 | |||
| 29 | $(IMG): $(ELF) | $(BIN_DIR) | ||
| 30 | @echo Building $@ | ||
| 31 | $(OBJCOPY) -O binary $(ELF) $@ | ||
| 32 | |||
| 33 | $(ELF): $(OBJ) $(ASM_OBJ) | $(BIN_DIR) | ||
| 34 | @echo Building $@ | ||
| 35 | $(LD) $(LDFLAGS) $^ -T $(LINK) -o $@ | ||
| 36 | |||
| 37 | $(OBJ_DIR)/%.o: $(SRC_DIR)/%.c | $(BUILD_DIR) | ||
| 38 | @echo Building $< "->" $@ | ||
| 39 | $(CC) $(CFLAGS) -c $< -o $@ | ||
| 40 | |||
| 41 | $(OBJ_DIR)/%.o: $(SRC_DIR)/%.s | $(BUILD_DIR) | ||
| 42 | @echo Building $< "->" $@ | ||
| 43 | $(AS) $< -o $@ | ||
| 44 | |||
| 45 | clean: | ||
| 46 | rm -rf $(BUILD_DIR) | ||
| 47 | |||
| 48 | $(BUILD_DIR): | ||
| 49 | mkdir -p $(BUILD_DIR) | ||
| 50 | |||
| 51 | $(BIN_DIR): | ||
| 52 | mkdir -p $(BIN_DIR) | ||
| 53 | |||
| @@ -0,0 +1,10 @@ | |||
| 1 | #!/bin/sh | ||
| 2 | |||
| 3 | make | ||
| 4 | qemu-system-aarch64 \ | ||
| 5 | -cpu cortex-a53 \ | ||
| 6 | -m 1024 \ | ||
| 7 | -M raspi3b \ | ||
| 8 | -serial stdio \ | ||
| 9 | -kernel build/bin/kernel8.elf | ||
| 10 | |||
diff --git a/src/boot.s b/src/boot.s new file mode 100644 index 0000000..7baa463 --- /dev/null +++ b/src/boot.s | |||
| @@ -0,0 +1,44 @@ | |||
| 1 | /* | ||
| 2 | References: | ||
| 3 | https://wiki.osdev.org/Raspberry_Pi_Bare_Bones | ||
| 4 | https://jsandler18.github.io/tutorial/boot.html | ||
| 5 | https://jsandler18.github.io/explanations/boot_S.html | ||
| 6 | https://www.rpi4os.com/part1-bootstrapping/ | ||
| 7 | https://developer.arm.com/documentation/102422/0100/Example-solutions/System-control-solution | ||
| 8 | https://developer.arm.com/documentation/102422/0100/GAS-syntax-reference?lang=en | ||
| 9 | */ | ||
| 10 | |||
| 11 | .section ".text.boot" | ||
| 12 | |||
| 13 | .global _start | ||
| 14 | |||
| 15 | _start: | ||
| 16 | // Let core 0.0.0.0 be the only one running for now. The other cores halt. | ||
| 17 | // Each core has a unique affinity number: <aff3>.<aff2>.<aff1>.<aff0>. | ||
| 18 | // On AArch64, Aff3 takes bits 39-32. The code below copies bits 39-32 over | ||
| 19 | // to 31-24 so that we get a 32-bit value <aff3>.<aff2>.<aff1>.<aff0>. | ||
| 20 | mrs x0, MPIDR_EL1 | ||
| 21 | ubfx x1, x0, #32, #8 // x1[0..7] = Aff3; x[8..63] = 0 | ||
| 22 | bfi w0, w1, #24, #8 // w0[31..24] = Aff3 | ||
| 23 | cbnz w0, halt // All cores except 0.0.0.0 halt. | ||
| 24 | |||
| 25 | core0: | ||
| 26 | // Initialize the stack. The stack will grow below this boot code. | ||
| 27 | ldr x1, =_start | ||
| 28 | mov sp, x1 | ||
| 29 | |||
| 30 | // Zero-initialize the BSS section. | ||
| 31 | ldr x1, =__bss_start // Start address of BSS section. | ||
| 32 | ldr x2, =__bss_size // Size of the BSS section. | ||
| 33 | bss_init_loop: | ||
| 34 | str xzr, [x1], #8 // Store 64-bit 0 to addr; increment addr by 8 bytes. | ||
| 35 | sub x2, x2, #8 // Decrement remaining size. | ||
| 36 | cbnz x2, bss_init_loop // Loop back if remaining size is non-zero (>0). | ||
| 37 | |||
| 38 | // Jump to C main() | ||
| 39 | bl main | ||
| 40 | |||
| 41 | halt: | ||
| 42 | wfi // Wait for interrupt. Core enters low-power state. | ||
| 43 | b halt // Loop back. | ||
| 44 | |||
diff --git a/src/kernel.c b/src/kernel.c new file mode 100644 index 0000000..eb7d832 --- /dev/null +++ b/src/kernel.c | |||
| @@ -0,0 +1,4 @@ | |||
| 1 | void main() { | ||
| 2 | while (1); | ||
| 3 | } | ||
| 4 | |||
diff --git a/src/link.ld b/src/link.ld new file mode 100644 index 0000000..f1d1730 --- /dev/null +++ b/src/link.ld | |||
| @@ -0,0 +1,20 @@ | |||
| 1 | SECTIONS | ||
| 2 | { | ||
| 3 | . = 0x80000; /* Kernel load address for AArch64 */ | ||
| 4 | .text (READONLY) : { KEEP(*(.text.boot)) *(.text .text.* .gnu.linkonce.t*) } | ||
| 5 | .rodata (READONLY) : { *(.rodata .rodata.* .gnu.linkonce.r*) } | ||
| 6 | PROVIDE(_data = .); | ||
| 7 | .data : { *(.data .data.* .gnu.linkonce.d*) } | ||
| 8 | .bss (NOLOAD) : { | ||
| 9 | . = ALIGN(16); | ||
| 10 | __bss_start = .; | ||
| 11 | *(.bss .bss.*) | ||
| 12 | *(COMMON) | ||
| 13 | __bss_end = .; | ||
| 14 | } | ||
| 15 | _end = .; | ||
| 16 | |||
| 17 | /DISCARD/ : { *(.comment) *(.gnu*) *(.note*) *(.eh_frame*) } | ||
| 18 | } | ||
| 19 | __bss_size = (__bss_end - __bss_start); | ||
| 20 | |||
