From 7f943be8f0150ff1309086f1124b283fa5826c8a Mon Sep 17 00:00:00 2001 From: Liam Kerr Date: Sun, 8 Feb 2026 21:23:47 +0000 Subject: [PATCH] Initial Commit --- Makefile | 56 ++++++++++++++++++++++++++++++++++++++++++ build/boot/entry.o | Bin 0 -> 68848 bytes build/kernel/kernel.o | Bin 0 -> 6536 bytes linker.ld | 33 +++++++++++++++++++++++++ output/kernel.elf | Bin 0 -> 11360 bytes src/boot/entry.S | 14 +++++++++++ src/kernel/kernel.c | 11 +++++++++ 7 files changed, 114 insertions(+) create mode 100644 Makefile create mode 100644 build/boot/entry.o create mode 100644 build/kernel/kernel.o create mode 100644 linker.ld create mode 100755 output/kernel.elf create mode 100644 src/boot/entry.S create mode 100644 src/kernel/kernel.c 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 0000000000000000000000000000000000000000..400b3e472a08995f1cf7180de4c8e85d45a3728d GIT binary patch literal 68848 zcmeI!y>A>v7{~EveR1Lh;+HrfhzMeVL6LxS?1YFENDc@PC?bFfh!@4|oiFw&cRput zZ4w&NP|(pqiKuA#3uq}R`46B+NJun1&(4fJH@EK6Abm&j?d)%!ot^va%lWI8?kht4#z9xT|XKC&3Zg*p|b7M`0MSH0=7?jf4E{prkHCfaHCMBD4bK9qHkA;qHvj^Fn z%$}XgPR%r?&rLr&JwF)_i@cz_Ze7((qk}bjVI50h9fvRZ&3A4tTw7aMXTE@K*xr-uJ?%~wdsi-ZS9X@y`zt#a*K_OLUfEe$->{FiWnXsN!=mc+`@6kmOY*!w zaGhQ;Y->-ZvJ;QgtTT=pc5P}}LmD-yXnJHUcQcI7^LACK^|Pagd{FI<*M~gS{@B+i z(@3a4EI&PZTDev2kFVd&b1bPAKmRd#A{hzw&(!9bjNE0urlHS8+QRw|%hP#W{mHc4 zuk)nLB_pB!`6Rd9hMcHLEl(Z-tvYO-Zk};Bm)GBU4H;j*tDm;bNZZoA*_!)vP~{_~ zZfEh{LwazAW!}ECUJiDodHv#o^ak2?hh^GRv*uE(-+wM@m(EqtB>b#?-S=SbZ|#WqJJW z3;p!G;T~Jm`cu(7A-|wmyiREj@Au2RrQ5P_+pW+mI=#GEcJ7tZ+{nvZnyukbnpL{d zY3**V_qy919oz5g!%~bCbhmF0LP6eY6`j42;k?MVH#<6~o5CG!KaI`2EQ@Yyx75Lh z(-w3ZGYp<#)>Yq$ueC+y8n<)0W6$hr9BTicBQ~qZPt~W0-D8%7`zW~EeP((3OZ%Z_ zbErjl$OHfU?do{k((~IpukQF?z2A@V!P-xc{}19P&u;(# literal 0 HcmV?d00001 diff --git a/build/kernel/kernel.o b/build/kernel/kernel.o new file mode 100644 index 0000000000000000000000000000000000000000..83a7d90c81bc1a3fe2df0b3754be9a754624ac49 GIT binary patch literal 6536 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 literal 0 HcmV?d00001 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 + } +}