Skip to content

Commit

Permalink
[FREELDR] Enable UEFI boot for i386 and amd64
Browse files Browse the repository at this point in the history
Co-authored-by: Stanislav Motylkov <x86corez@gmail.com>
Co-authored-by: Hermès BÉLUSCA - MAÏTO <hermes.belusca-maito@reactos.org>
  • Loading branch information
3 people committed Oct 11, 2023
1 parent 0c164f0 commit de0ca39
Show file tree
Hide file tree
Showing 9 changed files with 435 additions and 65 deletions.
85 changes: 85 additions & 0 deletions boot/freeldr/freeldr/arch/uefi/amd64/uefiasm.S
@@ -0,0 +1,85 @@
/*
* PROJECT: FreeLoader UEFI Support
* LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later)
* PURPOSE: x64 assembly UEFI escape helper functions
* COPYRIGHT: Copyright 2023 Justin Miller <justinmiller100@gmail.com>
*/

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

EXTERN UefiServiceStack:QWORD
EXTERN BasicStack:QWORD
EXTERN ExecuteLoaderCleanly:PROC
EXTERN UefiExitBootServices:PROC

.code64

// void _exituefi(VOID)
PUBLIC _exituefi
_exituefi:
/* Save non-volatile registers */
push rbp
push rsi
push rdi
push rbx

/* Save the old stack */
mov rbx, rsp

/* Load the new stack */
xor rbp, rbp
mov rsp, qword ptr UefiServiceStack[rip]

/* Call the entry routine, passing the parameters */
mov rax, UefiExitBootServices[rip]
call rax

/* Retore old stack */
mov rsp, rbx

/* Retore non-volatiles */
pop rbx
pop rdi
pop rsi
pop rbp

#ifdef _USE_ML
lgdt fword ptr [_gdtptr]
#else
lgdt cs:[_gdtptr][rip] /* GAS isn't my friend - avoid letting it generate absolute addressing */
#endif

/* All done */
ret

// void _changestack(VOID)
PUBLIC _changestack
_changestack:
mov rax, rsp
mov rsp, BasicStack[rip]
push rax
call ExecuteLoaderCleanly[rip]
ret

.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
.quad gdt, 0 /* Base Address */
#endif

END
109 changes: 109 additions & 0 deletions boot/freeldr/freeldr/arch/uefi/i386/uefiasm.S
@@ -0,0 +1,109 @@
/*
* PROJECT: FreeLoader UEFI Support
* LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later)
* PURPOSE: i386 assembly UEFI escape helper functions
* COPYRIGHT: Copyright 2023 Justin Miller <justinmiller100@gmail.com>
*/

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

PUBLIC _gdtptr
PUBLIC _i386idtptr
PUBLIC __changestack
EXTERN _UefiServiceStack:DWORD
EXTERN _i386Idt:DWORD
EXTERN _ExecuteLoaderCleanly:PROC
EXTERN _UefiExitBootServices:PROC
EXTERN _BasicStack:DWORD
.code32

// void __exituefi(VOID)
PUBLIC __exituefi
__exituefi:
push ebp
push esi
push edi
push ebx

/* Save the old stack */
mov ebx, esp

/* Load the new stack */
xor ebp, ebp
mov esp, _UefiServiceStack

/* Call the entry routine, passing the parameters */
call _UefiExitBootServices

/* Retore old stack */
mov esp, ebx

/* Retore non-volatiles */
pop ebx
pop edi
pop esi
pop ebp

#ifdef _USE_ML
lidt fword ptr ds:[_i386idtptr]
lgdt fword ptr [_gdtptr]
#else
lgdt cs:[_gdtptr]
lidt _i386idtptr
#endif

/* All done */
ret

// void __reloadsegment(VOID)
PUBLIC __changestack
__changestack:
mov eax, esp
mov esp, _BasicStack
push eax
call _ExecuteLoaderCleanly
ret

.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
1 change: 0 additions & 1 deletion boot/freeldr/freeldr/arch/uefi/ueficon.c
Expand Up @@ -138,6 +138,5 @@ UefiConsGetCh(VOID)
/* UEFI will stack input requests, we have to clear it */
Key.UnicodeChar = 0;
Key.ScanCode = 0;
GlobalSystemTable->ConIn->Reset(GlobalSystemTable->ConIn, FALSE);
return KeyOutput;
}
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)
FldrCreateSystemKey(&SystemKey, "AT/AT COMPATIBLE");
#elif defined(_M_IA64)
FldrCreateSystemKey(&SystemKey, "Intel Itanium processor family");
#elif defined(_M_ARM) || defined(_M_ARM64)
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;
}

0 comments on commit de0ca39

Please sign in to comment.