summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--BuildConfig5
-rw-r--r--Makefile28
-rw-r--r--include/early/uart.h5
-rw-r--r--kernel/common/log.c10
-rw-r--r--kernel/riscv/kernel.c13
-rw-r--r--kernel/x86/kernel.c30
-rw-r--r--kernel/x86/linker.ld87
-rw-r--r--kernel/x86/start.S10
-rw-r--r--kernel/x86/uart.S18
-rw-r--r--riscv.BuildConfig11
-rw-r--r--x86.BuildConfig8
11 files changed, 206 insertions, 19 deletions
diff --git a/BuildConfig b/BuildConfig
deleted file mode 100644
index c985c6c..0000000
--- a/BuildConfig
+++ /dev/null
@@ -1,5 +0,0 @@
-kernel: kernel/riscv/*.c kernel/riscv/*.S kernel/common/*.c
-linker_script: kernel/riscv/linker.ld
-kernel_target: kernel/riscv
-modules: console
-console: console/*.c
diff --git a/Makefile b/Makefile
index ad38c9a..3eae704 100644
--- a/Makefile
+++ b/Makefile
@@ -7,14 +7,9 @@ OBJCOPY = llvm-objcopy
COMPILER = $(shell $(CC) --version | head -n 1)
LINKER = $(shell $(LD) --version | head -n 1)
+ARCH_NAME := $(shell grep '^arch:' BuildConfig | sed 's/^arch://' | awk '{$$1=$$1; print}')
-ARCH_FLAG = \
- --target=riscv32-unknown-elf \
- -march=rv32g \
- -mabi=ilp32 \
- -D__SYS_LITTLE_ENDIAN__
-
-
+ARCH_FLAG := $(shell grep '^arch_flag:' BuildConfig | sed 's/^arch_flag://' | awk '{$$1=$$1; print}')
COMMON_FLAGS = \
-ffreestanding \
-fno-builtin \
@@ -29,6 +24,7 @@ COMMON_FLAGS = \
-DVERSION='"$(VERSION)"' \
-DCOMPILER_NAME='"$(COMPILER)"' \
-DLINKER_NAME='"$(LINKER)"' \
+ -DARCH_NAME='"$(ARCH_NAME)"'
KERNEL_FLAG = $(COMMON_FLAGS) -static
MODULE_FLAG = $(COMMON_FLAGS) -fPIC -fpie
@@ -38,13 +34,10 @@ SECTION_FLAG = \
-fdata-sections \
-fno-common
-INCLUDE_FLAG = -Iinclude -Ikernel
+INCLUDE_FLAG = -Iinclude
OPT_FLAG = -O2 -g3
WARN_FLAG = -Wall -Wextra -Werror -Wundef
-KERNEL_LD_FLAG = -T $(KERNEL_LD) -nostdlib -m elf32lriscv --gc-sections
-MODULE_LD_FLAG = -nostdlib -shared -m elf32lriscv --gc-sections
-
KERNEL_OBJCOPY_FLAG = -O binary \
--strip-all \
--remove-section=.comment \
@@ -95,6 +88,10 @@ $(foreach module,$(MODULES),$(eval $(call module_template,$(module))))
KERNEL_SRCS = $(wildcard $(shell grep '^kernel:' BuildConfig | sed 's/^kernel://' | awk '{$$1=$$1; print}'))
KERNEL_LD := $(shell grep '^linker_script:' BuildConfig | sed 's/^linker_script://' | awk '{$$1=$$1; print}')
+
+KERNEL_LD_FLAG = $(shell grep '^link_flag:' BuildConfig | sed 's/^link_flag://' | awk '{$$1=$$1; print}')
+MODULE_LD_FLAG = -nostdlib -shared -m $(shell grep '^module_link_arch:' BuildConfig | sed 's/^module_link_arch://' | awk '{$$1=$$1; print}') --gc-sections
+
KERNEL_TARGET := $(shell grep '^kernel_target:' BuildConfig | sed 's/^kernel_target://' | awk '{$$1=$$1; print}')
KERNEL_OBJS = $(KERNEL_SRCS:.c=.o)
KERNEL_OBJS := $(KERNEL_OBJS:.S=.o)
@@ -117,8 +114,15 @@ GENERATED = \
.PHONY: all kernel kassemble clean modules $(MODULES)
$(V).SILENT:
+
+ifeq ($(shell grep '^needs_kassemble:' BuildConfig | sed 's/^needs_kassemble://' | awk '{$$1=$$1; print}'), yes)
all: kassemble kernel modules
kernel: $(KERNEL_IMAGE)
+else
+all: kernel modules
+kernel: $(KERNEL_ELF)
+endif
+
modules: $(MODULES)
kassemble: $(KASSEMBLE_BIN)
$(MODULES): $(MODULE_OBJECTS)
@@ -136,7 +140,7 @@ $(KASSEMBLE_BIN): $(KASSEMBLE_SRC)
$(KERNEL_ELF): $(KERNEL_OBJS) $(KERNEL_LD) | $(KERNEL_OUTDIR)/
@echo " LD $@"
- $(LD) $(KERNEL_LD_FLAG) $(KERNEL_OBJS) -o $@
+ $(LD) $(KERNEL_LD_FLAG) $(KERNEL_OBJS)
$(KERNEL_BIN): $(KERNEL_ELF) | $(KERNEL_OUTDIR)/
@echo " OBJCOPY $@"
diff --git a/include/early/uart.h b/include/early/uart.h
new file mode 100644
index 0000000..8d69678
--- /dev/null
+++ b/include/early/uart.h
@@ -0,0 +1,5 @@
+#pragma once
+#include <sys/stddef.h>
+
+void outb(uint16_t port, uint8_t val);
+uint8_t inb(uint16_t port);
diff --git a/kernel/common/log.c b/kernel/common/log.c
index f65c165..5f470f1 100644
--- a/kernel/common/log.c
+++ b/kernel/common/log.c
@@ -1,15 +1,21 @@
#include <sys/stddef.h>
#include <sys/log.h>
+void stub(char c) {
+ (void)c;
+}
+
__attribute__((section(".ringbuf"), aligned(64)))
volatile char log_ring[RINGBUF_SIZE];
static int pos = 0;
+static console_callback_t console_callback = stub;
void put_char(char c) {
log_ring[pos++] = c;
if (pos >= RINGBUF_SIZE)
pos = 0;
+ console_callback(c);
}
void put_string(const char *s) {
@@ -17,6 +23,10 @@ void put_string(const char *s) {
put_char(*s++);
}
+void register_console_callback(console_callback_t callback) {
+ console_callback = callback;
+}
+
void put_uint(unsigned int value, unsigned int radix) {
char tmp[16];
const char digits[] = "0123456789abcdef";
diff --git a/kernel/riscv/kernel.c b/kernel/riscv/kernel.c
index 46de696..e38134c 100644
--- a/kernel/riscv/kernel.c
+++ b/kernel/riscv/kernel.c
@@ -1,5 +1,4 @@
#include <sys/log.h>
-#include <sys/log.h>
#include <sys/mem.h>
#include <sys/cpio.h>
#include <early/dtb.h>
@@ -70,7 +69,7 @@ struct kernel_info *discover_arch(void *fdt) {
}
void kernel_main(size_t hart, void *fdt) {
- printk("wkern version %s (Compiler %s, Linker %s)\n", VERSION, COMPILER_NAME, LINKER_NAME);
+ printk("wkern version %s (Compiler %s, Linker %s) on %s\n", VERSION, COMPILER_NAME, LINKER_NAME, ARCH_NAME);
if (hart != 0)
return;
@@ -79,6 +78,16 @@ void kernel_main(size_t hart, void *fdt) {
if (!kernel_info) {
return;
}
+
+
+ uint8_t *bitmap = kemalloc(kernel_info->mem_size / (8 * PAGE_SIZE));
+ uintptr_t mem_start = (uintptr_t)kernel_info->mem_start;
+ uintptr_t initrd_start = (uintptr_t)kernel_info->initrd_start;
+ uintptr_t initrd_end = initrd_start + kernel_info->initrd_size;
+ for (; initrd_start <= initrd_end; initrd_start += PAGE_SIZE) {
+ uintptr_t offset = (initrd_start - mem_start) / PAGE_SIZE;
+ bitmap[offset / 8] = (uint8_t)(1u << (offset % 8));
+ }
}
void kernel_trap() {
diff --git a/kernel/x86/kernel.c b/kernel/x86/kernel.c
new file mode 100644
index 0000000..296d966
--- /dev/null
+++ b/kernel/x86/kernel.c
@@ -0,0 +1,30 @@
+#include <sys/stddef.h>
+#include <early/uart.h>
+#include <sys/log.h>
+
+#define COM1_PORT 0x3F8
+
+void serial_init(void) {
+ outb(COM1_PORT + 1, 0x00); // Disable interrupts
+ outb(COM1_PORT + 3, 0x80); // Enable DLAB (set baud rate divisor)
+ outb(COM1_PORT + 0, 0x01); // Set divisor to 1 (lo byte) -> 115200 baud
+ outb(COM1_PORT + 1, 0x00); // (hi byte)
+ outb(COM1_PORT + 3, 0x03); // 8 bits, no parity, one stop bit
+ outb(COM1_PORT + 2, 0xC7); // Enable FIFO, clear them, with 14-byte threshold
+ outb(COM1_PORT + 4, 0x0B); // IRQs enabled, RTS/DSR set
+}
+
+static int serial_tx_ready(void) {
+ return inb(COM1_PORT + 5) & 0x20;
+}
+
+void serial_putchar(char c) {
+ while (serial_tx_ready() == 0);
+ outb(COM1_PORT, c);
+}
+
+void kernel_main(void) {
+ serial_init();
+ register_console_callback(serial_putchar);
+ printk("wkern version %s (Compiler %s, Linker %s) on %s\n", VERSION, COMPILER_NAME, LINKER_NAME, ARCH_NAME);
+}
diff --git a/kernel/x86/linker.ld b/kernel/x86/linker.ld
new file mode 100644
index 0000000..067d4e4
--- /dev/null
+++ b/kernel/x86/linker.ld
@@ -0,0 +1,87 @@
+OUTPUT_ARCH(i386:x86-64)
+ENTRY(_start)
+
+MEMORY
+{
+ ROM (rx) : ORIGIN = 0x1000000, LENGTH = 1M
+ RAM (rwx) : ORIGIN = 0x1040000, LENGTH = 1M
+ LOGRAM (rw) : ORIGIN = 0x1080000, LENGTH = 1M
+}
+
+SECTIONS
+{
+ .header : {
+ KEEP(*(.header))
+ *(.header)
+ } > ROM
+
+ .text : {
+ KEEP(*(.text._start))
+ KEEP(*(.text.start))
+ *(.text)
+ *(.text.*)
+ } > ROM
+
+ .rodata : {
+ *(.rodata)
+ *(.rodata.*)
+ } > ROM
+
+ .init_array : {
+ __init_array_start = .;
+ KEEP(*(.init_array))
+ KEEP(*(.init_array.*))
+ __init_array_end = .;
+ } > ROM
+
+ .data : {
+ __data_start = .;
+ *(.data)
+ *(.data.*)
+ __data_end = .;
+ } > RAM AT> ROM
+ __data_load = LOADADDR(.data);
+
+ .bss : {
+ __bss_start = .;
+ *(.bss)
+ *(.bss.*)
+ *(COMMON)
+ __bss_end = .;
+ } > RAM
+
+ .stack (NOLOAD) : {
+ . = ALIGN(16);
+ __stack_bottom = .;
+ . += 8K;
+ __stack_top = .;
+ } > RAM
+
+ .ringbuf (NOLOAD) : ALIGN(64)
+ {
+ __ringbuf_start = .;
+ KEEP(*(.ringbuf))
+ . = ALIGN(64);
+ __ringbuf_end = .;
+ } > LOGRAM
+
+ .image_end (NOLOAD) : {
+ . = ALIGN(4);
+ __image_end = .;
+ } > ROM
+
+ /DISCARD/ : {
+ *(.eh_frame)
+ *(.eh_frame.*)
+ *(.eh_frame_hdr)
+ *(.comment)
+ *(.note.*)
+ *(.debug_*)
+ *(.stab*)
+ *(.llvm_*)
+ *(.rela.*)
+ }
+
+ __image_start = ORIGIN(ROM);
+ __image_size = __image_end - __image_start;
+}
diff --git a/kernel/x86/start.S b/kernel/x86/start.S
new file mode 100644
index 0000000..779657c
--- /dev/null
+++ b/kernel/x86/start.S
@@ -0,0 +1,10 @@
+.section .text._start
+.global _start
+
+_start:
+ call kernel_main
+1:
+ cli
+ hlt
+ jmp 1b
+
diff --git a/kernel/x86/uart.S b/kernel/x86/uart.S
new file mode 100644
index 0000000..416fad2
--- /dev/null
+++ b/kernel/x86/uart.S
@@ -0,0 +1,18 @@
+.section .text
+
+.global outb
+.global inb
+
+# void outb(uint16_t port, uint8_t val)
+outb:
+ mov %dl, %al
+ mov %cx, %dx
+ outb %al, %dx
+ ret
+
+# uint8_t inb(uint16_t port)
+inb:
+ mov %cx, %dx
+ inb %dx, %al
+ ret
+
diff --git a/riscv.BuildConfig b/riscv.BuildConfig
new file mode 100644
index 0000000..40dae12
--- /dev/null
+++ b/riscv.BuildConfig
@@ -0,0 +1,11 @@
+arch: RISC-V, 32 bit IMAFD_Zicsr Zifencei unknown ELF, System V ABI
+arch_flag: --target=riscv32-unknown-elf -march=rv32g -mabi=ilp32 -D__SYS_LITTLE_ENDIAN__
+link_flag: -T kernel/riscv/linker.ld -nostdlib -m elf32lriscv --gc-sections -o kernel/riscv/kernel.elf
+module_link_arch: elf32lriscv
+kernel: kernel/riscv/*.c kernel/riscv/*.S kernel/common/*.c
+linker_script: kernel/riscv/linker.ld
+kernel_target: kernel/riscv
+modules: console
+console: console/*.c
+
+needs_kassemble: yes
diff --git a/x86.BuildConfig b/x86.BuildConfig
new file mode 100644
index 0000000..8de6286
--- /dev/null
+++ b/x86.BuildConfig
@@ -0,0 +1,8 @@
+arch: i386 x86-64, 64 bit unknown PE/COFF UEFI, Windows ABI
+arch_flag: --target=x86_64-unknown-uefi -m64 -mcmodel=small -mno-red-zone -D__SYS_LITTLE_ENDIAN__
+link_flag: /out:kernel/x86/bImage.efi /subsystem:efi_application /entry:_start /nodefaultlib
+module_link_arch: elf_x86_64
+kernel: kernel/x86/*.c kernel/x86/*.S kernel/common/*.c
+kernel_target: kernel/x86
+
+needs_kassemble: no