Skip to content

Commit

Permalink
[UEFI] Enable UEFI boot for i386 and amd64
Browse files Browse the repository at this point in the history
Add some some small fixes found during testing
leave UEFI environment correctly and pass boot
  • Loading branch information
DarkFire01 committed Jul 18, 2023
1 parent e505394 commit 051597b
Show file tree
Hide file tree
Showing 12 changed files with 366 additions and 16 deletions.
47 changes: 47 additions & 0 deletions 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 <justinmiller100@gmail.com>
*/

#include <asm.inc>
#include <arch/pc/x86common.h>
#include <arch/pc/pcbios.h>

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
73 changes: 73 additions & 0 deletions 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 <justinmiller100@gmail.com>
*/

#include <asm.inc>
#include <arch/pc/x86common.h>
#include <arch/pc/pcbios.h>

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
6 changes: 0 additions & 6 deletions boot/freeldr/freeldr/arch/uefi/stubs.c
Expand Up @@ -43,12 +43,6 @@ UefiGetExtendedBIOSData(PULONG ExtendedBIOSDataArea,

}

PCONFIGURATION_COMPONENT_DATA
UefiHwDetect(VOID)
{
return 0;
}

VOID
UefiPcBeep(VOID)
{
Expand Down
149 changes: 149 additions & 0 deletions 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 <justinmiller100@gmail.com>
*/

/* INCLUDES ******************************************************************/

#include <uefildr.h>

#include <debug.h>
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;
}
11 changes: 11 additions & 0 deletions boot/freeldr/freeldr/arch/uefi/uefimem.c
Expand Up @@ -27,6 +27,7 @@ AddMemoryDescriptor(

/* GLOBALS *******************************************************************/

extern ULONG LoaderPagesSpanned;
extern EFI_SYSTEM_TABLE* GlobalSystemTable;
extern EFI_HANDLE GlobalImageHandle;
extern REACTOS_INTERNAL_BGCONTEXT framebufferData;
Expand Down Expand Up @@ -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,
Expand Down
1 change: 0 additions & 1 deletion boot/freeldr/freeldr/arch/uefi/uefisetup.c
Expand Up @@ -14,7 +14,6 @@ DBG_DEFAULT_CHANNEL(WARNING);

extern EFI_SYSTEM_TABLE* GlobalSystemTable;
extern EFI_HANDLE GlobalImageHandle;
BOOLEAN AcpiPresent = FALSE;

/* FUNCTIONS ******************************************************************/

Expand Down
4 changes: 2 additions & 2 deletions boot/freeldr/freeldr/lib/mm/meminit.c
Expand Up @@ -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;
Expand All @@ -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)
Expand Down
26 changes: 26 additions & 0 deletions boot/freeldr/freeldr/ntldr/arch/amd64/winldr.c
Expand Up @@ -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
27 changes: 27 additions & 0 deletions boot/freeldr/freeldr/ntldr/arch/i386/winldr.c
Expand Up @@ -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

0 comments on commit 051597b

Please sign in to comment.