Skip to content

Commit

Permalink
[UEFI][ENVIRON] 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
Implement UEFI keystrokes
leave UEFI environment correctly and pass boot
  • Loading branch information
DarkFire01 committed May 4, 2023
1 parent df72bcd commit 370f7e8
Show file tree
Hide file tree
Showing 12 changed files with 460 additions and 22 deletions.
46 changes: 46 additions & 0 deletions boot/freeldr/freeldr/arch/uefi/arch/amd64/uefiasm.S
@@ -0,0 +1,46 @@
/*
* 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>

.code64
EXTERN UefiExitToKernel:PROC
EXTERN EndofExitStack:QWORD
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
84 changes: 84 additions & 0 deletions boot/freeldr/freeldr/arch/uefi/arch/i386/uefiasm.S
@@ -0,0 +1,84 @@
/*
* 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>

.code32
PUBLIC _gdtptr
PUBLIC _i386idtptr
EXTERN _i386Idt:DWORD
EXTERN _EndofExitStack:DWORD
EXTERN _UefiExitToKernel:PROC

// VOID _LeaveUEFIStack(VOID);
PUBLIC __LeaveUEFIStack
__LeaveUEFIStack:
#ifdef _USE_ML
lgdt fword ptr _gdtptr
lidt fword ptr ds:[_i386idtptr]
#else
lgdt cs:_gdtptr
lidt _i386idtptr
#endif
mov esp, _EndofExitStack
call _UefiExitToKernel

// void __reloadsegment(VOID)
PUBLIC __reloadsegment
__reloadsegment:
mov ax, PMODE_DS
mov ds, ax
mov es, ax
mov fs, ax
mov gs, ax
mov ss, ax
nop
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
18 changes: 0 additions & 18 deletions boot/freeldr/freeldr/arch/uefi/stubs.c
Expand Up @@ -50,30 +50,12 @@ UefiGetExtendedBIOSData(PULONG ExtendedBIOSDataArea,

}

PCONFIGURATION_COMPONENT_DATA
UefiHwDetect(VOID)
{
return 0;
}

VOID
UefiPcBeep(VOID)
{
/* Not possible on UEFI, for now */
}

BOOLEAN
UefiConsKbHit(VOID)
{
return FALSE;
}

int
UefiConsGetCh(void)
{
return 0;
}

VOID
UefiHwIdle(VOID)
{
Expand Down
71 changes: 71 additions & 0 deletions boot/freeldr/freeldr/arch/uefi/ueficon.c
Expand Up @@ -16,6 +16,8 @@ extern EFI_SYSTEM_TABLE* GlobalSystemTable;
static unsigned CurrentCursorX = 0;
static unsigned CurrentCursorY = 0;
static unsigned CurrentAttr = 0x0f;
static EFI_INPUT_KEY Key;
static BOOLEAN scancode;

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

Expand Down Expand Up @@ -59,3 +61,72 @@ UefiConsPutChar(int c)
CurrentCursorY++;
}
}

/* Read into the public Keystroke handler */
BOOLEAN
UefiConsKbHit(VOID)
{
Key.UnicodeChar = 0;
Key.ScanCode = 0;
GlobalSystemTable->ConIn->ReadKeyStroke(GlobalSystemTable->ConIn, &Key);

if (Key.UnicodeChar != 0)
{
scancode = FALSE;
return TRUE;
}
else if (Key.ScanCode != 0)
{
scancode = TRUE;
return TRUE;
}

return FALSE;
}

int
UefiConsGetCh(void)
{
/* The UEFI Scan codes are in an entirely different order than BIOS. */
if (scancode)
{
switch (Key.ScanCode)
{
case SCAN_UP:
return KEY_UP;
case SCAN_DOWN:
return KEY_DOWN;
case SCAN_RIGHT:
return KEY_RIGHT;
case SCAN_LEFT:
return KEY_LEFT;
case SCAN_F1:
return KEY_F1;
case SCAN_F2:
return KEY_F2;
case SCAN_F3:
return KEY_F3;
case SCAN_F4:
return KEY_F4;
case SCAN_F5:
return KEY_F5;
case SCAN_F6:
return KEY_F6;
case SCAN_F7:
return KEY_F7;
case SCAN_F8:
return KEY_F8;
case SCAN_F9:
return KEY_F9;
case SCAN_F10:
return KEY_F10;
case SCAN_ESC:
return KEY_ESC;
}
return Key.ScanCode;
}
else
{
return Key.UnicodeChar;
}
}
151 changes: 151 additions & 0 deletions boot/freeldr/freeldr/arch/uefi/uefihw.c
@@ -0,0 +1,151 @@
/*
* 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)
{
UINT32 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(EFI_GUID)))
{
rsdp = (RSDP_DESCRIPTOR*)GlobalSystemTable->ConfigurationTable[i].VendorTable;
break;
}
}

return rsdp;
}

static
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 */
FldrCreateSystemKey(&SystemKey);
#if defined(_M_IX86) || defined(_M_AMD64) /* Taken from Windows 11 */
FldrSetIdentifier(SystemKey, "AT/AT COMPATIBLE");
#elif defined(_M_IA64) /* Taken from Windows XP 64-bit*/
FldrSetIdentifier(SystemKey, "Intel Itanium processor family");
#elif defined(_M_ARM) || defined(_M_ARM64) /* Taken from Windows RT/11 */
FldrSetIdentifier(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 370f7e8

Please sign in to comment.