From c8907598f58cbb4f9217c5a9147c0a01e79ba0a5 Mon Sep 17 00:00:00 2001 From: Justin Miller Date: Sat, 14 Feb 2026 16:26:20 -0800 Subject: [PATCH] [UEFILDR][FREELDR] Some x64 ABI violations and memory map fixes (#8668) * [UEFILDR][FREELDR] Don't let LoaderPangesSpanned span half of mem space * [FREELDR][UEFILDR] Fix x64 ABI Violations --- .../freeldr/freeldr/arch/uefi/amd64/uefiasm.S | 19 ++++++++++++++++++- boot/freeldr/freeldr/arch/uefi/uefildr.c | 2 ++ boot/freeldr/freeldr/arch/uefi/uefimem.c | 11 ----------- boot/freeldr/freeldr/ntldr/wlmemory.c | 7 +++++++ 4 files changed, 27 insertions(+), 12 deletions(-) diff --git a/boot/freeldr/freeldr/arch/uefi/amd64/uefiasm.S b/boot/freeldr/freeldr/arch/uefi/amd64/uefiasm.S index c4cd78d1e0b..6da8464f036 100644 --- a/boot/freeldr/freeldr/arch/uefi/amd64/uefiasm.S +++ b/boot/freeldr/freeldr/arch/uefi/amd64/uefiasm.S @@ -32,6 +32,14 @@ _exituefi: xor rbp, rbp mov rsp, qword ptr UefiServiceStack[rip] + /* + * Maintain the MS x64 ABI for calls into C/firmware: + * - 16-byte alignment at call site + * - 32-byte shadow space reserved by the caller + */ + and rsp, -16 + sub rsp, HEX(20) + /* Call the entry routine, passing the parameters */ mov rax, UefiExitBootServices[rip] call rax @@ -57,9 +65,18 @@ _exituefi: // void _changestack(VOID) PUBLIC _changestack _changestack: + /* Preserve the current stack pointer as an argument */ mov rax, rsp + + /* Switch to the basic stack top */ mov rsp, BasicStack[rip] - push rax + + /* Ensure proper MS x64 ABI alignment and shadow space */ + and rsp, -16 + sub rsp, HEX(20) + + /* ExecuteLoaderCleanly(PVOID PreviousStack) */ + mov rcx, rax call ExecuteLoaderCleanly[rip] ret diff --git a/boot/freeldr/freeldr/arch/uefi/uefildr.c b/boot/freeldr/freeldr/arch/uefi/uefildr.c index 08f7efc3ec0..52f7711b513 100644 --- a/boot/freeldr/freeldr/arch/uefi/uefildr.c +++ b/boot/freeldr/freeldr/arch/uefi/uefildr.c @@ -82,6 +82,7 @@ Quit: return 0; } +DECLSPEC_NORETURN void ExecuteLoaderCleanly(PVOID PreviousStack) { @@ -89,6 +90,7 @@ ExecuteLoaderCleanly(PVOID PreviousStack) UefiServiceStack = PreviousStack; RunLoader(); + Reboot(); UNREACHABLE; } diff --git a/boot/freeldr/freeldr/arch/uefi/uefimem.c b/boot/freeldr/freeldr/arch/uefi/uefimem.c index 00da46a155f..cbaf3c6b885 100644 --- a/boot/freeldr/freeldr/arch/uefi/uefimem.c +++ b/boot/freeldr/freeldr/arch/uefi/uefimem.c @@ -27,7 +27,6 @@ AddMemoryDescriptor( /* GLOBALS *******************************************************************/ -extern ULONG LoaderPagesSpanned; extern EFI_SYSTEM_TABLE* GlobalSystemTable; extern EFI_HANDLE GlobalImageHandle; @@ -215,16 +214,6 @@ UefiMemGetMemoryMap(ULONG *MemoryMapSize) } } - /* Sometimes our loader can be loaded into higher memory than we ever allocate */ - if (MemoryType == LoaderLoadedProgram) - { - if (((MapEntry->PhysicalStart + (MapEntry->NumberOfPages * PAGE_SIZE)) >> EFI_PAGE_SHIFT) > LoaderPagesSpanned) - { - /* This value needs to be adjusted if this occurs */ - LoaderPagesSpanned = ((MapEntry->PhysicalStart + (MapEntry->NumberOfPages * PAGE_SIZE)) >> EFI_PAGE_SHIFT); - } - } - /* We really don't want to touch these reserved spots at all */ if (MemoryType != LoaderReserve) { diff --git a/boot/freeldr/freeldr/ntldr/wlmemory.c b/boot/freeldr/freeldr/ntldr/wlmemory.c index 1be38e97864..9bd32bdf324 100644 --- a/boot/freeldr/freeldr/ntldr/wlmemory.c +++ b/boot/freeldr/freeldr/ntldr/wlmemory.c @@ -326,6 +326,13 @@ WinLdrSetupMemoryLayout(IN OUT PLOADER_PARAMETER_BLOCK LoaderBlock) WinLdrpDumpMemoryDescriptors(LoaderBlock); //FIXME: Delete! +#ifdef UEFIBOOT + extern PVOID OsLoaderBase; + extern SIZE_T OsLoaderSize; + /* UEFILDR can be above the 2GB-ish range, we don't want to map the whole area */ + Status = MempSetupPaging((ULONG_PTR)OsLoaderBase / PAGE_SIZE, OsLoaderSize / PAGE_SIZE, FALSE); +#endif + // Map our loader image, so we can continue running /*Status = MempSetupPaging(OsLoaderBase >> MM_PAGE_SHIFT, OsLoaderSize >> MM_PAGE_SHIFT); if (!Status)