Initial Commit

This commit is contained in:
Liam Kerr 2026-02-08 21:23:47 +00:00
commit 7f943be8f0
7 changed files with 114 additions and 0 deletions

56
Makefile Normal file
View file

@ -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)

BIN
build/boot/entry.o Normal file

Binary file not shown.

BIN
build/kernel/kernel.o Normal file

Binary file not shown.

33
linker.ld Normal file
View file

@ -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 = .);
}

BIN
output/kernel.elf Executable file

Binary file not shown.

14
src/boot/entry.S Normal file
View file

@ -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:

11
src/kernel/kernel.c Normal file
View file

@ -0,0 +1,11 @@
#include <stdint.h>
#include <stddef.h>
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
}
}