commit 7f943be8f0150ff1309086f1124b283fa5826c8a Author: Liam Kerr Date: Sun Feb 8 21:23:47 2026 +0000 Initial Commit diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..6ccc8e0 --- /dev/null +++ b/Makefile @@ -0,0 +1,56 @@ +# Toolchain +CC = riscv64-unknown-elf-gcc +LD = riscv64-unknown-elf-ld + +# Directories +SRC_DIR = src +BUILD_DIR = build +OUTPUT_DIR = output + +# Flags +# Added -O0 for easier debugging and -g for symbols +CFLAGS = -Wall -Wextra -ffreestanding -nostdlib -mcmodel=medany -Iinclude -O0 -g +LDFLAGS = -T linker.ld + +# 1. Find sources +SRCS_C = $(shell find $(SRC_DIR) -name "*.c") +SRCS_S = $(shell find $(SRC_DIR) -name "*.S") + +# 2. Object mapping +OBJS_C = $(patsubst $(SRC_DIR)/%.c, $(BUILD_DIR)/%.o, $(SRCS_C)) +OBJS_S = $(patsubst $(SRC_DIR)/%.S, $(BUILD_DIR)/%.o, $(SRCS_S)) +# Put Assembly first to help the linker find _start +OBJS = $(OBJS_S) $(OBJS_C) + +# 3. List of all required build subdirectories +OBJ_DIRS = $(sort $(dir $(OBJS))) + +TARGET = $(OUTPUT_DIR)/kernel.elf + +.PHONY: all clean run + +all: $(TARGET) + +# The final link step +# Added -Wl, to pass LDFLAGS to the actual linker +$(TARGET): $(OBJS) | $(OUTPUT_DIR) + $(CC) $(CFLAGS) -Wl,$(LDFLAGS) $(OBJS) -o $(TARGET) + +# Rule for C files +$(BUILD_DIR)/%.o: $(SRC_DIR)/%.c | $(OBJ_DIRS) + $(CC) $(CFLAGS) -c $< -o $@ + +# Rule for Assembly files +$(BUILD_DIR)/%.o: $(SRC_DIR)/%.S | $(OBJ_DIRS) + $(CC) $(CFLAGS) -c $< -o $@ + +# Create directories using order-only prerequisites (|) +$(OBJ_DIRS) $(OUTPUT_DIR): + mkdir -p $@ + +run: all + clear + qemu-system-riscv64 -M virt -bios none -kernel $(TARGET) -nographic + +clean: + rm -rf $(BUILD_DIR) $(OUTPUT_DIR) diff --git a/build/boot/entry.o b/build/boot/entry.o new file mode 100644 index 0000000..400b3e4 Binary files /dev/null and b/build/boot/entry.o differ diff --git a/build/kernel/kernel.o b/build/kernel/kernel.o new file mode 100644 index 0000000..83a7d90 Binary files /dev/null and b/build/kernel/kernel.o differ diff --git a/linker.ld b/linker.ld new file mode 100644 index 0000000..98a4528 --- /dev/null +++ b/linker.ld @@ -0,0 +1,33 @@ +ENTRY(_start) + +SECTIONS +{ + . = 0x80000000; + + .text : ALIGN(4K) { + /* This matches the .section .text.boot in your assembly */ + *(.text.boot) + *(.text .text.*) + } + + .rodata : ALIGN(4K) { + *(.rodata .rodata.*) + } + + .data : ALIGN(4K) { + *(.data .data.*) + } + + .bss : ALIGN(4K) { + PROVIDE(_bss_start = .); + *(.bss .bss.*) + *(COMMON) + PROVIDE(_bss_end = .); + } + + /* Keep the stack at the very end to prevent it from overwriting code if it overflows */ + . = ALIGN(16); + PROVIDE(_stack_bottom = .); + . += 4096; + PROVIDE(stack_top = .); +} diff --git a/output/kernel.elf b/output/kernel.elf new file mode 100755 index 0000000..74cd1f9 Binary files /dev/null and b/output/kernel.elf differ diff --git a/src/boot/entry.S b/src/boot/entry.S new file mode 100644 index 0000000..0940865 --- /dev/null +++ b/src/boot/entry.S @@ -0,0 +1,14 @@ +.section .text +.global _start +_start: + la sp, stack_top # Set up the stack pointer + call kmain # Jump to our C code +loop: + wfi # Wait for Interrupt (saves CPU) + j loop # Infinite loop if C returns + +.section .bss +.align 16 +stack_low: + .skip 4096 # 4KB of stack space +stack_top: diff --git a/src/kernel/kernel.c b/src/kernel/kernel.c new file mode 100644 index 0000000..6ce9346 --- /dev/null +++ b/src/kernel/kernel.c @@ -0,0 +1,11 @@ +#include +#include + +void kmain() { + char *uart = (char *)0x10000000; + char *msg = "Hello, OS World!\n"; + + for (int i = 0; msg[i] != '\0'; i++) { + *uart = msg[i]; // Write each character to the UART + } +}