6#include <kernel/version.h>
31#define GOP_HEIGHT 1080
32#define GOP_USE_DEFAULT_RES 1
34#define MEM_BASIC_ALLOCATOR_RESERVE_PERCENTAGE 10
35#define MEM_BASIC_ALLOCATOR_MIN_PAGES 8192
37#define EXIT_BOOT_SERVICES_MAX_RETRIES 5
47 if (systemTable ==
NULL || systemTable->ConfigurationTable ==
NULL)
52 EFI_GUID acpi2TableGuid = ACPI_20_TABLE_GUID;
53 EFI_GUID acpi1TableGuid = ACPI_TABLE_GUID;
56 for (
uint64_t i = 0; i < systemTable->NumberOfTableEntries; i++)
58 if (CompareGuid(&systemTable->ConfigurationTable[i].VendorGuid, &acpi2TableGuid) == 0)
60 if (CompareMem(
"RSD PTR ", systemTable->ConfigurationTable[i].VendorTable, 8) == 0)
62 rsdp = systemTable->ConfigurationTable[i].VendorTable;
74 Print(L
" ACPI 2.0+ RSDP found at 0x%lx\n", rsdp);
78 Print(L
" ACPI 2.0+ RSDP not found, falling back to ACPI 1.0\n");
80 for (
uint64_t i = 0; i < systemTable->NumberOfTableEntries; i++)
82 if (CompareGuid(&systemTable->ConfigurationTable[i].VendorGuid, &acpi1TableGuid) == 0)
84 if (CompareMem(
"RSD PTR ", systemTable->ConfigurationTable[i].VendorTable, 8) == 0)
86 rsdp = systemTable->ConfigurationTable[i].VendorTable;
93 Print(L
" ACPI 1.0 RSDP found at 0x%lx\n", rsdp);
97 Print(L
" WARNING: No ACPI RSDP found in configuration table\n");
101#if !(GOP_USE_DEFAULT_RES)
116 for (UINT32 modeIndex = 0; modeIndex <
gop->Mode->MaxMode; modeIndex++)
118 EFI_GRAPHICS_OUTPUT_MODE_INFORMATION* modeInfo =
NULL;
121 EFI_STATUS status = uefi_call_wrapper(
gop->QueryMode, 4,
gop, modeIndex, &infoSize, &modeInfo);
122 if (EFI_ERROR(status))
127 int64_t deltaX = (
int64_t)modeInfo->HorizontalResolution - requestedWidth;
128 int64_t deltaY = (
int64_t)modeInfo->VerticalResolution - requestedHeight;
131 if (distance < bestDistance)
133 bestMode = modeIndex;
134 bestDistance = distance;
157 return uefi_call_wrapper(
gop->SetMode, 2,
gop, targetMode);
175 return EFI_INVALID_PARAMETER;
178 EFI_GRAPHICS_OUTPUT_PROTOCOL*
gop =
NULL;
179 EFI_GUID gopGuid = EFI_GRAPHICS_OUTPUT_PROTOCOL_GUID;
181 EFI_STATUS status = uefi_call_wrapper(BS->LocateProtocol, 3, &gopGuid,
NULL, (
void**)&
gop);
182 if (EFI_ERROR(status))
184 Print(L
" ERROR: Failed to locate GOP (0x%lx)\n", status);
188#if !(GOP_USE_DEFAULT_RES)
191 if (EFI_ERROR(status))
193 Print(L
" WARNING: Failed to set requested mode, using default (0x%lx)\n", status);
197 buffer->physAddr =
gop->Mode->FrameBufferBase;
199 buffer->size =
gop->Mode->FrameBufferSize;
204 switch (
gop->Mode->Info->PixelFormat)
206 case PixelRedGreenBlueReserved8BitPerColor:
207 Print(L
" Pixel format: RGB (32-bit)\n");
209 case PixelBlueGreenRedReserved8BitPerColor:
210 Print(L
" Pixel format: BGR (32-bit)\n");
213 Print(L
" WARNING: Pixel format is bitmask-based, may require custom handling\n");
216 Print(L
" WARNING: Framebuffer not available, BLT only mode\n");
219 Print(L
" WARNING: Unknown pixel format (%d)\n",
gop->Mode->Info->PixelFormat);
223 Print(L
" GOP: 0x%lx-0x%lx %lux%lu, stride=%lu, size=%lu bytes\n",
buffer->physAddr,
308 return EFI_INVALID_PARAMETER;
314 return EFI_OUT_OF_RESOURCES;
349 size_t availablePages = 0;
354 if (desc->Type == EfiConventionalMemory)
356 availablePages += desc->NumberOfPages;
360 return availablePages;
372 if (EFI_ERROR(status))
374 Print(L
" ERROR: Failed to get memory map (0x%lx)\n", status);
384 status = uefi_call_wrapper(BS->AllocatePages, 4, AllocateAnyPages, EfiLoaderData,
basicAllocator.maxPages,
389 if (EFI_ERROR(status))
391 Print(L
" ERROR: Failed to allocate page pool (0x%lx)\n", status);
418 for (
size_t i = 0; i < amount; i++)
450 if (regionEnd > maxPhysicalAddress)
452 maxPhysicalAddress = regionEnd;
471 if (
page_table_map(table, (
void*)desc->VirtualStart, desc->PhysicalStart, desc->NumberOfPages,
504static bool wstr_to_str(
char* dest,
size_t destSize,
const CHAR16* src)
506 if (dest ==
NULL || destSize == 0)
512 for (i = 0; i < destSize - 1 && src !=
NULL && src[i] != L
'\0'; i++)
514 dest[i] = (char)src[i];
518 return src ==
NULL || src[i] == L
'\0';
532 FreePool(file->
data);
576 if (parentDir ==
NULL || fileName ==
NULL)
581 EFI_FILE* efiFile =
NULL;
584 EFI_STATUS status = uefi_call_wrapper(parentDir->Open, 5, parentDir, &efiFile, (CHAR16*)fileName,
585 EFI_FILE_MODE_READ, EFI_FILE_READ_ONLY | EFI_FILE_HIDDEN | EFI_FILE_SYSTEM);
586 if (EFI_ERROR(status))
600 EFI_FILE_INFO* fileInfo = LibFileInfo(efiFile);
601 if (fileInfo ==
NULL)
606 file->
size = fileInfo->FileSize;
611 file->
data = AllocatePool(file->
size);
617 UINTN readSize = file->
size;
618 status = uefi_call_wrapper(efiFile->Read, 3, efiFile, &readSize, file->
data);
619 if (EFI_ERROR(status) || readSize != file->
size)
625 uefi_call_wrapper(efiFile->Close, 1, efiFile);
633 uefi_call_wrapper(efiFile->Close, 1, efiFile);
647 if (dirHandle ==
NULL || dirName ==
NULL)
663 UINTN infoBufferSize =
sizeof(EFI_FILE_INFO) + 256 *
sizeof(CHAR16);
664 EFI_FILE_INFO* fileInfo = AllocatePool(infoBufferSize);
665 if (fileInfo ==
NULL)
673 UINTN readSize = infoBufferSize;
674 EFI_STATUS status = uefi_call_wrapper(dirHandle->Read, 3, dirHandle, &readSize, fileInfo);
676 if (EFI_ERROR(status))
688 if (fileInfo->FileName[0] == L
'.' && fileInfo->FileName[1] == L
'\0')
693 if (fileInfo->FileName[0] == L
'.' && fileInfo->FileName[1] == L
'.' && fileInfo->FileName[2] == L
'\0')
698 if (fileInfo->Attribute & EFI_FILE_DIRECTORY)
700 EFI_FILE* childHandle =
NULL;
701 status = uefi_call_wrapper(dirHandle->Open, 5, dirHandle, &childHandle, fileInfo->FileName,
702 EFI_FILE_MODE_READ, EFI_FILE_READ_ONLY | EFI_FILE_HIDDEN | EFI_FILE_SYSTEM);
704 if (EFI_ERROR(status))
712 uefi_call_wrapper(childHandle->Close, 1, childHandle);
750 if (disk ==
NULL || rootHandle ==
NULL)
752 return EFI_INVALID_PARAMETER;
755 EFI_FILE* rootDir =
NULL;
756 EFI_STATUS status = uefi_call_wrapper(rootHandle->Open, 5, rootHandle, &rootDir, L
"root", EFI_FILE_MODE_READ,
757 EFI_FILE_READ_ONLY | EFI_FILE_HIDDEN | EFI_FILE_SYSTEM);
759 if (EFI_ERROR(status))
761 Print(L
" No 'root' subdirectory, loading from volume root...\n");
767 uefi_call_wrapper(rootDir->Close, 1, rootDir);
772 Print(L
" ERROR: Failed to load root directory contents\n");
773 return EFI_LOAD_ERROR;
788 if (kernel ==
NULL || rootHandle ==
NULL)
790 return EFI_INVALID_PARAMETER;
793 EFI_FILE* kernelDir =
NULL;
794 EFI_FILE* kernelFile =
NULL;
795 void* fileData =
NULL;
796 EFI_PHYSICAL_ADDRESS kernelPhys = 0;
802 status = uefi_call_wrapper(rootHandle->Open, 5, rootHandle, &kernelDir, L
"kernel", EFI_FILE_MODE_READ, 0);
803 if (EFI_ERROR(status))
805 Print(L
" ERROR: Failed to open kernel directory (0x%lx)\n", status);
809 status = uefi_call_wrapper(kernelDir->Open, 5, kernelDir, &kernelFile, L
"kernel", EFI_FILE_MODE_READ, 0);
810 if (EFI_ERROR(status))
812 Print(L
" ERROR: Failed to open kernel file (0x%lx)\n", status);
816 EFI_FILE_INFO* fileInfo = LibFileInfo(kernelFile);
817 if (fileInfo ==
NULL)
819 Print(L
" ERROR: Failed to get kernel file info\n");
820 status = EFI_LOAD_ERROR;
824 size_t fileSize = fileInfo->FileSize;
829 Print(L
" ERROR: Kernel file is empty\n");
830 status = EFI_LOAD_ERROR;
834 fileData = AllocatePool(fileSize);
835 if (fileData ==
NULL)
837 Print(L
" ERROR: Failed to allocate memory for kernel file\n");
838 status = EFI_OUT_OF_RESOURCES;
842 UINTN readSize = fileSize;
843 status = uefi_call_wrapper(kernelFile->Read, 3, kernelFile, &readSize, fileData);
844 if (EFI_ERROR(status))
846 Print(L
" ERROR: Failed to read kernel file: (0x%lx)\n", status);
850 if (readSize != fileSize)
852 Print(L
" ERROR: Incomplete kernel read (%lu of %lu bytes)\n", readSize, fileSize);
853 status = EFI_LOAD_ERROR;
857 Print(L
" File size %lu bytes\n", fileSize);
862 Print(L
" ERROR: Invalid kernel ELF (%lu)\n", elfResult);
863 status = EFI_LOAD_ERROR;
868 size_t kernelSize = maxVaddr - minVaddr;
871 Print(L
" Allocating %lu pages for kernel...\n", kernelPageCount);
873 uefi_call_wrapper(BS->AllocatePages, 4, AllocateAnyPages, EfiReservedMemoryType, kernelPageCount, &kernelPhys);
874 if (EFI_ERROR(status))
876 Print(L
" ERROR: Failed to allocate kernel pages (0x%lx)", status);
880 Print(L
" Loading kernel...\n");
884 Print(L
" Entry Code: ");
885 for (
size_t i = 0; i < 16; i++)
891 Print(L
" Kernel loaded at 0x%lx, entry=0x%lx, size=%lu\n", kernelPhys, kernel->
elf.
header->
e_entry, kernelSize);
893 status = EFI_SUCCESS;
896 if (EFI_ERROR(status) && fileData !=
NULL)
900 if (kernelFile !=
NULL)
902 uefi_call_wrapper(kernelFile->Close, 1, kernelFile);
904 if (kernelDir !=
NULL)
906 uefi_call_wrapper(kernelDir->Close, 1, kernelDir);
908 if (EFI_ERROR(status) && kernelPhys != 0)
910 uefi_call_wrapper(BS->FreePages, 2, kernelPhys, kernelPageCount);
922 Print(L
"Start %a-bootloader %a (Built %a %a)\n", OS_NAME, OS_VERSION, __DATE__, __TIME__);
924 Print(L
"Start %a-bootloader DEBUG %a (Built %a %a)\n", OS_NAME, OS_VERSION, __DATE__, __TIME__);
926 Print(L
"Copyright (C) 2026 Kai Norberg. MIT Licensed.\n");
938 if (rootFile ==
NULL)
940 return EFI_INVALID_PARAMETER;
943 EFI_LOADED_IMAGE* loadedImage =
NULL;
944 EFI_GUID lipGuid = EFI_LOADED_IMAGE_PROTOCOL_GUID;
945 EFI_GUID fsGuid = EFI_SIMPLE_FILE_SYSTEM_PROTOCOL_GUID;
946 EFI_FILE_IO_INTERFACE* ioVolume =
NULL;
948 EFI_STATUS status = uefi_call_wrapper(BS->HandleProtocol, 3, imageHandle, &lipGuid, (
void**)&loadedImage);
949 if (EFI_ERROR(status))
951 Print(L
" ERROR: Failed to get loaded image protocol (0x%lx)\n", status);
955 status = uefi_call_wrapper(BS->HandleProtocol, 3, loadedImage->DeviceHandle, &fsGuid, (
void**)&ioVolume);
956 if (EFI_ERROR(status))
958 Print(L
" ERROR: Failed to get file system protocol (0x%lx)\n", status);
962 status = uefi_call_wrapper(ioVolume->OpenVolume, 2, ioVolume, rootFile);
963 if (EFI_ERROR(status))
965 Print(L
" ERROR: Failed to open root volume (0x%lx)\n", status);
986 return EFI_INVALID_PARAMETER;
991 Print(L
"Initializing GOP...\n");
993 if (EFI_ERROR(status))
995 Print(L
"FATAL: Failed to initialize graphics (0x%lx)\n", status);
999 Print(L
"Locating ACPI RSDP...\n");
1003 Print(L
"FATAL: ACPI RSDP not found in system configuration table\n");
1004 return EFI_NOT_FOUND;
1009 Print(L
"Loading boot volume...\n");
1010 EFI_FILE* rootHandle =
NULL;
1012 if (EFI_ERROR(status))
1014 Print(L
"FATAL: Failed to open boot volume (0x%lx)\n", status);
1018 Print(L
"Initializing disk...\n");
1020 if (EFI_ERROR(status))
1022 uefi_call_wrapper(rootHandle->Close, 1, rootHandle);
1026 Print(L
"Loading kernel...\n");
1028 if (EFI_ERROR(status))
1030 uefi_call_wrapper(rootHandle->Close, 1, rootHandle);
1034 uefi_call_wrapper(rootHandle->Close, 1, rootHandle);
1036 Print(L
"Boot info populated.\n");
1051 return EFI_INVALID_PARAMETER;
1055 UINT32 retryCount = 0;
1057 Print(L
"Exiting boot services...\n");
1067 if (EFI_ERROR(status))
1069 Print(L
" ERROR: Failed to get memory map: 0x%lx", status);
1075 if (status == EFI_SUCCESS)
1080 if (status == EFI_INVALID_PARAMETER)
1082 Print(L
" WARNING: Stale key, retrying.\n");
1087 Print(L
" ERROR: Maximum retries reached, aborting.\n");
1092 uefi_call_wrapper(BS->Stall, 1, 1000);
1096 Print(L
" ERROR: Failed to exit boot services (0x%lx)\n", status);
1115EFI_STATUS
efi_main(EFI_HANDLE imageHandle, EFI_SYSTEM_TABLE* systemTable)
1117 InitializeLib(imageHandle, systemTable);
1119 uefi_call_wrapper(BS->SetWatchdogTimer, 4, 0, 0, 0,
NULL);
1120 uefi_call_wrapper(systemTable->ConOut->ClearScreen, 1, systemTable->ConOut);
1124 Print(L
"Initializing memory allocator...\n");
1126 if (EFI_ERROR(status))
1128 Print(L
"FATAL: Failed to initialize memory allocator (0x%lx)\n", status);
1132 Print(L
"Allocating boot info structure...\n");
1136 Print(L
"FATAL: Failed to allocate boot info structure\n");
1137 return EFI_OUT_OF_RESOURCES;
1141 if (EFI_ERROR(status))
1148 if (EFI_ERROR(status))
#define MAX_NAME
Maximum length of names.
EFI_PHYSICAL_ADDRESS buffer
#define BOOT_MEMORY_MAP_GET_DESCRIPTOR(map, index)
#define GOP_WIDTH
Ignored if GOP_USE_DEFAULT_RES is set to 1.
static EFI_STATUS volume_open_root(EFI_FILE **rootFile, EFI_HANDLE imageHandle)
Opens the root volume of the boot device.
#define EXIT_BOOT_SERVICES_MAX_RETRIES
static void mem_page_table_init(page_table_t *table, boot_memory_map_t *map, boot_gop_t *gop, boot_kernel_t *kernel)
Initializes the kernel page table with all required mappings.
static size_t mem_count_available_pages(boot_memory_map_t *map)
Calculates the total available conventional memory.
EFI_STATUS efi_main(EFI_HANDLE imageHandle, EFI_SYSTEM_TABLE *systemTable)
UEFI entry point.
static EFI_STATUS gop_set_mode(EFI_GRAPHICS_OUTPUT_PROTOCOL *gop, int64_t requestedWidth, int64_t requestedHeight)
Sets the graphics mode to best match the requested resolution.
#define MEM_BASIC_ALLOCATOR_RESERVE_PERCENTAGE
panic_code_t
Panic error codes for debugging when boot services are unavailable.
static uint64_t basic_allocator_alloc_pages(pfn_t *pfns, size_t amount)
Allocate pages from the basic allocator.
static EFI_STATUS mem_map_init(boot_memory_map_t *map)
Initializes the EFI memory map structure.
#define MEM_BASIC_ALLOCATOR_MIN_PAGES
static EFI_STATUS boot_info_populate(EFI_HANDLE imageHandle, EFI_SYSTEM_TABLE *systemTable, boot_info_t *bootInfo)
Populates the boot information structure.
static bool wstr_to_str(char *dest, size_t destSize, const CHAR16 *src)
Copies a wide character string to a narrow character buffer.
static EFI_STATUS disk_init(boot_disk_t *disk, EFI_FILE *rootHandle)
Loads the initial RAM disk from the boot volume.
static void mem_map_cleanup(boot_memory_map_t *map)
Free the memory map structure.
static void boot_dir_free(boot_dir_t *dir)
Recursively frees a directory tree.
static EFI_STATUS boot_services_exit(EFI_HANDLE imageHandle, boot_info_t *bootInfo)
Exits UEFI boot services and prepares for kernel handoff.
static EFI_STATUS kernel_load(boot_kernel_t *kernel, EFI_FILE *rootHandle)
Loads and validates the kernel ELF file.
EFI_PHYSICAL_ADDRESS buffer
static void * rsdp_locate(EFI_SYSTEM_TABLE *systemTable)
Locates the ACPI RSDP from the EFI configuration table.
static const uint32_t PANIC_COLORS[]
Color values for panic display.
static _NORETURN void panic_halt(panic_code_t code)
Halts the system with a colored screen indicating the error.
static UINT32 gop_find_best_mode(EFI_GRAPHICS_OUTPUT_PROTOCOL *gop, int64_t requestedWidth, int64_t requestedHeight)
Finds the best matching graphics mode for the requested resolution.
static void boot_file_free(boot_file_t *file)
Frees a boot file structure and its data.
static struct @40 basicAllocator
Basic page allocator state.
#define GOP_HEIGHT
Ignored if GOP_USE_DEFAULT_RES is set to 1.
static EFI_STATUS mem_allocator_init(void)
Initializes the basic page allocator.
static boot_file_t * disk_load_file(EFI_FILE *parentDir, const CHAR16 *fileName)
Loads a single file from an EFI file handle.
static void splash_screen_display(void)
Displays the bootloader splash screen.
static boot_dir_t * disk_load_dir(EFI_FILE *dirHandle, const CHAR16 *dirName)
Recursively loads a directory and its contents.
@ PANIC_ALLOCATOR_EXHAUSTED
@ PANIC_HIGHER_HALF_INVALID
static uint64_t gop_init(void)
#define PML_CALLBACK_NONE
Special callback ID that indicates no callback is associated with the page.
static uint64_t page_table_map(page_table_t *table, void *addr, phys_addr_t phys, size_t amount, pml_flags_t flags, pml_callback_id_t callbackId)
Maps a range of virtual addresses to physical addresses in the page table.
#define PHYS_TO_PFN(_addr)
Convert a physical address to its PFN.
#define PML_LOWER_TO_HIGHER(addr)
Converts an address from the lower half to the higher half.
size_t pfn_t
Page Frame Number type.
static uint64_t page_table_init(page_table_t *table, pml_alloc_pages_t allocPages, pml_free_pages_t freePages)
Initializes a page table.
#define PML_HIGHER_HALF_START
The start of the higher half of the address space.
#define ASM(...)
Inline assembly macro.
#define ARRAY_SIZE(x)
Get the number of elements in a static array.
void elf64_load_segments(const Elf64_File *elf, Elf64_Addr base, Elf64_Off offset)
Load all loadable segments of an ELF file into memory.
uint64_t elf64_validate(Elf64_File *elf, void *data, uint64_t size)
Validate a files content and initalize a ELF64_File structure using it.
void elf64_get_loadable_bounds(const Elf64_File *elf, Elf64_Addr *minAddr, Elf64_Addr *maxAddr)
Get the loadable virtual memory bounds of an ELF file.
uint64_t Elf64_Addr
ELF64 Unsigned program address.
static void list_push_back(list_t *list, list_entry_t *entry)
Pushes an entry to the end of the list.
static bool list_is_empty(list_t *list)
Checks if a list is empty.
static void list_entry_init(list_entry_t *entry)
Initializes a list entry.
static list_entry_t * list_pop_front(list_t *list)
Pops the first entry from the list.
static void list_init(list_t *list)
Initializes a list.
#define BYTES_TO_PAGES(amount)
Convert a size in bytes to pages.
#define NULL
Pointer error value.
#define ERR
Integer error value.
#define PAGE_SIZE
The size of a memory page in bytes.
#define CONTAINER_OF(ptr, type, member)
Container of macro.
static void cr3_write(uint64_t value)
__UINTPTR_TYPE__ uintptr_t
Elf64_Addr e_entry
Entry point virtual address.
Elf64_Ehdr * header
The data in the file, pointed to the start of the ELF header.
EFI_MEMORY_DESCRIPTOR * descriptors
char name[MAX_NAME]
The name of the dentry, immutable after creation.
A entry in a doubly linked list.