From b34a1f15df98e348175e9bb21a3ee0ea828d9007 Mon Sep 17 00:00:00 2001 From: Ahmed Arif Date: Thu, 26 Mar 2026 19:36:14 +0100 Subject: [PATCH] [FREELDR:UEFI] Fix amd64 assembly calling convention and GDT reload (#8698) - Fix #GP crash on UEFI x64 boot caused by `call ExecuteLoaderCleanly[rip]` and `mov rax, UefiExitBootServices[rip]; call rax` generating indirect calls that read function code bytes as a pointer. - Reload CS and data segments after `lgdt` to avoid #GP from stale UEFI selectors (e.g. CS=0x38) exceeding the new GDT limit. --- .../freeldr/freeldr/arch/uefi/amd64/uefiasm.S | 40 +++++++++++++++++-- 1 file changed, 36 insertions(+), 4 deletions(-) diff --git a/boot/freeldr/freeldr/arch/uefi/amd64/uefiasm.S b/boot/freeldr/freeldr/arch/uefi/amd64/uefiasm.S index 6da8464f036..869fd4bd537 100644 --- a/boot/freeldr/freeldr/arch/uefi/amd64/uefiasm.S +++ b/boot/freeldr/freeldr/arch/uefi/amd64/uefiasm.S @@ -41,8 +41,7 @@ _exituefi: sub rsp, HEX(20) /* Call the entry routine, passing the parameters */ - mov rax, UefiExitBootServices[rip] - call rax + call UefiExitBootServices /* Retore old stack */ mov rsp, rbx @@ -53,12 +52,44 @@ _exituefi: pop rsi pop rbp + /* + * We are now outside firmware services and about to replace the GDT. + * Keep maskable interrupts disabled during this transition window. + */ + cli + #ifdef _USE_ML lgdt fword ptr [_gdtptr] #else lgdt cs:[_gdtptr][rip] /* GAS isn't my friend - avoid letting it generate absolute addressing */ #endif + /* + * Reload CS with a valid selector from the new GDT. + * The UEFI firmware's CS (e.g. 0x38) may exceed our GDT limit, + * so we must load CS=0x10 (long mode code segment) via far return. + */ +#ifdef _USE_ML + lea rax, [reload_cs] +#else + lea rax, reload_cs[rip] +#endif + push HEX(10) + push rax + .byte HEX(48), HEX(CB) /* retfq */ + +reload_cs: + /* Reload data segments with DS selector 0x18 */ + mov ax, HEX(18) + mov ds, ax + mov es, ax + mov fs, ax + mov gs, ax + + /* SS must use a ring-0 writable data selector */ + mov ax, HEX(28) + mov ss, ax + /* All done */ ret @@ -77,7 +108,7 @@ _changestack: /* ExecuteLoaderCleanly(PVOID PreviousStack) */ mov rcx, rax - call ExecuteLoaderCleanly[rip] + call ExecuteLoaderCleanly ret .align 8 @@ -89,10 +120,11 @@ gdt: .word HEX(FFFF), HEX(0000), HEX(9E00), HEX(0000) /* 20: 16-bit real mode CS */ .word HEX(FFFF), HEX(0000), HEX(9200), HEX(0000) /* 28: 16-bit real mode DS */ .word HEX(FFFF), HEX(0000), HEX(9B00), HEX(00CF) /* 30: compat mode CS */ + .word HEX(0000), HEX(0000), HEX(9800), HEX(0020) /* 38: long mode CS (UEFI selector compatibility) */ /* GDT table pointer */ _gdtptr: - .word HEX(37) /* Limit */ + .word HEX(3F) /* Limit */ #ifdef _USE_ML .quad gdt /* Base Address */ #else