From 61c12a11dad4f6e88c1d2ebdf90ca770290ccc83 Mon Sep 17 00:00:00 2001 From: Quinten Kock Date: Mon, 30 Nov 2020 01:13:42 +0100 Subject: [PATCH] Initial commit --- .gitignore | 5 ++ .gitmodules | 3 + Makefile | 55 +++++++++++++ ext/limine | 1 + ext/limine.cfg | 6 ++ src-stivale2/Makefile | 23 ++++++ src-stivale2/README.md | 27 +++++++ src-stivale2/linker.ld | 33 ++++++++ src-stivale2/main-stivale2.c | 51 ++++++++++++ src-stivale2/stivale2.h | 150 +++++++++++++++++++++++++++++++++++ 10 files changed, 354 insertions(+) create mode 100644 .gitignore create mode 100644 .gitmodules create mode 100644 Makefile create mode 160000 ext/limine create mode 100644 ext/limine.cfg create mode 100644 src-stivale2/Makefile create mode 100644 src-stivale2/README.md create mode 100644 src-stivale2/linker.ld create mode 100644 src-stivale2/main-stivale2.c create mode 100644 src-stivale2/stivale2.h diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..30fd1c6 --- /dev/null +++ b/.gitignore @@ -0,0 +1,5 @@ +build/* +kernel.elf +kernel2.elf +*.o +zig-cache/ diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000..f1e1882 --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "ext/limine"] + path = ext/limine + url = https://github.com/limine-bootloader/limine diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..0076909 --- /dev/null +++ b/Makefile @@ -0,0 +1,55 @@ +CC = zig cc -target x86_64-freestanding +LD = ld +KERNEL_HDD = build/disk.hdd + +CFLAGS = -O2 -pipe -Wall -Wextra + +CHARDFLAGS := $(CFLAGS) \ + -std=gnu99 \ + -masm=intel \ + -fno-pic \ + -mno-sse \ + -mno-sse2 \ + -mno-mmx \ + -mno-80387 \ + -mno-red-zone \ + -mcmodel=kernel \ + -ffreestanding \ + -fno-stack-protector \ + -Isrc/ \ + +LDHARDFLAGS := $(LDFLAGS) \ + -static \ + -nostdlib \ + -no-pie \ + -z max-page-size=0x1000 \ + -T src/linker.ld + +.PHONY: clean all +.DEFAULT_GOAL = $(KERNEL_HDD) + +disk: $(KERNEL_HDD) +run: $(KERNEL_HDD) + qemu-system-x86_64 -m 2G -hda $(KERNEL_HDD) + +src-stivale2/kernel2.elf: + $(MAKE) -C src-stivale2 + +ext/limine/limine-install: + $(MAKE) -C ext/limine/ limine-install + +$(KERNEL_HDD): ext/limine/limine-install src-stivale2/kernel2.elf + -mkdir build + rm -f $(KERNEL_HDD) + dd if=/dev/zero bs=1M count=0 seek=64 of=$(KERNEL_HDD) + parted -s $(KERNEL_HDD) mklabel msdos + parted -s $(KERNEL_HDD) mkpart primary 1 100% + echfs-utils -m -p0 $(KERNEL_HDD) quick-format 32768 + echfs-utils -m -p0 $(KERNEL_HDD) import src-stivale/kernel.elf kernel.elf + echfs-utils -m -p0 $(KERNEL_HDD) import src-stivale2/kernel2.elf kernel2.elf + echfs-utils -m -p0 $(KERNEL_HDD) import ext/limine.cfg limine.cfg + ext/limine/limine-install ext/limine/limine.bin $(KERNEL_HDD) + +clean: + rm -f $(KERNEL_HDD) + $(MAKE) -C src-stivale2 clean diff --git a/ext/limine b/ext/limine new file mode 160000 index 0000000..8c4f3ec --- /dev/null +++ b/ext/limine @@ -0,0 +1 @@ +Subproject commit 8c4f3ecfde9e6ceedb0f061ceea346aefd8354ff diff --git a/ext/limine.cfg b/ext/limine.cfg new file mode 100644 index 0000000..31e9f93 --- /dev/null +++ b/ext/limine.cfg @@ -0,0 +1,6 @@ +TIMEOUT=5 + +:OS2 +PROTOCOL=stivale2 +KERNEL_PATH=bios://:1/kernel2.elf +KERNEL_CMDLINE=Hi! diff --git a/src-stivale2/Makefile b/src-stivale2/Makefile new file mode 100644 index 0000000..23f6b0d --- /dev/null +++ b/src-stivale2/Makefile @@ -0,0 +1,23 @@ +TARGET := kernel2.elf + +CC = zig cc -target x86_64-freestanding +CFLAGS = -O2 +LD = ld -m elf_x86_64 +QEMU = qemu-system-x86_64 +QEMUFLAGS = -m 1G -enable-kvm -cpu host +LDINTERNALFLAGS := -Tlinker.ld +INTERNALCFLAGS := -I. \ + +CFILES := $(shell find ./ -type f -name '*.c') +OBJ := $(CFILES:.c=.o) + +all: $(TARGET) + +$(TARGET): $(OBJ) + $(LD) $(LDINTERNALFLAGS) $(OBJ) -o $@ + +%.o: %.c + $(CC) $(CFLAGS) $(INTERNALCFLAGS) -c $< -o $@ + +clean: + rm -rf $(TARGET) *.o diff --git a/src-stivale2/README.md b/src-stivale2/README.md new file mode 100644 index 0000000..7b3342c --- /dev/null +++ b/src-stivale2/README.md @@ -0,0 +1,27 @@ +The stivale 2 protocol is a replacement for the stivale protocol that is able to be cleanly extended without breaking changes, it has support for extra features such as SMP compared to the older protocol. + +## the stivale 2 header +This structure must be present in the `.stivale2hdr` section in order for your kernel to be loaded by stivale 2. + +```c +struct stivale2_header { + uint64_t entry_point; + uint64_t stack; + uint64_t flags; + uint64_t tags; +} __attribute__((packed)); +``` + +If `entry_point` is 0 then the ELF entry point will be jumped to, otherwise the address specified will be used, `stack` will be loaded into the stack pointer register, as of now `flags` is 1 if KASLR is to be enabled. + +`tags` is a pointer to the first of a linked list of tags which determine the features requested by the kernel, the base structure of a tag is: + +```c +struct stivale2_hdr_tag { + uint64_t identifier; + uint64_t next; +} __attribute__((packed)); +``` + +Where `identifier` determines the type of the tag, while `next` determines the next tag, a value of `NULL` indicates the end of the list. +For further information on the supported tags consule the [Stivale2 Specification](https://github.com/limine-bootloader/limine/blob/master/STIVALE2.md) diff --git a/src-stivale2/linker.ld b/src-stivale2/linker.ld new file mode 100644 index 0000000..284a143 --- /dev/null +++ b/src-stivale2/linker.ld @@ -0,0 +1,33 @@ +ENTRY(_start) + +SECTIONS +{ + kernel_phys_offset = 0xffffffff80000000; + . = kernel_phys_offset + 0x100000; + + .stivale2hdr ALIGN(4K) : + { + KEEP(*(.stivalehdr)) + } + + .text ALIGN(4K) : + { + KEEP(*(.text*)) + } + + .rodata ALIGN(4K) : + { + KEEP(*(.rodata*)) + } + + .data ALIGN(4K) : + { + KEEP(*(.data*)) + } + + .bss ALIGN(4K) : + { + KEEP(*(COMMON)) + KEEP(*(.bss*)) + } +} diff --git a/src-stivale2/main-stivale2.c b/src-stivale2/main-stivale2.c new file mode 100644 index 0000000..de225f0 --- /dev/null +++ b/src-stivale2/main-stivale2.c @@ -0,0 +1,51 @@ +#include +#include +#include + +#define VGA_ADDRESS 0xb8000 +#define VGA_COLOR(character, color) ((uint16_t) (character) | (uint16_t) (color) << 8) +#define VGA_BLACK 0 +#define VGA_BLUE 1 +#define VGA_GREEN 2 +#define VGA_CYAN 3 +#define VGA_RED 4 +#define VGA_PURPLE 5 +#define VGA_BROWN 6 +#define VGA_GRAY 7 +#define VGA_DARK_GRAY 8 +#define VGA_LIGHT_BLUE 9 +#define VGA_LIGH_GREEN 10 +#define VGA_LIGHT_CYAN 11 +#define VGA_LIGHT_RED 12 +#define VGA_LIGHT_PURPLE 13 +#define VGA_YELLOW 14 +#define VGA_WHITE 15 + +static uint8_t stack[4096] = {0}; +void stivale2_main(struct stivale2_struct *info); + +struct stivale2_header_tag_smp smp_request = { + .tag = { + .identifier = STIVALE2_HEADER_TAG_SMP_ID, + .next = 0 + }, + .flags = 0 +}; + +__attribute__((section(".stivale2hdr"), used)) +struct stivale2_header header2 = { + .entry_point = (uint64_t)stivale2_main, + .stack = (uintptr_t)stack + sizeof(stack), + .flags = 0, + .tags = (uint64_t)&smp_request +}; + +void stivale2_main(struct stivale2_struct *info) { + volatile uint16_t *vga_buffer = (uint16_t*)VGA_ADDRESS; + vga_buffer[0] = VGA_COLOR('h', VGA_GREEN); + vga_buffer[1] = VGA_COLOR('e', VGA_GREEN); + vga_buffer[2] = VGA_COLOR('l', VGA_GREEN); + vga_buffer[3] = VGA_COLOR('l', VGA_GREEN); + vga_buffer[4] = VGA_COLOR('o', VGA_GREEN); + asm volatile ("hlt"); +} diff --git a/src-stivale2/stivale2.h b/src-stivale2/stivale2.h new file mode 100644 index 0000000..b07daa1 --- /dev/null +++ b/src-stivale2/stivale2.h @@ -0,0 +1,150 @@ +#ifndef __STIVALE__STIVALE2_H__ +#define __STIVALE__STIVALE2_H__ + +#include + +struct stivale2_tag { + uint64_t identifier; + uint64_t next; +} __attribute__((packed)); + +/* --- Header --------------------------------------------------------------- */ +/* Information passed from the kernel to the bootloader */ + +struct stivale2_header { + uint64_t entry_point; + uint64_t stack; + uint64_t flags; + uint64_t tags; +} __attribute__((packed)); + +#define STIVALE2_HEADER_TAG_FRAMEBUFFER_ID 0x3ecc1bc43d0f7971 + +struct stivale2_header_tag_framebuffer { + struct stivale2_tag tag; + uint16_t framebuffer_width; + uint16_t framebuffer_height; + uint16_t framebuffer_bpp; +} __attribute__((packed)); + +#define STIVALE2_HEADER_TAG_SMP_ID 0x1ab015085f3273df + +struct stivale2_header_tag_smp { + struct stivale2_tag tag; + uint64_t flags; +} __attribute__((packed)); + +#define STIVALE2_HEADER_TAG_5LV_PAGING_ID 0x932f477032007e8f + +/* --- Struct --------------------------------------------------------------- */ +/* Information passed from the bootloader to the kernel */ + +struct stivale2_struct { +#define STIVALE2_BOOTLOADER_BRAND_SIZE 64 + char bootloader_brand[STIVALE2_BOOTLOADER_BRAND_SIZE]; + +#define STIVALE2_BOOTLOADER_VERSION_SIZE 64 + char bootloader_version[STIVALE2_BOOTLOADER_VERSION_SIZE]; + + uint64_t tags; +} __attribute__((packed)); + +#define STIVALE2_STRUCT_TAG_CMDLINE_ID 0xe5e76a1b4597a781 + +struct stivale2_struct_tag_cmdline { + struct stivale2_tag tag; + uint64_t cmdline; +} __attribute__((packed)); + +#define STIVALE2_STRUCT_TAG_MEMMAP_ID 0x2187f79e8612de07 + +enum { + STIVALE2_MMAP_USABLE = 1, + STIVALE2_MMAP_RESERVED = 2, + STIVALE2_MMAP_ACPI_RECLAIMABLE = 3, + STIVALE2_MMAP_ACPI_NVS = 4, + STIVALE2_MMAP_BAD_MEMORY = 5, + STIVALE2_MMAP_BOOTLOADER_RECLAIMABLE = 0x1000, + STIVALE2_MMAP_KERNEL_AND_MODULES = 0x1001 +}; + +struct stivale2_mmap_entry { + uint64_t base; + uint64_t length; + uint32_t type; + uint32_t unused; +} __attribute__((packed)); + +struct stivale2_struct_tag_memmap { + struct stivale2_tag tag; + uint64_t entries; + struct stivale2_mmap_entry memmap[]; +} __attribute__((packed)); + +#define STIVALE2_STRUCT_TAG_FRAMEBUFFER_ID 0x506461d2950408fa + +struct stivale2_struct_tag_framebuffer { + struct stivale2_tag tag; + uint64_t framebuffer_addr; + uint16_t framebuffer_width; + uint16_t framebuffer_height; + uint16_t framebuffer_pitch; + uint16_t framebuffer_bpp; +} __attribute__((packed)); + +#define STIVALE2_STRUCT_TAG_MODULES_ID 0x4b6fe466aade04ce + +struct stivale2_module { + uint64_t begin; + uint64_t end; + +#define STIVALE2_MODULE_STRING_SIZE 128 + char string[STIVALE2_MODULE_STRING_SIZE]; +} __attribute__((packed)); + +struct stivale2_struct_tag_modules { + struct stivale2_tag tag; + uint64_t module_count; + struct stivale2_module modules[]; +} __attribute__((packed)); + +#define STIVALE2_STRUCT_TAG_RSDP_ID 0x9e1786930a375e78 + +struct stivale2_struct_tag_rsdp { + struct stivale2_tag tag; + uint64_t rsdp; +} __attribute__((packed)); + +#define STIVALE2_STRUCT_TAG_EPOCH_ID 0x566a7bed888e1407 + +struct stivale2_struct_tag_epoch { + struct stivale2_tag tag; + uint64_t epoch; +} __attribute__((packed)); + +#define STIVALE2_STRUCT_TAG_FIRMWARE_ID 0x359d837855e3858c + +struct stivale2_struct_tag_firmware { + struct stivale2_tag tag; + uint64_t flags; +} __attribute__((packed)); + +#define STIVALE2_STRUCT_TAG_SMP_ID 0x34d1d96339647025 + +struct stivale2_smp_info { + uint32_t processor_id; + uint32_t lapic_id; + uint64_t target_stack; + uint64_t goto_address; + uint64_t extra_argument; +} __attribute__((packed)); + +struct stivale2_struct_tag_smp { + struct stivale2_tag tag; + uint64_t flags; + uint64_t cpu_count; + struct stivale2_smp_info smp_info[]; +} __attribute__((packed)); + +#endif +