diff --git a/boot/freeldr/freeldr/arch/uefi/arch/amd64/uefiasm.S b/boot/freeldr/freeldr/arch/uefi/arch/amd64/uefiasm.S new file mode 100644 index 0000000000000..f5b68626f228c --- /dev/null +++ b/boot/freeldr/freeldr/arch/uefi/arch/amd64/uefiasm.S @@ -0,0 +1,47 @@ +/* + * PROJECT: FreeLoader UEFI Support + * LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later) + * PURPOSE: UEFI assembly exit code + * COPYRIGHT: Copyright 2023 Justin Miller + */ + +#include +#include +#include + +EXTERN UefiExitToKernel:PROC +EXTERN EndofExitStack:QWORD + +.code64 +PUBLIC gdtptr + +.align 8 +gdt: + .word HEX(0000), HEX(0000), HEX(0000), HEX(0000) /* 00: NULL descriptor */ + .word HEX(0000), HEX(0000), HEX(0000), HEX(0000) /* 08: */ + .word HEX(0000), HEX(0000), HEX(9800), HEX(0020) /* 10: long mode CS */ + .word HEX(FFFF), HEX(0000), HEX(F300), HEX(00CF) /* 18: long mode DS */ + .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 */ + +/* GDT table pointer */ +gdtptr: + .word HEX(37) /* Limit */ +#ifdef _USE_ML + .quad gdt /* Base Address */ +#else + .long gdt, 0 /* Base Address */ +#endif + +PUBLIC __ExitUefi +__ExitUefi: +#ifdef _USE_ML + lgdt fword ptr gdtptr +#else + lgdt cs:gdtptr +#endif + mov rsp, EndofExitStack + call UefiExitToKernel + hlt +END diff --git a/boot/freeldr/freeldr/arch/uefi/arch/i386/uefiasm.S b/boot/freeldr/freeldr/arch/uefi/arch/i386/uefiasm.S new file mode 100644 index 0000000000000..c9a0e7c276e1b --- /dev/null +++ b/boot/freeldr/freeldr/arch/uefi/arch/i386/uefiasm.S @@ -0,0 +1,73 @@ +/* + * PROJECT: FreeLoader UEFI Support + * LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later) + * PURPOSE: UEFI assembly exit code + * COPYRIGHT: Copyright 2023 Justin Miller + */ + +#include +#include +#include + +EXTERN _i386Idt:DWORD +EXTERN _EndofExitStack:DWORD +EXTERN _UefiExitToKernel:PROC + +.code32 +PUBLIC _gdtptr +PUBLIC _i386idtptr + +// VOID _LeaveUEFIStack(VOID); +PUBLIC __ExitUefi +__ExitUefi: +#ifdef _USE_ML + lgdt fword ptr _gdtptr + lidt fword ptr ds:[_i386idtptr] +#else + lgdt cs:_gdtptr + lidt _i386idtptr +#endif + mov esp, _EndofExitStack + call _UefiExitToKernel + + .align 4 /* force 4-byte alignment */ +gdt: + /* NULL Descriptor */ + .word HEX(0000) + .word HEX(0000) + .word HEX(0000) + .word HEX(0000) + + /* 32-bit flat CS */ + .word HEX(FFFF) + .word HEX(0000) + .word HEX(9A00) + .word HEX(00CF) + + /* 32-bit flat DS */ + .word HEX(FFFF) + .word HEX(0000) + .word HEX(9200) + .word HEX(00CF) + + /* 16-bit real mode CS */ + .word HEX(FFFF) + .word HEX(0000) + .word HEX(9E00) + .word HEX(0000) + + /* 16-bit real mode DS */ + .word HEX(FFFF) + .word HEX(0000) + .word HEX(9200) + .word HEX(0000) + +/* GDT table pointer */ +_gdtptr: + .word HEX(27) /* Limit */ + .long gdt, 0 /* Base Address */ + +_i386idtptr: + .word 255 /* Limit */ + .long _i386Idt /* Base Address */ +END diff --git a/boot/freeldr/freeldr/arch/uefi/stubs.c b/boot/freeldr/freeldr/arch/uefi/stubs.c index ac5cebab51cdb..e9263d60ba3df 100644 --- a/boot/freeldr/freeldr/arch/uefi/stubs.c +++ b/boot/freeldr/freeldr/arch/uefi/stubs.c @@ -43,12 +43,6 @@ UefiGetExtendedBIOSData(PULONG ExtendedBIOSDataArea, } -PCONFIGURATION_COMPONENT_DATA -UefiHwDetect(VOID) -{ - return 0; -} - VOID UefiPcBeep(VOID) { diff --git a/boot/freeldr/freeldr/arch/uefi/uefihw.c b/boot/freeldr/freeldr/arch/uefi/uefihw.c new file mode 100644 index 0000000000000..8e7589c7dce9a --- /dev/null +++ b/boot/freeldr/freeldr/arch/uefi/uefihw.c @@ -0,0 +1,149 @@ +/* + * PROJECT: FreeLoader UEFI Support + * LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later) + * PURPOSE: Hardware detection routines + * COPYRIGHT: Copyright 2022 Justin Miller + */ + +/* INCLUDES ******************************************************************/ + +#include + +#include +DBG_DEFAULT_CHANNEL(WARNING); + +/* GLOBALS *******************************************************************/ + +extern EFI_SYSTEM_TABLE * GlobalSystemTable; +extern EFI_HANDLE GlobalImageHandle; +extern UCHAR PcBiosDiskCount; +extern EFI_MEMORY_DESCRIPTOR* EfiMemoryMap; +extern UINT32 FreeldrDescCount; + +BOOLEAN AcpiPresent = FALSE; + +/* FUNCTIONS *****************************************************************/ + +static +PRSDP_DESCRIPTOR +FindAcpiBios(VOID) +{ + UINTN i; + RSDP_DESCRIPTOR* rsdp = NULL; + EFI_GUID acpi2_guid = EFI_ACPI_20_TABLE_GUID; + + for (i = 0; i < GlobalSystemTable->NumberOfTableEntries; i++) + { + if (!memcmp(&GlobalSystemTable->ConfigurationTable[i].VendorGuid, &acpi2_guid, sizeof(acpi2_guid))) + { + rsdp = (RSDP_DESCRIPTOR*)GlobalSystemTable->ConfigurationTable[i].VendorTable; + break; + } + } + + return rsdp; +} + +VOID +DetectAcpiBios(PCONFIGURATION_COMPONENT_DATA SystemKey, ULONG *BusNumber) +{ + PCONFIGURATION_COMPONENT_DATA BiosKey; + PCM_PARTIAL_RESOURCE_LIST PartialResourceList; + PCM_PARTIAL_RESOURCE_DESCRIPTOR PartialDescriptor; + PRSDP_DESCRIPTOR Rsdp; + PACPI_BIOS_DATA AcpiBiosData; + ULONG TableSize; + + Rsdp = FindAcpiBios(); + + if (Rsdp) + { + /* Set up the flag in the loader block */ + AcpiPresent = TRUE; + + /* Calculate the table size */ + TableSize = FreeldrDescCount * sizeof(BIOS_MEMORY_MAP) + + sizeof(ACPI_BIOS_DATA) - sizeof(BIOS_MEMORY_MAP); + + /* Set 'Configuration Data' value */ + PartialResourceList = FrLdrHeapAlloc(sizeof(CM_PARTIAL_RESOURCE_LIST) + + TableSize, TAG_HW_RESOURCE_LIST); + if (PartialResourceList == NULL) + { + ERR("Failed to allocate resource descriptor\n"); + return; + } + + RtlZeroMemory(PartialResourceList, sizeof(CM_PARTIAL_RESOURCE_LIST) + TableSize); + PartialResourceList->Version = 0; + PartialResourceList->Revision = 0; + PartialResourceList->Count = 1; + + PartialDescriptor = &PartialResourceList->PartialDescriptors[0]; + PartialDescriptor->Type = CmResourceTypeDeviceSpecific; + PartialDescriptor->ShareDisposition = CmResourceShareUndetermined; + PartialDescriptor->u.DeviceSpecificData.DataSize = TableSize; + + /* Fill the table */ + AcpiBiosData = (PACPI_BIOS_DATA)&PartialResourceList->PartialDescriptors[1]; + + if (Rsdp->revision > 0) + { + TRACE("ACPI >1.0, using XSDT address\n"); + AcpiBiosData->RSDTAddress.QuadPart = Rsdp->xsdt_physical_address; + } + else + { + TRACE("ACPI 1.0, using RSDT address\n"); + AcpiBiosData->RSDTAddress.LowPart = Rsdp->rsdt_physical_address; + } + + AcpiBiosData->Count = FreeldrDescCount; + memcpy(AcpiBiosData->MemoryMap, EfiMemoryMap, + FreeldrDescCount * sizeof(BIOS_MEMORY_MAP)); + + TRACE("RSDT %p, data size %x\n", Rsdp->rsdt_physical_address, + TableSize); + + /* Create new bus key */ + FldrCreateComponentKey(SystemKey, + AdapterClass, + MultiFunctionAdapter, + 0x0, + 0x0, + 0xFFFFFFFF, + "ACPI BIOS", + PartialResourceList, + sizeof(CM_PARTIAL_RESOURCE_LIST) + TableSize, + &BiosKey); + + /* Increment bus number */ + (*BusNumber)++; + } +} + +PCONFIGURATION_COMPONENT_DATA +UefiHwDetect(VOID) +{ + PCONFIGURATION_COMPONENT_DATA SystemKey; + ULONG BusNumber = 0; + + TRACE("DetectHardware()\n"); + + /* Create the 'System' key */ +#if defined(_M_IX86) || defined(_M_AMD64) /* Taken from Windows 11 */ + FldrCreateSystemKey(&SystemKey, "AT/AT COMPATIBLE"); +#elif defined(_M_IA64) /* Taken from Windows XP 64-bit*/ + FldrCreateSystemKey(&SystemKey, "Intel Itanium processor family"); +#elif defined(_M_ARM) || defined(_M_ARM64) /* Taken from Windows RT/11 */ + FldrCreateSystemKey(&SystemKey, "ARM processor family"); +#else + #error Please define a system key for your architecture +#endif + + /* Detect ACPI */ + DetectAcpiBios(SystemKey, &BusNumber); + + TRACE("DetectHardware() Done\n"); + return SystemKey; +} diff --git a/boot/freeldr/freeldr/arch/uefi/uefimem.c b/boot/freeldr/freeldr/arch/uefi/uefimem.c index 03a62150ef966..68df64099c09e 100644 --- a/boot/freeldr/freeldr/arch/uefi/uefimem.c +++ b/boot/freeldr/freeldr/arch/uefi/uefimem.c @@ -27,6 +27,7 @@ AddMemoryDescriptor( /* GLOBALS *******************************************************************/ +extern ULONG LoaderPagesSpanned; extern EFI_SYSTEM_TABLE* GlobalSystemTable; extern EFI_HANDLE GlobalImageHandle; extern REACTOS_INTERNAL_BGCONTEXT framebufferData; @@ -256,6 +257,16 @@ UefiMemGetMemoryMap(ULONG *MemoryMapSize) } } + /* Sometimes our loader can be loaded into higher memory than we ever allocate */ + if (MemoryType == LoaderLoadedProgram) + { + if ((MapEntry->PhysicalStart / EFI_PAGE_SIZE) > LoaderPagesSpanned) + { + /* This value needs to be adjusted if this occurs */ + LoaderPagesSpanned = (MapEntry->PhysicalStart / EFI_PAGE_SIZE); + } + } + UefiSetMemory(FreeldrMem, MapEntry->PhysicalStart, MapEntry->NumberOfPages, diff --git a/boot/freeldr/freeldr/arch/uefi/uefisetup.c b/boot/freeldr/freeldr/arch/uefi/uefisetup.c index 01d1be758a1b0..ec3b0d405a6c6 100644 --- a/boot/freeldr/freeldr/arch/uefi/uefisetup.c +++ b/boot/freeldr/freeldr/arch/uefi/uefisetup.c @@ -14,7 +14,6 @@ DBG_DEFAULT_CHANNEL(WARNING); extern EFI_SYSTEM_TABLE* GlobalSystemTable; extern EFI_HANDLE GlobalImageHandle; -BOOLEAN AcpiPresent = FALSE; /* FUNCTIONS ******************************************************************/ diff --git a/boot/freeldr/freeldr/lib/mm/meminit.c b/boot/freeldr/freeldr/lib/mm/meminit.c index aacccda480004..c60e0edb5fb58 100644 --- a/boot/freeldr/freeldr/lib/mm/meminit.c +++ b/boot/freeldr/freeldr/lib/mm/meminit.c @@ -440,7 +440,7 @@ PVOID MmFindLocationForPageLookupTable(PFN_NUMBER TotalPageCount) if (MemoryDescriptor->BasePage < CandidateBasePage) continue; // Continue, if the address is too high - if (MemoryDescriptor->BasePage + RequiredPages >= MM_MAX_PAGE_LOADER) continue; + if (MemoryDescriptor->BasePage + RequiredPages >= TotalPageCount) continue; // Memory block is more suitable than the previous one CandidateBasePage = MemoryDescriptor->BasePage; @@ -449,7 +449,7 @@ PVOID MmFindLocationForPageLookupTable(PFN_NUMBER TotalPageCount) // Calculate the end address for the lookup table PageLookupTableEndPage = min(CandidateBasePage + CandidatePageCount, - MM_MAX_PAGE_LOADER); + TotalPageCount); // Calculate the virtual address PageLookupTableMemAddress = (PVOID)((PageLookupTableEndPage * PAGE_SIZE) diff --git a/boot/freeldr/freeldr/ntldr/arch/amd64/winldr.c b/boot/freeldr/freeldr/ntldr/arch/amd64/winldr.c index 5c8043728442c..5a357468f81cd 100644 --- a/boot/freeldr/freeldr/ntldr/arch/amd64/winldr.c +++ b/boot/freeldr/freeldr/ntldr/arch/amd64/winldr.c @@ -429,3 +429,29 @@ VOID MempDump(VOID) { } + +#ifdef UEFIBOOT +PLOADER_PARAMETER_BLOCK PubLoaderBlockVA; +KERNEL_ENTRY_POINT PubKiSystemStartup; + +extern ULONG LoaderPagesSpanned; + +void __ExitUefi(VOID); + +VOID +WinldrFinalizeBoot( + PLOADER_PARAMETER_BLOCK LoaderBlockVA, + KERNEL_ENTRY_POINT KiSystemStartup) +{ + TRACE("Preparing to jump to kernel\n"); + PubLoaderBlockVA = LoaderBlockVA; + PubKiSystemStartup = KiSystemStartup; + __ExitUefi(); +} + +VOID +UefiExitToKernel(VOID) +{ + WinLdrExitToNtoskrnl(PubLoaderBlockVA, PubKiSystemStartup); +} +#endif diff --git a/boot/freeldr/freeldr/ntldr/arch/i386/winldr.c b/boot/freeldr/freeldr/ntldr/arch/i386/winldr.c index ec91b7313a159..b22f7cbf8246f 100644 --- a/boot/freeldr/freeldr/ntldr/arch/i386/winldr.c +++ b/boot/freeldr/freeldr/ntldr/arch/i386/winldr.c @@ -744,3 +744,30 @@ MempDump(VOID) } } #endif + +#ifdef UEFIBOOT +PLOADER_PARAMETER_BLOCK PubLoaderBlockVA; +KERNEL_ENTRY_POINT PubKiSystemStartup; + +extern ULONG LoaderPagesSpanned; + +VOID _ExitUefi(VOID); + +VOID +WinldrFinalizeBoot( + PLOADER_PARAMETER_BLOCK LoaderBlockVA, + KERNEL_ENTRY_POINT KiSystemStartup) +{ + TRACE("Preparing to jump to kernel\n"); + PubLoaderBlockVA = LoaderBlockVA; + PubKiSystemStartup = KiSystemStartup; + _ExitUefi(); +} + +VOID +UefiExitToKernel(VOID) +{ + WinLdrExitToNtoskrnl(PubLoaderBlockVA, PubKiSystemStartup); +} + +#endif diff --git a/boot/freeldr/freeldr/ntldr/winldr.c b/boot/freeldr/freeldr/ntldr/winldr.c index 9f51a5417218b..857f01874216f 100644 --- a/boot/freeldr/freeldr/ntldr/winldr.c +++ b/boot/freeldr/freeldr/ntldr/winldr.c @@ -1238,11 +1238,25 @@ LoadAndBootWindowsCommon( /* Map pages and create memory descriptors */ WinLdrSetupMemoryLayout(LoaderBlock); +#ifdef UEFIBOOT + WinldrFinalizeBoot(LoaderBlockVA, KiSystemStartup); +#endif + + /* Unify UEFI and BIOS back to the same exit point */ + WinLdrExitToNtoskrnl(LoaderBlockVA, KiSystemStartup); + + UNREACHABLE; // return ESUCCESS; +} + +VOID +WinLdrExitToNtoskrnl(PLOADER_PARAMETER_BLOCK LoaderBlockVA, + KERNEL_ENTRY_POINT KiSystemStartup) +{ /* Set processor context */ WinLdrSetProcessorContext(); - /* Save final value of LoaderPagesSpanned */ - LoaderBlock->Extension->LoaderPagesSpanned = LoaderPagesSpanned; + /* Save final value of LoaderPagesSpanned */ + LoaderBlockVA->Extension->LoaderPagesSpanned = LoaderPagesSpanned; TRACE("Hello from paged mode, KiSystemStartup %p, LoaderBlockVA %p!\n", KiSystemStartup, LoaderBlockVA); @@ -1258,8 +1272,6 @@ LoadAndBootWindowsCommon( /* Pass control */ (*KiSystemStartup)(LoaderBlockVA); - - UNREACHABLE; // return ESUCCESS; } VOID diff --git a/boot/freeldr/freeldr/ntldr/winldr.h b/boot/freeldr/freeldr/ntldr/winldr.h index 20a20ba7cce02..963876c3d03c0 100644 --- a/boot/freeldr/freeldr/ntldr/winldr.h +++ b/boot/freeldr/freeldr/ntldr/winldr.h @@ -172,6 +172,14 @@ MempSetupPaging(IN PFN_NUMBER StartPage, IN PFN_NUMBER NumberOfPages, IN BOOLEAN KernelMapping); +VOID +WinldrFinalizeBoot(PLOADER_PARAMETER_BLOCK LoaderBlockVA, + KERNEL_ENTRY_POINT KiSystemStartup); + +VOID +WinLdrExitToNtoskrnl(PLOADER_PARAMETER_BLOCK LoaderBlockVA, + KERNEL_ENTRY_POINT KiSystemStartup); + VOID MempUnmapPage(PFN_NUMBER Page); diff --git a/boot/freeldr/freeldr/uefi.cmake b/boot/freeldr/freeldr/uefi.cmake index 76483f0529ef2..7ce9cda354960 100644 --- a/boot/freeldr/freeldr/uefi.cmake +++ b/boot/freeldr/freeldr/uefi.cmake @@ -16,6 +16,7 @@ list(APPEND UEFILDR_ARC_SOURCE arch/uefi/stubs.c arch/uefi/ueficon.c arch/uefi/uefidisk.c + arch/uefi/uefihw.c arch/uefi/uefimem.c arch/uefi/uefisetup.c arch/uefi/uefiutil.c @@ -24,10 +25,13 @@ list(APPEND UEFILDR_ARC_SOURCE if(ARCH STREQUAL "i386") list(APPEND UEFILDR_COMMON_ASM_SOURCE - arch/i386/i386trap.S) - + arch/i386/i386trap.S + arch/uefi/arch/i386/uefiasm.S) + list(APPEND UEFILDR_ARC_SOURCE + arch/i386/i386idt.c) elseif(ARCH STREQUAL "amd64") - #TBD + list(APPEND UEFILDR_COMMON_ASM_SOURCE + arch/uefi/arch/amd64/uefiasm.S) elseif(ARCH STREQUAL "arm") list(APPEND UEFILDR_ARC_SOURCE arch/arm/macharm.c