From 1ee5dcbd0bce7898a94b6f08d6bb18a9947280a0 Mon Sep 17 00:00:00 2001 From: karina Date: Mon, 20 Apr 2026 08:30:08 +0400 Subject: [PATCH] feat: working bootloader and basic kernel (just dyes screen green) --- Bootloader/CMakeLists.txt | 1 + Bootloader/Source/main.c | 145 ++++++++++++++++++++++++++++++++++++-- Bootloader/justfile | 10 +-- Common/bootinfo.h | 35 +++++++++ Kernel/CMakeLists.txt | 30 ++++++++ Kernel/Source/entry.S | 22 ++++++ Kernel/justfile | 12 ++++ Kernel/linker.ld | 0 justfile | 19 +++-- 9 files changed, 258 insertions(+), 16 deletions(-) create mode 100644 Common/bootinfo.h create mode 100644 Kernel/CMakeLists.txt create mode 100644 Kernel/Source/entry.S create mode 100644 Kernel/justfile create mode 100644 Kernel/linker.ld diff --git a/Bootloader/CMakeLists.txt b/Bootloader/CMakeLists.txt index 84eb761..930f51c 100644 --- a/Bootloader/CMakeLists.txt +++ b/Bootloader/CMakeLists.txt @@ -24,6 +24,7 @@ add_library(posix_uefi_lib OBJECT ${POSIX_UEFI_SOURCES}) target_compile_options(posix_uefi_lib PRIVATE ${UEFI_COMPILE_OPTIONS}) target_include_directories(posix_uefi_lib PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/Source/uefi) + add_executable(BOOTAA64 Source/main.c) target_compile_options(BOOTAA64 PRIVATE ${UEFI_COMPILE_OPTIONS}) diff --git a/Bootloader/Source/main.c b/Bootloader/Source/main.c index a9dc6bb..2f5d06c 100644 --- a/Bootloader/Source/main.c +++ b/Bootloader/Source/main.c @@ -1,7 +1,144 @@ #include "uefi/uefi.h" // IWYU pragma: keep +#include "../../Common/bootinfo.h" -int main() { - printf("Meow!\n"); - while (1) __asm__ ("wfi"); - return 0; +void print(wchar_t* msg) { + ST->ConOut->OutputString(ST->ConOut, msg); +} + +efi_status_t die() { + while(1) __asm__ volatile("wfi"); + return EFI_ABORTED; +} + +int compare_guid(efi_guid_t* a, efi_guid_t* b) { + uint8_t* p1 = (uint8_t*)a; + uint8_t* p2 = (uint8_t*)b; + for (int i = 0; i < 16; i++) { + if (p1[i] != p2[i]) return 0; + } + return 1; +} + +int main() +{ + efi_gop_t* gop = NULL; + efi_guid_t gop_guid = EFI_GRAPHICS_OUTPUT_PROTOCOL_GUID; + ST->BootServices->LocateProtocol(&gop_guid, 0, (void**)&gop); + + efi_guid_t dtb_guid = {0xb1b621d5, 0xf19c, 0x41a5, {0x83, 0x0b, 0xd9, 0x15, 0x2c, 0x69, 0xaa, 0xe0}}; + void* dtbAddress = NULL; + + for (uintn_t i = 0; i < ST->NumberOfTableEntries; i++) { + if (compare_guid(&ST->ConfigurationTable[i].VendorGuid, &dtb_guid)) { + dtbAddress = ST->ConfigurationTable[i].VendorTable; + break; + } + } + + if (!dtbAddress) { + print(L"Failed to find DTB!\r\n"); + return die(); + } + + efi_loaded_image_protocol_t* loaded_image; + efi_guid_t lip_guid = EFI_LOADED_IMAGE_PROTOCOL_GUID; + gBS->HandleProtocol(IM, &lip_guid, (void**)&loaded_image); + + efi_simple_file_system_protocol_t* fs; + efi_guid_t sfsp_guid = EFI_SIMPLE_FILE_SYSTEM_PROTOCOL_GUID; + gBS->HandleProtocol(loaded_image->DeviceHandle, &sfsp_guid, (void**)&fs); + + efi_file_handle_t* root; + fs->OpenVolume(fs, &root); + + efi_file_handle_t* kernel_file; + uintn_t kinfo_size = 0; + efi_file_info_t* kfile_info = NULL; + efi_guid_t fi_guid = EFI_FILE_INFO_GUID; + + efi_status_t status = root->Open(root, &kernel_file, L"ksOSKernel.bin", EFI_FILE_MODE_READ, 0); + if (EFI_ERROR(status)) { + print(L"Cant find ksOSKernel.bin\r\n"); + return die(); + } + + status = kernel_file->GetInfo(kernel_file, &fi_guid, &kinfo_size, NULL); + if (status == EFI_BUFFER_TOO_SMALL) { + gBS->AllocatePool(EfiLoaderData, kinfo_size, (void**)&kfile_info); + status = kernel_file->GetInfo(kernel_file, &fi_guid, &kinfo_size, kfile_info); + } + + uint64_t kernel_size = kfile_info->FileSize; + uintn_t kernel_size_read = (uintn_t)kernel_size; + + uintn_t kernel_pages = (kernel_size + 0xFFF) / 0x1000; + efi_physical_address_t kernel_addr = 0; + + status = gBS->AllocatePages(AllocateAnyPages, EfiLoaderData, kernel_pages, &kernel_addr); + if (EFI_ERROR(status)) { + print(L"Failed to allocate ANY memory for kernel!\r\n"); + return die(); + } + + kernel_file->Read(kernel_file, &kernel_size_read, (void*)kernel_addr); \ + printf("Kernel loaded at %p\r\n", (void*)kernel_addr); + + Bootinfo* bootInfo = (Bootinfo*)malloc(sizeof(Bootinfo)); + bootInfo->magic = BOOTINFO_MAGIC; + + bootInfo->kernelInfo.kernelAddress = (void*)kernel_addr; + bootInfo->kernelInfo.kernelSize = kernel_size; + + bootInfo->framebuffer.base = (BIUInt32*)gop->Mode->FrameBufferBase; + bootInfo->framebuffer.baseSize = gop->Mode->FrameBufferSize; + bootInfo->framebuffer.height = gop->Mode->Information->VerticalResolution; + bootInfo->framebuffer.width = gop->Mode->Information->HorizontalResolution; + bootInfo->framebuffer.pitch = gop->Mode->Information->PixelsPerScanLine; + + bootInfo->dtb = dtbAddress; + printf("DTB located at: %p\r\n", (void*)dtbAddress); + + uintn_t map_size = 0; + efi_memory_descriptor_t *map = NULL; + uintn_t map_key; + uintn_t desc_size; + uint32_t desc_version; + + + print(L"Almost ready to jump :D. Working with memory map\r\n"); + + gBS->GetMemoryMap(&map_size, NULL, &map_key, &desc_size, &desc_version); + map_size += 4096; + // woah letsgoo + status = gBS->AllocatePool(EfiLoaderData, map_size, (void**)&map); + if (EFI_ERROR(status)) { + print(L"Failed to allocate pool\r\n"); + } + + do { + status = gBS->GetMemoryMap(&map_size, map, &map_key, &desc_size, &desc_version); + if (EFI_ERROR(status)) { + break; + } + + bootInfo->memoryMap.descriptorSize = desc_size; + bootInfo->memoryMap.descriptorVersion = desc_version; + bootInfo->memoryMap.mapSize = map_size; + bootInfo->memoryMap.mapKey = map_key; + bootInfo->memoryMap.map = map; + + status = gBS->ExitBootServices(IM, map_key); + if (status == EFI_SUCCESS) { + break; // FUCK OFF; + } + map_size += 2 * desc_size; + } while (EFI_ERROR(status)); + + typedef void (__attribute__((sysv_abi)) *kentry)(Bootinfo*); + kentry kmain = (kentry)kernel_addr; + + kmain(bootInfo); // yay! :D + + + return EFI_SUCCESS; } \ No newline at end of file diff --git a/Bootloader/justfile b/Bootloader/justfile index 07fb39f..0925817 100644 --- a/Bootloader/justfile +++ b/Bootloader/justfile @@ -1,14 +1,14 @@ BUILD_DIR := env_var_or_default("BUILD_DIR", justfile_directory() + "/.build") TEMP_DIR := env_var_or_default("TEMP_DIR", BUILD_DIR + "/temp") build: - cmake -B {{TEMP_DIR}}/bootloader -S . \ + cmake -B {{TEMP_DIR}}/Bootloader -S . \ -DCMAKE_TOOLCHAIN_FILE=Source/cmake/aarch64-uefi.cmake \ -DCMAKE_BUILD_TYPE=Release - cmake --build {{TEMP_DIR}}/bootloader + cmake --build {{TEMP_DIR}}/Bootloader - cp {{TEMP_DIR}}/bootloader/efi_bin/BOOTAA64.EFI {{BUILD_DIR}}/bootloader/BOOTAA64.EFI - @echo "✅ Bootloader ready at: {{BUILD_DIR}}/bootloader/BOOTAA64.EFI" + cp {{TEMP_DIR}}/Bootloader/efi_bin/BOOTAA64.EFI {{BUILD_DIR}}/Bootloader/BOOTAA64.EFI + @echo "✅ Bootloader ready at: {{BUILD_DIR}}/Bootloader/BOOTAA64.EFI" clean: - rm -rf {{TEMP_DIR}}/bootloader + rm -rf {{TEMP_DIR}}/Bootloader diff --git a/Common/bootinfo.h b/Common/bootinfo.h new file mode 100644 index 0000000..d1aa387 --- /dev/null +++ b/Common/bootinfo.h @@ -0,0 +1,35 @@ +#pragma once + +typedef unsigned int BIUInt32; +typedef unsigned long long BIUInt64; + +typedef struct { + BIUInt32* base; + BIUInt64 baseSize; + BIUInt64 width; + BIUInt64 height; + BIUInt64 pitch; +} BIFramebuffer; + +typedef struct { + void* map; + BIUInt64 mapSize; + BIUInt64 descriptorSize; + BIUInt32 mapKey; + BIUInt32 descriptorVersion; +} BIMemoryMap; + +typedef struct { + BIUInt64 kernelSize; + void* kernelAddress; +} BIKernelInfo; + +typedef struct { + BIUInt64 magic; + BIKernelInfo kernelInfo; + void* dtb; + BIMemoryMap memoryMap; + BIFramebuffer framebuffer; +} Bootinfo; + +#define BOOTINFO_MAGIC 0x736F6E7961 \ No newline at end of file diff --git a/Kernel/CMakeLists.txt b/Kernel/CMakeLists.txt new file mode 100644 index 0000000..396055d --- /dev/null +++ b/Kernel/CMakeLists.txt @@ -0,0 +1,30 @@ +cmake_minimum_required(VERSION 3.10) +project(MyShittyKernel LANGUAGES ASM C) + +if(NOT LLVM_BIN) + execute_process(COMMAND brew --prefix llvm OUTPUT_VARIABLE LLVM_PREFIX OUTPUT_STRIP_TRAILING_WHITESPACE) + set(LLVM_BIN "${LLVM_PREFIX}/bin") +endif() + +set(CMAKE_C_COMPILER "${LLVM_BIN}/clang") +set(CMAKE_ASM_COMPILER "${LLVM_BIN}/clang") +set(LLVM_OBJCOPY "${LLVM_BIN}/llvm-objcopy") + +set(TARGET_TRIPLE aarch64-none-elf) +add_compile_options(--target=${TARGET_TRIPLE} -ffreestanding -nostdlib -O0 -g) + +set(LINKER_SCRIPT ${CMAKE_CURRENT_SOURCE_DIR}/linker.ld) +add_link_options( + --target=${TARGET_TRIPLE} + -fuse-ld=lld + -nostdlib + -static + -Wl,-T,${LINKER_SCRIPT} +) + +add_executable(kernel.elf Source/entry.S) + +add_custom_command(TARGET kernel.elf POST_BUILD + COMMAND ${LLVM_OBJCOPY} -O binary kernel.elf kernel.bin + COMMENT "kernel.elf -> kernel.bin" +) \ No newline at end of file diff --git a/Kernel/Source/entry.S b/Kernel/Source/entry.S new file mode 100644 index 0000000..ec602e7 --- /dev/null +++ b/Kernel/Source/entry.S @@ -0,0 +1,22 @@ +.section .text.boot, "ax" +.global _start + +_start: + add x1, x0, #64 // x1 = BIFramebuffer + ldr x2, [x1] // x2 = base + ldr x3, [x1, #16] // x3 = width + ldr x4, [x1, #24] // x4 = height + + mul x5, x3, x4 + + mov w6, #0x00FF00 + movk w6, #0x0000, lsl #16 + +fill_loop: + cbz x5, done + str w6, [x2], #4 + sub x5, x5, #1 + b fill_loop + +done: + b done \ No newline at end of file diff --git a/Kernel/justfile b/Kernel/justfile new file mode 100644 index 0000000..3c01cea --- /dev/null +++ b/Kernel/justfile @@ -0,0 +1,12 @@ +BUILD_DIR := env_var_or_default("BUILD_DIR", justfile_directory() + "/.build") +TEMP_DIR := env_var_or_default("TEMP_DIR", BUILD_DIR + "/temp") +build: + cmake -B {{TEMP_DIR}}/Kernel -S . + + cmake --build {{TEMP_DIR}}/Kernel + + cp {{TEMP_DIR}}/Kernel/kernel.bin {{BUILD_DIR}}/Kernel/ksOSKernel.bin + @echo "✅ Kernel ready at: {{BUILD_DIR}}/Kernel/ksOSKernel.bin" + +clean: + rm -rf {{TEMP_DIR}}/Kernel diff --git a/Kernel/linker.ld b/Kernel/linker.ld new file mode 100644 index 0000000..e69de29 diff --git a/justfile b/justfile index d10524f..207c749 100644 --- a/justfile +++ b/justfile @@ -28,21 +28,24 @@ CPU := if ARCH_NAME == "aarch64" { "host" } else { "max" } export BUILD_DIR := justfile_directory() + "/.build" export TEMP_DIR := BUILD_DIR + "/temp" -export BOOT_BIN := BUILD_DIR + "/bootloader/BOOTAA64.EFI" +export BOOT_BIN := BUILD_DIR + "/Bootloader/BOOTAA64.EFI" export IMG_FILE := BUILD_DIR + "/ksOS.img" mod Bootloader +mod Kernel _default: just --list _prep: - @mkdir -p {{BUILD_DIR}}/bootloader - @mkdir -p {{TEMP_DIR}}/bootloader + @mkdir -p {{BUILD_DIR}}/Bootloader + @mkdir -p {{TEMP_DIR}}/Bootloader + @mkdir -p {{BUILD_DIR}}/Kernel @build: _prep @echo "🛠️ Building everything..." just Bootloader build + just Kernel build @_image: build @echo "💾 Creating image..." @@ -50,19 +53,21 @@ _prep: @mkfs.fat -F 32 {{IMG_FILE}} > /dev/null @mmd -i {{IMG_FILE}} ::/EFI ::/EFI/BOOT @mcopy -i {{IMG_FILE}} {{BOOT_BIN}} ::/EFI/BOOT/BOOTAA64.EFI + @mcopy -i {{IMG_FILE}} {{BUILD_DIR}}/Kernel/ksOSKernel.bin ::/ksOSKernel.bin @run: _image @echo "🚀 Launching..." qemu-system-aarch64 {{ACCEL}} \ - -machine virt \ + -machine virt,acpi=off \ -cpu {{CPU}} \ -m 512M \ - -device virtio-gpu-pci \ + -device ramfb \ -display cocoa,show-cursor=on \ -drive if=pflash,format=raw,readonly=on,file={{OVMF_ARM}} \ -drive file={{IMG_FILE}},format=raw,if=none,id=hd0 \ -device virtio-blk-device,drive=hd0 \ - -serial mon:stdio - + -serial stdio \ + -monitor telnet:127.0.0.1:5555,server,nowait + @clean: rm -rf {{BUILD_DIR}} \ No newline at end of file