mirror of
https://github.com/reactos/reactos.git
synced 2024-12-27 09:34:43 +00:00
[FREELDR] Implement the memory managment functions for UEFI (#5174)
CORE-11954 - EFI binaries have a different subsystem in the PE header; - ENVIRON: Make sure INTN and UINTN are 64bit for 64bit platforms; - Handle UEFI Memory maps and translate it for freeldr; - Add FAILED_TO_EXIT_BOOTSERVICES Freeldr BSoD code.
This commit is contained in:
parent
83e83bfd2c
commit
ccef43f3b0
12 changed files with 346 additions and 24 deletions
|
@ -197,6 +197,7 @@ typedef signed char CHAR8;
|
|||
typedef signed char INT8;
|
||||
#endif
|
||||
|
||||
#ifndef _WIN64
|
||||
///
|
||||
/// Unsigned value of native width. (4 bytes on supported 32-bit processor instructions;
|
||||
/// 8 bytes on supported 64-bit processor instructions.)
|
||||
|
@ -207,6 +208,18 @@ typedef UINT32 UINTN;
|
|||
/// 8 bytes on supported 64-bit processor instructions.)
|
||||
///
|
||||
typedef INT32 INTN;
|
||||
#else
|
||||
///
|
||||
/// Unsigned value of native width. (4 bytes on supported 32-bit processor instructions;
|
||||
/// 8 bytes on supported 64-bit processor instructions.)
|
||||
///
|
||||
typedef UINT64 UINTN;
|
||||
///
|
||||
/// Signed value of native width. (4 bytes on supported 32-bit processor instructions;
|
||||
/// 8 bytes on supported 64-bit processor instructions.)
|
||||
///
|
||||
typedef INT64 INTN;
|
||||
#endif
|
||||
|
||||
//
|
||||
// Processor specific defines
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/*
|
||||
* PROJECT: Freeldr UEFI Extension
|
||||
* PROJECT: FreeLoader UEFI Support
|
||||
* LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later)
|
||||
* PURPOSE: UEFI stubs
|
||||
* PURPOSE: Function stubs
|
||||
* COPYRIGHT: Copyright 2022 Justin Miller <justinmiller100@gmail.com>
|
||||
*/
|
||||
|
||||
|
@ -41,12 +41,6 @@ UefiVideoSync(VOID)
|
|||
|
||||
}
|
||||
|
||||
PFREELDR_MEMORY_DESCRIPTOR
|
||||
UefiMemGetMemoryMap(ULONG *MemoryMapSize)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
VOID
|
||||
UefiGetExtendedBIOSData(PULONG ExtendedBIOSDataArea,
|
||||
PULONG ExtendedBIOSDataSize)
|
||||
|
@ -94,12 +88,6 @@ UefiHwDetect(VOID)
|
|||
return 0;
|
||||
}
|
||||
|
||||
VOID
|
||||
UefiPrepareForReactOS(VOID)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
VOID
|
||||
UefiPcBeep(VOID)
|
||||
{
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/*
|
||||
* PROJECT: Freeldr UEFI Extension
|
||||
* PROJECT: FreeLoader UEFI Support
|
||||
* LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later)
|
||||
* PURPOSE: UEFI Console output
|
||||
* PURPOSE: Console output
|
||||
* COPYRIGHT: Copyright 2022 Justin Miller <justinmiller100@gmail.com>
|
||||
*/
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/*
|
||||
* PROJECT: Freeldr UEFI Extension
|
||||
* PROJECT: FreeLoader UEFI Support
|
||||
* LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later)
|
||||
* PURPOSE: UEFI Entry point and helpers
|
||||
* PURPOSE: Entry point and helpers
|
||||
* COPYRIGHT: Copyright 2022 Justin Miller <justinmiller100@gmail.com>
|
||||
*/
|
||||
|
||||
|
|
312
boot/freeldr/freeldr/arch/uefi/uefimem.c
Normal file
312
boot/freeldr/freeldr/arch/uefi/uefimem.c
Normal file
|
@ -0,0 +1,312 @@
|
|||
/*
|
||||
* PROJECT: FreeLoader UEFI Support
|
||||
* LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later)
|
||||
* PURPOSE: Memory Management Functions
|
||||
* COPYRIGHT: Copyright 2022 Justin Miller <justinmiller100@gmail.com>
|
||||
*/
|
||||
|
||||
/* INCLUDES ******************************************************************/
|
||||
|
||||
#include <uefildr.h>
|
||||
|
||||
#include <debug.h>
|
||||
DBG_DEFAULT_CHANNEL(WARNING);
|
||||
|
||||
#define NEXT_MEMORY_DESCRIPTOR(Descriptor, DescriptorSize) \
|
||||
(EFI_MEMORY_DESCRIPTOR*)((char*)(Descriptor) + (DescriptorSize))
|
||||
#define EXIT_STACK_SIZE 0x1000
|
||||
#define UNUSED_MAX_DESCRIPTOR_COUNT 10000
|
||||
|
||||
ULONG
|
||||
AddMemoryDescriptor(
|
||||
_Inout_ PFREELDR_MEMORY_DESCRIPTOR List,
|
||||
_In_ ULONG MaxCount,
|
||||
_In_ PFN_NUMBER BasePage,
|
||||
_In_ PFN_NUMBER PageCount,
|
||||
_In_ TYPE_OF_MEMORY MemoryType);
|
||||
|
||||
/* GLOBALS *******************************************************************/
|
||||
|
||||
extern EFI_SYSTEM_TABLE* GlobalSystemTable;
|
||||
extern EFI_HANDLE GlobalImageHandle;
|
||||
extern REACTOS_INTERNAL_BGCONTEXT framebufferData;
|
||||
|
||||
EFI_MEMORY_DESCRIPTOR* EfiMemoryMap = NULL;
|
||||
UINT32 FreeldrDescCount;
|
||||
PVOID OsLoaderBase;
|
||||
SIZE_T OsLoaderSize;
|
||||
EFI_HANDLE PublicBootHandle;
|
||||
PVOID ExitStack;
|
||||
PVOID EndofExitStack;
|
||||
|
||||
/* FUNCTIONS *****************************************************************/
|
||||
|
||||
static
|
||||
VOID
|
||||
PUEFI_LoadMemoryMap(
|
||||
_Out_ UINTN* LocMapKey,
|
||||
_Out_ UINTN* LocMapSize,
|
||||
_Out_ UINTN* LocDescriptorSize,
|
||||
_Out_ UINT32* LocDescriptorVersion)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
UINTN AllocationSize = 0;
|
||||
ULONG Count = 0;
|
||||
|
||||
Status = GlobalSystemTable->BootServices->GetMemoryMap(LocMapSize,
|
||||
EfiMemoryMap,
|
||||
LocMapKey,
|
||||
LocDescriptorSize,
|
||||
LocDescriptorVersion);
|
||||
|
||||
/* Reallocate and retrieve again the needed memory map size (since memory
|
||||
* allocated by AllocatePool() counts in the map), until it's OK. */
|
||||
while (Status != EFI_SUCCESS)
|
||||
{
|
||||
/* Reallocate the memory map buffer */
|
||||
if (EfiMemoryMap)
|
||||
GlobalSystemTable->BootServices->FreePool(EfiMemoryMap);
|
||||
|
||||
/* If MapSize never reports the correct size after the first time, increment */
|
||||
AllocationSize = *LocMapSize + (*LocDescriptorSize * Count);
|
||||
GlobalSystemTable->BootServices->AllocatePool(EfiLoaderData, AllocationSize,
|
||||
(VOID**)&EfiMemoryMap);
|
||||
Status = GlobalSystemTable->BootServices->GetMemoryMap(LocMapSize,
|
||||
EfiMemoryMap,
|
||||
LocMapKey,
|
||||
LocDescriptorSize,
|
||||
LocDescriptorVersion);
|
||||
Count++;
|
||||
}
|
||||
}
|
||||
|
||||
static
|
||||
VOID
|
||||
UefiSetMemory(
|
||||
_Inout_ PFREELDR_MEMORY_DESCRIPTOR MemoryMap,
|
||||
_In_ ULONG_PTR BaseAddress,
|
||||
_In_ PFN_COUNT Size,
|
||||
_In_ TYPE_OF_MEMORY MemoryType)
|
||||
{
|
||||
ULONG_PTR BasePage, PageCount;
|
||||
|
||||
BasePage = BaseAddress / EFI_PAGE_SIZE;
|
||||
PageCount = Size;
|
||||
|
||||
/* Add the memory descriptor */
|
||||
FreeldrDescCount = AddMemoryDescriptor(MemoryMap,
|
||||
UNUSED_MAX_DESCRIPTOR_COUNT,
|
||||
BasePage,
|
||||
PageCount,
|
||||
MemoryType);
|
||||
}
|
||||
|
||||
VOID
|
||||
ReserveMemory(
|
||||
_Inout_ PFREELDR_MEMORY_DESCRIPTOR MemoryMap,
|
||||
_In_ ULONG_PTR BaseAddress,
|
||||
_In_ PFN_NUMBER Size,
|
||||
_In_ TYPE_OF_MEMORY MemoryType,
|
||||
_In_ PCHAR Usage)
|
||||
{
|
||||
ULONG_PTR BasePage, PageCount;
|
||||
ULONG i;
|
||||
|
||||
BasePage = BaseAddress / PAGE_SIZE;
|
||||
PageCount = ADDRESS_AND_SIZE_TO_SPAN_PAGES(BaseAddress, Size);
|
||||
|
||||
for (i = 0; i < FreeldrDescCount; i++)
|
||||
{
|
||||
/* Check for conflicting descriptor */
|
||||
if ((MemoryMap[i].BasePage < BasePage + PageCount) &&
|
||||
(MemoryMap[i].BasePage + MemoryMap[i].PageCount > BasePage))
|
||||
{
|
||||
/* Check if the memory is free */
|
||||
if (MemoryMap[i].MemoryType != LoaderFree)
|
||||
{
|
||||
FrLdrBugCheckWithMessage(
|
||||
MEMORY_INIT_FAILURE,
|
||||
__FILE__,
|
||||
__LINE__,
|
||||
"Failed to reserve memory in the range 0x%Ix - 0x%Ix for %s",
|
||||
BaseAddress,
|
||||
Size,
|
||||
Usage);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Add the memory descriptor */
|
||||
FreeldrDescCount = AddMemoryDescriptor(MemoryMap,
|
||||
UNUSED_MAX_DESCRIPTOR_COUNT,
|
||||
BasePage,
|
||||
PageCount,
|
||||
MemoryType);
|
||||
}
|
||||
|
||||
static
|
||||
TYPE_OF_MEMORY
|
||||
UefiConvertToFreeldrDesc(EFI_MEMORY_TYPE EfiMemoryType)
|
||||
{
|
||||
switch (EfiMemoryType)
|
||||
{
|
||||
case EfiReservedMemoryType:
|
||||
return LoaderReserve;
|
||||
case EfiLoaderCode:
|
||||
return LoaderLoadedProgram;
|
||||
case EfiLoaderData:
|
||||
return LoaderLoadedProgram;
|
||||
case EfiBootServicesCode:
|
||||
return LoaderFirmwareTemporary;
|
||||
case EfiBootServicesData:
|
||||
return LoaderFirmwareTemporary;
|
||||
case EfiRuntimeServicesCode:
|
||||
return LoaderFirmwarePermanent;
|
||||
case EfiRuntimeServicesData:
|
||||
return LoaderFirmwarePermanent;
|
||||
case EfiConventionalMemory:
|
||||
return LoaderFree;
|
||||
case EfiUnusableMemory:
|
||||
return LoaderBad;
|
||||
case EfiACPIReclaimMemory:
|
||||
return LoaderFirmwareTemporary;
|
||||
case EfiACPIMemoryNVS:
|
||||
return LoaderReserve;
|
||||
case EfiMemoryMappedIO:
|
||||
return LoaderReserve;
|
||||
case EfiMemoryMappedIOPortSpace:
|
||||
return LoaderReserve;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return LoaderReserve;
|
||||
}
|
||||
|
||||
PFREELDR_MEMORY_DESCRIPTOR
|
||||
UefiMemGetMemoryMap(ULONG *MemoryMapSize)
|
||||
{
|
||||
EFI_LOADED_IMAGE_PROTOCOL *LoadedImage;
|
||||
UINT32 DescriptorVersion;
|
||||
SIZE_T FreeldrMemMapSize;
|
||||
UINTN DescriptorSize;
|
||||
EFI_STATUS Status;
|
||||
UINTN MapSize;
|
||||
UINTN MapKey;
|
||||
UINT32 Index;
|
||||
|
||||
EFI_GUID EfiLoadedImageProtocol = EFI_LOADED_IMAGE_PROTOCOL_GUID;
|
||||
PFREELDR_MEMORY_DESCRIPTOR FreeldrMem = NULL;
|
||||
EFI_MEMORY_DESCRIPTOR* MapEntry = NULL;
|
||||
UINT32 EntryCount = 0;
|
||||
FreeldrDescCount = 0;
|
||||
|
||||
Status = GlobalSystemTable->BootServices->HandleProtocol(GlobalImageHandle,
|
||||
&EfiLoadedImageProtocol,
|
||||
(VOID**)&LoadedImage);
|
||||
if (Status != EFI_SUCCESS)
|
||||
{
|
||||
TRACE("Failed to find LoadedImageHandle with status: %d\n", Status);
|
||||
UiMessageBoxCritical("Unable to initialize memory manager.");
|
||||
return NULL;
|
||||
}
|
||||
OsLoaderBase = LoadedImage->ImageBase;
|
||||
OsLoaderSize = LoadedImage->ImageSize;
|
||||
PublicBootHandle = LoadedImage->DeviceHandle;
|
||||
EfiMemoryMap = NULL;
|
||||
|
||||
TRACE("UefiMemGetMemoryMap: Gather memory map\n");
|
||||
PUEFI_LoadMemoryMap(&MapKey,
|
||||
&MapSize,
|
||||
&DescriptorSize,
|
||||
&DescriptorVersion);
|
||||
|
||||
TRACE("Value of MapKey: %d\n", MapKey);
|
||||
TRACE("Value of MapSize: %d\n", MapSize);
|
||||
TRACE("Value of DescriptorSize: %d\n", DescriptorSize);
|
||||
TRACE("Value of DescriptorVersion: %d\n", DescriptorVersion);
|
||||
|
||||
EntryCount = (MapSize / DescriptorSize);
|
||||
|
||||
FreeldrMemMapSize = (sizeof(FREELDR_MEMORY_DESCRIPTOR) * EntryCount);
|
||||
Status = GlobalSystemTable->BootServices->AllocatePool(EfiLoaderData,
|
||||
FreeldrMemMapSize,
|
||||
(void**)&FreeldrMem);
|
||||
if (Status != EFI_SUCCESS)
|
||||
{
|
||||
TRACE("Failed to allocate pool with status %d\n", Status);
|
||||
UiMessageBoxCritical("Unable to initialize memory manager.");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
RtlZeroMemory(FreeldrMem, FreeldrMemMapSize);
|
||||
MapEntry = EfiMemoryMap;
|
||||
for (Index = 0; Index < EntryCount; ++Index)
|
||||
{
|
||||
TYPE_OF_MEMORY MemoryType = UefiConvertToFreeldrDesc(MapEntry->Type);
|
||||
if (MemoryType == LoaderFree)
|
||||
{
|
||||
Status = GlobalSystemTable->BootServices->AllocatePages(AllocateAddress,
|
||||
EfiLoaderData,
|
||||
MapEntry->NumberOfPages,
|
||||
&MapEntry->PhysicalStart);
|
||||
if (Status != EFI_SUCCESS)
|
||||
{
|
||||
/* We failed to reserve the page, so change its type */
|
||||
MemoryType = LoaderFirmwareTemporary;
|
||||
}
|
||||
}
|
||||
|
||||
UefiSetMemory(FreeldrMem,
|
||||
MapEntry->PhysicalStart,
|
||||
MapEntry->NumberOfPages,
|
||||
MemoryType);
|
||||
|
||||
MapEntry = NEXT_MEMORY_DESCRIPTOR(MapEntry, DescriptorSize);
|
||||
}
|
||||
|
||||
*MemoryMapSize = FreeldrDescCount;
|
||||
return FreeldrMem;
|
||||
}
|
||||
|
||||
static VOID
|
||||
UefiExitBootServices(VOID)
|
||||
{
|
||||
UINTN MapKey;
|
||||
UINTN MapSize;
|
||||
EFI_STATUS Status;
|
||||
UINTN DescriptorSize;
|
||||
UINT32 DescriptorVersion;
|
||||
|
||||
TRACE("Attempting to exit bootsevices\n");
|
||||
PUEFI_LoadMemoryMap(&MapKey,
|
||||
&MapSize,
|
||||
&DescriptorSize,
|
||||
&DescriptorVersion);
|
||||
|
||||
Status = GlobalSystemTable->BootServices->ExitBootServices(GlobalImageHandle, MapKey);
|
||||
/* UEFI spec demands twice! */
|
||||
if (Status != EFI_SUCCESS)
|
||||
Status = GlobalSystemTable->BootServices->ExitBootServices(GlobalImageHandle, MapKey);
|
||||
|
||||
if (Status != EFI_SUCCESS)
|
||||
{
|
||||
TRACE("Failed to exit boot services with status: %d\n", Status);
|
||||
FrLdrBugCheckWithMessage(EXIT_BOOTSERVICES_FAILURE,
|
||||
__FILE__,
|
||||
__LINE__,
|
||||
"Failed to exit boot services with status: %d",
|
||||
Status);
|
||||
}
|
||||
else
|
||||
{
|
||||
TRACE("Exited bootservices\n");
|
||||
}
|
||||
}
|
||||
|
||||
VOID
|
||||
UefiPrepareForReactOS(VOID)
|
||||
{
|
||||
UefiExitBootServices();
|
||||
ExitStack = MmAllocateMemoryWithType(EXIT_STACK_SIZE, LoaderOsloaderStack);
|
||||
EndofExitStack = (PVOID)((ULONG_PTR)ExitStack + EXIT_STACK_SIZE);
|
||||
}
|
|
@ -1,7 +1,7 @@
|
|||
/*
|
||||
* PROJECT: Freeldr UEFI Extension
|
||||
* PROJECT: FreeLoader UEFI Support
|
||||
* LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later)
|
||||
* PURPOSE: UEFI Mach Setup
|
||||
* PURPOSE: Machine Setup
|
||||
* COPYRIGHT: Copyright 2022 Justin Miller <justinmiller100@gmail.com>
|
||||
*/
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/*
|
||||
* PROJECT: Freeldr UEFI Extension
|
||||
* PROJECT: FreeLoader UEFI Support
|
||||
* LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later)
|
||||
* PURPOSE: UEFI Utils source
|
||||
* PURPOSE: Utils source
|
||||
* COPYRIGHT: Copyright 2022 Justin Miller <justinmiller100@gmail.com>
|
||||
*/
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/*
|
||||
* PROJECT: Freeldr UEFI Extension
|
||||
* PROJECT: FreeLoader UEFI Support
|
||||
* LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later)
|
||||
* PURPOSE: UEFI Video output
|
||||
* PURPOSE: Video output
|
||||
* COPYRIGHT: Copyright 2022 Justin Miller <justinmiller100@gmail.com>
|
||||
*/
|
||||
|
||||
|
|
|
@ -141,6 +141,9 @@ enum _FRLDR_BUGCHECK_CODES
|
|||
MISSING_HARDWARE_REQUIREMENTS,
|
||||
FREELDR_IMAGE_CORRUPTION,
|
||||
MEMORY_INIT_FAILURE,
|
||||
#ifdef UEFIBOOT
|
||||
EXIT_BOOTSERVICES_FAILURE,
|
||||
#endif
|
||||
};
|
||||
|
||||
extern char *BugCodeStrings[];
|
||||
|
|
|
@ -518,6 +518,9 @@ char *BugCodeStrings[] =
|
|||
"MISSING_HARDWARE_REQUIREMENTS",
|
||||
"FREELDR_IMAGE_CORRUPTION",
|
||||
"MEMORY_INIT_FAILURE",
|
||||
#ifdef UEFIBOOT
|
||||
"EXIT_BOOTSERVICES_FAILURE",
|
||||
#endif
|
||||
};
|
||||
|
||||
ULONG_PTR BugCheckInfo[5];
|
||||
|
|
|
@ -238,6 +238,7 @@ static
|
|||
VOID
|
||||
MmCheckFreeldrImageFile(VOID)
|
||||
{
|
||||
#ifndef UEFIBOOT
|
||||
PIMAGE_NT_HEADERS NtHeaders;
|
||||
PIMAGE_FILE_HEADER FileHeader;
|
||||
PIMAGE_OPTIONAL_HEADER OptionalHeader;
|
||||
|
@ -308,6 +309,7 @@ MmCheckFreeldrImageFile(VOID)
|
|||
|
||||
/* Calculate the full image size */
|
||||
FrLdrImageSize = (ULONG_PTR)&__ImageBase + OptionalHeader->SizeOfImage - FREELDR_BASE;
|
||||
#endif
|
||||
}
|
||||
|
||||
BOOLEAN MmInitializeMemoryManager(VOID)
|
||||
|
|
|
@ -18,6 +18,7 @@ list(APPEND UEFILDR_ARC_SOURCE
|
|||
arch/uefi/uefivid.c
|
||||
arch/uefi/uefiutil.c
|
||||
arch/uefi/ueficon.c
|
||||
arch/uefi/uefimem.c
|
||||
arch/vgafont.c)
|
||||
|
||||
if(ARCH STREQUAL "i386")
|
||||
|
|
Loading…
Reference in a new issue