1630 lines
59 KiB
C
1630 lines
59 KiB
C
// UEFI bootloader entry point. This file performs firmware discovery and the minimum fixed-image/raw-file handoff needed to enter the kernel.
|
|
|
|
// The loader interprets only the [boot] system_volume bootstrap selector. It scans drivers.ini v2,
|
|
// verifies and maps fixed kernel/HAL images, translates firmware state, and exits boot services.
|
|
|
|
#include <efi.h>
|
|
#include <efilib.h>
|
|
#include <stdbool.h>
|
|
#include <stddef.h>
|
|
#include <string.h>
|
|
#include <intrin.h>
|
|
#include <common/boot_volume_selector.h>
|
|
#include <ntlite/boot_info.h>
|
|
#include <ntlite/memory_map.h>
|
|
#include "boot_pe.h"
|
|
#pragma intrinsic(_disable)
|
|
|
|
int _fltused = 0;
|
|
|
|
#define KERNEL_VIRT_BASE 0xFFFF800000000000ULL
|
|
#define PHYS_MAP_BASE 0xFFFF880000000000ULL
|
|
#define PAGE_SIZE 4096ULL
|
|
#define BOOT_PAGE_PRESENT 0x01ULL
|
|
#define BOOT_PAGE_WRITE 0x02ULL
|
|
#define BOOT_PAGE_CACHE_WB 0x00ULL
|
|
#define BOOT_PAGE_CACHE_WC 0x08ULL
|
|
#define BOOT_PAGE_CACHE_UC 0x10ULL
|
|
|
|
#ifndef BOOT_VOLUME_DIAGNOSTICS
|
|
#if defined(NDEBUG)
|
|
#define BOOT_VOLUME_DIAGNOSTICS 0
|
|
#else
|
|
#define BOOT_VOLUME_DIAGNOSTICS 1
|
|
#endif
|
|
#endif
|
|
|
|
// Implements the ascii Str To Unicode Str S operation.
|
|
static int AsciiStrToUnicodeStrS(const char* Source, CHAR16* Dest, size_t DestMax) {
|
|
if (!Source || !Dest || !DestMax) return -1;
|
|
|
|
for (size_t i = 0; i < DestMax; i++) {
|
|
if ((Dest[i] = (unsigned char)Source[i]) == '\0') return 0;
|
|
}
|
|
|
|
Dest[DestMax - 1] = '\0';
|
|
return -1; // Buffer too small
|
|
}
|
|
|
|
// Implements the ascii Str Cpy S operation.
|
|
static int AsciiStrCpyS(char* Dest, size_t DestMax, const char* Source) {
|
|
if (!Dest || !Source || !DestMax) return -1;
|
|
|
|
for (size_t i = 0; i < DestMax; i++) {
|
|
if ((Dest[i] = Source[i]) == '\0') return 0;
|
|
}
|
|
|
|
Dest[DestMax - 1] = '\0'; // Ensure termination on truncation
|
|
return -1;
|
|
}
|
|
|
|
// Allocates and links the minimal x86-64 page tables used before KernelMain runs.
|
|
static UINT64* AllocPage(EFI_PHYSICAL_ADDRESS* physOut) {
|
|
EFI_PHYSICAL_ADDRESS phys = 0;
|
|
EFI_STATUS status = gBS->AllocatePages(AllocateAnyPages, EfiLoaderData, 1, &phys);
|
|
if (EFI_ERROR(status))
|
|
return NULL;
|
|
gBS->SetMem((VOID*)phys, PAGE_SIZE, 0);
|
|
if (physOut) *physOut = phys;
|
|
return (UINT64*)phys;
|
|
}
|
|
|
|
#define PML4_IDX(va) (((va) >> 39) & 0x1FF)
|
|
#define PDPT_IDX(va) (((va) >> 30) & 0x1FF)
|
|
#define PDT_IDX(va) (((va) >> 21) & 0x1FF)
|
|
#define PT_IDX(va) (((va) >> 12) & 0x1FF)
|
|
|
|
#define PAGE_2M (2ULL * 1024ULL * 1024ULL)
|
|
#define PAGE_1G (1024ULL * 1024ULL * 1024ULL)
|
|
|
|
static UINT64* gPml4;
|
|
|
|
// Implements the ensure Table operation.
|
|
static UINT64* EnsureTable(UINT64* parent, UINTN index) {
|
|
if (!parent)
|
|
return NULL;
|
|
UINT64* entry = &parent[index];
|
|
if (!(*entry & 1)) {
|
|
EFI_PHYSICAL_ADDRESS p;
|
|
UINT64* child = AllocPage(&p);
|
|
if (!child)
|
|
return NULL;
|
|
*entry = p | 3;
|
|
return child;
|
|
}
|
|
return (UINT64*)(*entry & ~0xFFFULL);
|
|
}
|
|
|
|
// Maps one 4 KiB page.
|
|
static bool Map4K(UINT64 virt, UINT64 phys, UINT64 flags) {
|
|
UINT64* pdpt = EnsureTable(gPml4, PML4_IDX(virt));
|
|
UINT64* pdt = EnsureTable(pdpt, PDPT_IDX(virt));
|
|
UINT64* pt = EnsureTable(pdt, PDT_IDX(virt));
|
|
if (!pt)
|
|
return false;
|
|
pt[PT_IDX(virt)] = phys | flags;
|
|
return true;
|
|
}
|
|
|
|
// Maps one 2 MiB page.
|
|
static bool Map2M(UINT64 virt, UINT64 phys, UINT64 flags) {
|
|
UINT64* pdpt = EnsureTable(gPml4, PML4_IDX(virt));
|
|
UINT64* pdt = EnsureTable(pdpt, PDPT_IDX(virt));
|
|
if (!pdt)
|
|
return false;
|
|
pdt[PDT_IDX(virt)] = phys | flags | 0x80ULL;
|
|
return true;
|
|
}
|
|
|
|
// Maps one 1 GiB page.
|
|
static bool Map1G(UINT64 virt, UINT64 phys, UINT64 flags) {
|
|
UINT64* pdpt = EnsureTable(gPml4, PML4_IDX(virt));
|
|
if (!pdpt)
|
|
return false;
|
|
pdpt[PDPT_IDX(virt)] = phys | flags | 0x80ULL;
|
|
return true;
|
|
}
|
|
|
|
// Maps one range using the largest naturally aligned page size available.
|
|
static bool MapRangeSmart(UINT64 virt, UINT64 phys, UINT64 size, UINT64 flags) {
|
|
while (size) {
|
|
bool mapped;
|
|
if ((virt & (PAGE_1G - 1)) == 0 && (phys & (PAGE_1G - 1)) == 0 && size >= PAGE_1G) {
|
|
mapped = Map1G(virt, phys, flags);
|
|
virt += PAGE_1G;
|
|
phys += PAGE_1G;
|
|
size -= PAGE_1G;
|
|
} else if ((virt & (PAGE_2M - 1)) == 0 && (phys & (PAGE_2M - 1)) == 0 && size >= PAGE_2M) {
|
|
mapped = Map2M(virt, phys, flags);
|
|
virt += PAGE_2M;
|
|
phys += PAGE_2M;
|
|
size -= PAGE_2M;
|
|
} else {
|
|
mapped = Map4K(virt, phys, flags);
|
|
virt += PAGE_SIZE;
|
|
phys += PAGE_SIZE;
|
|
size -= PAGE_SIZE;
|
|
}
|
|
if (!mapped)
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
// Returns whether a firmware descriptor describes memory that is safe to expose through the direct map.
|
|
static bool IsDirectMapRamType(EFI_MEMORY_TYPE type) {
|
|
switch (type) {
|
|
case EfiLoaderCode:
|
|
case EfiLoaderData:
|
|
case EfiBootServicesCode:
|
|
case EfiBootServicesData:
|
|
case EfiRuntimeServicesCode:
|
|
case EfiRuntimeServicesData:
|
|
case EfiConventionalMemory:
|
|
case EfiACPIReclaimMemory:
|
|
case EfiACPIMemoryNVS:
|
|
return true;
|
|
default:
|
|
return false;
|
|
}
|
|
}
|
|
|
|
// Converts firmware cache attributes into the kernel's canonical PAT policy.
|
|
static UINT64 DirectMapCacheFlags(const EFI_MEMORY_DESCRIPTOR* desc) {
|
|
if (!desc)
|
|
return BOOT_PAGE_CACHE_UC;
|
|
if (desc->Attribute & (EFI_MEMORY_UC | EFI_MEMORY_UCE | EFI_MEMORY_WT))
|
|
return BOOT_PAGE_CACHE_UC;
|
|
if (desc->Attribute & EFI_MEMORY_WC)
|
|
return BOOT_PAGE_CACHE_WC;
|
|
return BOOT_PAGE_CACHE_WB;
|
|
}
|
|
|
|
static bool MapRangeSkipping(UINT64 virt, UINT64 phys, UINT64 size, UINT64 flags,
|
|
const UINT64* holes, UINTN holeCount) {
|
|
UINT64 curVirt = virt;
|
|
UINT64 curPhys = phys;
|
|
UINT64 end = virt + size;
|
|
|
|
for (UINTN i = 0; i < holeCount; i++) {
|
|
UINT64 hStart = holes[i * 2 + 0];
|
|
UINT64 hEnd = holes[i * 2 + 1];
|
|
if (hEnd <= curVirt || hStart >= end) continue;
|
|
|
|
if (curVirt < hStart) {
|
|
UINT64 prefixSize = hStart - curVirt;
|
|
if (!MapRangeSmart(curVirt, curPhys, prefixSize, flags))
|
|
return false;
|
|
curPhys += prefixSize;
|
|
curVirt += prefixSize;
|
|
}
|
|
|
|
if (curVirt < hEnd) {
|
|
UINT64 skip = hEnd - curVirt;
|
|
curVirt += skip;
|
|
curPhys += skip;
|
|
}
|
|
}
|
|
|
|
if (curVirt < end && !MapRangeSmart(curVirt, curPhys, end - curVirt, flags))
|
|
return false;
|
|
return true;
|
|
}
|
|
|
|
// File loading and boot handoff helpers.
|
|
static EFI_HANDLE gBootDevice;
|
|
static EFI_FILE_PROTOCOL* gBootRoot;
|
|
static EFI_FILE_PROTOCOL* gSystemRoot;
|
|
|
|
typedef struct BOOT_EFI_MEMORY_MAP {
|
|
EFI_MEMORY_DESCRIPTOR* Buffer;
|
|
UINTN Capacity;
|
|
UINTN Size;
|
|
UINTN Key;
|
|
UINTN DescriptorSize;
|
|
UINT32 DescriptorVersion;
|
|
} BOOT_EFI_MEMORY_MAP;
|
|
|
|
// Allocates zeroed loader-data pages whose physical address remains valid in the boot handoff.
|
|
static EFI_STATUS BootAllocatePages(UINTN pageCount, EFI_PHYSICAL_ADDRESS* physicalOut) {
|
|
if (!physicalOut || pageCount == 0)
|
|
return EFI_INVALID_PARAMETER;
|
|
EFI_PHYSICAL_ADDRESS physical = 0;
|
|
EFI_STATUS status = gBS->AllocatePages(AllocateAnyPages, EfiLoaderData, pageCount, &physical);
|
|
if (EFI_ERROR(status))
|
|
return status;
|
|
gBS->SetMem((VOID*)physical, pageCount * PAGE_SIZE, 0);
|
|
*physicalOut = physical;
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
// Opens one boot-volume file and returns its exact byte length.
|
|
static EFI_STATUS BootOpenFile(EFI_FILE_PROTOCOL* root, CHAR16* path,
|
|
EFI_FILE_PROTOCOL** fileOut, UINTN* sizeOut) {
|
|
if (!root || !path || !fileOut || !sizeOut)
|
|
return EFI_INVALID_PARAMETER;
|
|
|
|
EFI_FILE_PROTOCOL* file = NULL;
|
|
EFI_STATUS status = root->Open(root, &file, path, EFI_FILE_MODE_READ, 0);
|
|
if (EFI_ERROR(status))
|
|
return status;
|
|
|
|
UINTN infoSize = 0;
|
|
status = file->GetInfo(file, &gEfiFileInfoGuid, &infoSize, NULL);
|
|
if (status != EFI_BUFFER_TOO_SMALL || infoSize < sizeof(EFI_FILE_INFO)) {
|
|
file->Close(file);
|
|
return EFI_LOAD_ERROR;
|
|
}
|
|
|
|
EFI_FILE_INFO* info = NULL;
|
|
status = gBS->AllocatePool(EfiBootServicesData, infoSize, (VOID**)&info);
|
|
if (EFI_ERROR(status)) {
|
|
file->Close(file);
|
|
return status;
|
|
}
|
|
|
|
status = file->GetInfo(file, &gEfiFileInfoGuid, &infoSize, info);
|
|
if (!EFI_ERROR(status)) {
|
|
if (info->FileSize > (UINT64)(~(UINTN)0))
|
|
status = EFI_BAD_BUFFER_SIZE;
|
|
else
|
|
*sizeOut = (UINTN)info->FileSize;
|
|
}
|
|
|
|
gBS->FreePool(info);
|
|
if (EFI_ERROR(status)) {
|
|
file->Close(file);
|
|
return status;
|
|
}
|
|
|
|
*fileOut = file;
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
// Reads a temporary file into boot-services memory and appends one NUL byte for text-safe inspection.
|
|
static EFI_STATUS BootReadPoolFile(EFI_FILE_PROTOCOL* root, CHAR16* path,
|
|
UINT8** bufferOut, UINTN* sizeOut) {
|
|
if (!root || !path || !bufferOut || !sizeOut)
|
|
return EFI_INVALID_PARAMETER;
|
|
|
|
*bufferOut = NULL;
|
|
*sizeOut = 0;
|
|
EFI_FILE_PROTOCOL* file = NULL;
|
|
UINTN fileSize = 0;
|
|
EFI_STATUS status = BootOpenFile(root, path, &file, &fileSize);
|
|
if (EFI_ERROR(status))
|
|
return status;
|
|
if (fileSize == ~(UINTN)0) {
|
|
file->Close(file);
|
|
return EFI_BAD_BUFFER_SIZE;
|
|
}
|
|
|
|
UINT8* buffer = NULL;
|
|
status = gBS->AllocatePool(EfiBootServicesData, fileSize + 1u, (VOID**)&buffer);
|
|
if (EFI_ERROR(status)) {
|
|
file->Close(file);
|
|
return status;
|
|
}
|
|
gBS->SetMem(buffer, fileSize + 1u, 0);
|
|
|
|
UINTN bytesRead = fileSize;
|
|
status = file->Read(file, &bytesRead, buffer);
|
|
file->Close(file);
|
|
if (EFI_ERROR(status) || bytesRead != fileSize) {
|
|
gBS->FreePool(buffer);
|
|
return EFI_ERROR(status) ? status : EFI_LOAD_ERROR;
|
|
}
|
|
|
|
*bufferOut = buffer;
|
|
*sizeOut = fileSize;
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
// Reads a retained raw file into its own loader-data pages and guarantees a trailing NUL byte.
|
|
static EFI_STATUS BootReadBlobFile(EFI_FILE_PROTOCOL* root, CHAR16* path, BOOT_BLOB* blobOut) {
|
|
if (!root || !path || !blobOut)
|
|
return EFI_INVALID_PARAMETER;
|
|
|
|
*blobOut = (BOOT_BLOB){0};
|
|
EFI_FILE_PROTOCOL* file = NULL;
|
|
UINTN fileSize = 0;
|
|
EFI_STATUS status = BootOpenFile(root, path, &file, &fileSize);
|
|
if (EFI_ERROR(status))
|
|
return status;
|
|
if (fileSize > UINT32_MAX) {
|
|
file->Close(file);
|
|
return EFI_BAD_BUFFER_SIZE;
|
|
}
|
|
|
|
UINTN allocationBytes = fileSize + 1u;
|
|
UINTN pageCount = (allocationBytes + PAGE_SIZE - 1u) / PAGE_SIZE;
|
|
if (pageCount == 0 || pageCount > UINT32_MAX) {
|
|
file->Close(file);
|
|
return EFI_BAD_BUFFER_SIZE;
|
|
}
|
|
|
|
EFI_PHYSICAL_ADDRESS physical = 0;
|
|
status = BootAllocatePages(pageCount, &physical);
|
|
if (EFI_ERROR(status)) {
|
|
file->Close(file);
|
|
return status;
|
|
}
|
|
|
|
UINTN bytesRead = fileSize;
|
|
status = file->Read(file, &bytesRead, (VOID*)physical);
|
|
file->Close(file);
|
|
if (EFI_ERROR(status) || bytesRead != fileSize) {
|
|
gBS->FreePages(physical, pageCount);
|
|
return EFI_ERROR(status) ? status : EFI_LOAD_ERROR;
|
|
}
|
|
|
|
BOOT_BLOB blob = {0};
|
|
blob.PhysicalBase = (uintptr_t)physical;
|
|
blob.Length = (uint32_t)fileSize;
|
|
blob.PageCount = (uint32_t)pageCount;
|
|
*blobOut = blob;
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
// Returns whether one character is horizontal line whitespace in the tiny boot configuration dialect.
|
|
static bool BootLineSpace(char c) {
|
|
return c == ' ' || c == '\t' || c == '\r';
|
|
}
|
|
|
|
// Trims horizontal whitespace from one immutable line span.
|
|
static void BootTrimSpan(const char** begin, const char** end) {
|
|
while (*begin < *end && BootLineSpace(**begin))
|
|
++*begin;
|
|
while (*end > *begin && BootLineSpace((*end)[-1]))
|
|
--*end;
|
|
}
|
|
|
|
// Returns whether one line span exactly matches a NUL-terminated ASCII string.
|
|
static bool BootSpanEquals(const char* begin, const char* end, const char* text) {
|
|
while (begin < end && *text) {
|
|
if (*begin++ != *text++)
|
|
return false;
|
|
}
|
|
return begin == end && *text == '\0';
|
|
}
|
|
|
|
// Extracts and parses only the system_volume key from boot.ini [boot].
|
|
static EFI_STATUS BootParseSystemVolume(const char* text, UINTN length,
|
|
BOOT_VOLUME_SELECTOR* selectorOut) {
|
|
if (!text || !selectorOut)
|
|
return EFI_INVALID_PARAMETER;
|
|
|
|
bool inBootSection = false;
|
|
bool selectorSeen = false;
|
|
BOOT_VOLUME_SELECTOR selector = {0};
|
|
UINTN offset = 0;
|
|
while (offset < length) {
|
|
UINTN lineStart = offset;
|
|
while (offset < length && text[offset] != '\n')
|
|
++offset;
|
|
UINTN lineEnd = offset;
|
|
if (offset < length)
|
|
++offset;
|
|
|
|
const char* begin = text + lineStart;
|
|
const char* end = text + lineEnd;
|
|
BootTrimSpan(&begin, &end);
|
|
if (begin == end || *begin == ';' || *begin == '#')
|
|
continue;
|
|
|
|
if (*begin == '[' && end[-1] == ']') {
|
|
const char* sectionBegin = begin + 1;
|
|
const char* sectionEnd = end - 1;
|
|
BootTrimSpan(§ionBegin, §ionEnd);
|
|
inBootSection = BootSpanEquals(sectionBegin, sectionEnd, "boot");
|
|
continue;
|
|
}
|
|
if (!inBootSection)
|
|
continue;
|
|
|
|
const char* equals = NULL;
|
|
for (const char* p = begin; p < end; ++p) {
|
|
if (*p == '=') {
|
|
equals = p;
|
|
break;
|
|
}
|
|
}
|
|
if (!equals)
|
|
continue;
|
|
|
|
const char* keyBegin = begin;
|
|
const char* keyEnd = equals;
|
|
const char* valueBegin = equals + 1;
|
|
const char* valueEnd = end;
|
|
BootTrimSpan(&keyBegin, &keyEnd);
|
|
if (!BootSpanEquals(keyBegin, keyEnd, "system_volume"))
|
|
continue;
|
|
|
|
if (selectorSeen)
|
|
return EFI_INVALID_PARAMETER;
|
|
BootTrimSpan(&valueBegin, &valueEnd);
|
|
if (!BootVolumeSelectorParse(valueBegin, (size_t)(valueEnd - valueBegin), &selector))
|
|
return EFI_INVALID_PARAMETER;
|
|
selectorSeen = true;
|
|
}
|
|
|
|
if (!selectorSeen)
|
|
return EFI_NOT_FOUND;
|
|
*selectorOut = selector;
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
// Returns whether one UEFI GUID equals one shared selector GUID.
|
|
static bool BootSelectorGuidEquals(const EFI_GUID* guid, const BOOT_VOLUME_GUID* selectorGuid) {
|
|
if (!guid || !selectorGuid)
|
|
return false;
|
|
return guid->Data1 == selectorGuid->Data1 &&
|
|
guid->Data2 == selectorGuid->Data2 &&
|
|
guid->Data3 == selectorGuid->Data3 &&
|
|
memcmp(guid->Data4, selectorGuid->Data4, sizeof(guid->Data4)) == 0;
|
|
}
|
|
|
|
// Finds the hard-drive media node that identifies one firmware partition handle.
|
|
static HARDDRIVE_DEVICE_PATH* BootFindHardDriveNode(EFI_DEVICE_PATH_PROTOCOL* devicePath) {
|
|
EFI_DEVICE_PATH_PROTOCOL* node = devicePath;
|
|
while (node && !IsDevicePathEnd(node)) {
|
|
UINTN nodeLength = DevicePathNodeLength(node);
|
|
if (nodeLength < sizeof(EFI_DEVICE_PATH_PROTOCOL))
|
|
return NULL;
|
|
if (DevicePathType(node) == MEDIA_DEVICE_PATH &&
|
|
DevicePathSubType(node) == MEDIA_HARDDRIVE_DP) {
|
|
UINTN requiredLength = offsetof(HARDDRIVE_DEVICE_PATH, SignatureType) +
|
|
sizeof(((HARDDRIVE_DEVICE_PATH*)0)->SignatureType);
|
|
if (nodeLength < requiredLength)
|
|
return NULL;
|
|
return (HARDDRIVE_DEVICE_PATH*)node;
|
|
}
|
|
node = NextDevicePathNode(node);
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
#if BOOT_VOLUME_DIAGNOSTICS
|
|
|
|
// Appends a fixed-width hexadecimal value to one diagnostic selector string.
|
|
static CHAR16* BootAppendHex(CHAR16* out, UINT64 value, UINTN digits) {
|
|
static const CHAR16 hex[] = L"0123456789ABCDEF";
|
|
for (UINTN i = digits; i != 0; --i)
|
|
*out++ = hex[(value >> ((i - 1u) * 4u)) & 0xFu];
|
|
return out;
|
|
}
|
|
|
|
// Formats the selector represented by one firmware hard-drive device-path node.
|
|
static bool BootFormatPartitionSelector(const HARDDRIVE_DEVICE_PATH* hardDrive,
|
|
CHAR16* selector, UINTN selectorChars) {
|
|
if (!hardDrive || !selector || selectorChars < 16u)
|
|
return false;
|
|
|
|
CHAR16* out = selector;
|
|
if (hardDrive->MBRType == MBR_TYPE_PCAT &&
|
|
hardDrive->SignatureType == SIGNATURE_TYPE_MBR) {
|
|
if (hardDrive->PartitionNumber == 0 || hardDrive->PartitionNumber > 4u)
|
|
return false;
|
|
uint32_t diskSignature = 0;
|
|
memcpy(&diskSignature, hardDrive->Signature, sizeof(diskSignature));
|
|
*out++ = L'm'; *out++ = L'b'; *out++ = L'r'; *out++ = L'/';
|
|
out = BootAppendHex(out, diskSignature, 8u);
|
|
*out++ = L'/';
|
|
*out++ = (CHAR16)(L'0' + hardDrive->PartitionNumber);
|
|
*out = L'\0';
|
|
return true;
|
|
}
|
|
|
|
if (hardDrive->MBRType == MBR_TYPE_EFI_PARTITION_TABLE_HEADER &&
|
|
hardDrive->SignatureType == SIGNATURE_TYPE_GUID) {
|
|
if (selectorChars < 41u)
|
|
return false;
|
|
EFI_GUID partitionGuid;
|
|
memcpy(&partitionGuid, hardDrive->Signature, sizeof(partitionGuid));
|
|
*out++ = L'g'; *out++ = L'p'; *out++ = L't'; *out++ = L'/';
|
|
out = BootAppendHex(out, partitionGuid.Data1, 8u);
|
|
*out++ = L'-';
|
|
out = BootAppendHex(out, partitionGuid.Data2, 4u);
|
|
*out++ = L'-';
|
|
out = BootAppendHex(out, partitionGuid.Data3, 4u);
|
|
*out++ = L'-';
|
|
out = BootAppendHex(out, partitionGuid.Data4[0], 2u);
|
|
out = BootAppendHex(out, partitionGuid.Data4[1], 2u);
|
|
*out++ = L'-';
|
|
for (UINTN i = 2; i < 8; ++i)
|
|
out = BootAppendHex(out, partitionGuid.Data4[i], 2u);
|
|
*out = L'\0';
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
// Prints firmware partition identities so development builds can copy the exact selector firmware exposes.
|
|
static void BootPrintPartitionSelectors(void) {
|
|
EFI_HANDLE* handles = NULL;
|
|
UINTN handleCount = 0;
|
|
EFI_STATUS status = gBS->LocateHandleBuffer(ByProtocol, &gEfiBlockIoProtocolGuid, NULL,
|
|
&handleCount, &handles);
|
|
if (EFI_ERROR(status)) {
|
|
Print(L"UEFI partition selector probe failed: %r\n", status);
|
|
return;
|
|
}
|
|
|
|
Print(L"UEFI partition selector candidates:\n");
|
|
UINTN candidateCount = 0;
|
|
for (UINTN i = 0; i < handleCount; ++i) {
|
|
EFI_BLOCK_IO_PROTOCOL* block = NULL;
|
|
status = gBS->HandleProtocol(handles[i], &gEfiBlockIoProtocolGuid, (VOID**)&block);
|
|
if (EFI_ERROR(status) || !block || !block->Media || !block->Media->MediaPresent ||
|
|
!block->Media->LogicalPartition) {
|
|
continue;
|
|
}
|
|
|
|
EFI_DEVICE_PATH_PROTOCOL* path = NULL;
|
|
status = gBS->HandleProtocol(handles[i], &gEfiDevicePathProtocolGuid, (VOID**)&path);
|
|
if (EFI_ERROR(status) || !path)
|
|
continue;
|
|
|
|
HARDDRIVE_DEVICE_PATH* hardDrive = BootFindHardDriveNode(path);
|
|
if (!hardDrive)
|
|
continue;
|
|
|
|
CHAR16 selector[48];
|
|
if (BootFormatPartitionSelector(hardDrive, selector, sizeof(selector) / sizeof(selector[0]))) {
|
|
Print(L" %s start_lba=%llu sectors=%llu\n", selector,
|
|
hardDrive->PartitionStart, hardDrive->PartitionSize);
|
|
} else {
|
|
Print(L" unsupported partition=%u mbr_type=%u signature_type=%u "
|
|
L"start_lba=%llu sectors=%llu signature=",
|
|
hardDrive->PartitionNumber, hardDrive->MBRType, hardDrive->SignatureType,
|
|
hardDrive->PartitionStart, hardDrive->PartitionSize);
|
|
for (UINTN byte = 0; byte < sizeof(hardDrive->Signature); ++byte)
|
|
Print(L"%02x", hardDrive->Signature[byte]);
|
|
Print(L"\n");
|
|
}
|
|
++candidateCount;
|
|
}
|
|
|
|
if (candidateCount == 0)
|
|
Print(L" <none>\n");
|
|
gBS->FreePool(handles);
|
|
}
|
|
|
|
#else
|
|
|
|
#define BootPrintPartitionSelectors() ((void)0)
|
|
|
|
#endif
|
|
|
|
// Returns whether one UEFI partition handle structurally matches the configured selector.
|
|
static bool BootPartitionMatches(EFI_HANDLE handle, const BOOT_VOLUME_SELECTOR* selector) {
|
|
if (!handle || !selector)
|
|
return false;
|
|
|
|
EFI_BLOCK_IO_PROTOCOL* block = NULL;
|
|
EFI_STATUS status = gBS->HandleProtocol(handle, &gEfiBlockIoProtocolGuid, (VOID**)&block);
|
|
if (EFI_ERROR(status) || !block || !block->Media || !block->Media->MediaPresent ||
|
|
!block->Media->LogicalPartition) {
|
|
return false;
|
|
}
|
|
|
|
EFI_DEVICE_PATH_PROTOCOL* path = NULL;
|
|
status = gBS->HandleProtocol(handle, &gEfiDevicePathProtocolGuid, (VOID**)&path);
|
|
if (EFI_ERROR(status) || !path)
|
|
return false;
|
|
|
|
HARDDRIVE_DEVICE_PATH* hardDrive = BootFindHardDriveNode(path);
|
|
if (!hardDrive)
|
|
return false;
|
|
|
|
if (selector->Kind == BootVolumeSelectorMbr) {
|
|
if (hardDrive->MBRType != MBR_TYPE_PCAT || hardDrive->SignatureType != SIGNATURE_TYPE_MBR ||
|
|
hardDrive->PartitionNumber != selector->Identity.Mbr.PartitionNumber) {
|
|
return false;
|
|
}
|
|
uint32_t diskSignature = 0;
|
|
memcpy(&diskSignature, hardDrive->Signature, sizeof(diskSignature));
|
|
return diskSignature == selector->Identity.Mbr.DiskSignature;
|
|
}
|
|
|
|
if (selector->Kind == BootVolumeSelectorGpt) {
|
|
if (hardDrive->MBRType != MBR_TYPE_EFI_PARTITION_TABLE_HEADER ||
|
|
hardDrive->SignatureType != SIGNATURE_TYPE_GUID) {
|
|
return false;
|
|
}
|
|
EFI_GUID partitionGuid;
|
|
memcpy(&partitionGuid, hardDrive->Signature, sizeof(partitionGuid));
|
|
return BootSelectorGuidEquals(&partitionGuid, &selector->Identity.Gpt.PartitionGuid);
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
// Finds exactly one firmware partition handle matching the structural system-volume selector.
|
|
static EFI_STATUS BootFindSystemPartition(const BOOT_VOLUME_SELECTOR* selector, EFI_HANDLE* handleOut) {
|
|
if (!selector || !handleOut)
|
|
return EFI_INVALID_PARAMETER;
|
|
|
|
*handleOut = NULL;
|
|
EFI_HANDLE* handles = NULL;
|
|
UINTN handleCount = 0;
|
|
EFI_STATUS status = gBS->LocateHandleBuffer(ByProtocol, &gEfiBlockIoProtocolGuid, NULL,
|
|
&handleCount, &handles);
|
|
if (EFI_ERROR(status))
|
|
return status;
|
|
|
|
EFI_HANDLE match = NULL;
|
|
UINTN matchCount = 0;
|
|
for (UINTN i = 0; i < handleCount; ++i) {
|
|
if (!BootPartitionMatches(handles[i], selector))
|
|
continue;
|
|
match = handles[i];
|
|
++matchCount;
|
|
}
|
|
gBS->FreePool(handles);
|
|
|
|
if (matchCount == 0)
|
|
return EFI_NOT_FOUND;
|
|
if (matchCount != 1)
|
|
return EFI_COMPROMISED_DATA;
|
|
*handleOut = match;
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
// Asks firmware to recursively connect currently visible controllers before retrying discovery.
|
|
static void BootConnectVisibleControllers(void) {
|
|
EFI_HANDLE* handles = NULL;
|
|
UINTN handleCount = 0;
|
|
EFI_STATUS status = gBS->LocateHandleBuffer(AllHandles, NULL, NULL, &handleCount, &handles);
|
|
if (EFI_ERROR(status))
|
|
return;
|
|
|
|
for (UINTN i = 0; i < handleCount; ++i)
|
|
gBS->ConnectController(handles[i], NULL, NULL, TRUE);
|
|
gBS->FreePool(handles);
|
|
}
|
|
|
|
// Returns whether one directory entry names an EFI image.
|
|
static bool BootIsEfiImageName(const CHAR16* name) {
|
|
if (!name)
|
|
return false;
|
|
UINTN length = StrLen(name);
|
|
if (length < 5)
|
|
return false;
|
|
const CHAR16* suffix = name + length - 4;
|
|
return suffix[0] == L'.' &&
|
|
(suffix[1] == L'e' || suffix[1] == L'E') &&
|
|
(suffix[2] == L'f' || suffix[2] == L'F') &&
|
|
(suffix[3] == L'i' || suffix[3] == L'I');
|
|
}
|
|
|
|
// Reads one variable-sized directory entry from a UEFI directory handle.
|
|
static EFI_STATUS BootReadDirectoryEntry(EFI_FILE_PROTOCOL* directory, EFI_FILE_INFO** infoOut) {
|
|
if (!directory || !infoOut)
|
|
return EFI_INVALID_PARAMETER;
|
|
|
|
*infoOut = NULL;
|
|
UINTN capacity = 512;
|
|
for (;;) {
|
|
EFI_FILE_INFO* info = NULL;
|
|
EFI_STATUS status = gBS->AllocatePool(EfiBootServicesData, capacity, (VOID**)&info);
|
|
if (EFI_ERROR(status))
|
|
return status;
|
|
|
|
UINTN size = capacity;
|
|
status = directory->Read(directory, &size, info);
|
|
if (status == EFI_BUFFER_TOO_SMALL) {
|
|
gBS->FreePool(info);
|
|
if (size <= capacity)
|
|
return EFI_LOAD_ERROR;
|
|
capacity = size;
|
|
continue;
|
|
}
|
|
if (EFI_ERROR(status)) {
|
|
gBS->FreePool(info);
|
|
return status;
|
|
}
|
|
if (size == 0) {
|
|
gBS->FreePool(info);
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
*infoOut = info;
|
|
return EFI_SUCCESS;
|
|
}
|
|
}
|
|
|
|
// Loads all optional filesystem UEFI drivers bundled on the boot anchor.
|
|
static EFI_STATUS BootLoadFilesystemDrivers(EFI_HANDLE imageHandle, UINTN* loadedCountOut) {
|
|
if (!imageHandle || !loadedCountOut)
|
|
return EFI_INVALID_PARAMETER;
|
|
|
|
*loadedCountOut = 0;
|
|
EFI_FILE_PROTOCOL* directory = NULL;
|
|
EFI_STATUS status = gBootRoot->Open(gBootRoot, &directory, L"EFI\\NTLite\\fs",
|
|
EFI_FILE_MODE_READ, 0);
|
|
if (EFI_ERROR(status))
|
|
return status;
|
|
|
|
for (;;) {
|
|
EFI_FILE_INFO* info = NULL;
|
|
status = BootReadDirectoryEntry(directory, &info);
|
|
if (EFI_ERROR(status))
|
|
break;
|
|
if (!info)
|
|
break;
|
|
|
|
if (!(info->Attribute & EFI_FILE_DIRECTORY) && BootIsEfiImageName(info->FileName)) {
|
|
static const CHAR16 prefix[] = L"\\EFI\\NTLite\\fs\\";
|
|
UINTN prefixChars = (sizeof(prefix) / sizeof(prefix[0])) - 1u;
|
|
UINTN nameChars = StrLen(info->FileName);
|
|
UINTN pathChars = prefixChars + nameChars + 1u;
|
|
if (pathChars < prefixChars || pathChars > (~(UINTN)0) / sizeof(CHAR16)) {
|
|
gBS->FreePool(info);
|
|
status = EFI_OUT_OF_RESOURCES;
|
|
break;
|
|
}
|
|
|
|
CHAR16* path = NULL;
|
|
status = gBS->AllocatePool(EfiBootServicesData, pathChars * sizeof(CHAR16),
|
|
(VOID**)&path);
|
|
if (EFI_ERROR(status)) {
|
|
gBS->FreePool(info);
|
|
break;
|
|
}
|
|
memcpy(path, prefix, prefixChars * sizeof(CHAR16));
|
|
memcpy(path + prefixChars, info->FileName, (nameChars + 1u) * sizeof(CHAR16));
|
|
|
|
EFI_DEVICE_PATH* devicePath = FileDevicePath(gBootDevice, path);
|
|
if (!devicePath) {
|
|
gBS->FreePool(path);
|
|
gBS->FreePool(info);
|
|
status = EFI_OUT_OF_RESOURCES;
|
|
break;
|
|
}
|
|
|
|
EFI_HANDLE driverImage = NULL;
|
|
EFI_STATUS driverStatus = gBS->LoadImage(FALSE, imageHandle, devicePath, NULL, 0,
|
|
&driverImage);
|
|
gBS->FreePool(devicePath);
|
|
if (!EFI_ERROR(driverStatus)) {
|
|
UINTN exitDataSize = 0;
|
|
CHAR16* exitData = NULL;
|
|
driverStatus = gBS->StartImage(driverImage, &exitDataSize, &exitData);
|
|
if (exitData)
|
|
gBS->FreePool(exitData);
|
|
if (EFI_ERROR(driverStatus)) {
|
|
gBS->UnloadImage(driverImage);
|
|
} else {
|
|
++*loadedCountOut;
|
|
Print(L"Loaded filesystem driver %s\n", info->FileName);
|
|
}
|
|
}
|
|
if (EFI_ERROR(driverStatus))
|
|
Print(L"Skipping filesystem driver %s: %r\n", info->FileName, driverStatus);
|
|
gBS->FreePool(path);
|
|
}
|
|
|
|
gBS->FreePool(info);
|
|
if (EFI_ERROR(status))
|
|
break;
|
|
}
|
|
|
|
directory->Close(directory);
|
|
if (EFI_ERROR(status))
|
|
return status;
|
|
return *loadedCountOut ? EFI_SUCCESS : EFI_NOT_FOUND;
|
|
}
|
|
|
|
// Opens the selected system volume, loading optional filesystem drivers only when firmware needs them.
|
|
static EFI_STATUS BootOpenSystemVolume(EFI_HANDLE imageHandle,
|
|
const BOOT_VOLUME_SELECTOR* selector,
|
|
EFI_FILE_PROTOCOL** rootOut) {
|
|
if (!imageHandle || !selector || !rootOut)
|
|
return EFI_INVALID_PARAMETER;
|
|
|
|
*rootOut = NULL;
|
|
EFI_HANDLE partition = NULL;
|
|
EFI_STATUS status = BootFindSystemPartition(selector, &partition);
|
|
if (status == EFI_NOT_FOUND) {
|
|
BootConnectVisibleControllers();
|
|
BootPrintPartitionSelectors();
|
|
status = BootFindSystemPartition(selector, &partition);
|
|
}
|
|
if (EFI_ERROR(status))
|
|
return status;
|
|
|
|
gBS->ConnectController(partition, NULL, NULL, TRUE);
|
|
EFI_SIMPLE_FILE_SYSTEM_PROTOCOL* fs = NULL;
|
|
status = gBS->HandleProtocol(partition, &gEfiSimpleFileSystemProtocolGuid, (VOID**)&fs);
|
|
if (EFI_ERROR(status)) {
|
|
UINTN loadedDrivers = 0;
|
|
EFI_STATUS loadStatus = BootLoadFilesystemDrivers(imageHandle, &loadedDrivers);
|
|
if (EFI_ERROR(loadStatus) && loadStatus != EFI_NOT_FOUND)
|
|
return loadStatus;
|
|
if (loadedDrivers != 0)
|
|
gBS->ConnectController(partition, NULL, NULL, TRUE);
|
|
status = gBS->HandleProtocol(partition, &gEfiSimpleFileSystemProtocolGuid, (VOID**)&fs);
|
|
}
|
|
if (EFI_ERROR(status) || !fs)
|
|
return EFI_ERROR(status) ? status : EFI_NOT_FOUND;
|
|
|
|
return fs->OpenVolume(fs, rootOut);
|
|
}
|
|
|
|
typedef EFI_STATUS (*BOOT_DRIVER_VISITOR)(const char* id, const char* image, void* context);
|
|
|
|
// The firmware recognizes only the identity, image, and start fields in driver sections.
|
|
// Graph validation and all other configuration semantics belong to the kernel.
|
|
static EFI_STATUS BootVisitDriverLines(const char* text, UINTN length,
|
|
BOOT_DRIVER_VISITOR visitor, void* context) {
|
|
if (!text || !visitor || length == 0 || length > 64u * 1024u)
|
|
return EFI_INVALID_PARAMETER;
|
|
|
|
char id[BOOT_FILE_NAME_MAX] = {0};
|
|
char image[BOOT_FILE_NAME_MAX] = {0};
|
|
bool driverSection = false;
|
|
bool bootPhase = false;
|
|
UINTN offset = 0;
|
|
while (offset <= length) {
|
|
UINTN lineStart = offset;
|
|
while (offset < length && text[offset] != '\n') ++offset;
|
|
const char* begin = text + lineStart;
|
|
const char* end = text + offset;
|
|
if (offset < length) ++offset;
|
|
else ++offset; // Process the final section exactly once.
|
|
BootTrimSpan(&begin, &end);
|
|
if (begin == end || *begin == ';' || *begin == '#') continue;
|
|
if (*begin == '[') {
|
|
if (driverSection && bootPhase) {
|
|
if (!id[0] || !image[0]) return EFI_INVALID_PARAMETER;
|
|
EFI_STATUS status = visitor(id, image, context);
|
|
if (EFI_ERROR(status)) return status;
|
|
}
|
|
driverSection = false;
|
|
bootPhase = false;
|
|
id[0] = '\0';
|
|
image[0] = '\0';
|
|
if (end[-1] != ']') return EFI_INVALID_PARAMETER;
|
|
const char* section = begin + 1;
|
|
const char* sectionEnd = end - 1;
|
|
if ((UINTN)(sectionEnd - section) > 7u &&
|
|
memcmp(section, "driver.", 7u) == 0) {
|
|
section += 7;
|
|
UINTN n = (UINTN)(sectionEnd - section);
|
|
if (n == 0 || n >= sizeof(id)) return EFI_INVALID_PARAMETER;
|
|
memcpy(id, section, n);
|
|
id[n] = '\0';
|
|
driverSection = true;
|
|
}
|
|
continue;
|
|
}
|
|
if (!driverSection) continue;
|
|
const char* equals = begin;
|
|
while (equals < end && *equals != '=') ++equals;
|
|
if (equals == end) return EFI_INVALID_PARAMETER;
|
|
const char* keyEnd = equals;
|
|
const char* value = equals + 1;
|
|
BootTrimSpan(&begin, &keyEnd);
|
|
BootTrimSpan(&value, &end);
|
|
for (const char* p = value; p < end; ++p) {
|
|
if (*p == '#' || *p == ';') {
|
|
end = p;
|
|
BootTrimSpan(&value, &end);
|
|
break;
|
|
}
|
|
}
|
|
if (BootSpanEquals(begin, keyEnd, "image")) {
|
|
UINTN n = (UINTN)(end - value);
|
|
if (n == 0 || n >= sizeof(image)) return EFI_INVALID_PARAMETER;
|
|
memcpy(image, value, n);
|
|
image[n] = '\0';
|
|
} else if (BootSpanEquals(begin, keyEnd, "start")) {
|
|
bootPhase = BootSpanEquals(value, end, "boot");
|
|
}
|
|
}
|
|
if (driverSection && bootPhase) {
|
|
if (!id[0] || !image[0]) return EFI_INVALID_PARAMETER;
|
|
return visitor(id, image, context);
|
|
}
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
typedef struct BOOT_DRIVER_COUNT_CONTEXT {
|
|
uint32_t Count;
|
|
} BOOT_DRIVER_COUNT_CONTEXT;
|
|
|
|
static EFI_STATUS BootCountDriver(const char* id, const char* image, void* context) {
|
|
(void)id;
|
|
(void)image;
|
|
BOOT_DRIVER_COUNT_CONTEXT* count = (BOOT_DRIVER_COUNT_CONTEXT*)context;
|
|
if (count->Count == UINT32_MAX) return EFI_OUT_OF_RESOURCES;
|
|
++count->Count;
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
typedef struct BOOT_DRIVER_LOAD_CONTEXT {
|
|
BOOT_FILE* Files;
|
|
uint32_t Capacity;
|
|
uint32_t Index;
|
|
} BOOT_DRIVER_LOAD_CONTEXT;
|
|
|
|
// Loads one identified boot image into retained physical pages.
|
|
static EFI_STATUS BootLoadDriver(const char* id, const char* image, void* context) {
|
|
BOOT_DRIVER_LOAD_CONTEXT* load = (BOOT_DRIVER_LOAD_CONTEXT*)context;
|
|
if (!load || load->Index >= load->Capacity) return EFI_INVALID_PARAMETER;
|
|
UINTN idLength = strlen(id);
|
|
UINTN length = strlen(image);
|
|
if (idLength == 0 || idLength >= BOOT_FILE_NAME_MAX ||
|
|
length < 5 || length >= BOOT_FILE_NAME_MAX ||
|
|
memcmp(image + length - 4, ".sys", 4) != 0)
|
|
return EFI_INVALID_PARAMETER;
|
|
for (UINTN i = 0; i < length; ++i) {
|
|
char c = image[i];
|
|
if (!((c >= 'a' && c <= 'z') || (c >= '0' && c <= '9') ||
|
|
c == '-' || c == '_' || c == '.')) return EFI_INVALID_PARAMETER;
|
|
}
|
|
CHAR16 unicodeName[BOOT_FILE_NAME_MAX];
|
|
if (AsciiStrToUnicodeStrS(image, unicodeName, BOOT_FILE_NAME_MAX) != 0)
|
|
return EFI_INVALID_PARAMETER;
|
|
CHAR16 path[128];
|
|
UnicodeSPrint(path, sizeof(path), L"drivers\\%s", unicodeName);
|
|
BOOT_BLOB blob = {0};
|
|
EFI_STATUS status = BootReadBlobFile(gSystemRoot, path, &blob);
|
|
if (EFI_ERROR(status)) return status;
|
|
if (blob.Length == 0) {
|
|
gBS->FreePages(blob.PhysicalBase, blob.PageCount);
|
|
return EFI_LOAD_ERROR;
|
|
}
|
|
BOOT_FILE* file = &load->Files[load->Index++];
|
|
AsciiStrCpyS(file->DriverId, sizeof(file->DriverId), id);
|
|
AsciiStrCpyS(file->Image, sizeof(file->Image), image);
|
|
file->PhysicalBase = blob.PhysicalBase;
|
|
file->Length = blob.Length;
|
|
file->PageCount = blob.PageCount;
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
static EFI_STATUS BootLoadDrivers(const char* text, UINTN length, BOOT_FILE_LIST* listOut) {
|
|
if (!text || !listOut) return EFI_INVALID_PARAMETER;
|
|
*listOut = (BOOT_FILE_LIST){0};
|
|
BOOT_DRIVER_COUNT_CONTEXT count = {0};
|
|
EFI_STATUS status = BootVisitDriverLines(text, length, BootCountDriver, &count);
|
|
if (EFI_ERROR(status)) return status;
|
|
if (!count.Count || count.Count > 64u) return EFI_INVALID_PARAMETER;
|
|
UINTN descriptorBytes = (UINTN)count.Count * sizeof(BOOT_FILE);
|
|
UINTN pageCount = (descriptorBytes + PAGE_SIZE - 1u) / PAGE_SIZE;
|
|
EFI_PHYSICAL_ADDRESS physical = 0;
|
|
status = BootAllocatePages(pageCount, &physical);
|
|
if (EFI_ERROR(status)) return status;
|
|
BOOT_DRIVER_LOAD_CONTEXT load = {0};
|
|
load.Files = (BOOT_FILE*)physical;
|
|
load.Capacity = count.Count;
|
|
status = BootVisitDriverLines(text, length, BootLoadDriver, &load);
|
|
if (EFI_ERROR(status) || load.Index != count.Count) {
|
|
for (uint32_t i = 0; i < load.Index; ++i)
|
|
gBS->FreePages(load.Files[i].PhysicalBase, load.Files[i].PageCount);
|
|
gBS->FreePages(physical, pageCount);
|
|
return EFI_ERROR(status) ? status : EFI_LOAD_ERROR;
|
|
}
|
|
listOut->FilesPhysical = (uintptr_t)physical;
|
|
listOut->Count = count.Count;
|
|
listOut->PageCount = (uint32_t)pageCount;
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
// Allocates the page-backed versioned BOOT_INFO block passed into KernelMain.
|
|
static EFI_STATUS BootAllocateInfo(BOOT_INFO** infoOut) {
|
|
if (!infoOut)
|
|
return EFI_INVALID_PARAMETER;
|
|
|
|
*infoOut = NULL;
|
|
UINTN pageCount = (sizeof(BOOT_INFO) + PAGE_SIZE - 1u) / PAGE_SIZE;
|
|
EFI_PHYSICAL_ADDRESS physical = 0;
|
|
EFI_STATUS status = BootAllocatePages(pageCount, &physical);
|
|
if (EFI_ERROR(status))
|
|
return status;
|
|
|
|
BOOT_INFO* info = (BOOT_INFO*)physical;
|
|
info->Magic = BOOT_INFO_MAGIC;
|
|
info->Size = sizeof(BOOT_INFO);
|
|
info->Version = BOOT_INFO_VERSION;
|
|
*infoOut = info;
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
// Captures the firmware wall clock before runtime firmware services are abandoned.
|
|
static void BootCaptureTime(BOOT_INFO* info) {
|
|
EFI_TIME fwTime;
|
|
if (EFI_ERROR(gRT->GetTime(&fwTime, NULL)) ||
|
|
fwTime.Year < 1970 || fwTime.Month < 1 || fwTime.Month > 12 ||
|
|
fwTime.Day < 1 || fwTime.Day > 31 || fwTime.Hour > 23 ||
|
|
fwTime.Minute > 59 || fwTime.Second > 59 ||
|
|
fwTime.Nanosecond >= 1000000000U) {
|
|
return;
|
|
}
|
|
|
|
info->BootTime.Year = fwTime.Year;
|
|
info->BootTime.Month = fwTime.Month;
|
|
info->BootTime.Day = fwTime.Day;
|
|
info->BootTime.Hour = fwTime.Hour;
|
|
info->BootTime.Minute = fwTime.Minute;
|
|
info->BootTime.Second = fwTime.Second;
|
|
info->BootTime.Daylight = fwTime.Daylight;
|
|
info->BootTime.Nanosecond = fwTime.Nanosecond;
|
|
info->BootTime.TimeZoneMinutes = fwTime.TimeZone;
|
|
info->BootTime.Flags = BOOT_TIME_FLAG_VALID | BOOT_TIME_FLAG_UEFI;
|
|
if (fwTime.TimeZone != EFI_UNSPECIFIED_TIMEZONE)
|
|
info->BootTime.Flags |= BOOT_TIME_FLAG_TZ_KNOWN;
|
|
}
|
|
|
|
// Returns whether two complete EFI GUIDs are identical.
|
|
static bool BootGuidEqual(const EFI_GUID* a, const EFI_GUID* b) {
|
|
return a && b && memcmp(a, b, sizeof(EFI_GUID)) == 0;
|
|
}
|
|
|
|
// Captures the preferred ACPI RSDP pointer from the firmware configuration table.
|
|
static uintptr_t BootFindRsdp(EFI_SYSTEM_TABLE* systemTable) {
|
|
const EFI_GUID acpi2Guid = { 0x8868e871, 0xe4f1, 0x11d3, {0xbc, 0x22, 0x00, 0x80, 0xc7, 0x3c, 0x88, 0x81} };
|
|
const EFI_GUID acpi1Guid = { 0xeb9d2d30, 0x2d88, 0x11d3, {0x9a, 0x16, 0x00, 0x90, 0x27, 0x3f, 0xc1, 0x4d} };
|
|
uintptr_t acpi1 = 0;
|
|
|
|
for (UINTN i = 0; i < systemTable->NumberOfTableEntries; ++i) {
|
|
EFI_CONFIGURATION_TABLE* table = &systemTable->ConfigurationTable[i];
|
|
if (BootGuidEqual(&table->VendorGuid, &acpi2Guid))
|
|
return (uintptr_t)table->VendorTable;
|
|
if (BootGuidEqual(&table->VendorGuid, &acpi1Guid))
|
|
acpi1 = (uintptr_t)table->VendorTable;
|
|
}
|
|
return acpi1;
|
|
}
|
|
|
|
// Reserves the AP SIPI trampoline page below the legacy 640 KiB boundary while firmware can still allocate it.
|
|
static EFI_PHYSICAL_ADDRESS BootAllocateApTrampoline(void) {
|
|
EFI_PHYSICAL_ADDRESS physical = 0x0009F000ULL;
|
|
EFI_STATUS status = gBS->AllocatePages(AllocateMaxAddress, EfiLoaderData, 1, &physical);
|
|
if (EFI_ERROR(status) || physical == 0 || physical >= 0x000A0000ULL || (physical & 0xFFFULL))
|
|
return 0;
|
|
gBS->SetMem((VOID*)physical, PAGE_SIZE, 0);
|
|
return physical;
|
|
}
|
|
|
|
// Grows and refreshes one EFI memory-map buffer using boot-services memory.
|
|
static EFI_STATUS BootRefreshMemoryMap(BOOT_EFI_MEMORY_MAP* map) {
|
|
if (!map)
|
|
return EFI_INVALID_PARAMETER;
|
|
|
|
for (;;) {
|
|
UINTN size = map->Capacity;
|
|
UINTN key = 0;
|
|
UINTN descriptorSize = map->DescriptorSize;
|
|
UINT32 descriptorVersion = 0;
|
|
EFI_STATUS status = gBS->GetMemoryMap(&size, map->Buffer, &key,
|
|
&descriptorSize, &descriptorVersion);
|
|
if (status == EFI_BUFFER_TOO_SMALL) {
|
|
UINTN slack = descriptorSize ? descriptorSize * 16u : 4096u;
|
|
if (size > ~(UINTN)0 - slack)
|
|
return EFI_OUT_OF_RESOURCES;
|
|
UINTN capacity = size + slack;
|
|
EFI_MEMORY_DESCRIPTOR* replacement = NULL;
|
|
status = gBS->AllocatePool(EfiBootServicesData, capacity, (VOID**)&replacement);
|
|
if (EFI_ERROR(status))
|
|
return status;
|
|
if (map->Buffer)
|
|
gBS->FreePool(map->Buffer);
|
|
map->Buffer = replacement;
|
|
map->Capacity = capacity;
|
|
map->DescriptorSize = descriptorSize;
|
|
continue;
|
|
}
|
|
if (EFI_ERROR(status))
|
|
return status;
|
|
|
|
map->Size = size;
|
|
map->Key = key;
|
|
map->DescriptorSize = descriptorSize;
|
|
map->DescriptorVersion = descriptorVersion;
|
|
return EFI_SUCCESS;
|
|
}
|
|
}
|
|
|
|
// Releases one temporary EFI memory-map buffer before ExitBootServices.
|
|
static void BootFreeMemoryMap(BOOT_EFI_MEMORY_MAP* map) {
|
|
if (map && map->Buffer) {
|
|
gBS->FreePool(map->Buffer);
|
|
map->Buffer = NULL;
|
|
map->Capacity = 0;
|
|
}
|
|
}
|
|
|
|
// Maps one firmware memory descriptor to the generic post-ExitBootServices memory type.
|
|
static MEMORY_TYPE BootMemoryType(UINT32 type) {
|
|
switch ((EFI_MEMORY_TYPE)type) {
|
|
case EfiConventionalMemory:
|
|
return MemoryUsable;
|
|
case EfiMemoryMappedIO:
|
|
case EfiMemoryMappedIOPortSpace:
|
|
return MemoryMappedIO;
|
|
case EfiLoaderCode:
|
|
case EfiLoaderData:
|
|
return MemoryBootloader;
|
|
default:
|
|
return MemoryReserved;
|
|
}
|
|
}
|
|
|
|
// Converts one final EFI memory-map snapshot into the compact generic map, coalescing adjacent compatible ranges.
|
|
static EFI_STATUS BootConvertMemoryMap(const BOOT_EFI_MEMORY_MAP* efiMap, MEMORY_MAP* out) {
|
|
if (!efiMap || !efiMap->Buffer || !efiMap->DescriptorSize || !out)
|
|
return EFI_INVALID_PARAMETER;
|
|
|
|
out->Magic = MEMORY_MAP_MAGIC;
|
|
out->RegionCount = 0;
|
|
out->_pad = 0;
|
|
|
|
UINTN descriptorCount = efiMap->Size / efiMap->DescriptorSize;
|
|
for (UINTN i = 0; i < descriptorCount; ++i) {
|
|
const EFI_MEMORY_DESCRIPTOR* descriptor =
|
|
(const EFI_MEMORY_DESCRIPTOR*)((const UINT8*)efiMap->Buffer + i * efiMap->DescriptorSize);
|
|
if (descriptor->NumberOfPages == 0)
|
|
continue;
|
|
if (descriptor->NumberOfPages > UINT64_MAX / PAGE_SIZE)
|
|
return EFI_INVALID_PARAMETER;
|
|
|
|
uint64_t base = descriptor->PhysicalStart;
|
|
uint64_t length = descriptor->NumberOfPages * PAGE_SIZE;
|
|
MEMORY_TYPE type = BootMemoryType(descriptor->Type);
|
|
|
|
if (out->RegionCount != 0) {
|
|
MEMORY_REGION* previous = &out->Regions[out->RegionCount - 1u];
|
|
if (previous->Type == type &&
|
|
previous->Base <= UINT64_MAX - previous->Length &&
|
|
previous->Base + previous->Length == base &&
|
|
previous->Length <= UINT64_MAX - length) {
|
|
previous->Length += length;
|
|
continue;
|
|
}
|
|
}
|
|
|
|
if (out->RegionCount >= MEMORY_MAX_REGIONS)
|
|
return EFI_BUFFER_TOO_SMALL;
|
|
MEMORY_REGION* region = &out->Regions[out->RegionCount++];
|
|
region->Base = base;
|
|
region->Length = length;
|
|
region->Type = type;
|
|
region->_pad = 0;
|
|
}
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
// Sorts small virtual hole arrays used while constructing identity and direct mappings.
|
|
static void BootSortHoles(UINT64* holes, UINTN holeCount) {
|
|
for (UINTN pass = 0; pass < holeCount; ++pass) {
|
|
for (UINTN i = 1; i < holeCount; ++i) {
|
|
if (holes[i * 2] < holes[(i - 1u) * 2]) {
|
|
UINT64 start = holes[(i - 1u) * 2];
|
|
UINT64 end = holes[(i - 1u) * 2 + 1u];
|
|
holes[(i - 1u) * 2] = holes[i * 2];
|
|
holes[(i - 1u) * 2 + 1u] = holes[i * 2 + 1u];
|
|
holes[i * 2] = start;
|
|
holes[i * 2 + 1u] = end;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// Builds the bootstrap identity/direct mappings from one firmware map snapshot.
|
|
static EFI_STATUS BootMapFirmwareMemory(const BOOT_EFI_MEMORY_MAP* map, UINT64 framebufferBase,
|
|
UINT64 framebufferBytes) {
|
|
if (!map || !map->Buffer || !map->DescriptorSize)
|
|
return EFI_INVALID_PARAMETER;
|
|
|
|
UINT64 identityHoles[8];
|
|
UINT64 windowHoles[8];
|
|
UINTN identityHoleCount = 0;
|
|
UINTN windowHoleCount = 0;
|
|
|
|
identityHoles[identityHoleCount * 2] = 0;
|
|
identityHoles[identityHoleCount * 2 + 1u] = PAGE_SIZE;
|
|
++identityHoleCount;
|
|
|
|
if (framebufferBytes) {
|
|
identityHoles[identityHoleCount * 2] = framebufferBase;
|
|
identityHoles[identityHoleCount * 2 + 1u] = framebufferBase + framebufferBytes;
|
|
++identityHoleCount;
|
|
windowHoles[windowHoleCount * 2] = PHYS_MAP_BASE + framebufferBase;
|
|
windowHoles[windowHoleCount * 2 + 1u] = PHYS_MAP_BASE + framebufferBase + framebufferBytes;
|
|
++windowHoleCount;
|
|
}
|
|
|
|
identityHoles[identityHoleCount * 2] = 0xFEC00000ULL;
|
|
identityHoles[identityHoleCount * 2 + 1u] = 0xFEE01000ULL;
|
|
++identityHoleCount;
|
|
windowHoles[windowHoleCount * 2] = PHYS_MAP_BASE + 0xFEC00000ULL;
|
|
windowHoles[windowHoleCount * 2 + 1u] = PHYS_MAP_BASE + 0xFEE01000ULL;
|
|
++windowHoleCount;
|
|
|
|
BootSortHoles(identityHoles, identityHoleCount);
|
|
BootSortHoles(windowHoles, windowHoleCount);
|
|
|
|
UINTN descriptorCount = map->Size / map->DescriptorSize;
|
|
for (UINTN i = 0; i < descriptorCount; ++i) {
|
|
const EFI_MEMORY_DESCRIPTOR* descriptor =
|
|
(const EFI_MEMORY_DESCRIPTOR*)((const UINT8*)map->Buffer + i * map->DescriptorSize);
|
|
if (!IsDirectMapRamType(descriptor->Type))
|
|
continue;
|
|
|
|
UINT64 start = descriptor->PhysicalStart;
|
|
UINT64 size = descriptor->NumberOfPages * PAGE_SIZE;
|
|
UINT64 flags = BOOT_PAGE_PRESENT | BOOT_PAGE_WRITE | DirectMapCacheFlags(descriptor);
|
|
if (!MapRangeSkipping(start, start, size, flags, identityHoles, identityHoleCount) ||
|
|
!MapRangeSkipping(PHYS_MAP_BASE + start, start, size, flags, windowHoles, windowHoleCount)) {
|
|
return EFI_OUT_OF_RESOURCES;
|
|
}
|
|
}
|
|
|
|
for (UINT64 physical = 0xFEC00000ULL; physical < 0xFEE01000ULL; physical += PAGE_SIZE) {
|
|
UINT64 flags = BOOT_PAGE_PRESENT | BOOT_PAGE_WRITE | BOOT_PAGE_CACHE_UC;
|
|
if (!Map4K(physical, physical, flags) ||
|
|
!Map4K(PHYS_MAP_BASE + physical, physical, flags)) {
|
|
return EFI_OUT_OF_RESOURCES;
|
|
}
|
|
}
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
// Captures GOP information and maps the visible framebuffer with write-combining bootstrap mappings.
|
|
static EFI_STATUS BootCaptureFramebuffer(BOOT_INFO* info, UINT64* baseOut, UINT64* bytesOut) {
|
|
if (!info || !baseOut || !bytesOut)
|
|
return EFI_INVALID_PARAMETER;
|
|
|
|
*baseOut = 0;
|
|
*bytesOut = 0;
|
|
EFI_GRAPHICS_OUTPUT_PROTOCOL* gop = NULL;
|
|
EFI_STATUS status = gBS->LocateProtocol(&gEfiGraphicsOutputProtocolGuid, NULL, (VOID**)&gop);
|
|
if (EFI_ERROR(status))
|
|
return EFI_SUCCESS;
|
|
if (!gop || !gop->Mode || !gop->Mode->Info)
|
|
return EFI_LOAD_ERROR;
|
|
|
|
info->FramebufferBase = gop->Mode->FrameBufferBase;
|
|
info->FramebufferWidth = gop->Mode->Info->HorizontalResolution;
|
|
info->FramebufferHeight = gop->Mode->Info->VerticalResolution;
|
|
info->FramebufferStride = gop->Mode->Info->PixelsPerScanLine;
|
|
|
|
UINT64 rowBytes = (UINT64)info->FramebufferStride * 4u;
|
|
if (info->FramebufferHeight != 0 && rowBytes > UINT64_MAX / info->FramebufferHeight)
|
|
return EFI_BAD_BUFFER_SIZE;
|
|
UINT64 visibleBytes = rowBytes * info->FramebufferHeight;
|
|
if (info->FramebufferBase > UINT64_MAX - visibleBytes)
|
|
return EFI_BAD_BUFFER_SIZE;
|
|
|
|
UINT64 mapBase = info->FramebufferBase & ~(PAGE_SIZE - 1u);
|
|
UINT64 mapEnd = info->FramebufferBase + visibleBytes;
|
|
if (mapEnd > UINT64_MAX - (PAGE_SIZE - 1u))
|
|
return EFI_BAD_BUFFER_SIZE;
|
|
mapEnd = (mapEnd + PAGE_SIZE - 1u) & ~(PAGE_SIZE - 1u);
|
|
|
|
for (UINT64 physical = mapBase; physical < mapEnd; physical += PAGE_SIZE) {
|
|
UINT64 flags = BOOT_PAGE_PRESENT | BOOT_PAGE_WRITE | BOOT_PAGE_CACHE_WC;
|
|
if (!Map4K(PHYS_MAP_BASE + physical, physical, flags) ||
|
|
!Map4K(physical, physical, flags)) {
|
|
return EFI_OUT_OF_RESOURCES;
|
|
}
|
|
}
|
|
|
|
*baseOut = mapBase;
|
|
*bytesOut = mapEnd - mapBase;
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
// Returns whether two fixed virtual image ranges overlap or overflow.
|
|
static bool BootImageRangesOverlap(const BOOT_PE_INFO* a, const BOOT_PE_INFO* b) {
|
|
uint64_t aEnd = a->ImageBase + a->SizeOfImage;
|
|
uint64_t bEnd = b->ImageBase + b->SizeOfImage;
|
|
if (aEnd < a->ImageBase || bEnd < b->ImageBase)
|
|
return true;
|
|
return a->ImageBase < bEnd && b->ImageBase < aEnd;
|
|
}
|
|
|
|
// Materializes and maps one already-inspected fixed PE image.
|
|
static EFI_STATUS BootMaterializeCoreImage(const UINT8* raw, UINTN rawSize,
|
|
const BOOT_PE_INFO* peInfo, BOOT_IMAGE* imageOut) {
|
|
if (!raw || !peInfo || !imageOut)
|
|
return EFI_INVALID_PARAMETER;
|
|
|
|
*imageOut = (BOOT_IMAGE){0};
|
|
UINTN pageCount = ((UINTN)peInfo->SizeOfImage + PAGE_SIZE - 1u) / PAGE_SIZE;
|
|
if (pageCount == 0 || pageCount > UINT32_MAX)
|
|
return EFI_BAD_BUFFER_SIZE;
|
|
|
|
EFI_PHYSICAL_ADDRESS physical = 0;
|
|
EFI_STATUS status = BootAllocatePages(pageCount, &physical);
|
|
if (EFI_ERROR(status))
|
|
return status;
|
|
|
|
BOOT_PE_INFO loadedInfo;
|
|
BOOT_PE_STATUS peStatus = BootPeMaterialize(raw, rawSize, (VOID*)physical,
|
|
pageCount * PAGE_SIZE, &loadedInfo);
|
|
if (peStatus != BootPeSuccess) {
|
|
gBS->FreePages(physical, pageCount);
|
|
Print(L"PE materialize failed: %a\n", BootPeStatusName(peStatus));
|
|
return EFI_LOAD_ERROR;
|
|
}
|
|
|
|
for (UINTN page = 0; page < pageCount; ++page) {
|
|
if (!Map4K(loadedInfo.ImageBase + page * PAGE_SIZE,
|
|
physical + page * PAGE_SIZE,
|
|
BOOT_PAGE_PRESENT | BOOT_PAGE_WRITE)) {
|
|
gBS->FreePages(physical, pageCount);
|
|
return EFI_OUT_OF_RESOURCES;
|
|
}
|
|
}
|
|
|
|
BOOT_IMAGE image = {0};
|
|
image.VirtualBase = (uintptr_t)loadedInfo.ImageBase;
|
|
image.PhysicalBase = (uintptr_t)physical;
|
|
image.ImageSize = loadedInfo.SizeOfImage;
|
|
image.PageCount = (uint32_t)pageCount;
|
|
image.EntryRva = loadedInfo.EntryRva;
|
|
*imageOut = image;
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
// Releases one materialized core image after a pre-ExitBootServices load failure.
|
|
static void BootReleaseCoreImage(BOOT_IMAGE* image) {
|
|
if (!image || !image->PhysicalBase || !image->PageCount)
|
|
return;
|
|
gBS->FreePages((EFI_PHYSICAL_ADDRESS)image->PhysicalBase, image->PageCount);
|
|
*image = (BOOT_IMAGE){0};
|
|
}
|
|
|
|
// Loads, verifies, maps, and binds the two fixed bootstrap PE images.
|
|
static EFI_STATUS BootLoadCoreImages(BOOT_INFO* info) {
|
|
UINT8* kernelRaw = NULL;
|
|
UINT8* halRaw = NULL;
|
|
UINTN kernelRawSize = 0;
|
|
UINTN halRawSize = 0;
|
|
|
|
EFI_STATUS status = BootReadPoolFile(gSystemRoot, L"system\\colonel.exe", &kernelRaw, &kernelRawSize);
|
|
if (EFI_ERROR(status)) {
|
|
Print(L"Missing kernel image: %r\n", status);
|
|
return status;
|
|
}
|
|
status = BootReadPoolFile(gSystemRoot, L"system\\hal.dll", &halRaw, &halRawSize);
|
|
if (EFI_ERROR(status)) {
|
|
Print(L"Missing HAL image: %r\n", status);
|
|
gBS->FreePool(kernelRaw);
|
|
return status;
|
|
}
|
|
|
|
BOOT_PE_INFO kernelPe;
|
|
BOOT_PE_INFO halPe;
|
|
BOOT_PE_STATUS peStatus = BootPeInspect(kernelRaw, kernelRawSize, &kernelPe);
|
|
if (peStatus != BootPeSuccess) {
|
|
Print(L"Kernel PE validation failed: %a\n", BootPeStatusName(peStatus));
|
|
status = EFI_LOAD_ERROR;
|
|
goto cleanup;
|
|
}
|
|
peStatus = BootPeInspect(halRaw, halRawSize, &halPe);
|
|
if (peStatus != BootPeSuccess) {
|
|
Print(L"HAL PE validation failed: %a\n", BootPeStatusName(peStatus));
|
|
status = EFI_LOAD_ERROR;
|
|
goto cleanup;
|
|
}
|
|
|
|
if (kernelPe.ImageBase != KERNEL_VIRT_BASE ||
|
|
kernelPe.ImageBase + kernelPe.SizeOfImage > PHYS_MAP_BASE ||
|
|
halPe.ImageBase < KERNEL_VIRT_BASE || halPe.ImageBase + halPe.SizeOfImage > PHYS_MAP_BASE ||
|
|
BootImageRangesOverlap(&kernelPe, &halPe)) {
|
|
Print(L"Core image fixed bases are invalid or overlap. kernel=0x%016llX hal=0x%016llX\n",
|
|
kernelPe.ImageBase, halPe.ImageBase);
|
|
status = EFI_LOAD_ERROR;
|
|
goto cleanup;
|
|
}
|
|
|
|
status = BootMaterializeCoreImage(kernelRaw, kernelRawSize, &kernelPe, &info->KernelImage);
|
|
if (EFI_ERROR(status))
|
|
goto cleanup;
|
|
status = BootMaterializeCoreImage(halRaw, halRawSize, &halPe, &info->HalImage);
|
|
if (EFI_ERROR(status))
|
|
goto cleanup;
|
|
|
|
peStatus = BootPeRequireNoImports((const void*)info->HalImage.PhysicalBase, info->HalImage.ImageSize);
|
|
if (peStatus != BootPeSuccess) {
|
|
Print(L"HAL must be self-contained: %a\n", BootPeStatusName(peStatus));
|
|
status = EFI_LOAD_ERROR;
|
|
goto cleanup;
|
|
}
|
|
|
|
peStatus = BootPeResolveImports((void*)info->KernelImage.PhysicalBase, info->KernelImage.ImageSize,
|
|
(const void*)info->HalImage.PhysicalBase, info->HalImage.ImageSize,
|
|
"hal.dll", info->HalImage.VirtualBase);
|
|
if (peStatus != BootPeSuccess) {
|
|
Print(L"Kernel/HAL import binding failed: %a\n", BootPeStatusName(peStatus));
|
|
status = EFI_LOAD_ERROR;
|
|
goto cleanup;
|
|
}
|
|
|
|
status = EFI_SUCCESS;
|
|
|
|
cleanup:
|
|
gBS->FreePool(kernelRaw);
|
|
gBS->FreePool(halRaw);
|
|
if (EFI_ERROR(status)) {
|
|
BootReleaseCoreImage(&info->HalImage);
|
|
BootReleaseCoreImage(&info->KernelImage);
|
|
}
|
|
return status;
|
|
}
|
|
|
|
// Converts the final map and exits boot services with the exact map key used for the handoff.
|
|
static EFI_STATUS BootExitServices(EFI_HANDLE imageHandle, BOOT_INFO* info) {
|
|
BOOT_EFI_MEMORY_MAP map = {0};
|
|
for (uint32_t attempt = 0; attempt < 8u; ++attempt) {
|
|
EFI_STATUS status = BootRefreshMemoryMap(&map);
|
|
if (EFI_ERROR(status)) {
|
|
BootFreeMemoryMap(&map);
|
|
return status;
|
|
}
|
|
|
|
status = BootConvertMemoryMap(&map, &info->MemoryMap);
|
|
if (EFI_ERROR(status)) {
|
|
BootFreeMemoryMap(&map);
|
|
return status;
|
|
}
|
|
|
|
status = gBS->ExitBootServices(imageHandle, map.Key);
|
|
if (!EFI_ERROR(status)) {
|
|
// No firmware interrupt handler remains valid after this instruction.
|
|
_disable();
|
|
return EFI_SUCCESS;
|
|
}
|
|
if (status != EFI_INVALID_PARAMETER) {
|
|
BootFreeMemoryMap(&map);
|
|
return status;
|
|
}
|
|
}
|
|
|
|
BootFreeMemoryMap(&map);
|
|
return EFI_ABORTED;
|
|
}
|
|
|
|
// UEFI application entry point.
|
|
EFI_STATUS EFIAPI UefiMain(EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE* SystemTable) {
|
|
InitializeLib(ImageHandle, SystemTable);
|
|
|
|
EFI_LOADED_IMAGE_PROTOCOL* loadedImage = NULL;
|
|
EFI_STATUS status = gBS->HandleProtocol(ImageHandle, &gEfiLoadedImageProtocolGuid,
|
|
(VOID**)&loadedImage);
|
|
if (EFI_ERROR(status)) {
|
|
Print(L"Failed to get LoadedImage protocol: %r\n", status);
|
|
return status;
|
|
}
|
|
|
|
EFI_SIMPLE_FILE_SYSTEM_PROTOCOL* fs = NULL;
|
|
status = gBS->HandleProtocol(loadedImage->DeviceHandle, &gEfiSimpleFileSystemProtocolGuid,
|
|
(VOID**)&fs);
|
|
if (EFI_ERROR(status)) {
|
|
Print(L"Failed to get boot filesystem protocol: %r\n", status);
|
|
return status;
|
|
}
|
|
|
|
gBootDevice = loadedImage->DeviceHandle;
|
|
status = fs->OpenVolume(fs, &gBootRoot);
|
|
if (EFI_ERROR(status)) {
|
|
Print(L"Failed to open boot volume: %r\n", status);
|
|
return status;
|
|
}
|
|
|
|
BOOT_INFO* info = NULL;
|
|
status = BootAllocateInfo(&info);
|
|
if (EFI_ERROR(status)) {
|
|
Print(L"Failed to allocate BOOT_INFO: %r\n", status);
|
|
return status;
|
|
}
|
|
|
|
status = BootReadBlobFile(gBootRoot, L"boot.ini", &info->BootIni);
|
|
if (EFI_ERROR(status) || info->BootIni.Length == 0) {
|
|
if (!EFI_ERROR(status) && info->BootIni.PhysicalBase)
|
|
gBS->FreePages(info->BootIni.PhysicalBase, info->BootIni.PageCount);
|
|
Print(L"Mandatory boot.ini could not be loaded or is empty: %r\n",
|
|
EFI_ERROR(status) ? status : EFI_LOAD_ERROR);
|
|
return EFI_ERROR(status) ? status : EFI_LOAD_ERROR;
|
|
}
|
|
|
|
BootPrintPartitionSelectors();
|
|
|
|
BOOT_VOLUME_SELECTOR systemVolumeSelector = {0};
|
|
status = BootParseSystemVolume((const char*)info->BootIni.PhysicalBase,
|
|
info->BootIni.Length, &systemVolumeSelector);
|
|
if (EFI_ERROR(status)) {
|
|
Print(L"boot.ini [boot] system_volume is missing or invalid: %r\n", status);
|
|
return status;
|
|
}
|
|
|
|
status = BootOpenSystemVolume(ImageHandle, &systemVolumeSelector, &gSystemRoot);
|
|
if (EFI_ERROR(status)) {
|
|
Print(L"Configured system_volume could not be opened: %r\n", status);
|
|
return status;
|
|
}
|
|
|
|
status = BootReadBlobFile(gSystemRoot, L"drivers\\drivers.ini", &info->DriversIni);
|
|
if (EFI_ERROR(status)) {
|
|
Print(L"Mandatory drivers.ini could not be loaded: %r\n", status);
|
|
return status;
|
|
}
|
|
status = BootLoadDrivers((const char*)info->DriversIni.PhysicalBase,
|
|
info->DriversIni.Length, &info->BootDrivers);
|
|
if (EFI_ERROR(status)) {
|
|
Print(L"drivers.ini preload failed: %r\n", status);
|
|
return status;
|
|
}
|
|
|
|
BootCaptureTime(info);
|
|
info->RsdpPhysical = BootFindRsdp(SystemTable);
|
|
info->PhysicalMapBase = PHYS_MAP_BASE;
|
|
info->ApTrampolinePhys = (uintptr_t)BootAllocateApTrampoline();
|
|
if (!info->ApTrampolinePhys) {
|
|
Print(L"Failed to reserve the AP trampoline page below 640 KiB.\n");
|
|
return EFI_OUT_OF_RESOURCES;
|
|
}
|
|
|
|
gPml4 = AllocPage(NULL);
|
|
if (!gPml4) {
|
|
Print(L"Failed to allocate the bootstrap PML4.\n");
|
|
return EFI_OUT_OF_RESOURCES;
|
|
}
|
|
|
|
status = BootLoadCoreImages(info);
|
|
if (EFI_ERROR(status))
|
|
return status;
|
|
|
|
UINT64 framebufferBase = 0;
|
|
UINT64 framebufferBytes = 0;
|
|
status = BootCaptureFramebuffer(info, &framebufferBase, &framebufferBytes);
|
|
if (EFI_ERROR(status)) {
|
|
Print(L"Failed to map the boot framebuffer: %r\n", status);
|
|
return status;
|
|
}
|
|
|
|
BOOT_EFI_MEMORY_MAP bootstrapMap = {0};
|
|
status = BootRefreshMemoryMap(&bootstrapMap);
|
|
if (EFI_ERROR(status)) {
|
|
Print(L"Failed to obtain the bootstrap EFI memory map: %r\n", status);
|
|
return status;
|
|
}
|
|
status = BootMapFirmwareMemory(&bootstrapMap, framebufferBase, framebufferBytes);
|
|
BootFreeMemoryMap(&bootstrapMap);
|
|
if (EFI_ERROR(status)) {
|
|
Print(L"Failed to construct bootstrap physical mappings: %r\n", status);
|
|
return status;
|
|
}
|
|
|
|
Print(L"Boot drivers: %u, kernel=0x%016llX, hal=0x%016llX, RSDP=0x%016llX\n",
|
|
info->BootDrivers.Count,
|
|
info->KernelImage.VirtualBase,
|
|
info->HalImage.VirtualBase,
|
|
info->RsdpPhysical);
|
|
|
|
status = BootExitServices(ImageHandle, info);
|
|
if (EFI_ERROR(status)) {
|
|
Print(L"ExitBootServices failed: %r\n", status);
|
|
return status;
|
|
}
|
|
|
|
_disable();
|
|
UINT64 efer = __readmsr(0xC0000080);
|
|
__writemsr(0xC0000080, efer | (1ULL << 11));
|
|
__writecr3((UINT64)gPml4);
|
|
|
|
typedef void (*KERNEL_ENTRY)(BOOT_INFO*);
|
|
KERNEL_ENTRY kernelMain = (KERNEL_ENTRY)(info->KernelImage.VirtualBase + info->KernelImage.EntryRva);
|
|
kernelMain(info);
|
|
|
|
_disable();
|
|
for (;;)
|
|
__halt();
|
|
}
|