feat: working bootloader and basic kernel (just dyes screen green)
This commit is contained in:
@@ -24,6 +24,7 @@ add_library(posix_uefi_lib OBJECT ${POSIX_UEFI_SOURCES})
|
|||||||
target_compile_options(posix_uefi_lib PRIVATE ${UEFI_COMPILE_OPTIONS})
|
target_compile_options(posix_uefi_lib PRIVATE ${UEFI_COMPILE_OPTIONS})
|
||||||
target_include_directories(posix_uefi_lib PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/Source/uefi)
|
target_include_directories(posix_uefi_lib PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/Source/uefi)
|
||||||
|
|
||||||
|
|
||||||
add_executable(BOOTAA64 Source/main.c)
|
add_executable(BOOTAA64 Source/main.c)
|
||||||
target_compile_options(BOOTAA64 PRIVATE ${UEFI_COMPILE_OPTIONS})
|
target_compile_options(BOOTAA64 PRIVATE ${UEFI_COMPILE_OPTIONS})
|
||||||
|
|
||||||
|
|||||||
+141
-4
@@ -1,7 +1,144 @@
|
|||||||
#include "uefi/uefi.h" // IWYU pragma: keep
|
#include "uefi/uefi.h" // IWYU pragma: keep
|
||||||
|
#include "../../Common/bootinfo.h"
|
||||||
|
|
||||||
int main() {
|
void print(wchar_t* msg) {
|
||||||
printf("Meow!\n");
|
ST->ConOut->OutputString(ST->ConOut, msg);
|
||||||
while (1) __asm__ ("wfi");
|
}
|
||||||
return 0;
|
|
||||||
|
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;
|
||||||
}
|
}
|
||||||
+5
-5
@@ -1,14 +1,14 @@
|
|||||||
BUILD_DIR := env_var_or_default("BUILD_DIR", justfile_directory() + "/.build")
|
BUILD_DIR := env_var_or_default("BUILD_DIR", justfile_directory() + "/.build")
|
||||||
TEMP_DIR := env_var_or_default("TEMP_DIR", BUILD_DIR + "/temp")
|
TEMP_DIR := env_var_or_default("TEMP_DIR", BUILD_DIR + "/temp")
|
||||||
build:
|
build:
|
||||||
cmake -B {{TEMP_DIR}}/bootloader -S . \
|
cmake -B {{TEMP_DIR}}/Bootloader -S . \
|
||||||
-DCMAKE_TOOLCHAIN_FILE=Source/cmake/aarch64-uefi.cmake \
|
-DCMAKE_TOOLCHAIN_FILE=Source/cmake/aarch64-uefi.cmake \
|
||||||
-DCMAKE_BUILD_TYPE=Release
|
-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
|
cp {{TEMP_DIR}}/Bootloader/efi_bin/BOOTAA64.EFI {{BUILD_DIR}}/Bootloader/BOOTAA64.EFI
|
||||||
@echo "✅ Bootloader ready at: {{BUILD_DIR}}/bootloader/BOOTAA64.EFI"
|
@echo "✅ Bootloader ready at: {{BUILD_DIR}}/Bootloader/BOOTAA64.EFI"
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
rm -rf {{TEMP_DIR}}/bootloader
|
rm -rf {{TEMP_DIR}}/Bootloader
|
||||||
|
|||||||
@@ -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
|
||||||
@@ -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"
|
||||||
|
)
|
||||||
@@ -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
|
||||||
@@ -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
|
||||||
@@ -28,21 +28,24 @@ CPU := if ARCH_NAME == "aarch64" { "host" } else { "max" }
|
|||||||
|
|
||||||
export BUILD_DIR := justfile_directory() + "/.build"
|
export BUILD_DIR := justfile_directory() + "/.build"
|
||||||
export TEMP_DIR := BUILD_DIR + "/temp"
|
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"
|
export IMG_FILE := BUILD_DIR + "/ksOS.img"
|
||||||
|
|
||||||
mod Bootloader
|
mod Bootloader
|
||||||
|
mod Kernel
|
||||||
|
|
||||||
_default:
|
_default:
|
||||||
just --list
|
just --list
|
||||||
|
|
||||||
_prep:
|
_prep:
|
||||||
@mkdir -p {{BUILD_DIR}}/bootloader
|
@mkdir -p {{BUILD_DIR}}/Bootloader
|
||||||
@mkdir -p {{TEMP_DIR}}/bootloader
|
@mkdir -p {{TEMP_DIR}}/Bootloader
|
||||||
|
@mkdir -p {{BUILD_DIR}}/Kernel
|
||||||
|
|
||||||
@build: _prep
|
@build: _prep
|
||||||
@echo "🛠️ Building everything..."
|
@echo "🛠️ Building everything..."
|
||||||
just Bootloader build
|
just Bootloader build
|
||||||
|
just Kernel build
|
||||||
|
|
||||||
@_image: build
|
@_image: build
|
||||||
@echo "💾 Creating image..."
|
@echo "💾 Creating image..."
|
||||||
@@ -50,19 +53,21 @@ _prep:
|
|||||||
@mkfs.fat -F 32 {{IMG_FILE}} > /dev/null
|
@mkfs.fat -F 32 {{IMG_FILE}} > /dev/null
|
||||||
@mmd -i {{IMG_FILE}} ::/EFI ::/EFI/BOOT
|
@mmd -i {{IMG_FILE}} ::/EFI ::/EFI/BOOT
|
||||||
@mcopy -i {{IMG_FILE}} {{BOOT_BIN}} ::/EFI/BOOT/BOOTAA64.EFI
|
@mcopy -i {{IMG_FILE}} {{BOOT_BIN}} ::/EFI/BOOT/BOOTAA64.EFI
|
||||||
|
@mcopy -i {{IMG_FILE}} {{BUILD_DIR}}/Kernel/ksOSKernel.bin ::/ksOSKernel.bin
|
||||||
|
|
||||||
@run: _image
|
@run: _image
|
||||||
@echo "🚀 Launching..."
|
@echo "🚀 Launching..."
|
||||||
qemu-system-aarch64 {{ACCEL}} \
|
qemu-system-aarch64 {{ACCEL}} \
|
||||||
-machine virt \
|
-machine virt,acpi=off \
|
||||||
-cpu {{CPU}} \
|
-cpu {{CPU}} \
|
||||||
-m 512M \
|
-m 512M \
|
||||||
-device virtio-gpu-pci \
|
-device ramfb \
|
||||||
-display cocoa,show-cursor=on \
|
-display cocoa,show-cursor=on \
|
||||||
-drive if=pflash,format=raw,readonly=on,file={{OVMF_ARM}} \
|
-drive if=pflash,format=raw,readonly=on,file={{OVMF_ARM}} \
|
||||||
-drive file={{IMG_FILE}},format=raw,if=none,id=hd0 \
|
-drive file={{IMG_FILE}},format=raw,if=none,id=hd0 \
|
||||||
-device virtio-blk-device,drive=hd0 \
|
-device virtio-blk-device,drive=hd0 \
|
||||||
-serial mon:stdio
|
-serial stdio \
|
||||||
|
-monitor telnet:127.0.0.1:5555,server,nowait
|
||||||
|
|
||||||
@clean:
|
@clean:
|
||||||
rm -rf {{BUILD_DIR}}
|
rm -rf {{BUILD_DIR}}
|
||||||
Reference in New Issue
Block a user