diff --git a/common/entry.s3.c b/common/entry.s3.c index 56559a28..12fe8d62 100644 --- a/common/entry.s3.c +++ b/common/entry.s3.c @@ -28,6 +28,8 @@ void stage3_common(void); #if defined (UEFI) extern symbol __slide; +extern symbol __image_size; +extern symbol _start; noreturn void uefi_entry(EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE *SystemTable) { gST = SystemTable; @@ -37,6 +39,28 @@ noreturn void uefi_entry(EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE *SystemTable) EFI_STATUS status; +#if defined (__x86_64__) + if ((uintptr_t)__slide >= 0x100000000) { + size_t image_size_pages = ALIGN_UP((size_t)__image_size, 4096) / 4096; + size_t new_base; + for (new_base = 0x1000; new_base + image_size_pages < 0x100000000; new_base += 0x1000) { + EFI_PHYSICAL_ADDRESS _new_base = (EFI_PHYSICAL_ADDRESS)new_base; + status = gBS->AllocatePages(AllocateAddress, EfiLoaderData, image_size_pages, &_new_base); + if (status == 0) { + goto new_base_gotten; + } + } + panic(false, "Limine does not support being loaded above 4GiB"); +new_base_gotten: + memcpy((void *)new_base, __slide, (size_t)__image_size); + __attribute__((ms_abi)) + void (*new_entry_point)(EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE *SystemTable); + new_entry_point = (void *)(new_base + ((uintptr_t)_start - (uintptr_t)__slide)); + new_entry_point(ImageHandle, SystemTable); + __builtin_unreachable(); + } +#endif + gST->ConOut->EnableCursor(gST->ConOut, false); init_memmap(); @@ -52,12 +76,6 @@ noreturn void uefi_entry(EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE *SystemTable) init_gdt(); #endif -#if defined (__x86_64__) - if ((uintptr_t)__slide >= 0x100000000) { - panic(false, "Limine does not support being loaded above 4GiB"); - } -#endif - disk_create_index(); boot_volume = NULL;