From e9705f75793063e2a4da07eda2f16c304bb1239d Mon Sep 17 00:00:00 2001 From: Drew Galbraith Date: Wed, 17 May 2023 20:20:53 -0700 Subject: [PATCH] Barebones Kernel Commit Uses limine to boot off of a disk. Outputs a character to the debug port. --- .gitignore | 1 + CMakeLists.txt | 24 +++++++++++++++++++++++ init-dbg.sh | 2 ++ scripts/build_image.sh | 39 +++++++++++++++++++++++++++++++++++++ zion/CMakeLists.txt | 36 ++++++++++++++++++++++++++++++++++ zion/boot/limine.cfg | 9 +++++++++ zion/linker.ld | 44 ++++++++++++++++++++++++++++++++++++++++++ zion/zion.cpp | 14 ++++++++++++++ 8 files changed, 169 insertions(+) create mode 100644 .gitignore create mode 100644 CMakeLists.txt create mode 100755 init-dbg.sh create mode 100644 scripts/build_image.sh create mode 100644 zion/CMakeLists.txt create mode 100644 zion/boot/limine.cfg create mode 100644 zion/linker.ld create mode 100644 zion/zion.cpp diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..cf496c6 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +builddbg/ diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..19ba2aa --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,24 @@ +cmake_minimum_required(VERSION 3.2) + +# Set because our cross compiler can't do dynamic linking? +set(CMAKE_TRY_COMPILE_TARGET_TYPE "STATIC_LIBRARY") + +project(AcadiaOS VERSION 0.0.1 LANGUAGES CXX ASM-ATT) + +set(CMAKE_CXX_STANDARD 20) +set(CMAKE_CXX_STANDARD_REQUIRED True) +set(CMAKE_EXPORT_COMPILE_COMMANDS True) + +add_subdirectory(zion) + +add_custom_command( + OUTPUT disk.img + COMMAND sudo sh ../scripts/build_image.sh disk.img + DEPENDS zion + USES_TERMINAL +) + +add_custom_target(qemu + COMMAND qemu-system-x86_64 -d guest_errors -m 1G -serial stdio -hda disk.img --boot c + DEPENDS disk.img + USES_TERMINAL) diff --git a/init-dbg.sh b/init-dbg.sh new file mode 100755 index 0000000..2fc9230 --- /dev/null +++ b/init-dbg.sh @@ -0,0 +1,2 @@ +#! /bin/bash +cmake -B builddbg/ -G Ninja -D CMAKE_CXX_COMPILER=x86_64-elf-gcc -D CMAKE_ASM-ATT_COMPILER=x86_64-elf-as -D CMAKE_BUILD_TYPE=Debug diff --git a/scripts/build_image.sh b/scripts/build_image.sh new file mode 100644 index 0000000..8cc970c --- /dev/null +++ b/scripts/build_image.sh @@ -0,0 +1,39 @@ +#!/us + +set -e + +if [[ $# -ne 1 ]]; then + echo "Must specify disk image name." +fi + +dd if=/dev/zero of=$1 bs=1M count=200 + +dev=$(losetup --find --partscan --show $1) +if [ -z "$dev" ]; then + echo "Couldn't mount loopback device" + exit 1; +fi +echo "Loopback device: ${dev}" + +cleanup() { + umount efi + rm -rf efi +} +trap cleanup EXIT + +parted -s $dev mklabel gpt mkpart EFI fat32 1MiB 10MiB mkpart ext2 10MiB 100% set 1 esp on +mkfs.fat -F 12 "${dev}p1" +mke2fs "${dev}p2" + +limine-deploy "${dev}" + +mkdir -p efi/ +mount "${dev}p1" efi/ + +mkdir -p efi/EFI/BOOT +cp /usr/share/limine/BOOTX64.EFI efi/EFI/BOOT +cp /usr/share/limine/limine.sys efi/ +cp ../zion/boot/limine.cfg efi/ +cp zion/zion efi/ + +chown drew:drew $1 diff --git a/zion/CMakeLists.txt b/zion/CMakeLists.txt new file mode 100644 index 0000000..45734b4 --- /dev/null +++ b/zion/CMakeLists.txt @@ -0,0 +1,36 @@ +add_executable(zion + zion.cpp) + +# -c -- Don't run the linker. +# -nostdlib -- Don't include the standard library. +# -mabi=sysv -- Explicitly specify the ABI since we will rely on it. +# -mno-red-zone -- Don't put data below the stack pointer (clobbered by interrupts). +# -mcmodel=kernel -- Assume the kernel code is running in the higher half. +# -mgeneral-regs-only -- Prevent GCC from using a whole host of nonsense registers (that we have to enable). +# Hopefully preceded by -mgeneral-regs-only +# -mno-80387 +# -mno-mmx +# -mno-3dnow +# -mno-sse -mno-sse2 +# -MMD -- Something with the preprocessor? +set(_Z_COMPILE_FLAGS "${CMAKE_CXX_FLAGS} -ffreestanding -nostdlib -mabi=sysv -mno-red-zone -mcmodel=kernel -mgeneral-regs-only") +# -mno-80387 -mno-mmx -mno-3dnow -mno-sse -mno-sse2 -MMD + +set(_Z_LINK_SCRIPT "${CMAKE_CURRENT_SOURCE_DIR}/linker.ld") + +# -lgcc -- Link against gcc internals. Not sure if necessary. +# -nostdlib -- Don't try to link against the stdlib. +# -nostartfiles -- Don't try to link against crt0.s +# -static -- Prevent trying something with shared libraries (probably irrelevant). +# -z max-page-size=0x1000 -- Assume 4 KiB Pages. +set(_Z_LINK_FLAGS "-T ${_Z_LINK_SCRIPT} -lgcc -nostdlib -nostartfiles -static -z max-page-size=0x1000") + + +# Don't try to dynamically link. +set(CMAKE_SHARED_LIBRARY_LINK_CXX_FLAGS "") + +set_target_properties(zion + PROPERTIES + COMPILE_FLAGS "${_Z_COMPILE_FLAGS}" + LINK_FLAGS "${_Z_LINK_FLAGS}" + ) diff --git a/zion/boot/limine.cfg b/zion/boot/limine.cfg new file mode 100644 index 0000000..a418a0b --- /dev/null +++ b/zion/boot/limine.cfg @@ -0,0 +1,9 @@ +# Needs to be copied into the EFI partition of the drive. + +TIMEOUT=10 + +:AcadiaOS + +PROTOCOL=limine + +KERNEL_PATH=boot:///zion diff --git a/zion/linker.ld b/zion/linker.ld new file mode 100644 index 0000000..aed45ae --- /dev/null +++ b/zion/linker.ld @@ -0,0 +1,44 @@ +OUTPUT_FORMAT(elf64-x86-64) + +ENTRY (zion) + +/* Define the program headers we want so the bootloader gives us the right */ +/* MMU permissions */ +PHDRS +{ + text PT_LOAD FLAGS((1 << 0) | (1 << 2)) ; /* Execute + Read */ + rodata PT_LOAD FLAGS((1 << 2)) ; /* Read only */ + data PT_LOAD FLAGS((1 << 1) | (1 << 2)) ; /* Write + Read */ +} + +SECTIONS +{ + . = 0xffffffff80000000; + /* Add a symbol that indicates the start address of the kernel. */ + _kernel_start = .; + + .text : { + *(.text .text.*) + } :text + + /* Move to the next memory page for .rodata */ + . += CONSTANT(MAXPAGESIZE); + + .rodata : { + *(.rodata .rodata.*) + } :rodata + + /* Move to the next memory page for .data */ + . += CONSTANT(MAXPAGESIZE); + + .data : { + *(.data .data.*) + } :data + + .bss : { + *(COMMON) + *(.bss .bss.*) + } :data + /* Add a symbol that indicates the end address of the kernel. */ + _kernel_end = .; +} diff --git a/zion/zion.cpp b/zion/zion.cpp new file mode 100644 index 0000000..c22c920 --- /dev/null +++ b/zion/zion.cpp @@ -0,0 +1,14 @@ +#include + +#define COM1 0x3f8 + +void outb(uint16_t port, uint8_t value) { + asm volatile("outb %0, %1" ::"a"(value), "Nd"(port)); +} + +extern "C" void zion() { + outb(COM1, 'a'); + + while (1) + ; +}