diff options
| -rw-r--r-- | BuildConfig | 5 | ||||
| -rw-r--r-- | Makefile | 28 | ||||
| -rw-r--r-- | include/early/uart.h | 5 | ||||
| -rw-r--r-- | kernel/common/log.c | 10 | ||||
| -rw-r--r-- | kernel/riscv/kernel.c | 13 | ||||
| -rw-r--r-- | kernel/x86/kernel.c | 30 | ||||
| -rw-r--r-- | kernel/x86/linker.ld | 87 | ||||
| -rw-r--r-- | kernel/x86/start.S | 10 | ||||
| -rw-r--r-- | kernel/x86/uart.S | 18 | ||||
| -rw-r--r-- | riscv.BuildConfig | 11 | ||||
| -rw-r--r-- | x86.BuildConfig | 8 |
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 @@ -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 |
