summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Makefile61
-rwxr-xr-xbuild/kernel.elfbin0 -> 6616 bytes
-rw-r--r--build/src/boot/entry.d1
-rw-r--r--build/src/boot/entry.obin0 -> 2024 bytes
-rw-r--r--build/src/drivers/uart.d2
-rw-r--r--build/src/drivers/uart.obin0 -> 2688 bytes
-rw-r--r--build/src/kernel/main.d1
-rw-r--r--build/src/kernel/main.obin0 -> 3344 bytes
-rw-r--r--include/common/types.h14
-rw-r--r--include/drivers/uart.h7
-rw-r--r--kernel.cc69
-rw-r--r--linker.ld47
-rw-r--r--src/boot/entry.S28
-rw-r--r--src/drivers/uart.cc57
-rw-r--r--src/kernel/main.cc20
15 files changed, 307 insertions, 0 deletions
diff --git a/Makefile b/Makefile
new file mode 100644
index 0000000..4d80143
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,61 @@
+TOOLCHAIN := riscv64-linux-gnu
+CC := $(TOOLCHAIN)-gcc
+CXX := $(TOOLCHAIN)-g++
+LD := $(TOOLCHAIN)-ld
+OBJCOPY := $(TOOLCHAIN)-objcopy
+
+TARGET_ELF := build/kernel.elf
+TARGET_BIN := build/kernel.bin
+
+ARCH_FLAGS := -march=rv64gc -mabi=lp64 -mcmodel=medany
+CFLAGS := -Wall -Wextra -O2 -ffreestanding -nostdlib -Iinclude $(ARCH_FLAGS)
+CXXFLAGS := $(CFLAGS) -fno-exceptions -fno-rtti -fno-use-cxa-atexit
+
+SRC_DIRS := src
+SRCS_ASM := $(shell find $(SRC_DIRS) -name "*.S")
+SRCS_CXX := $(shell find $(SRC_DIRS) -name "*.cc")
+
+OBJS := $(SRCS_ASM:%.S=build/%.o) $(SRCS_CXX:%.cc=build/%.o)
+
+DEPS := $(OBJS:.o=.d)
+
+
+LINKER_SCRIPT := linker.ld
+
+QEMU := qemu-system-riscv64
+QEMU_FLAGS := -machine virt -m 128M -nographic -bios none -kernel $(TARGET_ELF)
+
+
+.PHONY: all clean run debug directories
+
+all: directories $(TARGET_ELF)
+
+$(TARGET_ELF): $(OBJS) $(LINKER_SCRIPT)
+ @echo "Linking $@"
+ @$(LD) -T $(LINKER_SCRIPT) -o $@ $(OBJS)
+
+build/%.o: %.S
+ @mkdir -p $(dir $@)
+ @echo "Compiling ASM $<"
+ @$(CC) $(CFLAGS) -MMD -c $< -o $@
+
+build/%.o: %.cc
+ @mkdir -p $(dir $@)
+ @echo "Compiling C++ $<"
+ @$(CXX) $(CXXFLAGS) -MMD -c $< -o $@
+
+directories:
+ @mkdir -p build
+
+run: all
+ @echo "Starting QEMU..."
+ $(QEMU) $(QEMU_FLAGS)
+
+debug: all
+ @echo "Starting QEMU in debug mode (connect with gdb-multiarch)..."
+ $(QEMU) $(QEMU_FLAGS) -S -s
+
+clean:
+ @rm -rf build
+
+-include $(DEPS) \ No newline at end of file
diff --git a/build/kernel.elf b/build/kernel.elf
new file mode 100755
index 0000000..e57b2af
--- /dev/null
+++ b/build/kernel.elf
Binary files differ
diff --git a/build/src/boot/entry.d b/build/src/boot/entry.d
new file mode 100644
index 0000000..db71800
--- /dev/null
+++ b/build/src/boot/entry.d
@@ -0,0 +1 @@
+build/src/boot/entry.o: src/boot/entry.S
diff --git a/build/src/boot/entry.o b/build/src/boot/entry.o
new file mode 100644
index 0000000..5244030
--- /dev/null
+++ b/build/src/boot/entry.o
Binary files differ
diff --git a/build/src/drivers/uart.d b/build/src/drivers/uart.d
new file mode 100644
index 0000000..e6ff9b6
--- /dev/null
+++ b/build/src/drivers/uart.d
@@ -0,0 +1,2 @@
+build/src/drivers/uart.o: src/drivers/uart.cc include/drivers/uart.h \
+ include/common/types.h
diff --git a/build/src/drivers/uart.o b/build/src/drivers/uart.o
new file mode 100644
index 0000000..9283f15
--- /dev/null
+++ b/build/src/drivers/uart.o
Binary files differ
diff --git a/build/src/kernel/main.d b/build/src/kernel/main.d
new file mode 100644
index 0000000..a31a83b
--- /dev/null
+++ b/build/src/kernel/main.d
@@ -0,0 +1 @@
+build/src/kernel/main.o: src/kernel/main.cc include/drivers/uart.h
diff --git a/build/src/kernel/main.o b/build/src/kernel/main.o
new file mode 100644
index 0000000..bf89688
--- /dev/null
+++ b/build/src/kernel/main.o
Binary files differ
diff --git a/include/common/types.h b/include/common/types.h
new file mode 100644
index 0000000..56500c5
--- /dev/null
+++ b/include/common/types.h
@@ -0,0 +1,14 @@
+#pragma once
+
+typedef unsigned char uint8_t;
+typedef unsigned short uint16_t;
+typedef unsigned int uint32_t;
+typedef unsigned long long uint64_t;
+
+typedef signed char int8_t;
+typedef signed short int16_t;
+typedef signed int int32_t;
+typedef signed long long int64_t;
+
+typedef uint64_t size_t;
+typedef uint64_t uintptr_t; \ No newline at end of file
diff --git a/include/drivers/uart.h b/include/drivers/uart.h
new file mode 100644
index 0000000..8bf4560
--- /dev/null
+++ b/include/drivers/uart.h
@@ -0,0 +1,7 @@
+#pragma once
+
+namespace Drivers {
+ void uart_init();
+ void uart_putc(char c);
+ void uart_puts(const char* s);
+} \ No newline at end of file
diff --git a/kernel.cc b/kernel.cc
new file mode 100644
index 0000000..f9cacba
--- /dev/null
+++ b/kernel.cc
@@ -0,0 +1,69 @@
+extern "C" void kernel_main();
+
+#define UART_ADDR 0x10000000UL
+
+#define THR_OFFSET 0x0
+#define LSR_OFFSET 0x5
+#define FCR_OFFSET 0x2
+#define LCR_OFFSET 0x3
+#define DLL_OFFSET 0x0
+#define DLH_OFFSET 0x1
+
+static void
+write_byte(unsigned long addr, char byte)
+{
+ *((volatile char *)addr) = byte;
+}
+
+static int
+is_tx_empty()
+{
+ return *((volatile char *)(UART_ADDR + LSR_OFFSET)) & (1 << 5);
+}
+
+void uart_init()
+{
+ write_byte(UART_ADDR + LCR_OFFSET, 0x80);
+
+ write_byte(UART_ADDR + DLL_OFFSET, 0x01);
+ write_byte(UART_ADDR + DLH_OFFSET, 0x00);
+
+ write_byte(UART_ADDR + LCR_OFFSET, 0x03);
+
+ write_byte(UART_ADDR + FCR_OFFSET, 0x07);
+}
+
+void put_char(char c)
+{
+ if (c == '\n')
+ {
+ put_char('\r');
+ }
+
+ while (!is_tx_empty())
+ {
+ }
+ write_byte(UART_ADDR + THR_OFFSET, c);
+}
+
+void print_str(const char *s)
+{
+ while (*s != '\0')
+ {
+ put_char(*s++);
+ }
+}
+
+void kernel_main()
+{
+ uart_init();
+
+ print_str("Modern DOS 1.0\n");
+ print_str("Hello OS! Running on RISC-V 64.\n");
+ print_str("Hello Ziyi Yang! Love from RUC");
+
+ while (1)
+ {
+
+ }
+} \ No newline at end of file
diff --git a/linker.ld b/linker.ld
new file mode 100644
index 0000000..0b01e98
--- /dev/null
+++ b/linker.ld
@@ -0,0 +1,47 @@
+OUTPUT_ARCH( "riscv" )
+ENTRY(_start)
+
+MEMORY
+{
+ ram (wxa) : ORIGIN = 0x80000000, LENGTH = 128M
+}
+
+SECTIONS
+{
+ . = 0x80000000;
+
+ .text : {
+ PROVIDE(_text_start = .);
+ *(.text.entry)
+ *(.text .text.*)
+ PROVIDE(_text_end = .);
+ } > ram
+
+ .rodata : {
+ . = ALIGN(16);
+ PROVIDE(_rodata_start = .);
+ *(.rodata .rodata.*)
+ PROVIDE(_rodata_end = .);
+ } > ram
+
+ .data : {
+ . = ALIGN(16);
+ PROVIDE(_data_start = .);
+ *(.data .data.*)
+ *(.sdata .sdata.*)
+ PROVIDE(_data_end = .);
+ } > ram
+
+ .bss : {
+ . = ALIGN(16);
+ PROVIDE(_bss_start = .);
+ *(.bss .bss.*)
+ *(.sbss .sbss.*)
+ PROVIDE(_bss_end = .);
+ } > ram
+
+ . = ALIGN(4096);
+ PROVIDE(_stack_top = . + 0x8000);
+ . = . + 0x8000;
+ PROVIDE(_heap_start = .);
+} \ No newline at end of file
diff --git a/src/boot/entry.S b/src/boot/entry.S
new file mode 100644
index 0000000..1a6f6b8
--- /dev/null
+++ b/src/boot/entry.S
@@ -0,0 +1,28 @@
+.section .text.entry
+.globl _start
+
+_start:
+ csrr t0, mhartid
+ bnez t0, .L_park_harts
+
+ la sp, _stack_top
+
+ la a0, _bss_start
+ la a1, _bss_end
+ bge a0, a1, .L_call_main
+
+.L_clear_bss:
+ sd zero, (a0)
+ addi a0, a0, 8
+ blt a0, a1, .L_clear_bss
+
+.L_call_main:
+ call kernel_main
+
+.L_infinite_loop:
+ wfi
+ j .L_infinite_loop
+
+.L_park_harts:
+ wfi
+ j .L_park_harts \ No newline at end of file
diff --git a/src/drivers/uart.cc b/src/drivers/uart.cc
new file mode 100644
index 0000000..758abd9
--- /dev/null
+++ b/src/drivers/uart.cc
@@ -0,0 +1,57 @@
+#include "drivers/uart.h"
+#include "common/types.h"
+
+#define UART0_BASE 0x10000000L
+
+#define UART_RBR 0x00 // Receiver Buffer Register (Read)
+#define UART_THR 0x00 // Transmitter Holding Register (Write)
+#define UART_IER 0x01 // Interrupt Enable Register
+#define UART_FCR 0x02 // FIFO Control Register
+#define UART_LCR 0x03 // Line Control Register
+#define UART_LSR 0x05 // Line Status Register
+
+#define UART_LSR_RX_READY 0x01
+#define UART_LSR_TX_EMPTY 0x20
+
+namespace Drivers{
+ inline volatile uint8_t &reg(uint32_t offset)
+ {
+ return *reinterpret_cast<volatile uint8_t *>(UART0_BASE + offset);
+ }
+
+ void uart_init()
+ {
+ reg(UART_IER) = 0x00;
+
+ reg(UART_LCR) = 0x80;
+ reg(0x00) = 0x03;
+ reg(0x01) = 0x00;
+
+ reg(UART_LCR) = 0x03;
+
+ reg(UART_FCR) = 0x07; // Enable FIFO, clear TX/RX queues
+ }
+
+ void uart_putc(char c)
+ {
+ if (c == '\n')
+ {
+ uart_putc('\r');
+ }
+
+ while ((reg(UART_LSR) & UART_LSR_TX_EMPTY) == 0)
+ {
+
+ }
+
+ reg(UART_THR) = c;
+ }
+
+ void uart_puts(const char *s)
+ {
+ while (*s)
+ {
+ uart_putc(*s++);
+ }
+ }
+} \ No newline at end of file
diff --git a/src/kernel/main.cc b/src/kernel/main.cc
new file mode 100644
index 0000000..49adf2b
--- /dev/null
+++ b/src/kernel/main.cc
@@ -0,0 +1,20 @@
+#include "drivers/uart.h"
+
+extern "C" void kernel_main()
+{
+
+ Drivers::uart_init();
+
+ Drivers::uart_puts("\n");
+ Drivers::uart_puts("Modern DOS v1.0 [RISC-V 64]\n");
+ Drivers::uart_puts("2025 Richard Qin\n");
+ Drivers::uart_puts("\n");
+
+ Drivers::uart_puts("A:\\> ");
+
+
+ while (1)
+ {
+
+ }
+} \ No newline at end of file