Move XTLDR under boot directory
This commit is contained in:
7
boot/xtldr/modules/CMakeLists.txt
Normal file
7
boot/xtldr/modules/CMakeLists.txt
Normal file
@@ -0,0 +1,7 @@
|
||||
add_subdirectory(acpi)
|
||||
add_subdirectory(beep)
|
||||
add_subdirectory(chainldr)
|
||||
add_subdirectory(dummy)
|
||||
add_subdirectory(framebuf)
|
||||
add_subdirectory(pecoff)
|
||||
add_subdirectory(xtos_o)
|
27
boot/xtldr/modules/acpi/CMakeLists.txt
Normal file
27
boot/xtldr/modules/acpi/CMakeLists.txt
Normal file
@@ -0,0 +1,27 @@
|
||||
# XT Boot Loader ACPI Support Module
|
||||
PROJECT(XTLDR_ACPI)
|
||||
|
||||
# Specify include directories
|
||||
include_directories(
|
||||
${EXECTOS_SOURCE_DIR}/sdk/xtdk
|
||||
${XTLDR_ACPI_SOURCE_DIR}/includes)
|
||||
|
||||
# Specify list of source code files
|
||||
list(APPEND XTLDR_ACPI_SOURCE
|
||||
${XTLDR_ACPI_SOURCE_DIR}/acpi.cc
|
||||
${XTLDR_ACPI_SOURCE_DIR}/data.cc)
|
||||
|
||||
# Link module executable
|
||||
add_executable(acpi ${XTLDR_ACPI_SOURCE})
|
||||
|
||||
# Add linker libraries
|
||||
target_link_libraries(acpi libxtldr libxtos)
|
||||
|
||||
# Set proper binary name and install target
|
||||
set_target_properties(acpi PROPERTIES SUFFIX .efi)
|
||||
set_install_target(acpi efi/boot/xtldr/modules)
|
||||
|
||||
# Set module entrypoint and subsystem
|
||||
set_entrypoint(acpi "XtLdrModuleMain")
|
||||
set_linker_map(acpi TRUE)
|
||||
set_subsystem(acpi efi_boot_service_driver)
|
439
boot/xtldr/modules/acpi/acpi.cc
Normal file
439
boot/xtldr/modules/acpi/acpi.cc
Normal file
@@ -0,0 +1,439 @@
|
||||
/**
|
||||
* PROJECT: ExectOS
|
||||
* COPYRIGHT: See COPYING.md in the top level directory
|
||||
* FILE: xtldr/modules/acpi/acpi.cc
|
||||
* DESCRIPTION: XTLDR ACPI Support Module
|
||||
* DEVELOPERS: Rafal Kupiec <belliash@codingworkshop.eu.org>
|
||||
*/
|
||||
|
||||
#include <acpi.hh>
|
||||
|
||||
|
||||
/* ACPI module information */
|
||||
MODULE_AUTHOR(L"Rafal Kupiec <belliash@codingworkshop.eu.org>");
|
||||
MODULE_DESCRIPTION(L"ACPI support");
|
||||
MODULE_LICENSE(L"GPLv3");
|
||||
MODULE_VERSION(L"0.1");
|
||||
|
||||
|
||||
/**
|
||||
* Attempts to get XSDP. If it is not found or checksum mismatch, it will try to get RSDP instead.
|
||||
*
|
||||
* @param AcpiTable
|
||||
* Suplies a pointer to memory area where XSDP or RSRP address will be stored.
|
||||
*
|
||||
* @return This routine returns a status code.
|
||||
*
|
||||
* @since XT 1.0
|
||||
*/
|
||||
XTCDECL
|
||||
EFI_STATUS
|
||||
Acpi::GetAcpiDescriptionPointer(OUT PVOID *AcpiTable)
|
||||
{
|
||||
PVOID Rsdp;
|
||||
|
||||
/* Try to get XSDP (ACPI 2.0) from system configuration tables */
|
||||
if(GetXsdpTable(&Rsdp) == STATUS_EFI_SUCCESS)
|
||||
{
|
||||
/* XSDP found, return success */
|
||||
*AcpiTable = Rsdp;
|
||||
return STATUS_EFI_SUCCESS;
|
||||
}
|
||||
|
||||
/* Try to get RSDP (ACPI 1.0) from system configuration tables */
|
||||
if(GetRsdpTable(&Rsdp) == STATUS_EFI_SUCCESS)
|
||||
{
|
||||
/* RSDP found, return success */
|
||||
*AcpiTable = Rsdp;
|
||||
return STATUS_EFI_SUCCESS;
|
||||
}
|
||||
|
||||
/* Neither XSDP nor RSDP found */
|
||||
return STATUS_EFI_NOT_FOUND;
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds ACPI description table with given signature.
|
||||
*
|
||||
* @param Signature
|
||||
* Supplies the signature of the desired ACPI table.
|
||||
*
|
||||
* @param PreviousTable
|
||||
* Supplies a pointer to the table to start searching from.
|
||||
*
|
||||
* @param AcpiTable
|
||||
* Supplies a pointer to memory area where ACPI table address will be stored, or NULLPTR if not found.
|
||||
*
|
||||
* @return This routine returns a status code.
|
||||
*
|
||||
* @since XT 1.0
|
||||
*/
|
||||
XTCDECL
|
||||
EFI_STATUS
|
||||
Acpi::GetAcpiTable(IN CONST UINT Signature,
|
||||
IN PVOID PreviousTable,
|
||||
OUT PVOID *AcpiTable)
|
||||
{
|
||||
PACPI_DESCRIPTION_HEADER TableHeader;
|
||||
SIZE_T RsdtIndex, TableIndex;
|
||||
EFI_STATUS Status;
|
||||
SIZE_T TableCount;
|
||||
PACPI_RSDP Rsdp;
|
||||
PACPI_RSDT Rsdt;
|
||||
BOOLEAN Xsdp;
|
||||
|
||||
/* Return NULLPTR by default if requested table not found */
|
||||
*AcpiTable = NULLPTR;
|
||||
|
||||
/* Get Root System Description Table Pointer */
|
||||
Status = GetAcpiDescriptionPointer((PVOID*)&Rsdp);
|
||||
if(Status != STATUS_EFI_SUCCESS)
|
||||
{
|
||||
/* ACPI tables not found, return error */
|
||||
return Status;
|
||||
}
|
||||
|
||||
/* Check if it is XSDP (ACPI 2.0) or RSDP (ACPI 1.0) */
|
||||
if(Rsdp->Revision >= 2 && Rsdp->XsdtAddress)
|
||||
{
|
||||
/* XSDP (ACPI 2.0) */
|
||||
Xsdp = TRUE;
|
||||
Rsdt = (PACPI_RSDT)(UINT_PTR)Rsdp->XsdtAddress;
|
||||
TableCount = (Rsdt->Header.Length - sizeof(ACPI_DESCRIPTION_HEADER)) / 8;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* RSDP (ACPI 1.0) */
|
||||
Xsdp = FALSE;
|
||||
Rsdt = (PACPI_RSDT)(UINT_PTR)Rsdp->RsdtAddress;
|
||||
TableCount = (Rsdt->Header.Length - sizeof(ACPI_DESCRIPTION_HEADER)) / 4;
|
||||
}
|
||||
|
||||
/* Iterate over all ACPI tables */
|
||||
for(TableIndex = 0; TableIndex < TableCount; TableIndex++)
|
||||
{
|
||||
/* Get table headers in reverse order */
|
||||
RsdtIndex = TableCount - TableIndex - 1;
|
||||
|
||||
/* Check if XSDP or RSDT is used */
|
||||
if(Xsdp)
|
||||
{
|
||||
/* Get table header from XSDT */
|
||||
TableHeader = (PACPI_DESCRIPTION_HEADER)(ULONG_PTR)((PULONGLONG)Rsdt->Tables)[RsdtIndex];
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Get table header from RSDT */
|
||||
TableHeader = (PACPI_DESCRIPTION_HEADER)(ULONG_PTR)((PULONG)Rsdt->Tables)[RsdtIndex];
|
||||
}
|
||||
|
||||
/* Check if previous table provided */
|
||||
if(PreviousTable != NULLPTR)
|
||||
{
|
||||
/* Check if this is a table previously found */
|
||||
if(TableHeader == (PVOID)PreviousTable)
|
||||
{
|
||||
/* Unset previous table */
|
||||
PreviousTable = NULLPTR;
|
||||
}
|
||||
|
||||
/* Skip to next ACPI table */
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Verify table signature */
|
||||
if((TableHeader->Signature == Signature))
|
||||
{
|
||||
/* Found requested ACPI table */
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Make sure table was found */
|
||||
if(TableHeader->Signature != Signature)
|
||||
{
|
||||
/* ACPI table not found, return error */
|
||||
return STATUS_EFI_NOT_FOUND;
|
||||
}
|
||||
|
||||
/* Don't validate FADT on old, broken firmwares with ACPI 2.0 or older */
|
||||
if(TableHeader->Signature != ACPI_FADT_SIGNATURE || TableHeader->Revision > 2)
|
||||
{
|
||||
/* Validate table checksum */
|
||||
if(!ValidateAcpiTable(TableHeader, TableHeader->Length))
|
||||
{
|
||||
/* Checksum mismatch, return error */
|
||||
return STATUS_EFI_CRC_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
/* Found valid ACPI table, return success */
|
||||
*AcpiTable = TableHeader;
|
||||
return STATUS_EFI_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the Advanced Programmable Interrupt Controller (APIC) base address.
|
||||
*
|
||||
* @param ApicBase
|
||||
* Supplies a pointer to memory area where APIC base address will be stored.
|
||||
*
|
||||
* @return This routine returns an EFI status code.
|
||||
*
|
||||
* @since XT 1.0
|
||||
*/
|
||||
XTCDECL
|
||||
EFI_STATUS
|
||||
Acpi::GetApicBase(OUT PVOID *ApicBase)
|
||||
{
|
||||
CPUID_REGISTERS CpuRegisters;
|
||||
|
||||
/* Prepare CPUID registers to query for APIC support */
|
||||
XtLdrProtocol->Memory.ZeroMemory(&CpuRegisters, sizeof(CPUID_REGISTERS));
|
||||
CpuRegisters.Leaf = CPUID_GET_STANDARD1_FEATURES;
|
||||
|
||||
/* Query CPUID */
|
||||
XtLdrProtocol->Cpu.CpuId(&CpuRegisters);
|
||||
|
||||
/* Check if APIC present */
|
||||
if((CpuRegisters.Edx & CPUID_FEATURES_EDX_APIC) == 0)
|
||||
{
|
||||
/* APIC is not supported by the CPU */
|
||||
return STATUS_EFI_UNSUPPORTED;
|
||||
}
|
||||
|
||||
/* Get APIC base address */
|
||||
*ApicBase = (PVOID)((UINT_PTR)XtLdrProtocol->Cpu.ReadModelSpecificRegister(0x1B) & 0xFFFFF000);
|
||||
|
||||
/* Return success */
|
||||
return STATUS_EFI_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets RSDP (ACPI 1.0) from EFI system configuration
|
||||
*
|
||||
* @param AcpiTable
|
||||
* Suplies a pointer to memory area where RSDP address will be stored.
|
||||
*
|
||||
* @return This routine returns a status code.
|
||||
*
|
||||
* @since XT 1.0
|
||||
*/
|
||||
XTCDECL
|
||||
EFI_STATUS
|
||||
Acpi::GetRsdpTable(OUT PVOID *AcpiTable)
|
||||
{
|
||||
EFI_GUID AcpiGuid = EFI_CONFIG_TABLE_ACPI_TABLE_GUID;
|
||||
EFI_STATUS Status;
|
||||
PVOID RsdpTable;
|
||||
|
||||
/* Get RSDP (ACPI 1.0) table from system configuration tables */
|
||||
Status = XtLdrProtocol->Utils.GetConfigurationTable(&AcpiGuid, &RsdpTable);
|
||||
if(Status != STATUS_EFI_SUCCESS || !ValidateAcpiTable(RsdpTable, 20))
|
||||
{
|
||||
/* RSDP not found or checksum mismatch */
|
||||
*AcpiTable = NULLPTR;
|
||||
return STATUS_EFI_NOT_FOUND;
|
||||
}
|
||||
|
||||
/* RSDP found, return success */
|
||||
*AcpiTable = RsdpTable;
|
||||
return STATUS_EFI_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets SMBIOS from EFI system configuration
|
||||
*
|
||||
* @param SmBiosTable
|
||||
* Suplies a pointer to memory area where SMBIOS address will be stored.
|
||||
*
|
||||
* @return This routine returns a status code.
|
||||
*
|
||||
* @since XT 1.0
|
||||
*/
|
||||
XTCDECL
|
||||
EFI_STATUS
|
||||
Acpi::GetSMBiosTable(OUT PVOID *SmBiosTable)
|
||||
{
|
||||
EFI_GUID SmBiosGuid = EFI_CONFIG_TABLE_SMBIOS_TABLE_GUID;
|
||||
PSMBIOS_TABLE_HEADER SmBios;
|
||||
EFI_STATUS Status;
|
||||
|
||||
/* Get SMBIOS table from system configuration tables */
|
||||
Status = XtLdrProtocol->Utils.GetConfigurationTable(&SmBiosGuid, (PVOID*)&SmBios);
|
||||
if(Status != STATUS_EFI_SUCCESS || !ValidateAcpiTable(SmBios, SmBios->Length))
|
||||
{
|
||||
/* SMBIOS not found or checksum mismatch */
|
||||
*SmBiosTable = NULLPTR;
|
||||
return STATUS_EFI_NOT_FOUND;
|
||||
}
|
||||
|
||||
/* SMBIOS found, return success */
|
||||
*SmBiosTable = SmBios;
|
||||
return STATUS_EFI_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets SMBIOS3 from EFI system configuration
|
||||
*
|
||||
* @param SmBiosTable
|
||||
* Suplies a pointer to memory area where SMBIOS3 address will be stored.
|
||||
*
|
||||
* @return This routine returns a status code.
|
||||
*
|
||||
* @since XT 1.0
|
||||
*/
|
||||
XTCDECL
|
||||
EFI_STATUS
|
||||
Acpi::GetSMBios3Table(OUT PVOID *SmBiosTable)
|
||||
{
|
||||
EFI_GUID SmBios3Guid = EFI_CONFIG_TABLE_SMBIOS3_TABLE_GUID;
|
||||
PSMBIOS3_TABLE_HEADER SmBios;
|
||||
EFI_STATUS Status;
|
||||
|
||||
/* Get SMBIOS3 table from system configuration tables */
|
||||
Status = XtLdrProtocol->Utils.GetConfigurationTable(&SmBios3Guid, (PVOID*)&SmBios);
|
||||
if(Status != STATUS_EFI_SUCCESS || !ValidateAcpiTable(SmBios, SmBios->Length))
|
||||
{
|
||||
/* SMBIOS3 not found or checksum mismatch */
|
||||
*SmBiosTable = NULLPTR;
|
||||
return STATUS_EFI_NOT_FOUND;
|
||||
}
|
||||
|
||||
/* SMBIOS3 found, return success */
|
||||
*SmBiosTable = SmBios;
|
||||
return STATUS_EFI_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets XSDP (ACPI 2.0) from EFI system configuration
|
||||
*
|
||||
* @param AcpiTable
|
||||
* Suplies a pointer to memory area where XSDP address will be stored.
|
||||
*
|
||||
* @return This routine returns a status code.
|
||||
*
|
||||
* @since XT 1.0
|
||||
*/
|
||||
XTCDECL
|
||||
EFI_STATUS
|
||||
Acpi::GetXsdpTable(OUT PVOID *AcpiTable)
|
||||
{
|
||||
EFI_GUID AcpiGuid = EFI_CONFIG_TABLE_ACPI20_TABLE_GUID;
|
||||
EFI_STATUS Status;
|
||||
PVOID XsdpTable;
|
||||
|
||||
/* Get XSDP (ACPI 2.0) from system configuration tables */
|
||||
Status = XtLdrProtocol->Utils.GetConfigurationTable(&AcpiGuid, &XsdpTable);
|
||||
if(Status != STATUS_EFI_SUCCESS || !ValidateAcpiTable(XsdpTable, 36))
|
||||
{
|
||||
/* XSDP not found or checksum mismatch */
|
||||
*AcpiTable = NULLPTR;
|
||||
return STATUS_EFI_NOT_FOUND;
|
||||
}
|
||||
|
||||
/* XSDP found, return success */
|
||||
*AcpiTable = XsdpTable;
|
||||
return STATUS_EFI_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* Initializes ACPI module by opening XTLDR protocol and installing ACPI protocol.
|
||||
*
|
||||
* @param ImageHandle
|
||||
* Firmware-allocated handle that identifies the image.
|
||||
*
|
||||
* @param SystemTable
|
||||
* Provides the EFI system table.
|
||||
*
|
||||
* @return This routine returns status code.
|
||||
*
|
||||
* @since XT 1.0
|
||||
*/
|
||||
XTCDECL
|
||||
EFI_STATUS
|
||||
Acpi::InitializeModule(IN EFI_HANDLE ImageHandle,
|
||||
IN PEFI_SYSTEM_TABLE SystemTable)
|
||||
{
|
||||
EFI_GUID Guid = XT_ACPI_PROTOCOL_GUID;
|
||||
EFI_STATUS Status;
|
||||
|
||||
/* Open the XTLDR protocol */
|
||||
Status = BlGetXtLdrProtocol(SystemTable, ImageHandle, &XtLdrProtocol);
|
||||
if(Status != STATUS_EFI_SUCCESS)
|
||||
{
|
||||
/* Failed to open the protocol, return error */
|
||||
return STATUS_EFI_PROTOCOL_ERROR;
|
||||
}
|
||||
|
||||
/* Set routines available via ACPI protocol */
|
||||
AcpiProtocol.GetAcpiDescriptionPointer = GetAcpiDescriptionPointer;
|
||||
AcpiProtocol.GetAcpiTable = GetAcpiTable;
|
||||
AcpiProtocol.GetApicBase = GetApicBase;
|
||||
AcpiProtocol.GetRsdpTable = GetRsdpTable;
|
||||
AcpiProtocol.GetSMBiosTable = GetSMBiosTable;
|
||||
AcpiProtocol.GetSMBios3Table = GetSMBios3Table;
|
||||
AcpiProtocol.GetXsdpTable = GetXsdpTable;
|
||||
|
||||
/* Install ACPI protocol */
|
||||
return XtLdrProtocol->Protocol.Install(&AcpiProtocol, &Guid);
|
||||
}
|
||||
|
||||
/**
|
||||
* Validates given ACPI table by calculating its checksum.
|
||||
*
|
||||
* @param Buffer
|
||||
* Supplies a pointer to the table to checksum.
|
||||
*
|
||||
* @param Size
|
||||
* Supplies the size of the table, in bytes.
|
||||
*
|
||||
* @return This routine returns TRUE if the table is valid, or FALSE otherwise.
|
||||
*
|
||||
* @since XT 1.0
|
||||
*/
|
||||
XTCDECL
|
||||
BOOLEAN
|
||||
Acpi::ValidateAcpiTable(IN PVOID Buffer,
|
||||
IN UINT_PTR Size)
|
||||
{
|
||||
PUCHAR Pointer;
|
||||
UCHAR Sum;
|
||||
|
||||
/* Initialize variables */
|
||||
Sum = 0;
|
||||
Pointer = (PUCHAR)Buffer;
|
||||
|
||||
/* Calculate checksum of given table */
|
||||
while(Size != 0)
|
||||
{
|
||||
Sum = (UCHAR)(Sum + *Pointer);
|
||||
Pointer += 1;
|
||||
Size -= 1;
|
||||
}
|
||||
|
||||
/* Return calculated checksum */
|
||||
return (Sum == 0) ? TRUE : FALSE;
|
||||
}
|
||||
|
||||
/**
|
||||
* This routine is the entry point of the XT EFI boot loader module.
|
||||
*
|
||||
* @param ImageHandle
|
||||
* Firmware-allocated handle that identifies the image.
|
||||
*
|
||||
* @param SystemTable
|
||||
* Provides the EFI system table.
|
||||
*
|
||||
* @return This routine returns status code.
|
||||
*
|
||||
* @since XT 1.0
|
||||
*/
|
||||
XTCDECL
|
||||
EFI_STATUS
|
||||
XtLdrModuleMain(IN EFI_HANDLE ImageHandle,
|
||||
IN PEFI_SYSTEM_TABLE SystemTable)
|
||||
{
|
||||
/* Initialize ACPI module */
|
||||
return Acpi::InitializeModule(ImageHandle, SystemTable);
|
||||
}
|
16
boot/xtldr/modules/acpi/data.cc
Normal file
16
boot/xtldr/modules/acpi/data.cc
Normal file
@@ -0,0 +1,16 @@
|
||||
/**
|
||||
* PROJECT: ExectOS
|
||||
* COPYRIGHT: See COPYING.md in the top level directory
|
||||
* FILE: xtldr/modules/acpi/data.cc
|
||||
* DESCRIPTION: ACPI module global and static data
|
||||
* DEVELOPERS: Rafal Kupiec <belliash@codingworkshop.eu.org>
|
||||
*/
|
||||
|
||||
#include <acpi.hh>
|
||||
|
||||
|
||||
/* ACPI Protocol */
|
||||
XTBL_ACPI_PROTOCOL Acpi::AcpiProtocol;
|
||||
|
||||
/* XTLDR protocol handler */
|
||||
PXTBL_LOADER_PROTOCOL Acpi::XtLdrProtocol;
|
40
boot/xtldr/modules/acpi/includes/acpi.hh
Normal file
40
boot/xtldr/modules/acpi/includes/acpi.hh
Normal file
@@ -0,0 +1,40 @@
|
||||
/**
|
||||
* PROJECT: ExectOS
|
||||
* COPYRIGHT: See COPYING.md in the top level directory
|
||||
* FILE: xtldr/modules/acpi/includes/acpi.hh
|
||||
* DESCRIPTION: XTLDR ACPI module header file
|
||||
* DEVELOPERS: Rafal Kupiec <belliash@codingworkshop.eu.org>
|
||||
*/
|
||||
|
||||
#ifndef __XTLDR_ACPI_ACPI_HH
|
||||
#define __XTLDR_ACPI_ACPI_HH
|
||||
|
||||
#include <xtblapi.h>
|
||||
|
||||
|
||||
/* ACPI module for XTLDR */
|
||||
class Acpi
|
||||
{
|
||||
private:
|
||||
STATIC XTBL_ACPI_PROTOCOL AcpiProtocol;
|
||||
STATIC PXTBL_LOADER_PROTOCOL XtLdrProtocol;
|
||||
|
||||
public:
|
||||
STATIC XTCDECL EFI_STATUS GetAcpiDescriptionPointer(OUT PVOID *AcpiTable);
|
||||
STATIC XTCDECL EFI_STATUS GetAcpiTable(IN CONST UINT Signature,
|
||||
IN PVOID PreviousTable,
|
||||
OUT PVOID *AcpiTable);
|
||||
STATIC XTCDECL EFI_STATUS GetApicBase(OUT PVOID *ApicBase);
|
||||
STATIC XTCDECL EFI_STATUS GetRsdpTable(OUT PVOID *AcpiTable);
|
||||
STATIC XTCDECL EFI_STATUS GetSMBiosTable(OUT PVOID *SmBiosTable);
|
||||
STATIC XTCDECL EFI_STATUS GetSMBios3Table(OUT PVOID *SmBiosTable);
|
||||
STATIC XTCDECL EFI_STATUS GetXsdpTable(OUT PVOID *AcpiTable);
|
||||
STATIC XTCDECL EFI_STATUS InitializeModule(IN EFI_HANDLE ImageHandle,
|
||||
IN PEFI_SYSTEM_TABLE SystemTable);
|
||||
|
||||
private:
|
||||
STATIC XTCDECL BOOLEAN ValidateAcpiTable(IN PVOID Buffer,
|
||||
IN UINT_PTR Size);
|
||||
};
|
||||
|
||||
#endif /* __XTLDR_ACPI_ACPI_HH */
|
27
boot/xtldr/modules/beep/CMakeLists.txt
Normal file
27
boot/xtldr/modules/beep/CMakeLists.txt
Normal file
@@ -0,0 +1,27 @@
|
||||
# XT Boot Loader Beep Module
|
||||
PROJECT(XTLDR_BEEP)
|
||||
|
||||
# Specify include directories
|
||||
include_directories(
|
||||
${EXECTOS_SOURCE_DIR}/sdk/xtdk
|
||||
${XTLDR_BEEP_SOURCE_DIR}/includes)
|
||||
|
||||
# Specify list of source code files
|
||||
list(APPEND XTLDR_BEEP_SOURCE
|
||||
${XTLDR_BEEP_SOURCE_DIR}/beep.cc
|
||||
${XTLDR_BEEP_SOURCE_DIR}/data.cc)
|
||||
|
||||
# Link module executable
|
||||
add_executable(beep ${XTLDR_BEEP_SOURCE})
|
||||
|
||||
# Add linker libraries
|
||||
target_link_libraries(beep libxtldr libxtos)
|
||||
|
||||
# Set proper binary name and install target
|
||||
set_target_properties(beep PROPERTIES SUFFIX .efi)
|
||||
set_install_target(beep efi/boot/xtldr/modules)
|
||||
|
||||
# Set module entrypoint and subsystem
|
||||
set_entrypoint(beep "XtLdrModuleMain")
|
||||
set_linker_map(beep TRUE)
|
||||
set_subsystem(beep efi_boot_service_driver)
|
238
boot/xtldr/modules/beep/beep.cc
Normal file
238
boot/xtldr/modules/beep/beep.cc
Normal file
@@ -0,0 +1,238 @@
|
||||
/**
|
||||
* PROJECT: ExectOS
|
||||
* COPYRIGHT: See COPYING.md in the top level directory
|
||||
* FILE: xtldr/modules/beep/beep.cc
|
||||
* DESCRIPTION: XTLDR Beep Module
|
||||
* DEVELOPERS: Rafal Kupiec <belliash@codingworkshop.eu.org>
|
||||
*/
|
||||
|
||||
#include <beep.hh>
|
||||
|
||||
|
||||
/* Beep module information */
|
||||
MODULE_AUTHOR(L"Rafal Kupiec <belliash@codingworkshop.eu.org>");
|
||||
MODULE_DESCRIPTION(L"Plays a GRUB compatible tune via PC speaker");
|
||||
MODULE_LICENSE(L"GPLv3");
|
||||
MODULE_VERSION(L"0.1");
|
||||
|
||||
|
||||
/**
|
||||
* Disables the PC speaker.
|
||||
*
|
||||
* @return This routine does not return any value.
|
||||
*
|
||||
* @since XT 1.0
|
||||
*/
|
||||
XTCDECL
|
||||
VOID
|
||||
Beep::DisableToneBeep()
|
||||
{
|
||||
UCHAR Status;
|
||||
|
||||
/* Stop the PC speaker */
|
||||
Status = XtLdrProtocol->IoPort.Read8(0x61);
|
||||
XtLdrProtocol->IoPort.Write8(0x61, Status & 0xFC);
|
||||
}
|
||||
|
||||
/**
|
||||
* Enables the PC speaker and plays a sound.
|
||||
*
|
||||
* @param Pitch
|
||||
* Specifies a pitch (in Hz) of the sound.
|
||||
*
|
||||
* @return This routine does not return any value.
|
||||
*
|
||||
* @since XT 1.0
|
||||
*/
|
||||
XTCDECL
|
||||
VOID
|
||||
Beep::EnableToneBeep(IN UINT Pitch)
|
||||
{
|
||||
UINT Counter;
|
||||
UCHAR Status;
|
||||
|
||||
/* Pitch only in range of 20..20000 */
|
||||
if(Pitch < 20)
|
||||
{
|
||||
Pitch = 20;
|
||||
}
|
||||
else if(Pitch > 20000)
|
||||
{
|
||||
Pitch = 20000;
|
||||
}
|
||||
|
||||
/* Set the desired frequency of the PIT clock */
|
||||
Counter = 0x1234DD / Pitch;
|
||||
XtLdrProtocol->IoPort.Write8(0x43, 0xB6);
|
||||
XtLdrProtocol->IoPort.Write8(0x43, 0xB6);
|
||||
XtLdrProtocol->IoPort.Write8(0x42, (UCHAR) Counter & 0xFF);
|
||||
XtLdrProtocol->IoPort.Write8(0x42, (UCHAR) (Counter >> 8) & 0xFF);
|
||||
|
||||
/* Start the PC speaker */
|
||||
Status = XtLdrProtocol->IoPort.Read8(0x61);
|
||||
XtLdrProtocol->IoPort.Write8(0x61, Status | 0x03);
|
||||
}
|
||||
|
||||
/**
|
||||
* Initializes BEEP module by opening XTLDR protocol and playing the tune.
|
||||
*
|
||||
* @param ImageHandle
|
||||
* Firmware-allocated handle that identifies the image.
|
||||
*
|
||||
* @param SystemTable
|
||||
* Provides the EFI system table.
|
||||
*
|
||||
* @return This routine returns status code.
|
||||
*
|
||||
* @since XT 1.0
|
||||
*/
|
||||
XTCDECL
|
||||
EFI_STATUS
|
||||
Beep::InitializeModule(IN EFI_HANDLE ImageHandle,
|
||||
IN PEFI_SYSTEM_TABLE SystemTable)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
PWCHAR Tune;
|
||||
|
||||
/* Open the XTLDR protocol */
|
||||
Status = BlGetXtLdrProtocol(SystemTable, ImageHandle, &XtLdrProtocol);
|
||||
if(Status != STATUS_EFI_SUCCESS)
|
||||
{
|
||||
/* Failed to open the protocol, return error */
|
||||
return STATUS_EFI_PROTOCOL_ERROR;
|
||||
}
|
||||
|
||||
/* Play the tune set in the configuration */
|
||||
XtLdrProtocol->Config.GetValue(L"TUNE", &Tune);
|
||||
PlayTune(Tune);
|
||||
|
||||
/* Return success */
|
||||
return STATUS_EFI_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* This routine plays a tune.
|
||||
*
|
||||
* @param Arguments
|
||||
* Optional list of parameters provided with the command.
|
||||
*
|
||||
* @return This routine does not return any value.
|
||||
*
|
||||
* @since XT 1.0
|
||||
*/
|
||||
XTCDECL
|
||||
VOID
|
||||
Beep::PlayTune(IN PWCHAR Arguments)
|
||||
{
|
||||
LONG Pitch, Duration, Tempo;
|
||||
PWCHAR Argument, LastArgument;
|
||||
|
||||
/* Reset pitch and duration */
|
||||
Duration = -1;
|
||||
Pitch = -1;
|
||||
Tempo = -1;
|
||||
|
||||
/* Tokenize provided list of arguments */
|
||||
Argument = XtLdrProtocol->WideString.Tokenize(Arguments, L" ", &LastArgument);
|
||||
|
||||
/* Iterate over all arguments */
|
||||
while(Argument != NULLPTR)
|
||||
{
|
||||
/* Check if tempo, pitch and duration are set */
|
||||
if(Tempo < 0)
|
||||
{
|
||||
/* Set the tempo */
|
||||
Tempo = WideStringToNumber(Argument);
|
||||
}
|
||||
else if(Pitch < 0)
|
||||
{
|
||||
/* Set the pitch */
|
||||
Pitch = WideStringToNumber(Argument);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Set the duration */
|
||||
Duration = WideStringToNumber(Argument);
|
||||
|
||||
/* Check pitch value */
|
||||
if(Pitch > 0)
|
||||
{
|
||||
/* Emit the beep tone */
|
||||
EnableToneBeep(Pitch);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Stop emitting beep tone */
|
||||
DisableToneBeep();
|
||||
}
|
||||
|
||||
/* Wait for duration time */
|
||||
XtLdrProtocol->Utils.SleepExecution(60000 * Duration / Tempo);
|
||||
|
||||
/* Reset pitch and duration */
|
||||
Pitch = -1;
|
||||
Duration = -1;
|
||||
}
|
||||
|
||||
/* Get next argument */
|
||||
Argument = XtLdrProtocol->WideString.Tokenize(NULLPTR, L" ", &LastArgument);
|
||||
}
|
||||
|
||||
/* Stop emitting beep tone */
|
||||
DisableToneBeep();
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts a wide string into a number.
|
||||
*
|
||||
* @param String
|
||||
* Supplies an input wide string.
|
||||
*
|
||||
* @return This routine returns the number that was converted from the wide string.
|
||||
*
|
||||
* @since XT 1.0
|
||||
*/
|
||||
XTCDECL
|
||||
UINT
|
||||
Beep::WideStringToNumber(IN PWCHAR String)
|
||||
{
|
||||
ULONG Number = 0;
|
||||
|
||||
/* Iterate over all characters until '\0' found */
|
||||
do
|
||||
{
|
||||
/* Check if this is a digit */
|
||||
if(*String - '0' < 10)
|
||||
{
|
||||
/* Add another digit to the number */
|
||||
Number *= 10;
|
||||
Number += *String - '0';
|
||||
}
|
||||
}
|
||||
while(*++String != L'\0');
|
||||
|
||||
/* Return number */
|
||||
return Number;
|
||||
}
|
||||
|
||||
/**
|
||||
* This routine is the entry point of the XT EFI boot loader module.
|
||||
*
|
||||
* @param ImageHandle
|
||||
* Firmware-allocated handle that identifies the image.
|
||||
*
|
||||
* @param SystemTable
|
||||
* Provides the EFI system table.
|
||||
*
|
||||
* @return This routine returns status code.
|
||||
*
|
||||
* @since XT 1.0
|
||||
*/
|
||||
XTCDECL
|
||||
EFI_STATUS
|
||||
XtLdrModuleMain(IN EFI_HANDLE ImageHandle,
|
||||
IN PEFI_SYSTEM_TABLE SystemTable)
|
||||
{
|
||||
/* Initialize BEEP module */
|
||||
return Beep::InitializeModule(ImageHandle, SystemTable);
|
||||
}
|
13
boot/xtldr/modules/beep/data.cc
Normal file
13
boot/xtldr/modules/beep/data.cc
Normal file
@@ -0,0 +1,13 @@
|
||||
/**
|
||||
* PROJECT: ExectOS
|
||||
* COPYRIGHT: See COPYING.md in the top level directory
|
||||
* FILE: xtldr/modules/beep/data.cc
|
||||
* DESCRIPTION: BEEP module global and static data
|
||||
* DEVELOPERS: Rafal Kupiec <belliash@codingworkshop.eu.org>
|
||||
*/
|
||||
|
||||
#include <beep.hh>
|
||||
|
||||
|
||||
/* XTLDR protocol handler */
|
||||
PXTBL_LOADER_PROTOCOL Beep::XtLdrProtocol;
|
32
boot/xtldr/modules/beep/includes/beep.hh
Normal file
32
boot/xtldr/modules/beep/includes/beep.hh
Normal file
@@ -0,0 +1,32 @@
|
||||
/**
|
||||
* PROJECT: ExectOS
|
||||
* COPYRIGHT: See COPYING.md in the top level directory
|
||||
* FILE: xtldr/modules/beep/includes/beep.hh
|
||||
* DESCRIPTION: XTLDR Beep Module header file
|
||||
* DEVELOPERS: Rafal Kupiec <belliash@codingworkshop.eu.org>
|
||||
*/
|
||||
|
||||
#ifndef __XTLDR_BEEP_BEEP_HH
|
||||
#define __XTLDR_BEEP_BEEP_HH
|
||||
|
||||
#include <xtblapi.h>
|
||||
|
||||
|
||||
/* BEEP module for XTLDR */
|
||||
class Beep
|
||||
{
|
||||
private:
|
||||
STATIC PXTBL_LOADER_PROTOCOL XtLdrProtocol;
|
||||
|
||||
public:
|
||||
STATIC XTCDECL EFI_STATUS InitializeModule(IN EFI_HANDLE ImageHandle,
|
||||
IN PEFI_SYSTEM_TABLE SystemTable);
|
||||
STATIC XTCDECL VOID PlayTune(IN PWCHAR Arguments);
|
||||
|
||||
private:
|
||||
STATIC XTCDECL VOID DisableToneBeep();
|
||||
STATIC XTCDECL VOID EnableToneBeep(IN UINT Pitch);
|
||||
STATIC XTCDECL UINT WideStringToNumber(IN PWCHAR String);
|
||||
};
|
||||
|
||||
#endif /* __XTLDR_BEEP_BEEP_HH */
|
27
boot/xtldr/modules/chainldr/CMakeLists.txt
Normal file
27
boot/xtldr/modules/chainldr/CMakeLists.txt
Normal file
@@ -0,0 +1,27 @@
|
||||
# XTLDR Chain Loader Module
|
||||
PROJECT(XTLDR_CHAINLDR)
|
||||
|
||||
# Specify include directories
|
||||
include_directories(
|
||||
${EXECTOS_SOURCE_DIR}/sdk/xtdk
|
||||
${XTLDR_CHAINLDR_SOURCE_DIR}/includes)
|
||||
|
||||
# Specify list of source code files
|
||||
list(APPEND XTLDR_CHAINLDR_SOURCE
|
||||
${XTLDR_CHAINLDR_SOURCE_DIR}/chainldr.cc
|
||||
${XTLDR_CHAINLDR_SOURCE_DIR}/data.cc)
|
||||
|
||||
# Link module executable
|
||||
add_executable(chainldr ${XTLDR_CHAINLDR_SOURCE})
|
||||
|
||||
# Add linker libraries
|
||||
target_link_libraries(chainldr libxtldr libxtos)
|
||||
|
||||
# Set proper binary name and install target
|
||||
set_target_properties(chainldr PROPERTIES SUFFIX .efi)
|
||||
set_install_target(chainldr efi/boot/xtldr/modules)
|
||||
|
||||
# Set module entrypoint and subsystem
|
||||
set_entrypoint(chainldr "XtLdrModuleMain")
|
||||
set_linker_map(chainldr TRUE)
|
||||
set_subsystem(chainldr efi_boot_service_driver)
|
186
boot/xtldr/modules/chainldr/chainldr.cc
Normal file
186
boot/xtldr/modules/chainldr/chainldr.cc
Normal file
@@ -0,0 +1,186 @@
|
||||
/**
|
||||
* PROJECT: ExectOS
|
||||
* COPYRIGHT: See COPYING.md in the top level directory
|
||||
* FILE: xtldr/modules/chainldr/chainldr.cc
|
||||
* DESCRIPTION: XTLDR Chain Loader
|
||||
* DEVELOPERS: Rafal Kupiec <belliash@codingworkshop.eu.org>
|
||||
*/
|
||||
|
||||
#include <chainldr.hh>
|
||||
|
||||
|
||||
/* ChainLoader module information */
|
||||
MODULE_AUTHOR(L"Rafal Kupiec <belliash@codingworkshop.eu.org>");
|
||||
MODULE_DESCRIPTION(L"XTLDR Chain Loader");
|
||||
MODULE_LICENSE(L"GPLv3");
|
||||
MODULE_VERSION(L"0.1");
|
||||
|
||||
|
||||
/**
|
||||
* Chainloads another boot loader.
|
||||
*
|
||||
* @param Parameters
|
||||
* Input parameters with detailed system configuration.
|
||||
*
|
||||
* @return This routine returns a status code.
|
||||
*
|
||||
* @since XT 1.0
|
||||
*/
|
||||
XTCDECL
|
||||
EFI_STATUS
|
||||
ChainLoader::BootSystem(IN PXTBL_BOOT_PARAMETERS Parameters)
|
||||
{
|
||||
EFI_GUID LIPGuid = EFI_LOADED_IMAGE_PROTOCOL_GUID;
|
||||
EFI_MEMMAP_DEVICE_PATH MemoryDevicePath[2];
|
||||
PEFI_LOADED_IMAGE_PROTOCOL LoadedImage;
|
||||
EFI_HANDLE DiskHandle, LoaderHandle;
|
||||
PEFI_FILE_HANDLE FsHandle, BootDir;
|
||||
EFI_STATUS Status;
|
||||
SIZE_T LoaderSize;
|
||||
PVOID LoaderData;
|
||||
|
||||
/* Check if image file is provided */
|
||||
if(Parameters->KernelFile == NULLPTR)
|
||||
{
|
||||
/* No image filename provided, return error code */
|
||||
XtLdrProtocol->Debug.Print(L"ERROR: No EFI image filename provided\n");
|
||||
return STATUS_EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
/* Open EFI volume */
|
||||
Status = XtLdrProtocol->Disk.OpenVolume(Parameters->DevicePath, &DiskHandle, &FsHandle);
|
||||
if(Status != STATUS_EFI_SUCCESS)
|
||||
{
|
||||
/* Failed to open a volume, return error code */
|
||||
XtLdrProtocol->Debug.Print(L"ERROR: Unable to open boot volume (Status Code: 0x%zX)\n", Status);
|
||||
return Status;
|
||||
}
|
||||
|
||||
/* Open boot directory and close FS handle */
|
||||
Status = FsHandle->Open(FsHandle, &BootDir, Parameters->EfiPath, EFI_FILE_MODE_READ, 0);
|
||||
FsHandle->Close(FsHandle);
|
||||
|
||||
/* Check if system path directory opened successfully */
|
||||
if(Status != STATUS_EFI_SUCCESS)
|
||||
{
|
||||
/* Failed to open directory */
|
||||
XtLdrProtocol->Debug.Print(L"ERROR: Unable to open system boot directory (Status Code: 0x%zX)\n", Status);
|
||||
|
||||
/* Close volume and return error code */
|
||||
XtLdrProtocol->Disk.CloseVolume(&DiskHandle);
|
||||
return Status;
|
||||
}
|
||||
|
||||
/* Read EFI image file from disk and close both directory and EFI volume */
|
||||
Status = XtLdrProtocol->Disk.ReadFile(BootDir, Parameters->KernelFile, &LoaderData, &LoaderSize);
|
||||
BootDir->Close(BootDir);
|
||||
XtLdrProtocol->Disk.CloseVolume(&DiskHandle);
|
||||
|
||||
/* Setup device path for EFI image */
|
||||
MemoryDevicePath[0].Header.Length[0] = sizeof(EFI_MEMMAP_DEVICE_PATH);
|
||||
MemoryDevicePath[0].Header.Length[1] = sizeof(EFI_MEMMAP_DEVICE_PATH) >> 8;
|
||||
MemoryDevicePath[0].Header.Type = EFI_HARDWARE_DEVICE_PATH;
|
||||
MemoryDevicePath[0].Header.SubType = EFI_HARDWARE_MEMMAP_DP;
|
||||
MemoryDevicePath[0].MemoryType = EfiLoaderData;
|
||||
MemoryDevicePath[0].StartingAddress = (UINT_PTR)LoaderData;
|
||||
MemoryDevicePath[0].EndingAddress = (UINT_PTR)LoaderData + LoaderSize;
|
||||
MemoryDevicePath[1].Header.Length[0] = sizeof(EFI_DEVICE_PATH_PROTOCOL);
|
||||
MemoryDevicePath[1].Header.Length[1] = sizeof(EFI_DEVICE_PATH_PROTOCOL) >> 8;
|
||||
MemoryDevicePath[1].Header.Type = EFI_END_DEVICE_PATH;
|
||||
MemoryDevicePath[1].Header.SubType = EFI_END_ENTIRE_DP;
|
||||
|
||||
/* Load EFI image */
|
||||
Status = XtLdrProtocol->Utils.LoadEfiImage((PEFI_DEVICE_PATH_PROTOCOL)MemoryDevicePath,
|
||||
LoaderData, LoaderSize, &LoaderHandle);
|
||||
if(Status != STATUS_EFI_SUCCESS)
|
||||
{
|
||||
/* Failed to chainload EFI binary, return error code */
|
||||
XtLdrProtocol->Debug.Print(L"ERROR: Unable to chainload '%S' (Status Code: 0x%zX)\n",
|
||||
Parameters->KernelFile, Status);
|
||||
return Status;
|
||||
}
|
||||
|
||||
/* Access loaded image protocol */
|
||||
Status = XtLdrProtocol->Protocol.OpenHandle(LoaderHandle, (PVOID *)&LoadedImage, &LIPGuid);
|
||||
if(Status != STATUS_EFI_SUCCESS)
|
||||
{
|
||||
/* Failed to open EFI_LOADED_IMAGE_PROTOCOL, return error code */
|
||||
XtLdrProtocol->Debug.Print(L"ERROR: Unable to access binary interface (Status Code: 0x%zX)\n", Status);
|
||||
return Status;
|
||||
}
|
||||
|
||||
/* Check if parameters provided */
|
||||
if(Parameters->Parameters)
|
||||
{
|
||||
/* Pass arguments to chainloaded image */
|
||||
LoadedImage->LoadOptionsSize = XtLdrProtocol->WideString.Length(Parameters->Parameters, 0) * sizeof(WCHAR);
|
||||
LoadedImage->LoadOptions = Parameters->Parameters;
|
||||
}
|
||||
|
||||
/* Set device handle as LoadImage() is not going to do it */
|
||||
LoadedImage->DeviceHandle = DiskHandle;
|
||||
|
||||
/* Chainload EFI image */
|
||||
return XtLdrProtocol->Utils.StartEfiImage(LoaderHandle);
|
||||
}
|
||||
|
||||
/**
|
||||
* Initializes CHAINLDR module by opening XTLDR protocol and installing CHAINLOADER protocol.
|
||||
*
|
||||
* @param ImageHandle
|
||||
* Firmware-allocated handle that identifies the image.
|
||||
*
|
||||
* @param SystemTable
|
||||
* Provides the EFI system table.
|
||||
*
|
||||
* @return This routine returns status code.
|
||||
*
|
||||
* @since XT 1.0
|
||||
*/
|
||||
XTCDECL
|
||||
EFI_STATUS
|
||||
ChainLoader::InitializeModule(IN EFI_HANDLE ImageHandle,
|
||||
IN PEFI_SYSTEM_TABLE SystemTable)
|
||||
{
|
||||
EFI_GUID Guid = XT_CHAIN_BOOT_PROTOCOL_GUID;
|
||||
EFI_STATUS Status;
|
||||
|
||||
/* Open the XTLDR protocol */
|
||||
Status = BlGetXtLdrProtocol(SystemTable, ImageHandle, &XtLdrProtocol);
|
||||
if(Status != STATUS_EFI_SUCCESS)
|
||||
{
|
||||
/* Failed to open the protocol, return error */
|
||||
return STATUS_EFI_PROTOCOL_ERROR;
|
||||
}
|
||||
|
||||
/* Set routines available via ChainLoader boot protocol */
|
||||
BootProtocol.BootSystem = BootSystem;
|
||||
|
||||
/* Register XTOS boot protocol */
|
||||
XtLdrProtocol->Boot.RegisterProtocol(L"CHAINLOADER", &Guid);
|
||||
|
||||
/* Install XTOS protocol */
|
||||
return XtLdrProtocol->Protocol.Install(&BootProtocol, &Guid);
|
||||
}
|
||||
|
||||
/**
|
||||
* This routine is the entry point of the XT EFI boot loader module.
|
||||
*
|
||||
* @param ImageHandle
|
||||
* Firmware-allocated handle that identifies the image.
|
||||
*
|
||||
* @param SystemTable
|
||||
* Provides the EFI system table.
|
||||
*
|
||||
* @return This routine returns status code.
|
||||
*
|
||||
* @since XT 1.0
|
||||
*/
|
||||
XTCDECL
|
||||
EFI_STATUS
|
||||
XtLdrModuleMain(IN EFI_HANDLE ImageHandle,
|
||||
IN PEFI_SYSTEM_TABLE SystemTable)
|
||||
{
|
||||
/* Initialize CHAINLDR module */
|
||||
return ChainLoader::InitializeModule(ImageHandle, SystemTable);
|
||||
}
|
16
boot/xtldr/modules/chainldr/data.cc
Normal file
16
boot/xtldr/modules/chainldr/data.cc
Normal file
@@ -0,0 +1,16 @@
|
||||
/**
|
||||
* PROJECT: ExectOS
|
||||
* COPYRIGHT: See COPYING.md in the top level directory
|
||||
* FILE: xtldr/modules/chainldr/data.cc
|
||||
* DESCRIPTION: CHAINLDR module global and static data
|
||||
* DEVELOPERS: Rafal Kupiec <belliash@codingworkshop.eu.org>
|
||||
*/
|
||||
|
||||
#include <chainldr.hh>
|
||||
|
||||
|
||||
/* ChainLoader Boot Protocol */
|
||||
XTBL_BOOT_PROTOCOL ChainLoader::BootProtocol;
|
||||
|
||||
/* XTLDR protocol handler */
|
||||
PXTBL_LOADER_PROTOCOL ChainLoader::XtLdrProtocol;
|
28
boot/xtldr/modules/chainldr/includes/chainldr.hh
Normal file
28
boot/xtldr/modules/chainldr/includes/chainldr.hh
Normal file
@@ -0,0 +1,28 @@
|
||||
/**
|
||||
* PROJECT: ExectOS
|
||||
* COPYRIGHT: See COPYING.md in the top level directory
|
||||
* FILE: xtldr/modules/chainldr/includes/chainldr.hh
|
||||
* DESCRIPTION: XTLDR Chain Loader header file
|
||||
* DEVELOPERS: Rafal Kupiec <belliash@codingworkshop.eu.org>
|
||||
*/
|
||||
|
||||
#ifndef __XTLDR_CHAINLDR_CHAINLDR_HH
|
||||
#define __XTLDR_CHAINLDR_CHAINLDR_HH
|
||||
|
||||
#include <xtblapi.h>
|
||||
|
||||
|
||||
/* CHAINLDR module for XTLDR */
|
||||
class ChainLoader
|
||||
{
|
||||
private:
|
||||
STATIC XTBL_BOOT_PROTOCOL BootProtocol;
|
||||
STATIC PXTBL_LOADER_PROTOCOL XtLdrProtocol;
|
||||
|
||||
public:
|
||||
STATIC XTCDECL EFI_STATUS BootSystem(IN PXTBL_BOOT_PARAMETERS Parameters);
|
||||
STATIC XTCDECL EFI_STATUS InitializeModule(IN EFI_HANDLE ImageHandle,
|
||||
IN PEFI_SYSTEM_TABLE SystemTable);
|
||||
};
|
||||
|
||||
#endif /* __XTLDR_CHAINLDR_CHAINLDR_HH */
|
27
boot/xtldr/modules/dummy/CMakeLists.txt
Normal file
27
boot/xtldr/modules/dummy/CMakeLists.txt
Normal file
@@ -0,0 +1,27 @@
|
||||
# XT Boot Loader Dummy Module
|
||||
PROJECT(XTLDR_DUMMY)
|
||||
|
||||
# Specify include directories
|
||||
include_directories(
|
||||
${EXECTOS_SOURCE_DIR}/sdk/xtdk
|
||||
${XTLDR_DUMMY_SOURCE_DIR}/includes)
|
||||
|
||||
# Specify list of source code files
|
||||
list(APPEND XTLDR_DUMMY_SOURCE
|
||||
${XTLDR_DUMMY_SOURCE_DIR}/dummy.cc
|
||||
${XTLDR_DUMMY_SOURCE_DIR}/data.cc)
|
||||
|
||||
# Link module executable
|
||||
add_executable(dummy ${XTLDR_DUMMY_SOURCE})
|
||||
|
||||
# Add linker libraries
|
||||
target_link_libraries(dummy libxtldr)
|
||||
|
||||
# Set proper binary name and install target
|
||||
set_target_properties(dummy PROPERTIES SUFFIX .efi)
|
||||
set_install_target(dummy efi/boot/xtldr/modules)
|
||||
|
||||
# Set module entrypoint and subsystem
|
||||
set_entrypoint(dummy "XtLdrModuleMain")
|
||||
set_linker_map(dummy TRUE)
|
||||
set_subsystem(dummy efi_boot_service_driver)
|
16
boot/xtldr/modules/dummy/data.cc
Normal file
16
boot/xtldr/modules/dummy/data.cc
Normal file
@@ -0,0 +1,16 @@
|
||||
/**
|
||||
* PROJECT: ExectOS
|
||||
* COPYRIGHT: See COPYING.md in the top level directory
|
||||
* FILE: xtldr/modules/dummy/data.cc
|
||||
* DESCRIPTION: Dummy XTLDR module global and static data
|
||||
* DEVELOPERS: Rafal Kupiec <belliash@codingworkshop.eu.org>
|
||||
*/
|
||||
|
||||
#include <dummy.hh>
|
||||
|
||||
|
||||
/* Dummy Boot Protocol handler */
|
||||
XTBL_BOOT_PROTOCOL Dummy::DummyProtocol;
|
||||
|
||||
/* XTLDR protocol handler */
|
||||
PXTBL_LOADER_PROTOCOL Dummy::XtLdrProtocol;
|
95
boot/xtldr/modules/dummy/dummy.cc
Normal file
95
boot/xtldr/modules/dummy/dummy.cc
Normal file
@@ -0,0 +1,95 @@
|
||||
/**
|
||||
* PROJECT: ExectOS
|
||||
* COPYRIGHT: See COPYING.md in the top level directory
|
||||
* FILE: xtldr/modules/dummy/dummy.cc
|
||||
* DESCRIPTION: XTLDR Dummy Module
|
||||
* DEVELOPERS: Rafal Kupiec <belliash@codingworkshop.eu.org>
|
||||
*/
|
||||
|
||||
#include <dummy.hh>
|
||||
|
||||
|
||||
/* Dummy module information */
|
||||
MODULE_AUTHOR(L"Rafal Kupiec <belliash@codingworkshop.eu.org>");
|
||||
MODULE_DESCRIPTION(L"XTLDR Dummy Module");
|
||||
MODULE_LICENSE(L"GPLv3");
|
||||
MODULE_VERSION(L"0.1");
|
||||
|
||||
|
||||
/**
|
||||
* Stub boot routine.
|
||||
*
|
||||
* @param Parameters
|
||||
* Supplies all parameters associated with the chosen boot menu entry.
|
||||
*
|
||||
* @return This routine returns a status code.
|
||||
*
|
||||
* @since XT 1.0
|
||||
*/
|
||||
XTCDECL
|
||||
EFI_STATUS
|
||||
Dummy::BootSystem(IN PXTBL_BOOT_PARAMETERS Parameters)
|
||||
{
|
||||
return STATUS_EFI_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* Initializes DUMMY module by opening XTLDR protocol and installing DUMMY protocol.
|
||||
*
|
||||
* @param ImageHandle
|
||||
* Firmware-allocated handle that identifies the image.
|
||||
*
|
||||
* @param SystemTable
|
||||
* Provides the EFI system table.
|
||||
*
|
||||
* @return This routine returns status code.
|
||||
*
|
||||
* @since XT 1.0
|
||||
*/
|
||||
XTCDECL
|
||||
EFI_STATUS
|
||||
Dummy::InitializeModule(IN EFI_HANDLE ImageHandle,
|
||||
IN PEFI_SYSTEM_TABLE SystemTable)
|
||||
{
|
||||
EFI_GUID DummyGuid = XT_DUMMY_BOOT_PROTOCOL_GUID;
|
||||
EFI_STATUS Status;
|
||||
|
||||
/* Open the XTLDR protocol */
|
||||
Status = BlGetXtLdrProtocol(SystemTable, ImageHandle, &XtLdrProtocol);
|
||||
if(Status != STATUS_EFI_SUCCESS)
|
||||
{
|
||||
/* Failed to open the protocol, return error */
|
||||
return STATUS_EFI_PROTOCOL_ERROR;
|
||||
}
|
||||
|
||||
/* Set boot protocol routines */
|
||||
DummyProtocol.BootSystem = BootSystem;
|
||||
|
||||
/* Register XTOS boot protocol */
|
||||
XtLdrProtocol->Boot.RegisterProtocol(L"DUMMYOS", &DummyGuid);
|
||||
|
||||
/* Register DUMMY protocol as XTOS boot protocol */
|
||||
return XtLdrProtocol->Protocol.Install(&DummyProtocol, &DummyGuid);
|
||||
}
|
||||
|
||||
/**
|
||||
* This routine is the entry point of the XT EFI boot loader module.
|
||||
*
|
||||
* @param ImageHandle
|
||||
* Firmware-allocated handle that identifies the image.
|
||||
*
|
||||
* @param SystemTable
|
||||
* Provides the EFI system table.
|
||||
*
|
||||
* @return This routine returns a status code.
|
||||
*
|
||||
* @since XT 1.0
|
||||
*/
|
||||
XTCDECL
|
||||
EFI_STATUS
|
||||
XtLdrModuleMain(IN EFI_HANDLE ImageHandle,
|
||||
IN PEFI_SYSTEM_TABLE SystemTable)
|
||||
{
|
||||
/* Initialize DUMMY module */
|
||||
return Dummy::InitializeModule(ImageHandle, SystemTable);
|
||||
}
|
28
boot/xtldr/modules/dummy/includes/dummy.hh
Normal file
28
boot/xtldr/modules/dummy/includes/dummy.hh
Normal file
@@ -0,0 +1,28 @@
|
||||
/**
|
||||
* PROJECT: ExectOS
|
||||
* COPYRIGHT: See COPYING.md in the top level directory
|
||||
* FILE: xtldr/modules/dummy/includes/dummy.hh
|
||||
* DESCRIPTION: XTLDR Dummy Module header file
|
||||
* DEVELOPERS: Rafal Kupiec <belliash@codingworkshop.eu.org>
|
||||
*/
|
||||
|
||||
#ifndef __XTLDR_DUMMY_DUMMY_HH
|
||||
#define __XTLDR_DUMMY_DUMMY_HH
|
||||
|
||||
#include <xtblapi.h>
|
||||
|
||||
|
||||
/* DUMMY module for XTLDR */
|
||||
class Dummy
|
||||
{
|
||||
private:
|
||||
STATIC XTBL_BOOT_PROTOCOL DummyProtocol;
|
||||
STATIC PXTBL_LOADER_PROTOCOL XtLdrProtocol;
|
||||
|
||||
public:
|
||||
STATIC EFI_STATUS BootSystem(IN PXTBL_BOOT_PARAMETERS Parameters);
|
||||
STATIC EFI_STATUS InitializeModule(IN EFI_HANDLE ImageHandle,
|
||||
IN PEFI_SYSTEM_TABLE SystemTable);
|
||||
};
|
||||
|
||||
#endif/* __XTLDR_DUMMY_DUMMY_HH */
|
27
boot/xtldr/modules/framebuf/CMakeLists.txt
Normal file
27
boot/xtldr/modules/framebuf/CMakeLists.txt
Normal file
@@ -0,0 +1,27 @@
|
||||
# XTLDR FrameBuffer support module
|
||||
PROJECT(XTLDR_FRAMEBUF)
|
||||
|
||||
# Specify include directories
|
||||
include_directories(
|
||||
${EXECTOS_SOURCE_DIR}/sdk/xtdk
|
||||
${XTLDR_FRAMEBUF_SOURCE_DIR}/includes)
|
||||
|
||||
# Specify list of source code files
|
||||
list(APPEND XTLDR_FRAMEBUF_SOURCE
|
||||
${XTLDR_FRAMEBUF_SOURCE_DIR}/framebuf.cc
|
||||
${XTLDR_FRAMEBUF_SOURCE_DIR}/data.cc)
|
||||
|
||||
# Link bootloader executable
|
||||
add_executable(framebuf ${XTLDR_FRAMEBUF_SOURCE})
|
||||
|
||||
# Add linker libraries
|
||||
target_link_libraries(framebuf libxtldr)
|
||||
|
||||
# Set proper binary name and install target
|
||||
set_target_properties(framebuf PROPERTIES SUFFIX .efi)
|
||||
set_install_target(framebuf efi/boot/xtldr/modules)
|
||||
|
||||
# Set module entrypoint and subsystem
|
||||
set_entrypoint(framebuf "XtLdrModuleMain")
|
||||
set_linker_map(framebuf TRUE)
|
||||
set_subsystem(framebuf efi_boot_service_driver)
|
19
boot/xtldr/modules/framebuf/data.cc
Normal file
19
boot/xtldr/modules/framebuf/data.cc
Normal file
@@ -0,0 +1,19 @@
|
||||
/**
|
||||
* PROJECT: ExectOS
|
||||
* COPYRIGHT: See COPYING.md in the top level directory
|
||||
* FILE: xtldr/modules/framebuf/data.cc
|
||||
* DESCRIPTION: EFI framebuffer module global and static data
|
||||
* DEVELOPERS: Rafal Kupiec <belliash@codingworkshop.eu.org>
|
||||
*/
|
||||
|
||||
#include <framebuf.hh>
|
||||
|
||||
|
||||
/* Framebuffer display information */
|
||||
XTBL_FRAMEBUFFER_INFORMATION FrameBuffer::DisplayInfo;
|
||||
|
||||
/* Framebuffer protocol handler */
|
||||
XTBL_FRAMEBUFFER_PROTOCOL FrameBuffer::FbProtocol;
|
||||
|
||||
/* XTLDR protocol handler */
|
||||
PXTBL_LOADER_PROTOCOL FrameBuffer::XtLdrProtocol;
|
810
boot/xtldr/modules/framebuf/framebuf.cc
Normal file
810
boot/xtldr/modules/framebuf/framebuf.cc
Normal file
@@ -0,0 +1,810 @@
|
||||
/**
|
||||
* PROJECT: ExectOS
|
||||
* COPYRIGHT: See COPYING.md in the top level directory
|
||||
* FILE: xtldr/modules/framebuf/framebuf.cc
|
||||
* DESCRIPTION: EFI framebuffer support module for XTLDR
|
||||
* DEVELOPERS: Rafal Kupiec <belliash@codingworkshop.eu.org>
|
||||
*/
|
||||
|
||||
#include <framebuf.hh>
|
||||
|
||||
|
||||
/* PE/COFF_O module information */
|
||||
MODULE_AUTHOR(L"Rafal Kupiec <belliash@codingworkshop.eu.org>");
|
||||
MODULE_DESCRIPTION(L"EFI FB (FrameBuffer) support");
|
||||
MODULE_LICENSE(L"GPLv3");
|
||||
MODULE_VERSION(L"0.2");
|
||||
|
||||
|
||||
/**
|
||||
* Finds a PCI Display Adapter and returns its framebuffer address.
|
||||
*
|
||||
* @param Address
|
||||
* Supplies a pointer to the memory area where framebuffer address will be stored.
|
||||
*
|
||||
* @return This routine returns a status code.
|
||||
*
|
||||
* @since XT 1.0
|
||||
*/
|
||||
XTCDECL
|
||||
EFI_STATUS
|
||||
FrameBuffer::FindFramebufferAddress(OUT PEFI_PHYSICAL_ADDRESS Address)
|
||||
{
|
||||
EFI_GUID PciIoGuid = EFI_PCI_IO_PROTOCOL_GUID;
|
||||
PEFI_ACPI_ADDRESS_SPACE_DESCRIPTOR BarInfo;
|
||||
PEFI_PCI_IO_PROTOCOL IoProtocol;
|
||||
ULONGLONG FramebufAddressLength;
|
||||
PCI_TYPE0_DEVICE PciDevice;
|
||||
PVOID FramebufAddress;
|
||||
UINT_PTR HandlesCount;
|
||||
EFI_HANDLE *Handles;
|
||||
EFI_STATUS Status;
|
||||
UINT Index;
|
||||
|
||||
/* Initialize variables */
|
||||
FramebufAddressLength = 0;
|
||||
Handles = NULLPTR;
|
||||
|
||||
/* Locate EFI_PCI_IO_PROTOCOL handles */
|
||||
Status = XtLdrProtocol->Protocol.LocateHandles(&Handles, &HandlesCount, &PciIoGuid);
|
||||
if(Status != STATUS_EFI_SUCCESS)
|
||||
{
|
||||
/* Failed to get handles, return error code */
|
||||
XtLdrProtocol->Debug.Print(L"ERROR: Failed to get handles (Status Code: 0x%zX)\n", Status);
|
||||
return Status;
|
||||
}
|
||||
|
||||
/* Iterate through handles */
|
||||
for(Index = 0; Index < HandlesCount; Index++)
|
||||
{
|
||||
/* Open EFI_PCI_IO_PROTOCOL handle */
|
||||
Status = XtLdrProtocol->Protocol.OpenHandle(Handles[Index], (PVOID *)&IoProtocol, &PciIoGuid);
|
||||
if(Status != STATUS_EFI_SUCCESS)
|
||||
{
|
||||
/* Failed to open protocol, continue with next handle */
|
||||
XtLdrProtocol->Debug.Print(L"ERROR: Failed to open protocol (Status Code: 0x%zX)\n", Status);
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Read PCI controller registers from PCI configuration space */
|
||||
Status = IoProtocol->Pci.Read(IoProtocol, EfiPciIoWidthUint32, 0, sizeof(PciDevice) / sizeof(UINT), &PciDevice);
|
||||
if(Status != STATUS_EFI_SUCCESS)
|
||||
{
|
||||
/* Failed to read PCI device class */
|
||||
XtLdrProtocol->Debug.Print(L"ERROR: Failed to read class (Status Code: 0x%zX)\n", Status);
|
||||
|
||||
/* Close protocol and continue with next handle */
|
||||
XtLdrProtocol->Protocol.Close(&Handles[Index], &PciIoGuid);
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Check if device is a graphics adapter */
|
||||
if(PciDevice.Hdr.ClassCode[2] != 0x03)
|
||||
{
|
||||
/* Not a graphics adapter, close protocol and continue with next handle */
|
||||
XtLdrProtocol->Protocol.Close(&Handles[Index], &PciIoGuid);
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Iterate through all PCI device's Base Address Registers (BARs) */
|
||||
for(UINT Bars = 0; Bars < 6; Bars++)
|
||||
{
|
||||
/* Get BAR attributes */
|
||||
Status = IoProtocol->GetBarAttributes(IoProtocol, Bars, NULLPTR, (VOID **)&BarInfo);
|
||||
if(Status != STATUS_EFI_SUCCESS)
|
||||
{
|
||||
/* Failed to get BAR attributes, continue with next BAR */
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Check if this BAR is 'Memory Range' of 'ACPI QWORD Address Space' */
|
||||
if(BarInfo->SpaceDescriptor == EFI_ACPI_ADDRESS64_SPACE_DESCRIPTOR &&
|
||||
BarInfo->ResourceType == EFI_ACPI_ADDRESS_SPACE_TYPE_MEMORY)
|
||||
{
|
||||
/* Check if this BAR is the biggest we've seen so far */
|
||||
if(BarInfo->AddressLength > FramebufAddressLength)
|
||||
{
|
||||
/* The biggest BAR should be the framebuffer; save its address and length */
|
||||
FramebufAddress = (PVOID)(ULONG_PTR)(BarInfo->AddressRangeMin << 16);
|
||||
FramebufAddressLength = BarInfo->AddressLength;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Close handle and continue with next one */
|
||||
XtLdrProtocol->Protocol.Close(&Handles[Index], &PciIoGuid);
|
||||
}
|
||||
|
||||
/* Set framebuffer address and return success */
|
||||
*Address = (EFI_PHYSICAL_ADDRESS)FramebufAddress;
|
||||
return STATUS_EFI_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculates color mask and shift based upon pixel bit mask.
|
||||
*
|
||||
* @param PixelBitMask
|
||||
* Provides a pixel bit mask.
|
||||
*
|
||||
* @param ColorSize
|
||||
* Supplies a pointer to the memory area where the color size will be stored.
|
||||
*
|
||||
* @param ColorShift
|
||||
* Supplies a pointer to the memory area where the color shift (position) will be stored.
|
||||
*
|
||||
* @return This routine does not return any value.
|
||||
*
|
||||
* @since XT 1.0
|
||||
*/
|
||||
XTCDECL
|
||||
VOID
|
||||
FrameBuffer::GetColorMask(IN UINT PixelBitMask,
|
||||
OUT PUSHORT ColorSize,
|
||||
OUT PUSHORT ColorShift)
|
||||
{
|
||||
UINT Shift, Size;
|
||||
|
||||
/* Initialize variables */
|
||||
Shift = 0;
|
||||
Size = 0;
|
||||
|
||||
/* Make sure EfiMask is not zero */
|
||||
if(PixelBitMask)
|
||||
{
|
||||
/* Get color shift */
|
||||
while((PixelBitMask & 1) == 0)
|
||||
{
|
||||
Shift++;
|
||||
PixelBitMask >>= 1;
|
||||
}
|
||||
|
||||
/* Get color size */
|
||||
while((PixelBitMask & 1) == 1)
|
||||
{
|
||||
Size++;
|
||||
PixelBitMask >>= 1;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/* Set color mask and shift */
|
||||
*ColorShift = Shift;
|
||||
*ColorSize = Size;
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides an EFI Frame Buffer protocol driver name used for initialization.
|
||||
*
|
||||
* @param Protocol
|
||||
* Supplies a pointer to the memory area where framebuffer driver information will be stored.
|
||||
*
|
||||
* @return This routine returns a status code.
|
||||
*
|
||||
* @since XT 1.0
|
||||
*/
|
||||
XTCDECL
|
||||
EFI_STATUS
|
||||
FrameBuffer::GetDisplayDriver(OUT PEFI_GRAPHICS_PROTOCOL Protocol)
|
||||
{
|
||||
/* Check if framebuffer is initialized */
|
||||
if(!DisplayInfo.Initialized)
|
||||
{
|
||||
/* Return error if framebuffer is not initialized */
|
||||
return STATUS_EFI_NOT_READY;
|
||||
}
|
||||
|
||||
/* Copy framebuffer driver information */
|
||||
*Protocol = DisplayInfo.Protocol;
|
||||
|
||||
/* Return success */
|
||||
return STATUS_EFI_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns information about EFI Frame Buffer.
|
||||
*
|
||||
* @param FbInfo
|
||||
* Supplies a pointer to the memory area where framebuffer information will be stored.
|
||||
*
|
||||
* @return This routine returns a status code.
|
||||
*
|
||||
* @since XT 1.0
|
||||
*/
|
||||
XTCDECL
|
||||
EFI_STATUS
|
||||
FrameBuffer::GetDisplayInformation(OUT PEFI_PHYSICAL_ADDRESS FrameBufferBase,
|
||||
OUT PULONG_PTR FrameBufferSize,
|
||||
OUT PXTBL_FRAMEBUFFER_MODE_INFORMATION ModeInfo)
|
||||
{
|
||||
/* Check if framebuffer is initialized */
|
||||
if(!DisplayInfo.Initialized)
|
||||
{
|
||||
/* Return error if framebuffer is not initialized */
|
||||
return STATUS_EFI_NOT_READY;
|
||||
}
|
||||
|
||||
/* Set basic framebuffer information */
|
||||
*FrameBufferBase = DisplayInfo.FrameBufferBase;
|
||||
*FrameBufferSize = DisplayInfo.FrameBufferSize;
|
||||
|
||||
/* Set framebuffer mode information */
|
||||
ModeInfo->Width = DisplayInfo.ModeInfo.Width;
|
||||
ModeInfo->Height = DisplayInfo.ModeInfo.Height;
|
||||
ModeInfo->Depth = DisplayInfo.ModeInfo.Depth;
|
||||
ModeInfo->RefreshRate = DisplayInfo.ModeInfo.RefreshRate;
|
||||
ModeInfo->BitsPerPixel = DisplayInfo.ModeInfo.BitsPerPixel;
|
||||
ModeInfo->BytesPerPixel = DisplayInfo.ModeInfo.BytesPerPixel;
|
||||
ModeInfo->PixelsPerScanLine = DisplayInfo.ModeInfo.PixelsPerScanLine;
|
||||
ModeInfo->Pitch = DisplayInfo.ModeInfo.Pitch;
|
||||
ModeInfo->PixelFormat = DisplayInfo.ModeInfo.PixelFormat;
|
||||
ModeInfo->PixelInformation = DisplayInfo.ModeInfo.PixelInformation;
|
||||
|
||||
/* Return success */
|
||||
return STATUS_EFI_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Gets information about the current display mode and stores it in internal structure.
|
||||
*
|
||||
* @return This routine returns a status code.
|
||||
*
|
||||
* @since XT 1.0
|
||||
*/
|
||||
XTCDECL
|
||||
EFI_STATUS
|
||||
FrameBuffer::GetModeInformation()
|
||||
{
|
||||
PEFI_GRAPHICS_OUTPUT_MODE_INFORMATION ModeInfo;
|
||||
EFI_PIXEL_BITMASK PixelBitMask;
|
||||
XTSTATUS Status;
|
||||
UINT_PTR Size;
|
||||
|
||||
switch(DisplayInfo.Protocol)
|
||||
{
|
||||
case GOP:
|
||||
/* Query GOP mode information */
|
||||
Status = DisplayInfo.Driver.Gop->QueryMode(DisplayInfo.Driver.Gop,
|
||||
DisplayInfo.Driver.Gop->Mode->Mode,
|
||||
&Size, &ModeInfo);
|
||||
if(Status != STATUS_EFI_SUCCESS)
|
||||
{
|
||||
/* Failed to get GOP mode information, return error */
|
||||
return Status;
|
||||
}
|
||||
|
||||
/* Get pixel bit mask information */
|
||||
GetPixelInformation(&DisplayInfo.Driver.Gop->Mode->Info->PixelInformation);
|
||||
|
||||
/* Store GOP framebuffer information */
|
||||
DisplayInfo.ModeInfo.Width = DisplayInfo.Driver.Gop->Mode->Info->HorizontalResolution;
|
||||
DisplayInfo.ModeInfo.Height = DisplayInfo.Driver.Gop->Mode->Info->VerticalResolution;
|
||||
DisplayInfo.ModeInfo.Depth = DisplayInfo.ModeInfo.BitsPerPixel;
|
||||
DisplayInfo.ModeInfo.PixelsPerScanLine = DisplayInfo.Driver.Gop->Mode->Info->PixelsPerScanLine;
|
||||
DisplayInfo.ModeInfo.Pitch = DisplayInfo.ModeInfo.PixelsPerScanLine *
|
||||
(DisplayInfo.ModeInfo.BitsPerPixel / 8);
|
||||
DisplayInfo.ModeInfo.RefreshRate = 0;
|
||||
|
||||
/* Store pixel format information and frame buffer size */
|
||||
DisplayInfo.ModeInfo.PixelFormat = DisplayInfo.Driver.Gop->Mode->Info->PixelFormat;
|
||||
DisplayInfo.FrameBufferSize = DisplayInfo.Driver.Gop->Mode->FrameBufferSize;
|
||||
break;
|
||||
case UGA:
|
||||
/* Query UGA mode information */
|
||||
Status = DisplayInfo.Driver.Uga->GetMode(DisplayInfo.Driver.Uga, &DisplayInfo.ModeInfo.Width,
|
||||
&DisplayInfo.ModeInfo.Height, &DisplayInfo.ModeInfo.Depth,
|
||||
&DisplayInfo.ModeInfo.RefreshRate);
|
||||
if(Status != STATUS_EFI_SUCCESS)
|
||||
{
|
||||
/* Failed to get UGA mode information, return error */
|
||||
return Status;
|
||||
}
|
||||
|
||||
/* Get pixel bit mask information */
|
||||
PixelBitMask = (EFI_PIXEL_BITMASK){0, 0, 0, 0};
|
||||
GetPixelInformation(&PixelBitMask);
|
||||
|
||||
/* Store UGA framebuffer information */
|
||||
DisplayInfo.ModeInfo.PixelsPerScanLine = DisplayInfo.ModeInfo.Width;
|
||||
DisplayInfo.ModeInfo.Pitch = DisplayInfo.ModeInfo.PixelsPerScanLine *
|
||||
(DisplayInfo.ModeInfo.BitsPerPixel / 8);
|
||||
|
||||
/* Store pixel format information and recalculate frame buffer size */
|
||||
DisplayInfo.ModeInfo.PixelFormat = PixelBlueGreenRedReserved8BitPerColor;
|
||||
DisplayInfo.FrameBufferSize = DisplayInfo.ModeInfo.Width *
|
||||
DisplayInfo.ModeInfo.Height *
|
||||
DisplayInfo.ModeInfo.BytesPerPixel + 1024;
|
||||
break;
|
||||
default:
|
||||
/* This should never be reached as no other display driver is supported */
|
||||
break;
|
||||
}
|
||||
|
||||
/* Return success */
|
||||
return STATUS_EFI_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets pixel information based on the reported pixel format.
|
||||
*
|
||||
* @param FrameBufferInfo
|
||||
* Supplies a pointer to the framebuffer information structure.
|
||||
*
|
||||
* @param PixelsBitMask
|
||||
* Supplies a pointer to the pixel bit mask information provided by EFI graphics protocol.
|
||||
*
|
||||
* @return This routine does not return any value.
|
||||
*
|
||||
* @since XT 1.0
|
||||
*/
|
||||
XTCDECL
|
||||
VOID
|
||||
FrameBuffer::GetPixelInformation(IN PEFI_PIXEL_BITMASK PixelsBitMask)
|
||||
{
|
||||
UINT CompoundMask;
|
||||
|
||||
/* Check reported pixel format */
|
||||
switch(DisplayInfo.ModeInfo.PixelFormat)
|
||||
{
|
||||
case PixelBlueGreenRedReserved8BitPerColor:
|
||||
/* BGRR, 32 bits per pixel */
|
||||
DisplayInfo.ModeInfo.BitsPerPixel = 32;
|
||||
DisplayInfo.ModeInfo.PixelInformation.BlueShift = 0;
|
||||
DisplayInfo.ModeInfo.PixelInformation.BlueSize = 8;
|
||||
DisplayInfo.ModeInfo.PixelInformation.GreenShift = 8;
|
||||
DisplayInfo.ModeInfo.PixelInformation.GreenSize = 8;
|
||||
DisplayInfo.ModeInfo.PixelInformation.RedShift = 16;
|
||||
DisplayInfo.ModeInfo.PixelInformation.RedSize = 8;
|
||||
DisplayInfo.ModeInfo.PixelInformation.ReservedShift = 24;
|
||||
DisplayInfo.ModeInfo.PixelInformation.ReservedSize = 8;
|
||||
break;
|
||||
case PixelRedGreenBlueReserved8BitPerColor:
|
||||
/* RGBR, 32 bits per pixel */
|
||||
DisplayInfo.ModeInfo.BitsPerPixel = 32;
|
||||
DisplayInfo.ModeInfo.PixelInformation.BlueShift = 16;
|
||||
DisplayInfo.ModeInfo.PixelInformation.BlueSize = 8;
|
||||
DisplayInfo.ModeInfo.PixelInformation.GreenShift = 8;
|
||||
DisplayInfo.ModeInfo.PixelInformation.GreenSize = 8;
|
||||
DisplayInfo.ModeInfo.PixelInformation.RedShift = 0;
|
||||
DisplayInfo.ModeInfo.PixelInformation.RedSize = 8;
|
||||
DisplayInfo.ModeInfo.PixelInformation.ReservedShift = 24;
|
||||
DisplayInfo.ModeInfo.PixelInformation.ReservedSize = 8;
|
||||
break;
|
||||
case PixelBitMask:
|
||||
/* Assume 32 bits per pixel */
|
||||
DisplayInfo.ModeInfo.BitsPerPixel = 32;
|
||||
|
||||
/* Calculate compound mask */
|
||||
CompoundMask = PixelsBitMask->RedMask |
|
||||
PixelsBitMask->GreenMask |
|
||||
PixelsBitMask->BlueMask |
|
||||
PixelsBitMask->ReservedMask;
|
||||
|
||||
/* Recalculate bits per pixel */
|
||||
while((CompoundMask & (1 << 31)) == 0)
|
||||
{
|
||||
DisplayInfo.ModeInfo.BitsPerPixel--;
|
||||
CompoundMask <<= 1;
|
||||
}
|
||||
|
||||
/* Set pixel information */
|
||||
GetColorMask(PixelsBitMask->RedMask, &DisplayInfo.ModeInfo.PixelInformation.RedSize,
|
||||
&DisplayInfo.ModeInfo.PixelInformation.RedShift);
|
||||
GetColorMask(PixelsBitMask->GreenMask, &DisplayInfo.ModeInfo.PixelInformation.GreenSize,
|
||||
&DisplayInfo.ModeInfo.PixelInformation.GreenShift);
|
||||
GetColorMask(PixelsBitMask->BlueMask, &DisplayInfo.ModeInfo.PixelInformation.BlueSize,
|
||||
&DisplayInfo.ModeInfo.PixelInformation.BlueShift);
|
||||
GetColorMask(PixelsBitMask->ReservedMask, &DisplayInfo.ModeInfo.PixelInformation.ReservedSize,
|
||||
&DisplayInfo.ModeInfo.PixelInformation.ReservedShift);
|
||||
break;
|
||||
default:
|
||||
/* Unknown pixel format */
|
||||
DisplayInfo.ModeInfo.BitsPerPixel = 0;
|
||||
DisplayInfo.ModeInfo.PixelInformation.BlueShift = 0;
|
||||
DisplayInfo.ModeInfo.PixelInformation.BlueSize = 0;
|
||||
DisplayInfo.ModeInfo.PixelInformation.GreenShift = 0;
|
||||
DisplayInfo.ModeInfo.PixelInformation.GreenSize = 0;
|
||||
DisplayInfo.ModeInfo.PixelInformation.RedShift = 0;
|
||||
DisplayInfo.ModeInfo.PixelInformation.RedSize = 0;
|
||||
DisplayInfo.ModeInfo.PixelInformation.ReservedShift = 0;
|
||||
DisplayInfo.ModeInfo.PixelInformation.ReservedSize = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
/* Calculate bytes per pixel based on bits per pixel */
|
||||
DisplayInfo.ModeInfo.BytesPerPixel = DisplayInfo.ModeInfo.BitsPerPixel >> 3;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines the preferred (native) screen resolution from EDID. This works only with GOP.
|
||||
*
|
||||
* @param PreferredWidth
|
||||
* Supplies a pointer to the memory area where preferred screen width will be stored.
|
||||
*
|
||||
* @param PreferredHeight
|
||||
* Supplies a pointer to the memory area where preferred screen height will be stored.
|
||||
*
|
||||
* @return This routine returns a status code.
|
||||
*
|
||||
* @since XT 1.0
|
||||
*/
|
||||
XTCDECL
|
||||
EFI_STATUS
|
||||
FrameBuffer::GetPreferredScreenResolution(OUT PUINT PreferredWidth,
|
||||
OUT PUINT PreferredHeight)
|
||||
{
|
||||
EFI_GUID GopGuid = EFI_GRAPHICS_OUTPUT_PROTOCOL_GUID;
|
||||
EFI_GUID EdidGuid = EFI_EDID_ACTIVE_PROTOCOL_GUID;
|
||||
PEFI_EDID_ACTIVE_PROTOCOL ActiveEdid;
|
||||
EFI_STATUS Status;
|
||||
|
||||
/* Check if framebuffer is initialized */
|
||||
if(!DisplayInfo.Initialized)
|
||||
{
|
||||
/* Framebuffer not ready to use EDID protocol */
|
||||
return STATUS_EFI_NOT_READY;
|
||||
}
|
||||
|
||||
/* Check if GOP device driver is used */
|
||||
if(DisplayInfo.Protocol != GOP)
|
||||
{
|
||||
/* Unsupported device driver */
|
||||
return STATUS_EFI_UNSUPPORTED;
|
||||
}
|
||||
|
||||
/* Open EDID protocol */
|
||||
Status = XtLdrProtocol->Protocol.OpenHandle(DisplayInfo.Handle, (PVOID *)&ActiveEdid, &EdidGuid);
|
||||
if(Status != STATUS_EFI_SUCCESS)
|
||||
{
|
||||
/* Failed to open EDID protocol, close GOP protocol and return */
|
||||
XtLdrProtocol->Protocol.Close(&DisplayInfo.Handle, &GopGuid);
|
||||
return Status;
|
||||
}
|
||||
|
||||
/* Return preferred screen resolution */
|
||||
*PreferredWidth = ActiveEdid->Edid[0x38] | ((ActiveEdid->Edid[0x3A] & 0xF0) << 4);
|
||||
*PreferredHeight = ActiveEdid->Edid[0x3B] | ((ActiveEdid->Edid[0x3D] & 0xF0) << 4);
|
||||
|
||||
/* Close EDID & GOP protocols */
|
||||
XtLdrProtocol->Protocol.Close(&DisplayInfo.Handle, &EdidGuid);
|
||||
|
||||
/* Return success */
|
||||
return STATUS_EFI_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* Initializes FrameBuffer device on GOP and UGA compatible adapters.
|
||||
*
|
||||
* @return This routine returns a status code.
|
||||
*
|
||||
* @since XT 1.0
|
||||
*/
|
||||
XTCDECL
|
||||
EFI_STATUS
|
||||
FrameBuffer::InitializeDisplay()
|
||||
{
|
||||
EFI_GUID GopGuid = EFI_GRAPHICS_OUTPUT_PROTOCOL_GUID;
|
||||
EFI_GUID UgaGuid = EFI_UNIVERSAL_GRAPHICS_ADAPTER_PROTOCOL_GUID;
|
||||
PEFI_GRAPHICS_OUTPUT_MODE_INFORMATION GopModeInfo;
|
||||
UINT Depth, QueryMode, Refresh;
|
||||
UINT_PTR InfoSize;
|
||||
EFI_STATUS Status;
|
||||
|
||||
/* Check if framebuffer already initialized */
|
||||
if(!DisplayInfo.Initialized)
|
||||
{
|
||||
/* Print debug message */
|
||||
XtLdrProtocol->Debug.Print(L"Initializing framebuffer device\n");
|
||||
|
||||
/* Attempt to open EFI GOP protocol */
|
||||
Status = XtLdrProtocol->Protocol.Open(&DisplayInfo.Handle, (PVOID*)&DisplayInfo.Driver.Gop, &GopGuid);
|
||||
|
||||
/* Check if Graphics Output Protocol (GOP) is available */
|
||||
if(Status == STATUS_EFI_SUCCESS)
|
||||
{
|
||||
/* Check if there are any video modes available */
|
||||
if(DisplayInfo.Driver.Gop->Mode->MaxMode == 0)
|
||||
{
|
||||
/* No video modes available */
|
||||
XtLdrProtocol->Debug.Print(L"ERROR: No GOP video mode available\n");
|
||||
|
||||
/* Close GOP protocol and return error */
|
||||
XtLdrProtocol->Protocol.Close(&DisplayInfo.Handle, &GopGuid);
|
||||
return STATUS_EFI_UNSUPPORTED;
|
||||
}
|
||||
|
||||
/* Query current graphics mode */
|
||||
QueryMode = DisplayInfo.Driver.Gop->Mode == NULLPTR ? 0 : DisplayInfo.Driver.Gop->Mode->Mode;
|
||||
Status = DisplayInfo.Driver.Gop->QueryMode(DisplayInfo.Driver.Gop, QueryMode, &InfoSize, &GopModeInfo);
|
||||
if(Status == STATUS_EFI_NOT_STARTED)
|
||||
{
|
||||
/* Set the mode to circumvent buggy UEFI firmware */
|
||||
Status = DisplayInfo.Driver.Gop->SetMode(DisplayInfo.Driver.Gop, 0);
|
||||
}
|
||||
if(Status != STATUS_EFI_SUCCESS)
|
||||
{
|
||||
/* Unable to query GOP modes */
|
||||
XtLdrProtocol->Debug.Print(L"ERROR: Failed to get GOP native mode (Status Code: 0x%zX)\n");
|
||||
|
||||
/* Close GOP protocol and return error */
|
||||
XtLdrProtocol->Protocol.Close(&DisplayInfo.Handle, &GopGuid);
|
||||
return STATUS_EFI_UNSUPPORTED;
|
||||
}
|
||||
|
||||
/* Store frame buffer base address and protocol used */
|
||||
DisplayInfo.FrameBufferBase = DisplayInfo.Driver.Gop->Mode->FrameBufferBase;
|
||||
DisplayInfo.DefaultMode = DisplayInfo.Driver.Gop->Mode->Mode;
|
||||
DisplayInfo.Protocol = GOP;
|
||||
|
||||
/* Get current mode information */
|
||||
Status = GetModeInformation();
|
||||
if(Status != STATUS_EFI_SUCCESS)
|
||||
{
|
||||
/* Unable to get mode information */
|
||||
XtLdrProtocol->Debug.Print(L"ERROR: Failed to get GOP mode information (Status Code: 0x%zX)\n");
|
||||
|
||||
/* Close GOP protocol and return error */
|
||||
XtLdrProtocol->Protocol.Close(&DisplayInfo.Handle, &GopGuid);
|
||||
return STATUS_EFI_UNSUPPORTED;
|
||||
}
|
||||
|
||||
/* Found GOP */
|
||||
XtLdrProtocol->Debug.Print(L"Found EFI-GOP compatible display adapter @ %P (%zu bytes)\n",
|
||||
DisplayInfo.FrameBufferBase, DisplayInfo.FrameBufferSize);
|
||||
|
||||
/* Close GOP protocol */
|
||||
Status = XtLdrProtocol->Protocol.Close(&DisplayInfo.Handle, &GopGuid);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* GOP is unavailable, attempt to open UGA protocol */
|
||||
Status = XtLdrProtocol->Protocol.Open(&DisplayInfo.Handle, (PVOID*)&DisplayInfo.Driver.Uga, &UgaGuid);
|
||||
|
||||
/* Check if Universal Graphics Adapter (UGA) is available */
|
||||
if(Status == STATUS_EFI_SUCCESS)
|
||||
{
|
||||
/* Get current video mode */
|
||||
Status = DisplayInfo.Driver.Uga->GetMode(DisplayInfo.Driver.Uga, &DisplayInfo.ModeInfo.Width,
|
||||
&DisplayInfo.ModeInfo.Height, &Depth, &Refresh);
|
||||
if(Status != STATUS_EFI_SUCCESS)
|
||||
{
|
||||
/* Unable to get current UGA mode */
|
||||
XtLdrProtocol->Debug.Print(L"ERROR: Failed to get current UGA mode (Status Code: 0x%zX)\n", Status);
|
||||
|
||||
/* Close UGA protocol and return error */
|
||||
XtLdrProtocol->Protocol.Close(&DisplayInfo.Handle, &UgaGuid);
|
||||
return STATUS_EFI_DEVICE_ERROR;
|
||||
}
|
||||
|
||||
/* Find framebuffer address */
|
||||
Status = FindFramebufferAddress(&DisplayInfo.FrameBufferBase);
|
||||
if(Status != STATUS_EFI_SUCCESS)
|
||||
{
|
||||
/* Unable to find framebuffer address */
|
||||
XtLdrProtocol->Debug.Print(L"ERROR: Failed to get EFI FB address (Status Code: 0x%zX)\n", Status);
|
||||
|
||||
/* Close UGA protocol and return error */
|
||||
XtLdrProtocol->Protocol.Close(&DisplayInfo.Handle, &UgaGuid);
|
||||
return STATUS_EFI_DEVICE_ERROR;
|
||||
}
|
||||
|
||||
/* Store framebuffer protocol information */
|
||||
DisplayInfo.DefaultMode = 0;
|
||||
DisplayInfo.Protocol = UGA;
|
||||
|
||||
/* Get mode information */
|
||||
Status = GetModeInformation();
|
||||
if(Status != STATUS_EFI_SUCCESS)
|
||||
{
|
||||
/* Unable to get mode information */
|
||||
XtLdrProtocol->Debug.Print(L"ERROR: Failed to get UGA mode information (Status Code: 0x%zX)\n");
|
||||
return STATUS_EFI_UNSUPPORTED;
|
||||
}
|
||||
|
||||
/* Found UGA */
|
||||
XtLdrProtocol->Debug.Print(L"Found EFI-UGA compatible display adapter @ %P (%zu bytes)\n",
|
||||
DisplayInfo.FrameBufferBase, DisplayInfo.FrameBufferSize);
|
||||
|
||||
/* Close UGA protocol */
|
||||
XtLdrProtocol->Protocol.Close(&DisplayInfo.Handle, &UgaGuid);
|
||||
}
|
||||
}
|
||||
|
||||
/* Make sure framebuffer initialized properly */
|
||||
if(DisplayInfo.Protocol == NONE)
|
||||
{
|
||||
/* GOP and UGA unavailable */
|
||||
XtLdrProtocol->Debug.Print(L"WARNING: No display adapter found!\n");
|
||||
return STATUS_EFI_NOT_FOUND;
|
||||
}
|
||||
|
||||
XtLdrProtocol->Debug.Print(L"Current screen resolution is %ux%ux%u\n", DisplayInfo.ModeInfo.Width,
|
||||
DisplayInfo.ModeInfo.Height, DisplayInfo.ModeInfo.BitsPerPixel);
|
||||
|
||||
/* Set framebuffer initialization flag */
|
||||
DisplayInfo.Initialized = TRUE;
|
||||
}
|
||||
|
||||
/* Return success */
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* Initializes FRAMEBUF module by opening XTLDR protocol and installing FRAMEBUF protocol.
|
||||
*
|
||||
* @param ImageHandle
|
||||
* Firmware-allocated handle that identifies the image.
|
||||
*
|
||||
* @param SystemTable
|
||||
* Provides the EFI system table.
|
||||
*
|
||||
* @return This routine returns status code.
|
||||
*
|
||||
* @since XT 1.0
|
||||
*/
|
||||
XTCDECL
|
||||
EFI_STATUS
|
||||
FrameBuffer::InitializeModule(IN EFI_HANDLE ImageHandle,
|
||||
IN PEFI_SYSTEM_TABLE SystemTable)
|
||||
{
|
||||
EFI_GUID Guid = XT_FRAMEBUFFER_PROTOCOL_GUID;
|
||||
EFI_STATUS Status;
|
||||
|
||||
/* Open the XTLDR protocol */
|
||||
Status = BlGetXtLdrProtocol(SystemTable, ImageHandle, &XtLdrProtocol);
|
||||
if(Status != STATUS_EFI_SUCCESS)
|
||||
{
|
||||
/* Failed to open loader protocol */
|
||||
return STATUS_EFI_PROTOCOL_ERROR;
|
||||
}
|
||||
|
||||
/* Set initial framebuffer state */
|
||||
DisplayInfo.Protocol = NONE;
|
||||
DisplayInfo.Initialized = FALSE;
|
||||
|
||||
/* Set routines available via XTLDR framebuffer protocol */
|
||||
FbProtocol.GetDisplayDriver = GetDisplayDriver;
|
||||
FbProtocol.GetDisplayInformation = GetDisplayInformation;
|
||||
FbProtocol.GetPreferredScreenResolution = GetPreferredScreenResolution;
|
||||
FbProtocol.Initialize = InitializeDisplay;
|
||||
FbProtocol.SetScreenResolution = SetScreenResolution;
|
||||
|
||||
/* Register XTOS boot protocol */
|
||||
return XtLdrProtocol->Protocol.Install(&FbProtocol, &Guid);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets custom screen resolution, based on the provided width and height.
|
||||
*
|
||||
* @param Width
|
||||
* Supplies the width of the screen.
|
||||
*
|
||||
* @param Height
|
||||
* Supplies the height of the screen.
|
||||
*
|
||||
* @return This routine returns a status code.
|
||||
*
|
||||
* @since XT 1.0
|
||||
*/
|
||||
XTCDECL
|
||||
EFI_STATUS
|
||||
FrameBuffer::SetScreenResolution(IN UINT Width,
|
||||
IN UINT Height)
|
||||
{
|
||||
PEFI_GRAPHICS_OUTPUT_MODE_INFORMATION ModeInfo;
|
||||
BOOLEAN ModeChanged;
|
||||
EFI_STATUS Status;
|
||||
UINT_PTR Size;
|
||||
UINT Mode;
|
||||
|
||||
/* Check if framebuffer is initialized */
|
||||
if(!DisplayInfo.Initialized)
|
||||
{
|
||||
/* Framebuffer not ready to change screen mode */
|
||||
return STATUS_EFI_NOT_READY;
|
||||
}
|
||||
|
||||
ModeChanged = FALSE;
|
||||
|
||||
/* Change screen mode depending on display adapter protocol */
|
||||
switch(DisplayInfo.Protocol)
|
||||
{
|
||||
case GOP:
|
||||
/* GOP available, check if user specified screen resolution */
|
||||
if(Width == 0 || Height == 0)
|
||||
{
|
||||
/* No resolution specified, temporarily set lowest supported screen resolution */
|
||||
Status = DisplayInfo.Driver.Gop->SetMode(DisplayInfo.Driver.Gop, 1);
|
||||
if(Status == STATUS_EFI_SUCCESS)
|
||||
{
|
||||
/* Restore default graphics mode */
|
||||
Status = DisplayInfo.Driver.Gop->SetMode(DisplayInfo.Driver.Gop, DisplayInfo.DefaultMode);
|
||||
ModeChanged = (Status == STATUS_EFI_SUCCESS) ? TRUE : FALSE;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* User specified screen resolution, find a corresponding mode */
|
||||
Mode = 1;
|
||||
while(Mode <= DisplayInfo.Driver.Gop->Mode->MaxMode)
|
||||
{
|
||||
/* Get mode information */
|
||||
Status = DisplayInfo.Driver.Gop->QueryMode(DisplayInfo.Driver.Gop, Mode, &Size, &ModeInfo);
|
||||
if(Status == STATUS_EFI_SUCCESS && Size >= sizeof(*ModeInfo) && ModeInfo != NULLPTR)
|
||||
{
|
||||
/* Check if match found */
|
||||
if(ModeInfo->HorizontalResolution == Width && ModeInfo->VerticalResolution == Height)
|
||||
{
|
||||
/* Found corresponding mode, attempt to set it */
|
||||
Status = DisplayInfo.Driver.Gop->SetMode(DisplayInfo.Driver.Gop, Mode);
|
||||
if(Status == STATUS_EFI_SUCCESS)
|
||||
{
|
||||
/* New mode set correctly, use it */
|
||||
ModeChanged = TRUE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Try with next mode */
|
||||
Mode++;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case UGA:
|
||||
/* Set UGA screen mode, trying to keep current color depth and refresh rate */
|
||||
Status = DisplayInfo.Driver.Uga->SetMode(DisplayInfo.Driver.Uga, Width, Height,
|
||||
DisplayInfo.ModeInfo.Depth,
|
||||
DisplayInfo.ModeInfo.RefreshRate);
|
||||
if(Status == STATUS_EFI_SUCCESS)
|
||||
{
|
||||
/* New mode set correctly, use it */
|
||||
ModeChanged = TRUE;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
/* This should never be reached */
|
||||
break;
|
||||
}
|
||||
|
||||
if(!ModeChanged)
|
||||
{
|
||||
/* Failed to change screen mode */
|
||||
XtLdrProtocol->Debug.Print(L"ERROR: Failed to change screen mode to %ux%u (Status Code: 0x%zX)\n",
|
||||
Width, Height, Status);
|
||||
return STATUS_EFI_UNSUPPORTED;
|
||||
}
|
||||
|
||||
/* Get new screen mode information */
|
||||
Status = GetModeInformation();
|
||||
if(Status == STATUS_EFI_SUCCESS)
|
||||
{
|
||||
XtLdrProtocol->Debug.Print(L"Changed screen resolution to %ux%ux%u\n", DisplayInfo.ModeInfo.Width,
|
||||
DisplayInfo.ModeInfo.Height, DisplayInfo.ModeInfo.BitsPerPixel);
|
||||
}
|
||||
|
||||
/* Return success */
|
||||
return STATUS_EFI_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* This routine is the entry point of the XT EFI boot loader module.
|
||||
*
|
||||
* @param ImageHandle
|
||||
* Firmware-allocated handle that identifies the image.
|
||||
*
|
||||
* @param SystemTable
|
||||
* Provides the EFI system table.
|
||||
*
|
||||
* @return This routine returns status code.
|
||||
*
|
||||
* @since XT 1.0
|
||||
*/
|
||||
XTCDECL
|
||||
EFI_STATUS
|
||||
XtLdrModuleMain(IN EFI_HANDLE ImageHandle,
|
||||
IN PEFI_SYSTEM_TABLE SystemTable)
|
||||
{
|
||||
/* Initialize FRAMEBUF module */
|
||||
return FrameBuffer::InitializeModule(ImageHandle, SystemTable);
|
||||
}
|
44
boot/xtldr/modules/framebuf/includes/framebuf.hh
Normal file
44
boot/xtldr/modules/framebuf/includes/framebuf.hh
Normal file
@@ -0,0 +1,44 @@
|
||||
/**
|
||||
* PROJECT: ExectOS
|
||||
* COPYRIGHT: See COPYING.md in the top level directory
|
||||
* FILE: xtldr/modules/framebuf/includes/framebuf.hh
|
||||
* DESCRIPTION: EFI Framebuffer support module header file
|
||||
* DEVELOPERS: Rafal Kupiec <belliash@codingworkshop.eu.org>
|
||||
*/
|
||||
|
||||
#ifndef __XTLDR_MODULES_FRAMEBUF_HH
|
||||
#define __XTLDR_MODULES_FRAMEBUF_HH
|
||||
|
||||
#include <xtblapi.h>
|
||||
|
||||
|
||||
class FrameBuffer
|
||||
{
|
||||
private:
|
||||
STATIC XTBL_FRAMEBUFFER_INFORMATION DisplayInfo;
|
||||
STATIC XTBL_FRAMEBUFFER_PROTOCOL FbProtocol;
|
||||
STATIC PXTBL_LOADER_PROTOCOL XtLdrProtocol;
|
||||
|
||||
public:
|
||||
STATIC XTCDECL EFI_STATUS GetDisplayDriver(OUT PEFI_GRAPHICS_PROTOCOL Protocol);
|
||||
STATIC XTCDECL EFI_STATUS GetDisplayInformation(OUT PEFI_PHYSICAL_ADDRESS FrameBufferBase,
|
||||
OUT PULONG_PTR FrameBufferSize,
|
||||
OUT PXTBL_FRAMEBUFFER_MODE_INFORMATION ModeInfo);
|
||||
STATIC XTCDECL EFI_STATUS GetPreferredScreenResolution(OUT PUINT PreferredWidth,
|
||||
OUT PUINT PreferredHeight);
|
||||
STATIC XTCDECL EFI_STATUS InitializeDisplay();
|
||||
STATIC XTCDECL EFI_STATUS InitializeModule(IN EFI_HANDLE ImageHandle,
|
||||
IN PEFI_SYSTEM_TABLE SystemTable);
|
||||
STATIC XTCDECL EFI_STATUS SetScreenResolution(IN UINT Width,
|
||||
IN UINT Height);
|
||||
|
||||
private:
|
||||
STATIC EFI_STATUS FindFramebufferAddress(OUT PEFI_PHYSICAL_ADDRESS Address);
|
||||
STATIC XTCDECL VOID GetColorMask(IN UINT EfiMask,
|
||||
OUT PUSHORT ColorSize,
|
||||
OUT PUSHORT ColorShift);
|
||||
STATIC XTCDECL EFI_STATUS GetModeInformation();
|
||||
STATIC XTCDECL VOID GetPixelInformation(IN PEFI_PIXEL_BITMASK PixelsBitMask);
|
||||
};
|
||||
|
||||
#endif /* __XTLDR_MODULES_FRAMEBUF_HH */
|
27
boot/xtldr/modules/pecoff/CMakeLists.txt
Normal file
27
boot/xtldr/modules/pecoff/CMakeLists.txt
Normal file
@@ -0,0 +1,27 @@
|
||||
# XTLDR PE/COFF image support module
|
||||
PROJECT(XTLDR_PECOFF)
|
||||
|
||||
# Specify include directories
|
||||
include_directories(
|
||||
${EXECTOS_SOURCE_DIR}/sdk/xtdk
|
||||
${XTLDR_PECOFF_SOURCE_DIR}/includes)
|
||||
|
||||
# Specify list of source code files
|
||||
list(APPEND XTLDR_PECOFF_SOURCE
|
||||
${XTLDR_PECOFF_SOURCE_DIR}/data.cc
|
||||
${XTLDR_PECOFF_SOURCE_DIR}/pecoff.cc)
|
||||
|
||||
# Link module executable
|
||||
add_executable(pecoff ${XTLDR_PECOFF_SOURCE})
|
||||
|
||||
# Add linker libraries
|
||||
target_link_libraries(pecoff libxtldr libxtos)
|
||||
|
||||
# Set proper binary name and install target
|
||||
set_target_properties(pecoff PROPERTIES SUFFIX .efi)
|
||||
set_install_target(pecoff efi/boot/xtldr/modules)
|
||||
|
||||
# Set module entrypoint and subsystem
|
||||
set_entrypoint(pecoff "XtLdrModuleMain")
|
||||
set_linker_map(pecoff TRUE)
|
||||
set_subsystem(pecoff efi_boot_service_driver)
|
16
boot/xtldr/modules/pecoff/data.cc
Normal file
16
boot/xtldr/modules/pecoff/data.cc
Normal file
@@ -0,0 +1,16 @@
|
||||
/**
|
||||
* PROJECT: ExectOS
|
||||
* COPYRIGHT: See COPYING.md in the top level directory
|
||||
* FILE: xtldr/modules/pecoff/globals.cc
|
||||
* DESCRIPTION: Basic PE/COFF executable file format global and static data
|
||||
* DEVELOPERS: Rafal Kupiec <belliash@codingworkshop.eu.org>
|
||||
*/
|
||||
|
||||
#include <pecoff.hh>
|
||||
|
||||
|
||||
/* XTOS PE/COFF Image Protocol */
|
||||
XTBL_EXECUTABLE_IMAGE_PROTOCOL PeCoff::PeProtocol;
|
||||
|
||||
/* EFI XT Loader Protocol */
|
||||
PXTBL_LOADER_PROTOCOL PeCoff::XtLdrProtocol;
|
53
boot/xtldr/modules/pecoff/includes/pecoff.hh
Normal file
53
boot/xtldr/modules/pecoff/includes/pecoff.hh
Normal file
@@ -0,0 +1,53 @@
|
||||
/**
|
||||
* PROJECT: ExectOS
|
||||
* COPYRIGHT: See COPYING.md in the top level directory
|
||||
* FILE: xtldr/modules/pecoff/includes/pecoff.hh
|
||||
* DESCRIPTION: Basic PE/COFF executable file format support header
|
||||
* DEVELOPERS: Rafal Kupiec <belliash@codingworkshop.eu.org>
|
||||
*/
|
||||
|
||||
#ifndef __XTLDR_PECOFF_HH
|
||||
#define __XTLDR_PECOFF_HH
|
||||
|
||||
#include <xtblapi.h>
|
||||
|
||||
|
||||
/* PE/COFF module for XTLDR */
|
||||
class PeCoff
|
||||
{
|
||||
private:
|
||||
STATIC XTBL_EXECUTABLE_IMAGE_PROTOCOL PeProtocol;
|
||||
STATIC PXTBL_LOADER_PROTOCOL XtLdrProtocol;
|
||||
|
||||
public:
|
||||
STATIC XTCDECL EFI_STATUS GetEntryPoint(IN PVOID ImagePointer,
|
||||
OUT PVOID *EntryPoint);
|
||||
STATIC XTCDECL EFI_STATUS GetFileSize(IN PVOID ImagePointer,
|
||||
OUT PULONGLONG FileSize);
|
||||
STATIC XTCDECL EFI_STATUS GetImageSize(IN PVOID ImagePointer,
|
||||
OUT PUINT ImageSize);
|
||||
STATIC XTCDECL EFI_STATUS GetMachineType(IN PVOID ImagePointer,
|
||||
OUT PUSHORT MachineType);
|
||||
STATIC XTCDECL EFI_STATUS GetSection(IN PVOID ImagePointer,
|
||||
IN PCHAR SectionName,
|
||||
OUT PULONG *RawData);
|
||||
STATIC XTCDECL EFI_STATUS GetSubSystem(IN PVOID ImagePointer,
|
||||
OUT PUSHORT SubSystem);
|
||||
STATIC XTCDECL EFI_STATUS GetVersion(IN PVOID ImagePointer,
|
||||
OUT PUSHORT Version);
|
||||
STATIC XTCDECL EFI_STATUS InitializeModule(IN EFI_HANDLE ImageHandle,
|
||||
IN PEFI_SYSTEM_TABLE SystemTable);
|
||||
STATIC XTCDECL EFI_STATUS LoadImage(IN PEFI_FILE_HANDLE FileHandle,
|
||||
IN LOADER_MEMORY_TYPE MemoryType,
|
||||
IN PVOID VirtualAddress,
|
||||
OUT PVOID *ImagePointer);
|
||||
STATIC XTCDECL EFI_STATUS RelocateImage(IN PVOID ImagePointer,
|
||||
IN EFI_VIRTUAL_ADDRESS Address);
|
||||
STATIC XTCDECL EFI_STATUS UnloadImage(IN PVOID ImagePointer);
|
||||
STATIC XTCDECL EFI_STATUS VerifyImage(IN PVOID ImagePointer);
|
||||
|
||||
private:
|
||||
STATIC XTCDECL EFI_STATUS RelocateLoadedImage(IN PPECOFF_IMAGE_CONTEXT Image);
|
||||
};
|
||||
|
||||
#endif /* __XTLDR_PECOFF_HH */
|
923
boot/xtldr/modules/pecoff/pecoff.cc
Normal file
923
boot/xtldr/modules/pecoff/pecoff.cc
Normal file
@@ -0,0 +1,923 @@
|
||||
/**
|
||||
* PROJECT: ExectOS
|
||||
* COPYRIGHT: See COPYING.md in the top level directory
|
||||
* FILE: xtldr/modules/pecoff/pecoff.cc
|
||||
* DESCRIPTION: Basic PE/COFF executable file format support module
|
||||
* DEVELOPERS: Rafal Kupiec <belliash@codingworkshop.eu.org>
|
||||
*/
|
||||
|
||||
#include <pecoff.hh>
|
||||
|
||||
|
||||
/* PE/COFF_O module information */
|
||||
MODULE_AUTHOR(L"Rafal Kupiec <belliash@codingworkshop.eu.org>");
|
||||
MODULE_DESCRIPTION(L"Basic PE/COFF executable file format support");
|
||||
MODULE_LICENSE(L"GPLv3");
|
||||
MODULE_VERSION(L"0.1");
|
||||
|
||||
|
||||
/**
|
||||
* Returns the address of the entry point.
|
||||
*
|
||||
* @param ImagePointer
|
||||
* Supplies a pointer to the PE/COFF context structure representing the loaded image.
|
||||
*
|
||||
* @param EntryPoint
|
||||
* Supplies a pointer to the memory area where address of the image entry point will be stored.
|
||||
*
|
||||
* @return This routine returns a status code.
|
||||
*
|
||||
* @since XT 1.0
|
||||
*/
|
||||
XTCDECL
|
||||
EFI_STATUS
|
||||
PeCoff::GetEntryPoint(IN PVOID ImagePointer,
|
||||
OUT PVOID *EntryPoint)
|
||||
{
|
||||
PPECOFF_IMAGE_CONTEXT Image;
|
||||
|
||||
/* Get PE/COFF image pointer*/
|
||||
Image = (PPECOFF_IMAGE_CONTEXT)ImagePointer;
|
||||
|
||||
/* Validate input data */
|
||||
if(!Image || !Image->PeHeader)
|
||||
{
|
||||
/* Invalid parameter passed */
|
||||
return STATUS_EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
/* Check PE/COFF image type */
|
||||
if(Image->PeHeader->OptionalHeader32.Magic == PECOFF_IMAGE_PE_OPTIONAL_HDR64_MAGIC)
|
||||
{
|
||||
/* Get entry point from 64-bit optional header */
|
||||
*EntryPoint = (PUCHAR)Image->VirtualAddress + Image->PeHeader->OptionalHeader64.AddressOfEntryPoint;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Get entry point from 32-bit optional header */
|
||||
*EntryPoint = (PUCHAR)Image->VirtualAddress + Image->PeHeader->OptionalHeader32.AddressOfEntryPoint;
|
||||
}
|
||||
|
||||
/* Return success */
|
||||
return STATUS_EFI_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the size of the loaded PE/COFF file.
|
||||
*
|
||||
* @param ImagePointer
|
||||
* Supplies a pointer to the PE/COFF context structure representing the loaded image.
|
||||
*
|
||||
* @param ImageSize
|
||||
* Supplies a pointer to the memory area where file size will be stored.
|
||||
*
|
||||
* @return This routine returns a status code.
|
||||
*
|
||||
* @since XT 1.0
|
||||
*/
|
||||
XTCDECL
|
||||
EFI_STATUS
|
||||
PeCoff::GetFileSize(IN PVOID ImagePointer,
|
||||
OUT PULONGLONG FileSize)
|
||||
{
|
||||
PPECOFF_IMAGE_CONTEXT Image;
|
||||
|
||||
/* Get PE/COFF image pointer*/
|
||||
Image = (PPECOFF_IMAGE_CONTEXT)ImagePointer;
|
||||
|
||||
/* Validate input data */
|
||||
if(!Image || !Image->ImageSize)
|
||||
{
|
||||
/* Invalid parameter passed */
|
||||
return STATUS_EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
/* Get image size and return success */
|
||||
*FileSize = Image->FileSize;
|
||||
return STATUS_EFI_NOT_FOUND;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the size of the loaded PE/COFF image.
|
||||
*
|
||||
* @param ImagePointer
|
||||
* Supplies a pointer to the PE/COFF context structure representing the loaded image.
|
||||
*
|
||||
* @param ImageSize
|
||||
* Supplies a pointer to the memory area where image size will be stored.
|
||||
*
|
||||
* @return This routine returns a status code.
|
||||
*
|
||||
* @since XT 1.0
|
||||
*/
|
||||
XTCDECL
|
||||
EFI_STATUS
|
||||
PeCoff::GetImageSize(IN PVOID ImagePointer,
|
||||
OUT PUINT ImageSize)
|
||||
{
|
||||
PPECOFF_IMAGE_CONTEXT Image;
|
||||
|
||||
/* Get PE/COFF image pointer*/
|
||||
Image = (PPECOFF_IMAGE_CONTEXT)ImagePointer;
|
||||
|
||||
/* Validate input data */
|
||||
if(!Image || !Image->ImageSize)
|
||||
{
|
||||
/* Invalid parameter passed */
|
||||
return STATUS_EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
/* Get image size and return success */
|
||||
*ImageSize = Image->ImageSize;
|
||||
return STATUS_EFI_NOT_FOUND;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the machine type of the PE/COFF image.
|
||||
*
|
||||
* @param ImagePointer
|
||||
* Supplies a pointer to the PE/COFF context structure representing the loaded image.
|
||||
*
|
||||
* @param MachineType
|
||||
* Supplies a pointer to the memory area where a value defined for the 'machine' field will be stored.
|
||||
*
|
||||
* @return This routine returns a status code.
|
||||
*
|
||||
* @since XT 1.0
|
||||
*/
|
||||
XTCDECL
|
||||
EFI_STATUS
|
||||
PeCoff::GetMachineType(IN PVOID ImagePointer,
|
||||
OUT PUSHORT MachineType)
|
||||
{
|
||||
PPECOFF_IMAGE_CONTEXT Image;
|
||||
|
||||
/* Get PE/COFF image pointer*/
|
||||
Image = (PPECOFF_IMAGE_CONTEXT)ImagePointer;
|
||||
|
||||
/* Validate input data */
|
||||
if(!Image || !Image->PeHeader)
|
||||
{
|
||||
/* Invalid parameter passed */
|
||||
return STATUS_EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
/* Get image machine type and return success */
|
||||
*MachineType = Image->PeHeader->FileHeader.Machine;
|
||||
return STATUS_EFI_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an address to the specified section in the PE/COFF image.
|
||||
*
|
||||
* @param ImagePointer
|
||||
* Supplies a pointer to the PE/COFF context structure representing the loaded image.
|
||||
*
|
||||
* @param SectionName
|
||||
* Supplies a name of the requested section.
|
||||
*
|
||||
* @param RawData
|
||||
* Supplies a pointer to the memory area where the address of the requested section will be stored.
|
||||
*
|
||||
* @return This routine returns a status code.
|
||||
*
|
||||
* @since XT 1.0
|
||||
*/
|
||||
XTCDECL
|
||||
EFI_STATUS
|
||||
PeCoff::GetSection(IN PVOID ImagePointer,
|
||||
IN PCHAR SectionName,
|
||||
OUT PULONG *RawData)
|
||||
{
|
||||
PPECOFF_IMAGE_SECTION_HEADER SectionHeader;
|
||||
PPECOFF_IMAGE_CONTEXT Image;
|
||||
SIZE_T SectionNameLength;
|
||||
USHORT SectionIndex;
|
||||
|
||||
/* Get PE/COFF image pointer*/
|
||||
Image = (PPECOFF_IMAGE_CONTEXT)ImagePointer;
|
||||
|
||||
/* Validate input data */
|
||||
if(!Image || !Image->PeHeader)
|
||||
{
|
||||
/* Invalid parameter passed */
|
||||
return STATUS_EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
/* Check PE/COFF image type */
|
||||
if(Image->PeHeader->OptionalHeader32.Magic == PECOFF_IMAGE_PE_OPTIONAL_HDR64_MAGIC)
|
||||
{
|
||||
/* Find section header in 64-bit optional header */
|
||||
SectionHeader = (PPECOFF_IMAGE_SECTION_HEADER)((PUCHAR)&Image->PeHeader->OptionalHeader64 +
|
||||
Image->PeHeader->FileHeader.SizeOfOptionalHeader);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Find section header in 32-bit optional header */
|
||||
SectionHeader = (PPECOFF_IMAGE_SECTION_HEADER)((PUCHAR)&Image->PeHeader->OptionalHeader32 +
|
||||
Image->PeHeader->FileHeader.SizeOfOptionalHeader);
|
||||
}
|
||||
|
||||
/* Get section name length */
|
||||
SectionNameLength = XtLdrProtocol->String.Length(SectionName, 0);
|
||||
|
||||
/* Iterate through all image sections */
|
||||
for(SectionIndex = 0; SectionIndex < Image->PeHeader->FileHeader.NumberOfSections; SectionIndex++)
|
||||
{
|
||||
/* Check section name */
|
||||
if(XtLdrProtocol->String.Compare((PCHAR)SectionHeader[SectionIndex].Name, SectionName, SectionNameLength) == 0)
|
||||
{
|
||||
/* Store section address and return */
|
||||
*RawData = (PULONG)((PUCHAR)Image->Data + SectionHeader[SectionIndex].PointerToRawData);
|
||||
return STATUS_EFI_SUCCESS;
|
||||
}
|
||||
}
|
||||
|
||||
/* Section not found if reached here */
|
||||
return STATUS_EFI_NOT_FOUND;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an information about subsystem that is required to run PE/COFF image.
|
||||
*
|
||||
* @param ImagePointer
|
||||
* Supplies a pointer to the PE/COFF context structure representing the loaded image.
|
||||
*
|
||||
* @param SubSystem
|
||||
* Supplies a pointer to the memory area storing a value defined for the 'subsystem' field of the image.
|
||||
*
|
||||
* @return This routine returns a status code.
|
||||
*
|
||||
* @since XT 1.0
|
||||
*/
|
||||
XTCDECL
|
||||
EFI_STATUS
|
||||
PeCoff::GetSubSystem(IN PVOID ImagePointer,
|
||||
OUT PUSHORT SubSystem)
|
||||
{
|
||||
PPECOFF_IMAGE_CONTEXT Image;
|
||||
|
||||
/* Get PE/COFF image pointer*/
|
||||
Image = (PPECOFF_IMAGE_CONTEXT)ImagePointer;
|
||||
|
||||
/* Validate input data */
|
||||
if(!Image || !Image->PeHeader)
|
||||
{
|
||||
/* Invalid parameter passed */
|
||||
return STATUS_EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
/* Check PE/COFF image type */
|
||||
if(Image->PeHeader->OptionalHeader32.Magic == PECOFF_IMAGE_PE_OPTIONAL_HDR64_MAGIC)
|
||||
{
|
||||
/* Get image subsystem from 64-bit optional header */
|
||||
*SubSystem = Image->PeHeader->OptionalHeader64.Subsystem;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Get image subsystem from 32-bit optional header */
|
||||
*SubSystem = Image->PeHeader->OptionalHeader32.Subsystem;
|
||||
}
|
||||
|
||||
/* Return success */
|
||||
return STATUS_EFI_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an information about major image version.
|
||||
*
|
||||
* @param ImagePointer
|
||||
* Supplies a pointer to the PE/COFF context structure representing the loaded image.
|
||||
*
|
||||
* @param Version
|
||||
* Supplies a pointer to the memory area storing a major image version.
|
||||
*
|
||||
* @return This routine returns a status code.
|
||||
*
|
||||
* @since XT 1.0
|
||||
*/
|
||||
XTCDECL
|
||||
EFI_STATUS
|
||||
PeCoff::GetVersion(IN PVOID ImagePointer,
|
||||
OUT PUSHORT Version)
|
||||
{
|
||||
PPECOFF_IMAGE_CONTEXT Image;
|
||||
|
||||
/* Get PE/COFF image pointer*/
|
||||
Image = (PPECOFF_IMAGE_CONTEXT)ImagePointer;
|
||||
|
||||
/* Validate input data */
|
||||
if(!Image || !Image->PeHeader)
|
||||
{
|
||||
/* Invalid parameter passed */
|
||||
return STATUS_EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
/* Check PE/COFF image type */
|
||||
if(Image->PeHeader->OptionalHeader32.Magic == PECOFF_IMAGE_PE_OPTIONAL_HDR64_MAGIC)
|
||||
{
|
||||
/* Get image major version from 64-bit optional header */
|
||||
*Version = Image->PeHeader->OptionalHeader64.MajorImageVersion;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Get image major version from 32-bit optional header */
|
||||
*Version = Image->PeHeader->OptionalHeader32.MajorImageVersion;
|
||||
}
|
||||
|
||||
/* Return success */
|
||||
return STATUS_EFI_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* Initializes PECOFF module by opening XTLDR protocol and installing PECOFF protocol.
|
||||
*
|
||||
* @param ImageHandle
|
||||
* Firmware-allocated handle that identifies the image.
|
||||
*
|
||||
* @param SystemTable
|
||||
* Provides the EFI system table.
|
||||
*
|
||||
* @return This routine returns status code.
|
||||
*
|
||||
* @since XT 1.0
|
||||
*/
|
||||
XTCDECL
|
||||
EFI_STATUS
|
||||
PeCoff::InitializeModule(IN EFI_HANDLE ImageHandle,
|
||||
IN PEFI_SYSTEM_TABLE SystemTable)
|
||||
{
|
||||
EFI_GUID Guid = XT_PECOFF_IMAGE_PROTOCOL_GUID;
|
||||
EFI_STATUS Status;
|
||||
|
||||
/* Open the XTLDR protocol */
|
||||
Status = BlGetXtLdrProtocol(SystemTable, ImageHandle, &XtLdrProtocol);
|
||||
if(Status != STATUS_EFI_SUCCESS)
|
||||
{
|
||||
/* Failed to open loader protocol */
|
||||
return STATUS_EFI_PROTOCOL_ERROR;
|
||||
}
|
||||
|
||||
/* Set routines available via PE/COFF image protocol */
|
||||
PeProtocol.GetEntryPoint = GetEntryPoint;
|
||||
PeProtocol.GetFileSize = GetFileSize;
|
||||
PeProtocol.GetImageSize = GetImageSize;
|
||||
PeProtocol.GetMachineType = GetMachineType;
|
||||
PeProtocol.GetSection = GetSection;
|
||||
PeProtocol.GetSubSystem = GetSubSystem;
|
||||
PeProtocol.GetVersion = GetVersion;
|
||||
PeProtocol.LoadImage = LoadImage;
|
||||
PeProtocol.RelocateImage = RelocateImage;
|
||||
PeProtocol.UnloadImage = UnloadImage;
|
||||
PeProtocol.VerifyImage = VerifyImage;
|
||||
|
||||
/* Register PE/COFF protocol */
|
||||
return XtLdrProtocol->Protocol.Install(&PeProtocol, &Guid);
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads a PE/COFF image file.
|
||||
*
|
||||
* @param FileHandle
|
||||
* The handle of the opened portable executable (PE) file.
|
||||
*
|
||||
* @param MemoryType
|
||||
* Supplies the type of memory to be assigned to the memory descriptor.
|
||||
*
|
||||
* @param VirtualAddress
|
||||
* Optional virtual address pointing to the memory area where PE/COFF file will be loaded.
|
||||
*
|
||||
* @param Image
|
||||
* Supplies pointer to the memory area where loaded PE/COFF image context will be stored.
|
||||
*
|
||||
* @return This routine returns a status code.
|
||||
*
|
||||
* @since XT 1.0
|
||||
*/
|
||||
XTCDECL
|
||||
EFI_STATUS
|
||||
PeCoff::LoadImage(IN PEFI_FILE_HANDLE FileHandle,
|
||||
IN LOADER_MEMORY_TYPE MemoryType,
|
||||
IN PVOID VirtualAddress,
|
||||
OUT PVOID *ImagePointer)
|
||||
{
|
||||
EFI_GUID FileInfoGuid = EFI_FILE_INFO_PROTOCOL_GUID;
|
||||
PPECOFF_IMAGE_SECTION_HEADER SectionHeader;
|
||||
PPECOFF_IMAGE_CONTEXT ImageData;
|
||||
EFI_PHYSICAL_ADDRESS Address;
|
||||
PEFI_FILE_INFO FileInfo;
|
||||
UINT_PTR ReadSize;
|
||||
EFI_STATUS Status;
|
||||
UINT SectionSize;
|
||||
SIZE_T Pages;
|
||||
PUCHAR Data;
|
||||
UINT Index;
|
||||
|
||||
/* Set required size for getting file information */
|
||||
ReadSize = sizeof(EFI_FILE_INFO) + 32;
|
||||
|
||||
/* Allocate necessary amount of memory */
|
||||
Status = XtLdrProtocol->Memory.AllocatePool(ReadSize, (PVOID *)&FileInfo);
|
||||
if(Status != STATUS_EFI_SUCCESS)
|
||||
{
|
||||
/* Memory allocation failure */
|
||||
XtLdrProtocol->Debug.Print(L"ERROR: Memory allocation failure (Status Code: 0x%zX)\n", Status);
|
||||
return Status;
|
||||
}
|
||||
|
||||
/* First attempt to get file information */
|
||||
Status = FileHandle->GetInfo(FileHandle, &FileInfoGuid, &ReadSize, FileInfo);
|
||||
if(Status == STATUS_EFI_BUFFER_TOO_SMALL)
|
||||
{
|
||||
/* Buffer it too small, but EFI tells the required size, let's reallocate */
|
||||
XtLdrProtocol->Memory.FreePool(&FileInfo);
|
||||
Status = XtLdrProtocol->Memory.AllocatePool(ReadSize, (PVOID *)&FileInfo);
|
||||
if(Status != STATUS_EFI_SUCCESS)
|
||||
{
|
||||
/* Memory allocation failure */
|
||||
XtLdrProtocol->Debug.Print(L"ERROR: Memory allocation failure (Status Code: 0x%zX)\n", Status);
|
||||
return Status;
|
||||
}
|
||||
|
||||
/* Second attempt to get file information */
|
||||
Status = FileHandle->GetInfo(FileHandle, &FileInfoGuid, &ReadSize, FileInfo);
|
||||
}
|
||||
if(Status != STATUS_EFI_SUCCESS)
|
||||
{
|
||||
/* Unable to get file information */
|
||||
XtLdrProtocol->Debug.Print(L"ERROR: Failed to get PE/COFF file information (Status Code: 0x%zX)\n", Status);
|
||||
return Status;
|
||||
}
|
||||
|
||||
/* Allocate memory for storing image data */
|
||||
Status = XtLdrProtocol->Memory.AllocatePool(sizeof(PECOFF_IMAGE_CONTEXT), (PVOID *)&ImageData);
|
||||
if(Status != STATUS_EFI_SUCCESS)
|
||||
{
|
||||
/* Memory allocation failure */
|
||||
XtLdrProtocol->Debug.Print(L"ERROR: Memory allocation failure (Status Code: 0x%zX)\n", Status);
|
||||
return Status;
|
||||
}
|
||||
|
||||
/* Store file size and memory type, nullify data and free up memory */
|
||||
ImageData->Data = NULLPTR;
|
||||
ImageData->FileSize = FileInfo->FileSize;
|
||||
ImageData->MemoryType = MemoryType;
|
||||
XtLdrProtocol->Memory.FreePool(FileInfo);
|
||||
|
||||
/* Calculate number of pages */
|
||||
Pages = EFI_SIZE_TO_PAGES(ImageData->FileSize);
|
||||
|
||||
/* Allocate pages */
|
||||
Status = XtLdrProtocol->Memory.AllocatePages(AllocateAnyPages, Pages, &Address);
|
||||
if(Status != STATUS_EFI_SUCCESS)
|
||||
{
|
||||
/* Pages allocation failure */
|
||||
XtLdrProtocol->Debug.Print(L"ERROR: Pages allocation failure (Status Code: 0x%zX)\n", Status);
|
||||
XtLdrProtocol->Memory.FreePool(ImageData);
|
||||
return Status;
|
||||
}
|
||||
|
||||
/* Read PE/COFF image */
|
||||
ReadSize = Pages * EFI_PAGE_SIZE;
|
||||
Data = (PUCHAR)(UINT_PTR)Address;
|
||||
Status = FileHandle->Read(FileHandle, &ReadSize, Data);
|
||||
if(Status != STATUS_EFI_SUCCESS)
|
||||
{
|
||||
/* Failed to read data */
|
||||
XtLdrProtocol->Debug.Print(L"ERROR: Failed to read PE/COFF image file (Status Code: 0x%zX)\n", Status);
|
||||
XtLdrProtocol->Memory.FreePages(Pages, (EFI_PHYSICAL_ADDRESS)(UINT_PTR)Data);
|
||||
XtLdrProtocol->Memory.FreePool(ImageData);
|
||||
return Status;
|
||||
}
|
||||
|
||||
/* Extract DOS and PE headers */
|
||||
ImageData->DosHeader = (PPECOFF_IMAGE_DOS_HEADER)Data;
|
||||
ImageData->PeHeader = (PPECOFF_IMAGE_PE_HEADER)((PUCHAR)Data + ImageData->DosHeader->PeHeaderOffset);
|
||||
|
||||
/* Validate headers */
|
||||
Status = PeCoff::VerifyImage(ImageData);
|
||||
if(Status != STATUS_EFI_SUCCESS)
|
||||
{
|
||||
/* Header validation failed, probably broken or invalid PE/COFF image */
|
||||
XtLdrProtocol->Debug.Print(L"ERROR: Invalid PE/COFF image headers (Status Code: 0x%zX)\n", Status);
|
||||
XtLdrProtocol->Memory.FreePages(Pages, (EFI_PHYSICAL_ADDRESS)(UINT_PTR)Data);
|
||||
XtLdrProtocol->Memory.FreePool(ImageData);
|
||||
return Status;
|
||||
}
|
||||
|
||||
/* Make sure image is executable */
|
||||
if (!(ImageData->PeHeader->FileHeader.Characteristics & PECOFF_IMAGE_FILE_EXECUTABLE_IMAGE))
|
||||
{
|
||||
/* Loaded image is not executable */
|
||||
XtLdrProtocol->Debug.Print(L"ERROR: Non-executable PE/COFF image loaded\n");
|
||||
XtLdrProtocol->Memory.FreePages(Pages, (EFI_PHYSICAL_ADDRESS)(UINT_PTR)Data);
|
||||
XtLdrProtocol->Memory.FreePool(ImageData);
|
||||
return STATUS_EFI_LOAD_ERROR;
|
||||
}
|
||||
|
||||
/* Store image size depending on the PE/COFF image type */
|
||||
if(ImageData->PeHeader->OptionalHeader32.Magic == PECOFF_IMAGE_PE_OPTIONAL_HDR64_MAGIC)
|
||||
{
|
||||
/* Store 64-bit image size */
|
||||
ImageData->ImageSize = ImageData->PeHeader->OptionalHeader64.SizeOfImage;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Store 32-bit image size */
|
||||
ImageData->ImageSize = ImageData->PeHeader->OptionalHeader32.SizeOfImage;
|
||||
}
|
||||
|
||||
/* Calculate number of image pages */
|
||||
ImageData->ImagePages = EFI_SIZE_TO_PAGES(ImageData->ImageSize);
|
||||
|
||||
/* Allocate image pages */
|
||||
Status = XtLdrProtocol->Memory.AllocatePages(AllocateAnyPages, ImageData->ImagePages, &Address);
|
||||
if(Status != STATUS_EFI_SUCCESS)
|
||||
{
|
||||
/* Pages reallocation failure */
|
||||
XtLdrProtocol->Debug.Print(L"ERROR: Pages reallocation failure (Status Code: 0x%zX)\n", Status);
|
||||
XtLdrProtocol->Memory.FreePool(ImageData);
|
||||
return Status;
|
||||
}
|
||||
|
||||
/* Store image data and virtual address */
|
||||
ImageData->Data = (PUCHAR)(UINT_PTR)Address;
|
||||
ImageData->PhysicalAddress = (PVOID)(UINT_PTR)Address;
|
||||
if(VirtualAddress)
|
||||
{
|
||||
/* Virtual address passed to this routine */
|
||||
ImageData->VirtualAddress = VirtualAddress;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Virtual address not specified, use physical address */
|
||||
ImageData->VirtualAddress = (PVOID)(UINT_PTR)Address;
|
||||
}
|
||||
|
||||
/* Check the PE/COFF image type */
|
||||
if(ImageData->PeHeader->OptionalHeader32.Magic == PECOFF_IMAGE_PE_OPTIONAL_HDR64_MAGIC)
|
||||
{
|
||||
/* Copy all PE32+ sections */
|
||||
XtLdrProtocol->Memory.CopyMemory(ImageData->Data, Data, ImageData->PeHeader->OptionalHeader64.SizeOfHeaders);
|
||||
|
||||
/* Find PE32+ section header */
|
||||
SectionHeader = (PPECOFF_IMAGE_SECTION_HEADER)((PUCHAR)&ImageData->PeHeader->OptionalHeader64 +
|
||||
ImageData->PeHeader->FileHeader.SizeOfOptionalHeader);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Copy all PE32 sections */
|
||||
XtLdrProtocol->Memory.CopyMemory(ImageData->Data, Data, ImageData->PeHeader->OptionalHeader64.SizeOfHeaders);
|
||||
|
||||
/* Find PE32 section header */
|
||||
SectionHeader = (PPECOFF_IMAGE_SECTION_HEADER)((PUCHAR)&ImageData->PeHeader->OptionalHeader64 +
|
||||
ImageData->PeHeader->FileHeader.SizeOfOptionalHeader);
|
||||
}
|
||||
|
||||
/* Load each section into memory */
|
||||
for(Index = 0; Index < ImageData->PeHeader->FileHeader.NumberOfSections; Index++)
|
||||
{
|
||||
/* Check section raw data size and section virtual size */
|
||||
if(SectionHeader[Index].SizeOfRawData < SectionHeader[Index].Misc.VirtualSize)
|
||||
{
|
||||
/* Use raw data size if it is smaller than virtual size */
|
||||
SectionSize = SectionHeader[Index].SizeOfRawData;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* User virtual size otherwise */
|
||||
SectionSize = SectionHeader[Index].Misc.VirtualSize;
|
||||
}
|
||||
|
||||
/* Make sure section is available */
|
||||
if(SectionSize > 0 && SectionHeader[Index].PointerToRawData != 0)
|
||||
{
|
||||
/* Copy section */
|
||||
XtLdrProtocol->Memory.CopyMemory((PUCHAR)ImageData->Data + SectionHeader[Index].VirtualAddress,
|
||||
Data + SectionHeader[Index].PointerToRawData, SectionSize);
|
||||
}
|
||||
|
||||
/* Check if raw size is shorter than virtual size */
|
||||
if(SectionSize < SectionHeader[Index].Misc.VirtualSize)
|
||||
{
|
||||
/* Fill remaining space with zeroes */
|
||||
XtLdrProtocol->Memory.ZeroMemory((PUCHAR)ImageData->Data + SectionHeader[Index].VirtualAddress + SectionSize,
|
||||
SectionHeader[Index].Misc.VirtualSize - SectionSize);
|
||||
}
|
||||
}
|
||||
|
||||
/* Free pages */
|
||||
XtLdrProtocol->Memory.FreePages((EFI_PHYSICAL_ADDRESS)(UINT_PTR)Data, Pages);
|
||||
|
||||
/* Perform relocation fixups */
|
||||
Status = PeCoff::RelocateLoadedImage(ImageData);
|
||||
if(Status != STATUS_EFI_SUCCESS)
|
||||
{
|
||||
/* Failed to relocate image */
|
||||
XtLdrProtocol->Debug.Print(L"ERROR: PE/COFF image relocation failed (Status Code: 0x%zX)\n", Status);
|
||||
return Status;
|
||||
}
|
||||
|
||||
/* Store image data */
|
||||
*ImagePointer = ImageData;
|
||||
|
||||
/* Return SUCCESS */
|
||||
return STATUS_EFI_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* Relocates PE/COFF image to the specified address.
|
||||
*
|
||||
* @param ImagePointer
|
||||
* Supplies a pointer to the PE/COFF context structure representing the loaded image.
|
||||
*
|
||||
* @param Address
|
||||
* Specifies destination address of memory region, where image should be relocated.
|
||||
*
|
||||
* @return This routine returns a status code.
|
||||
*
|
||||
* @since XT 1.0
|
||||
*/
|
||||
XTCDECL
|
||||
EFI_STATUS
|
||||
PeCoff::RelocateImage(IN PVOID ImagePointer,
|
||||
IN EFI_VIRTUAL_ADDRESS Address)
|
||||
{
|
||||
PPECOFF_IMAGE_CONTEXT Image;
|
||||
ULONGLONG ImageBase, OldVirtualAddress;
|
||||
EFI_STATUS Status;
|
||||
|
||||
/* Get PE/COFF image pointer*/
|
||||
Image = (PPECOFF_IMAGE_CONTEXT)ImagePointer;
|
||||
|
||||
/* Store original virtual address */
|
||||
OldVirtualAddress = (UINT_PTR)Image->VirtualAddress;
|
||||
|
||||
/* Check PE/COFF image type */
|
||||
if(Image->PeHeader->OptionalHeader32.Magic == PECOFF_IMAGE_PE_OPTIONAL_HDR64_MAGIC)
|
||||
{
|
||||
/* This is 64-bit PE32+, store its image base address */
|
||||
ImageBase = Image->PeHeader->OptionalHeader64.ImageBase;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* This is 32-bit PE32, store its image base address */
|
||||
ImageBase = Image->PeHeader->OptionalHeader32.ImageBase;
|
||||
}
|
||||
|
||||
/* Overwrite virtual address and relocate image once again */
|
||||
Image->VirtualAddress = (PVOID)(Address - OldVirtualAddress + ImageBase);
|
||||
Status = PeCoff::RelocateLoadedImage(Image);
|
||||
if(Status != STATUS_EFI_SUCCESS)
|
||||
{
|
||||
/* Relocation failed */
|
||||
return Status;
|
||||
}
|
||||
|
||||
/* Store new image virtual address */
|
||||
Image->VirtualAddress = (PVOID)Address;
|
||||
|
||||
/* Return success */
|
||||
return STATUS_EFI_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* Relocates a loaded PE/COFF image.
|
||||
*
|
||||
* @param Image
|
||||
* Supplies a pointer to the PE/COFF context structure representing the loaded image.
|
||||
*
|
||||
* @return This routine returns a status code.
|
||||
*
|
||||
* @since XT 1.0
|
||||
*/
|
||||
XTCDECL
|
||||
EFI_STATUS
|
||||
PeCoff::RelocateLoadedImage(IN PPECOFF_IMAGE_CONTEXT Image)
|
||||
{
|
||||
PPECOFF_IMAGE_BASE_RELOCATION RelocationDir, RelocationEnd;
|
||||
PPECOFF_IMAGE_DATA_DIRECTORY DataDirectory;
|
||||
USHORT Offset, Type, Count;
|
||||
PUSHORT TypeOffset;
|
||||
ULONGLONG ImageBase;
|
||||
PUINT Address;
|
||||
PULONGLONG LongPtr;
|
||||
PUINT ShortPtr;
|
||||
|
||||
/* Make sure image is not stripped */
|
||||
if(Image->PeHeader->FileHeader.Characteristics & PECOFF_IMAGE_FILE_RELOCS_STRIPPED)
|
||||
{
|
||||
/* No relocation information found */
|
||||
XtLdrProtocol->Debug.Print(L"WARNING: PE/COFF image is stripped and contains no information about relocations\n");
|
||||
return STATUS_EFI_SUCCESS;
|
||||
}
|
||||
|
||||
/* Check PE/COFF image type */
|
||||
if(Image->PeHeader->OptionalHeader32.Magic == PECOFF_IMAGE_PE_OPTIONAL_HDR64_MAGIC)
|
||||
{
|
||||
/* Set relocation data directory and image base address */
|
||||
DataDirectory = &Image->PeHeader->OptionalHeader64.DataDirectory[PECOFF_IMAGE_DIRECTORY_ENTRY_BASERELOC];
|
||||
ImageBase = Image->PeHeader->OptionalHeader64.ImageBase;
|
||||
|
||||
/* Check if loaded 64-bit PE32+ image should be relocated */
|
||||
if(Image->PeHeader->OptionalHeader64.NumberOfRvaAndSizes <= PECOFF_IMAGE_DIRECTORY_ENTRY_BASERELOC ||
|
||||
DataDirectory->VirtualAddress == 0 || DataDirectory->Size < sizeof(PECOFF_IMAGE_BASE_RELOCATION))
|
||||
{
|
||||
/* No need to relocate the image */
|
||||
return STATUS_EFI_SUCCESS;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Check if loaded 32-bit PE32 image should be relocated */
|
||||
/* Set relocation data directory and image base address */
|
||||
DataDirectory = &Image->PeHeader->OptionalHeader32.DataDirectory[PECOFF_IMAGE_DIRECTORY_ENTRY_BASERELOC];
|
||||
ImageBase = Image->PeHeader->OptionalHeader32.ImageBase;
|
||||
|
||||
if(Image->PeHeader->OptionalHeader32.NumberOfRvaAndSizes <= PECOFF_IMAGE_DIRECTORY_ENTRY_BASERELOC ||
|
||||
DataDirectory->VirtualAddress == 0 || DataDirectory->Size < sizeof(PECOFF_IMAGE_BASE_RELOCATION))
|
||||
{
|
||||
/* No need to relocate the image */
|
||||
return STATUS_EFI_SUCCESS;
|
||||
}
|
||||
}
|
||||
|
||||
/* Set relocation pointers */
|
||||
RelocationDir = (PPECOFF_IMAGE_BASE_RELOCATION)((ULONG_PTR)Image->Data + DataDirectory->VirtualAddress);
|
||||
RelocationEnd = (PPECOFF_IMAGE_BASE_RELOCATION)((ULONG_PTR)RelocationDir + DataDirectory->Size);
|
||||
|
||||
/* Do relocations */
|
||||
while(RelocationDir < RelocationEnd && RelocationDir->SizeOfBlock > 0)
|
||||
{
|
||||
/* Calculate number of relocations needed, address and type offset */
|
||||
Count = (RelocationDir->SizeOfBlock - sizeof(PECOFF_IMAGE_BASE_RELOCATION)) / sizeof(USHORT);
|
||||
Address = (PUINT)((PUCHAR)Image->Data + RelocationDir->VirtualAddress);
|
||||
TypeOffset = (PUSHORT)((PUCHAR)RelocationDir + sizeof(PECOFF_IMAGE_BASE_RELOCATION));
|
||||
|
||||
/* Do relocations */
|
||||
while(Count--)
|
||||
{
|
||||
/* Calculate offset and relocation type */
|
||||
Offset = *TypeOffset & 0xFFF;
|
||||
Type = *TypeOffset >> 12;
|
||||
|
||||
/* Check if end of the loaded address reached */
|
||||
if((PVOID)(PUSHORT)(Address + Offset) >= (PUCHAR)Image->Data + Image->ImageSize)
|
||||
{
|
||||
/* Do not relocate after the end of loaded image */
|
||||
break;
|
||||
}
|
||||
|
||||
/* Make sure we are not going to relocate into .reloc section */
|
||||
if((ULONG_PTR)(Address + Offset) < (ULONG_PTR)RelocationDir ||
|
||||
(ULONG_PTR)(Address + Offset) >= (ULONG_PTR)RelocationEnd)
|
||||
{
|
||||
/* Apply relocation fixup */
|
||||
switch (Type)
|
||||
{
|
||||
case PECOFF_IMAGE_REL_BASED_ABSOLUTE:
|
||||
/* No relocation required */
|
||||
break;
|
||||
case PECOFF_IMAGE_REL_BASED_DIR64:
|
||||
/* 64-bit relocation */
|
||||
LongPtr = (PULONGLONG)((PUCHAR)Address + Offset);
|
||||
*LongPtr = *LongPtr - ImageBase + (UINT_PTR)Image->VirtualAddress;
|
||||
break;
|
||||
case PECOFF_IMAGE_REL_BASED_HIGHLOW:
|
||||
/* 32-bit relocation of hight and low half of address */
|
||||
ShortPtr = (PUINT)((PUCHAR)Address + Offset);
|
||||
*ShortPtr = *ShortPtr - ImageBase + (UINT_PTR)Image->VirtualAddress;
|
||||
break;
|
||||
default:
|
||||
/* Unknown or unsupported relocation type */
|
||||
return STATUS_EFI_UNSUPPORTED;
|
||||
}
|
||||
}
|
||||
/* Increment the type offset */
|
||||
TypeOffset++;
|
||||
}
|
||||
|
||||
/* Next relocation */
|
||||
RelocationDir = (PPECOFF_IMAGE_BASE_RELOCATION)((PUCHAR)RelocationDir + RelocationDir->SizeOfBlock);
|
||||
}
|
||||
|
||||
/* Return SUCCESS */
|
||||
return STATUS_EFI_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* Unloads a PE/COFF image file and frees allocated memory.
|
||||
*
|
||||
* @param ImagePointer
|
||||
* Supplies a pointer to the PE/COFF context structure representing the loaded image.
|
||||
*
|
||||
* @return This routine returns a status code.
|
||||
*
|
||||
* @since XT 1.0
|
||||
*/
|
||||
XTCDECL
|
||||
EFI_STATUS
|
||||
PeCoff::UnloadImage(IN PVOID ImagePointer)
|
||||
{
|
||||
PPECOFF_IMAGE_CONTEXT Image;
|
||||
EFI_STATUS Status;
|
||||
|
||||
/* Get PE/COFF image pointer*/
|
||||
Image = (PPECOFF_IMAGE_CONTEXT)ImagePointer;
|
||||
|
||||
/* Validate input data */
|
||||
if(!Image || !Image->Data)
|
||||
{
|
||||
/* Invalid parameter passed */
|
||||
return STATUS_EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
/* Free memory allocated for the image */
|
||||
Status = XtLdrProtocol->Memory.FreePages(Image->ImagePages, (EFI_PHYSICAL_ADDRESS)(UINT_PTR)Image->Data);
|
||||
Status |= XtLdrProtocol->Memory.FreePool(Image);
|
||||
|
||||
/* Return status */
|
||||
return Status;
|
||||
}
|
||||
|
||||
/**
|
||||
* Validates a PE/COFF image headers.
|
||||
*
|
||||
* @param ImagePointer
|
||||
* Supplies a pointer to the PE/COFF context structure representing the loaded image.
|
||||
*
|
||||
* @return This routine returns a status code.
|
||||
*
|
||||
* @since XT 1.0
|
||||
*/
|
||||
XTCDECL
|
||||
EFI_STATUS
|
||||
PeCoff::VerifyImage(IN PVOID ImagePointer)
|
||||
{
|
||||
PPECOFF_IMAGE_CONTEXT Image;
|
||||
|
||||
/* Get PE/COFF image pointer*/
|
||||
Image = (PPECOFF_IMAGE_CONTEXT)ImagePointer;
|
||||
|
||||
/* Validate input data */
|
||||
if(!Image || !Image->PeHeader)
|
||||
{
|
||||
/* Invalid parameter passed */
|
||||
return STATUS_EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
/* Validate file size */
|
||||
if(Image->FileSize < sizeof(PECOFF_IMAGE_DOS_HEADER))
|
||||
{
|
||||
/* PE/COFF image shorter than DOS header, return error*/
|
||||
return STATUS_EFI_END_OF_FILE;
|
||||
}
|
||||
|
||||
/* Validate DOS header */
|
||||
if(Image->DosHeader->Magic != PECOFF_IMAGE_DOS_SIGNATURE)
|
||||
{
|
||||
/* Invalid DOS signature, return error */
|
||||
return STATUS_EFI_INCOMPATIBLE_VERSION;
|
||||
}
|
||||
|
||||
/* Validate PE header */
|
||||
if(Image->PeHeader->Signature != PECOFF_IMAGE_NT_SIGNATURE &&
|
||||
Image->PeHeader->Signature != PECOFF_IMAGE_XT_SIGNATURE)
|
||||
{
|
||||
/* Invalid PE signature, return error */
|
||||
return STATUS_EFI_INCOMPATIBLE_VERSION;
|
||||
}
|
||||
|
||||
/* Validate optional header */
|
||||
if(Image->PeHeader->OptionalHeader32.Magic != PECOFF_IMAGE_PE_OPTIONAL_HDR32_MAGIC &&
|
||||
Image->PeHeader->OptionalHeader64.Magic != PECOFF_IMAGE_PE_OPTIONAL_HDR64_MAGIC)
|
||||
{
|
||||
/* Invalid optional header signature, return error */
|
||||
return STATUS_EFI_INCOMPATIBLE_VERSION;
|
||||
}
|
||||
|
||||
/* Return success */
|
||||
return STATUS_EFI_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* This routine is the entry point of the XT EFI boot loader module.
|
||||
*
|
||||
* @param ImageHandle
|
||||
* Firmware-allocated handle that identifies the image.
|
||||
*
|
||||
* @param SystemTable
|
||||
* Provides the EFI system table.
|
||||
*
|
||||
* @return This routine returns a status code.
|
||||
*
|
||||
* @since XT 1.0
|
||||
*/
|
||||
XTCDECL
|
||||
EFI_STATUS
|
||||
XtLdrModuleMain(IN EFI_HANDLE ImageHandle,
|
||||
IN PEFI_SYSTEM_TABLE SystemTable)
|
||||
{
|
||||
/* Initialize PECOFF module */
|
||||
return PeCoff::InitializeModule(ImageHandle, SystemTable);
|
||||
}
|
28
boot/xtldr/modules/xtos_o/CMakeLists.txt
Normal file
28
boot/xtldr/modules/xtos_o/CMakeLists.txt
Normal file
@@ -0,0 +1,28 @@
|
||||
# XT Boot Loader
|
||||
PROJECT(XTLDR_XTOS_O)
|
||||
|
||||
# Specify include directories
|
||||
include_directories(
|
||||
${EXECTOS_SOURCE_DIR}/sdk/xtdk
|
||||
${XTLDR_XTOS_O_SOURCE_DIR}/includes)
|
||||
|
||||
# Specify list of source code files
|
||||
list(APPEND XTLDR_XTOS_O_SOURCE
|
||||
${XTLDR_XTOS_O_SOURCE_DIR}/${ARCH}/memory.cc
|
||||
${XTLDR_XTOS_O_SOURCE_DIR}/data.cc
|
||||
${XTLDR_XTOS_O_SOURCE_DIR}/xtos.cc)
|
||||
|
||||
# Link bootloader executable
|
||||
add_executable(xtos_o ${XTLDR_XTOS_O_SOURCE})
|
||||
|
||||
# Add linker libraries
|
||||
target_link_libraries(xtos_o libxtos libxtldr)
|
||||
|
||||
# Set proper binary name and install target
|
||||
set_target_properties(xtos_o PROPERTIES SUFFIX .efi)
|
||||
set_install_target(xtos_o efi/boot/xtldr/modules)
|
||||
|
||||
# Set module entrypoint and subsystem
|
||||
set_entrypoint(xtos_o "XtLdrModuleMain")
|
||||
set_linker_map(xtos_o TRUE)
|
||||
set_subsystem(xtos_o efi_boot_service_driver)
|
298
boot/xtldr/modules/xtos_o/amd64/memory.cc
Normal file
298
boot/xtldr/modules/xtos_o/amd64/memory.cc
Normal file
@@ -0,0 +1,298 @@
|
||||
/**
|
||||
* PROJECT: ExectOS
|
||||
* COPYRIGHT: See COPYING.md in the top level directory
|
||||
* FILE: xtldr/amd64/memory.cc
|
||||
* DESCRIPTION: EFI memory management for AMD64 target
|
||||
* DEVELOPERS: Rafal Kupiec <belliash@codingworkshop.eu.org>
|
||||
* Aiken Harris <harraiken91@gmail.com>
|
||||
*/
|
||||
|
||||
#include <xtos.hh>
|
||||
|
||||
|
||||
/**
|
||||
* Determines the appropriate paging level (PML) for the AMD64 architecture.
|
||||
*
|
||||
* @param Parameters
|
||||
* A pointer to the wide character string containing the kernel boot parameters.
|
||||
*
|
||||
* @return This routine returns the appropriate page map level (5 if LA57 is enabled, 4 otherwise).
|
||||
*
|
||||
* @since XT 1.0
|
||||
*/
|
||||
XTCDECL
|
||||
ULONG
|
||||
Xtos::DeterminePagingLevel(IN CONST PWCHAR Parameters)
|
||||
{
|
||||
CPUID_REGISTERS CpuRegisters;
|
||||
|
||||
/* Prepare CPUID registers to query for STD7 features */
|
||||
XtLdrProtocol->Memory.ZeroMemory(&CpuRegisters, sizeof(CPUID_REGISTERS));
|
||||
CpuRegisters.Leaf = CPUID_GET_VENDOR_STRING;
|
||||
|
||||
/* Query CPUID */
|
||||
XtLdrProtocol->Cpu.CpuId(&CpuRegisters);
|
||||
|
||||
/* Verify if the CPU supports the STD7 feature leaf (0x00000007) */
|
||||
if(CpuRegisters.Eax >= CPUID_GET_STANDARD7_FEATURES)
|
||||
{
|
||||
/* Prepare CPUID registers to query for LA57 support */
|
||||
XtLdrProtocol->Memory.ZeroMemory(&CpuRegisters, sizeof(CPUID_REGISTERS));
|
||||
CpuRegisters.Leaf = CPUID_GET_STANDARD7_FEATURES;
|
||||
|
||||
/* Query CPUID */
|
||||
XtLdrProtocol->Cpu.CpuId(&CpuRegisters);
|
||||
|
||||
/* Check if eXtended Physical Addressing (XPA) is enabled and if LA57 is supported by the CPU */
|
||||
if((CpuRegisters.Ecx & CPUID_FEATURES_ECX_LA57) &&
|
||||
!(XtLdrProtocol->BootUtils.GetBooleanParameter(Parameters, L"NOXPA")))
|
||||
{
|
||||
/* Enable LA57 (PML5) */
|
||||
return 5;
|
||||
}
|
||||
}
|
||||
|
||||
/* Disable LA57 and use PML4 by default */
|
||||
return 4;
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds the actual memory mapping page table and enables paging. This routine exits EFI boot services as well.
|
||||
*
|
||||
* @param PageMap
|
||||
* Supplies a pointer to the page mapping structure.
|
||||
*
|
||||
* @return This routine returns a status code.
|
||||
*
|
||||
* @since XT 1.0
|
||||
*/
|
||||
XTCDECL
|
||||
EFI_STATUS
|
||||
Xtos::EnablePaging(IN PXTBL_PAGE_MAPPING PageMap)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
EFI_PHYSICAL_ADDRESS TrampolineAddress;
|
||||
PXT_TRAMPOLINE_ENTRY TrampolineEntry;
|
||||
ULONG_PTR TrampolineSize;
|
||||
PVOID TrampolineCode;
|
||||
|
||||
/* Build page map */
|
||||
Status = XtLdrProtocol->Memory.BuildPageMap(PageMap, (PageMap->PageMapLevel > 4) ? MM_P5E_LA57_BASE : MM_PXE_BASE);
|
||||
if(Status != STATUS_EFI_SUCCESS)
|
||||
{
|
||||
/* Failed to build page map */
|
||||
XtLdrProtocol->Debug.Print(L"Failed to build page map (Status code: %zX)\n", Status);
|
||||
return Status;
|
||||
}
|
||||
|
||||
/* Map memory for hardware layer */
|
||||
Status = MapHardwareMemoryPool(PageMap);
|
||||
if(Status != STATUS_EFI_SUCCESS)
|
||||
{
|
||||
/* Failed to map memory for hardware layer */
|
||||
XtLdrProtocol->Debug.Print(L"Failed to map memory for hardware leyer (Status code: %zX)\n", Status);
|
||||
return Status;
|
||||
}
|
||||
|
||||
/* Check the configured page map level to set the LA57 state accordingly */
|
||||
if(PageMap->PageMapLevel == 5)
|
||||
{
|
||||
/* Get the trampoline code information */
|
||||
XtLdrProtocol->BootUtils.GetTrampolineInformation(TrampolineEnableXpa, &TrampolineCode, &TrampolineSize);
|
||||
if(TrampolineCode == NULLPTR || TrampolineSize == 0)
|
||||
{
|
||||
/* Failed to get trampoline information */
|
||||
XtLdrProtocol->Debug.Print(L"Failed to get trampoline information\n");
|
||||
return STATUS_EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
/* Set the address of the trampoline code below 1MB */
|
||||
TrampolineAddress = MM_TRAMPOLINE_ADDRESS;
|
||||
|
||||
/* Allocate pages for the trampoline */
|
||||
Status = XtLdrProtocol->Memory.AllocatePages(AllocateAddress, EFI_SIZE_TO_PAGES(TrampolineSize), &TrampolineAddress);
|
||||
if(Status != STATUS_EFI_SUCCESS)
|
||||
{
|
||||
/* Failed to allocate memory for trampoline code */
|
||||
XtLdrProtocol->Debug.Print(L"Failed to allocate memory for trampoline code (Status code: %zX)\n", Status);
|
||||
return Status;
|
||||
}
|
||||
|
||||
/* Set the trampoline entry point and copy its code into the allocated buffer */
|
||||
TrampolineEntry = (PXT_TRAMPOLINE_ENTRY)(UINT_PTR)TrampolineAddress;
|
||||
XtLdrProtocol->Memory.CopyMemory((PVOID)TrampolineEntry, TrampolineCode, TrampolineSize);
|
||||
}
|
||||
|
||||
/* Exit EFI Boot Services */
|
||||
XtLdrProtocol->Debug.Print(L"Exiting EFI boot services\n");
|
||||
Status = XtLdrProtocol->Utils.ExitBootServices();
|
||||
if(Status != STATUS_EFI_SUCCESS)
|
||||
{
|
||||
/* Failed to exit boot services */
|
||||
XtLdrProtocol->Debug.Print(L"Failed to exit boot services (Status code: %zX)\n", Status);
|
||||
return STATUS_EFI_ABORTED;
|
||||
}
|
||||
|
||||
/* Check the configured page map level to set the LA57 state accordingly */
|
||||
if(PageMap->PageMapLevel == 5)
|
||||
{
|
||||
/* Enable Linear Address 57-bit (LA57) extension */
|
||||
XtLdrProtocol->Debug.Print(L"Enabling Linear Address 57-bit (LA57)\n");
|
||||
|
||||
/* Execute the trampoline to enable LA57 and write PML5 to CR3 */
|
||||
TrampolineEntry((UINT64)PageMap->PtePointer);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Disable Linear Address 57-bit (LA57) extension */
|
||||
XtLdrProtocol->Debug.Print(L"Disabling Linear Address 57-bit (LA57)\n");
|
||||
|
||||
/* Write PML4 to CR3 and enable paging */
|
||||
XtLdrProtocol->Cpu.WriteControlRegister(3, (UINT_PTR)PageMap->PtePointer);
|
||||
XtLdrProtocol->Cpu.WriteControlRegister(0, XtLdrProtocol->Cpu.ReadControlRegister(0) | CR0_PG);
|
||||
}
|
||||
|
||||
/* Return success */
|
||||
return STATUS_EFI_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* Maps the page table for hardware layer addess space.
|
||||
*
|
||||
* @param PageMap
|
||||
* Supplies a pointer to the page mapping structure.
|
||||
*
|
||||
* @return This routine returns a status code.
|
||||
*
|
||||
* @since XT 1.0
|
||||
*/
|
||||
XTCDECL
|
||||
EFI_STATUS
|
||||
Xtos::MapHardwareMemoryPool(IN PXTBL_PAGE_MAPPING PageMap)
|
||||
{
|
||||
PHARDWARE_PTE P5eBase, PdeBase, PpeBase, PxeBase;
|
||||
EFI_PHYSICAL_ADDRESS Address;
|
||||
EFI_STATUS Status;
|
||||
|
||||
if(PageMap->PageMapLevel == 5)
|
||||
{
|
||||
/* Get P5E (PML5) base address */
|
||||
P5eBase = (PHARDWARE_PTE)PageMap->PtePointer;
|
||||
|
||||
/* Check if P5E entry already exists */
|
||||
if(!P5eBase[(MM_HARDWARE_VA_START >> MM_P5I_SHIFT) & 0x1FF].Valid)
|
||||
{
|
||||
/* No valid P5E, allocate memory */
|
||||
Status = XtLdrProtocol->Memory.AllocatePages(AllocateAnyPages, 1, &Address);
|
||||
if(Status != STATUS_EFI_SUCCESS)
|
||||
{
|
||||
/* Memory allocation failure, return error */
|
||||
return Status;
|
||||
}
|
||||
|
||||
/* Zero fill memory used by P5E */
|
||||
XtLdrProtocol->Memory.ZeroMemory((PVOID)Address, EFI_PAGE_SIZE);
|
||||
|
||||
/* Make P5E valid */
|
||||
P5eBase[(MM_HARDWARE_VA_START >> MM_P5I_SHIFT) & 0x1FF].Valid = 1;
|
||||
P5eBase[(MM_HARDWARE_VA_START >> MM_P5I_SHIFT) & 0x1FF].PageFrameNumber = Address / EFI_PAGE_SIZE;
|
||||
P5eBase[(MM_HARDWARE_VA_START >> MM_P5I_SHIFT) & 0x1FF].Writable = 1;
|
||||
|
||||
/* Set PXE base address */
|
||||
PxeBase = (PHARDWARE_PTE)(UINT_PTR)Address;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Set PXE base address based on existing P5E */
|
||||
PxeBase = (PHARDWARE_PTE)((P5eBase[(MM_HARDWARE_VA_START >> MM_P5I_SHIFT) & 0x1FF].PageFrameNumber) << EFI_PAGE_SHIFT);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Get PXE (PML4) base address */
|
||||
PxeBase = (PHARDWARE_PTE)PageMap->PtePointer;
|
||||
}
|
||||
|
||||
/* Check if PXE entry already exists */
|
||||
if(!PxeBase[(MM_HARDWARE_VA_START >> MM_PXI_SHIFT) & 0x1FF].Valid)
|
||||
{
|
||||
/* No valid PXE, allocate memory */
|
||||
Status = XtLdrProtocol->Memory.AllocatePages(AllocateAnyPages, 1, &Address);
|
||||
if(Status != STATUS_EFI_SUCCESS)
|
||||
{
|
||||
/* Memory allocation failure, return error */
|
||||
return Status;
|
||||
}
|
||||
|
||||
/* Zero fill memory used by PXE */
|
||||
XtLdrProtocol->Memory.ZeroMemory((PVOID)Address, EFI_PAGE_SIZE);
|
||||
|
||||
/* Make PXE valid */
|
||||
PxeBase[(MM_HARDWARE_VA_START >> MM_PXI_SHIFT) & 0x1FF].Valid = 1;
|
||||
PxeBase[(MM_HARDWARE_VA_START >> MM_PXI_SHIFT) & 0x1FF].PageFrameNumber = Address / EFI_PAGE_SIZE;
|
||||
PxeBase[(MM_HARDWARE_VA_START >> MM_PXI_SHIFT) & 0x1FF].Writable = 1;
|
||||
|
||||
/* Set PPE base address */
|
||||
PpeBase = (PHARDWARE_PTE)(UINT_PTR)Address;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Set PPE base address based on existing PXE */
|
||||
PpeBase = (PHARDWARE_PTE)((PxeBase[(MM_HARDWARE_VA_START >> MM_PXI_SHIFT) & 0x1FF].PageFrameNumber) << EFI_PAGE_SHIFT);
|
||||
}
|
||||
|
||||
/* Check if PPE entry already exists */
|
||||
if(!PpeBase[(MM_HARDWARE_VA_START >> MM_PPI_SHIFT) & 0x1FF].Valid)
|
||||
{
|
||||
/* No valid PPE, allocate memory */
|
||||
Status = XtLdrProtocol->Memory.AllocatePages(AllocateAnyPages, 1, &Address);
|
||||
if(Status != STATUS_EFI_SUCCESS)
|
||||
{
|
||||
/* Memory allocation failure, return error */
|
||||
return Status;
|
||||
}
|
||||
|
||||
/* Zero fill memory used by PPE */
|
||||
XtLdrProtocol->Memory.ZeroMemory((PVOID)Address, EFI_PAGE_SIZE);
|
||||
|
||||
/* Make PPE valid */
|
||||
PpeBase[(MM_HARDWARE_VA_START >> MM_PPI_SHIFT) & 0x1FF].Valid = 1;
|
||||
PpeBase[(MM_HARDWARE_VA_START >> MM_PPI_SHIFT) & 0x1FF].PageFrameNumber = Address / EFI_PAGE_SIZE;
|
||||
PpeBase[(MM_HARDWARE_VA_START >> MM_PPI_SHIFT) & 0x1FF].Writable = 1;
|
||||
|
||||
/* Set PDE base address */
|
||||
PdeBase = (PHARDWARE_PTE)Address;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Set PDE base address, based on existing PPE */
|
||||
PdeBase = (PHARDWARE_PTE)((PpeBase[(MM_HARDWARE_VA_START >> MM_PPI_SHIFT) & 0x1FF].PageFrameNumber) << EFI_PAGE_SHIFT);
|
||||
}
|
||||
|
||||
/* Loop through 2 PDE entries */
|
||||
for(UINT Index = 0 ; Index < 2 ; Index++)
|
||||
{
|
||||
/* Check if PDE entry already exists */
|
||||
if(!PdeBase[((MM_HARDWARE_VA_START >> MM_PDI_SHIFT) & 0x1FF) + Index].Valid)
|
||||
{
|
||||
/* No valid PDE, allocate memory */
|
||||
Status = XtLdrProtocol->Memory.AllocatePages(AllocateAnyPages, 1, &Address);
|
||||
if(Status != STATUS_EFI_SUCCESS)
|
||||
{
|
||||
/* Memory allocation failure, return error */
|
||||
return Status;
|
||||
}
|
||||
|
||||
/* Zero fill memory used by PDE */
|
||||
XtLdrProtocol->Memory.ZeroMemory((PVOID)Address, EFI_PAGE_SIZE);
|
||||
|
||||
/* Make PDE valid */
|
||||
PdeBase[((MM_HARDWARE_VA_START >> MM_PDI_SHIFT) & 0x1FF) + Index].Valid = 1;
|
||||
PdeBase[((MM_HARDWARE_VA_START >> MM_PDI_SHIFT) & 0x1FF) + Index].PageFrameNumber = Address / EFI_PAGE_SIZE;
|
||||
PdeBase[((MM_HARDWARE_VA_START >> MM_PDI_SHIFT) & 0x1FF) + Index].Writable = 1;
|
||||
}
|
||||
}
|
||||
|
||||
/* Return success */
|
||||
return STATUS_EFI_SUCCESS;
|
||||
}
|
19
boot/xtldr/modules/xtos_o/data.cc
Normal file
19
boot/xtldr/modules/xtos_o/data.cc
Normal file
@@ -0,0 +1,19 @@
|
||||
/**
|
||||
* PROJECT: ExectOS
|
||||
* COPYRIGHT: See COPYING.md in the top level directory
|
||||
* FILE: xtldr/modules/xtos/data.cc
|
||||
* DESCRIPTION: XTOS module global and static data
|
||||
* DEVELOPERS: Rafal Kupiec <belliash@codingworkshop.eu.org>
|
||||
*/
|
||||
|
||||
#include <xtos.hh>
|
||||
|
||||
|
||||
/* XTOS Boot Protocol */
|
||||
XTBL_BOOT_PROTOCOL Xtos::BootProtocol;
|
||||
|
||||
/* XTOS PE/COFF Image Protocol */
|
||||
PXTBL_EXECUTABLE_IMAGE_PROTOCOL Xtos::PeCoffProtocol;
|
||||
|
||||
/* EFI XT Loader Protocol */
|
||||
PXTBL_LOADER_PROTOCOL Xtos::XtLdrProtocol;
|
181
boot/xtldr/modules/xtos_o/i686/memory.cc
Normal file
181
boot/xtldr/modules/xtos_o/i686/memory.cc
Normal file
@@ -0,0 +1,181 @@
|
||||
/**
|
||||
* PROJECT: ExectOS
|
||||
* COPYRIGHT: See COPYING.md in the top level directory
|
||||
* FILE: xtldr/i686/memory.cc
|
||||
* DESCRIPTION: EFI memory management for i686 target
|
||||
* DEVELOPERS: Rafal Kupiec <belliash@codingworkshop.eu.org>
|
||||
*/
|
||||
|
||||
#include <xtos.hh>
|
||||
|
||||
|
||||
/**
|
||||
* Determines the appropriate paging level (PML) for the i686 architecture.
|
||||
*
|
||||
* @param Parameters
|
||||
* A pointer to the wide character string containing the kernel boot parameters.
|
||||
*
|
||||
* @return This routine returns the appropriate page map level (3 if PAE is enabled, 2 otherwise).
|
||||
*
|
||||
* @since XT 1.0
|
||||
*/
|
||||
XTCDECL
|
||||
ULONG
|
||||
Xtos::DeterminePagingLevel(IN CONST PWCHAR Parameters)
|
||||
{
|
||||
CPUID_REGISTERS CpuRegisters;
|
||||
|
||||
/* Prepare CPUID registers to query for PAE support */
|
||||
XtLdrProtocol->Memory.ZeroMemory(&CpuRegisters, sizeof(CPUID_REGISTERS));
|
||||
CpuRegisters.Leaf = CPUID_GET_STANDARD1_FEATURES;
|
||||
|
||||
/* Query CPUID */
|
||||
XtLdrProtocol->Cpu.CpuId(&CpuRegisters);
|
||||
|
||||
/* Check if eXtended Physical Addressing (XPA) is enabled and if PAE is supported by the CPU */
|
||||
if((CpuRegisters.Edx & CPUID_FEATURES_EDX_PAE) &&
|
||||
!(XtLdrProtocol->BootUtils.GetBooleanParameter(Parameters, L"NOXPA")))
|
||||
{
|
||||
/* Enable PAE (PML3) */
|
||||
return 3;
|
||||
}
|
||||
|
||||
/* Disable PAE and use PML2 by default */
|
||||
return 2;
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds the actual memory mapping page table and enables paging. This routine exits EFI boot services as well.
|
||||
*
|
||||
* @param PageMap
|
||||
* Supplies a pointer to the page mapping structure.
|
||||
*
|
||||
* @return This routine returns a status code.
|
||||
*
|
||||
* @since XT 1.0
|
||||
*/
|
||||
XTCDECL
|
||||
EFI_STATUS
|
||||
Xtos::EnablePaging(IN PXTBL_PAGE_MAPPING PageMap)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
|
||||
/* Build page map */
|
||||
Status = XtLdrProtocol->Memory.BuildPageMap(PageMap, MM_PTE_BASE);
|
||||
if(Status != STATUS_EFI_SUCCESS)
|
||||
{
|
||||
/* Failed to build page map */
|
||||
XtLdrProtocol->Debug.Print(L"Failed to build page map (Status code: %zX)\n", Status);
|
||||
return Status;
|
||||
}
|
||||
|
||||
/* Map memory for hardware layer */
|
||||
Status = MapHardwareMemoryPool(PageMap);
|
||||
if(Status != STATUS_EFI_SUCCESS)
|
||||
{
|
||||
/* Failed to map memory for hardware layer */
|
||||
XtLdrProtocol->Debug.Print(L"Failed to map memory for hardware layer (Status code: %zX)\n", Status);
|
||||
return Status;
|
||||
}
|
||||
|
||||
/* Exit EFI Boot Services */
|
||||
XtLdrProtocol->Debug.Print(L"Exiting EFI boot services\n");
|
||||
Status = XtLdrProtocol->Utils.ExitBootServices();
|
||||
if(Status != STATUS_EFI_SUCCESS)
|
||||
{
|
||||
/* Failed to exit boot services */
|
||||
XtLdrProtocol->Debug.Print(L"Failed to exit boot services (Status code: %zX)\n", Status);
|
||||
return STATUS_EFI_ABORTED;
|
||||
}
|
||||
|
||||
/* Disable paging */
|
||||
XtLdrProtocol->Cpu.WriteControlRegister(0, XtLdrProtocol->Cpu.ReadControlRegister(0) & ~CR0_PG);
|
||||
|
||||
/* Check the configured page map level to set the PAE state accordingly */
|
||||
if(PageMap->PageMapLevel == 3)
|
||||
{
|
||||
/* Enable Physical Address Extension (PAE) */
|
||||
XtLdrProtocol->Debug.Print(L"Enabling Physical Address Extension (PAE)\n");
|
||||
XtLdrProtocol->Cpu.WriteControlRegister(4, XtLdrProtocol->Cpu.ReadControlRegister(4) | CR4_PAE);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Disable Physical Address Extension (PAE) */
|
||||
XtLdrProtocol->Debug.Print(L"Disabling Physical Address Extension (PAE)\n");
|
||||
XtLdrProtocol->Cpu.WriteControlRegister(4, XtLdrProtocol->Cpu.ReadControlRegister(4) & ~CR4_PAE);
|
||||
}
|
||||
|
||||
/* Write page mappings to CR3 */
|
||||
XtLdrProtocol->Cpu.WriteControlRegister(3, (UINT_PTR)PageMap->PtePointer);
|
||||
|
||||
/* Enable paging */
|
||||
XtLdrProtocol->Cpu.WriteControlRegister(0, XtLdrProtocol->Cpu.ReadControlRegister(0) | CR0_PG);
|
||||
|
||||
/* Return success */
|
||||
return STATUS_EFI_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* Maps the page table for hardware layer addess space.
|
||||
*
|
||||
* @param PageMap
|
||||
* Supplies a pointer to the page mapping structure.
|
||||
*
|
||||
* @return This routine returns a status code.
|
||||
*
|
||||
* @since XT 1.0
|
||||
*/
|
||||
XTCDECL
|
||||
EFI_STATUS
|
||||
Xtos::MapHardwareMemoryPool(IN PXTBL_PAGE_MAPPING PageMap)
|
||||
{
|
||||
EFI_PHYSICAL_ADDRESS Address;
|
||||
PHARDWARE_LEGACY_PTE LegacyPdeBase;
|
||||
PHARDWARE_MODERN_PTE PdeBase;
|
||||
EFI_STATUS Status;
|
||||
|
||||
/* Allocate memory */
|
||||
Status = XtLdrProtocol->Memory.AllocatePages(AllocateAnyPages, 1, &Address);
|
||||
if(Status != STATUS_EFI_SUCCESS)
|
||||
{
|
||||
/* Memory allocation failure, return error */
|
||||
return Status;
|
||||
}
|
||||
|
||||
/* Zero fill allocated memory */
|
||||
XtLdrProtocol->Memory.ZeroMemory((PVOID)Address, EFI_PAGE_SIZE);
|
||||
|
||||
/* Check if PAE is enabled (3-level paging) */
|
||||
if(PageMap->PageMapLevel == 3)
|
||||
{
|
||||
/* Get PDE base address (PAE enabled) */
|
||||
PdeBase = (PHARDWARE_MODERN_PTE)(((PHARDWARE_MODERN_PTE)PageMap->PtePointer)[MM_HARDWARE_VA_START >> MM_PPI_SHIFT].PageFrameNumber << MM_PAGE_SHIFT);
|
||||
|
||||
/* Make PDE valid */
|
||||
XtLdrProtocol->Memory.ZeroMemory(&PdeBase[(MM_HARDWARE_VA_START >> MM_PDI_SHIFT) & 0x1FF], sizeof(HARDWARE_MODERN_PTE));
|
||||
PdeBase[(MM_HARDWARE_VA_START >> MM_PDI_SHIFT) & 0x1FF].PageFrameNumber = Address >> MM_PAGE_SHIFT;
|
||||
PdeBase[(MM_HARDWARE_VA_START >> MM_PDI_SHIFT) & 0x1FF].Valid = 1;
|
||||
PdeBase[(MM_HARDWARE_VA_START >> MM_PDI_SHIFT) & 0x1FF].Writable = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Get PDE base address (PAE disabled) */
|
||||
LegacyPdeBase = (PHARDWARE_LEGACY_PTE)PageMap->PtePointer;
|
||||
|
||||
/* Check for a conflicting PDE */
|
||||
if(LegacyPdeBase[MM_HARDWARE_VA_START >> MM_PDI_LEGACY_SHIFT].Valid)
|
||||
{
|
||||
/* PDE already exists and is valid, nothing to do */
|
||||
return STATUS_EFI_SUCCESS;
|
||||
}
|
||||
|
||||
/* Make PDE valid */
|
||||
XtLdrProtocol->Memory.ZeroMemory(&LegacyPdeBase[MM_HARDWARE_VA_START >> MM_PDI_LEGACY_SHIFT], sizeof(HARDWARE_LEGACY_PTE));
|
||||
LegacyPdeBase[MM_HARDWARE_VA_START >> MM_PDI_LEGACY_SHIFT].Valid = 1;
|
||||
LegacyPdeBase[MM_HARDWARE_VA_START >> MM_PDI_LEGACY_SHIFT].PageFrameNumber = Address >> MM_PAGE_SHIFT;
|
||||
LegacyPdeBase[MM_HARDWARE_VA_START >> MM_PDI_LEGACY_SHIFT].Writable = 1;
|
||||
}
|
||||
|
||||
/* Return success */
|
||||
return STATUS_EFI_SUCCESS;
|
||||
}
|
78
boot/xtldr/modules/xtos_o/includes/xtos.hh
Normal file
78
boot/xtldr/modules/xtos_o/includes/xtos.hh
Normal file
@@ -0,0 +1,78 @@
|
||||
/**
|
||||
* PROJECT: ExectOS
|
||||
* COPYRIGHT: See COPYING.md in the top level directory
|
||||
* FILE: xtldr/modules/xtos/includes/xtos.hh
|
||||
* DESCRIPTION: XTOS boot protocol support header
|
||||
* DEVELOPERS: Rafal Kupiec <belliash@codingworkshop.eu.org>
|
||||
*/
|
||||
|
||||
#ifndef __XTLDR_MODULES_XTOS_HH
|
||||
#define __XTLDR_MODULES_XTOS_HH
|
||||
|
||||
#include <xtblapi.h>
|
||||
|
||||
|
||||
/* XTOS kernel entry point */
|
||||
typedef VOID (XTAPI *PXT_ENTRY_POINT)(IN PKERNEL_INITIALIZATION_BLOCK BootParameters);
|
||||
|
||||
/* XTOS trampoline entry point */
|
||||
typedef VOID (*PXT_TRAMPOLINE_ENTRY)(UINT64 PageMap);
|
||||
|
||||
|
||||
/* XTOS module for XTLDR */
|
||||
class Xtos
|
||||
{
|
||||
private:
|
||||
STATIC XTBL_BOOT_PROTOCOL BootProtocol;
|
||||
STATIC PXTBL_EXECUTABLE_IMAGE_PROTOCOL PeCoffProtocol;
|
||||
STATIC PXTBL_LOADER_PROTOCOL XtLdrProtocol;
|
||||
|
||||
public:
|
||||
STATIC XTCDECL EFI_STATUS BootSystem(IN PXTBL_BOOT_PARAMETERS Parameters);
|
||||
STATIC XTCDECL EFI_STATUS InitializeModule(IN EFI_HANDLE ImageHandle,
|
||||
IN PEFI_SYSTEM_TABLE SystemTable);
|
||||
|
||||
private:
|
||||
STATIC XTCDECL EFI_STATUS AddVirtualMemoryMapping(IN PLIST_ENTRY MemoryMappings,
|
||||
IN PVOID VirtualAddress,
|
||||
IN PVOID PhysicalAddress,
|
||||
IN UINT NumberOfPages,
|
||||
IN LOADER_MEMORY_TYPE MemoryType);
|
||||
STATIC XTCDECL LOADER_MEMORY_TYPE ConvertEfiMemoryType(IN EFI_MEMORY_TYPE EfiMemoryType);
|
||||
STATIC XTCDECL ULONG DeterminePagingLevel(IN CONST PWCHAR Parameters);
|
||||
STATIC XTCDECL EFI_STATUS EnablePaging(IN PXTBL_PAGE_MAPPING PageMap);
|
||||
STATIC XTCDECL VOID GetDisplayInformation(OUT PSYSTEM_RESOURCE_FRAMEBUFFER FrameBufferResource,
|
||||
IN PEFI_PHYSICAL_ADDRESS FrameBufferBase,
|
||||
IN PULONG_PTR FrameBufferSize,
|
||||
IN PXTBL_FRAMEBUFFER_MODE_INFORMATION FrameBufferModeInfo);
|
||||
STATIC XTCDECL EFI_STATUS GetMemoryDescriptorList(IN PXTBL_PAGE_MAPPING PageMap,
|
||||
IN PVOID *VirtualAddress,
|
||||
OUT PLIST_ENTRY MemoryDescriptorList);
|
||||
STATIC XTCDECL EFI_STATUS GetSystemResourcesList(IN PXTBL_PAGE_MAPPING PageMap,
|
||||
IN PVOID *VirtualAddress,
|
||||
OUT PLIST_ENTRY SystemResourcesList);
|
||||
STATIC XTCDECL EFI_STATUS GetVirtualAddress(IN PLIST_ENTRY MemoryMappings,
|
||||
IN PVOID PhysicalAddress,
|
||||
OUT PVOID *VirtualAddress);
|
||||
STATIC XTCDECL EFI_STATUS InitializeApicBase(IN PXTBL_PAGE_MAPPING PageMap);
|
||||
STATIC XTCDECL EFI_STATUS InitializeLoaderBlock(IN PXTBL_PAGE_MAPPING PageMap,
|
||||
IN PVOID *VirtualAddress,
|
||||
IN PXTBL_BOOT_PARAMETERS Parameters);
|
||||
STATIC XTCDECL EFI_STATUS InitializeVirtualMemory(IN OUT PLIST_ENTRY MemoryMappings,
|
||||
IN OUT PVOID *MemoryMapAddress);
|
||||
STATIC XTCDECL EFI_STATUS LoadModule(IN PEFI_FILE_HANDLE BootDir,
|
||||
IN PWCHAR FileName,
|
||||
IN PVOID VirtualAddress,
|
||||
IN LOADER_MEMORY_TYPE MemoryType,
|
||||
OUT PPECOFF_IMAGE_CONTEXT *ImageContext);
|
||||
STATIC XTCDECL EFI_STATUS MapHardwareMemoryPool(IN PXTBL_PAGE_MAPPING PageMap);
|
||||
STATIC XTCDECL EFI_STATUS MapVirtualMemory(IN PLIST_ENTRY MemoryMappings,
|
||||
IN UINT_PTR VirtualAddress,
|
||||
IN UINT_PTR PhysicalAddress,
|
||||
IN UINT NumberOfPages,
|
||||
IN OUT PVOID *PtePointer);
|
||||
STATIC XTCDECL EFI_STATUS RunBootSequence(IN PEFI_FILE_HANDLE BootDir,
|
||||
IN PXTBL_BOOT_PARAMETERS Parameters);
|
||||
};
|
||||
|
||||
#endif /* __XTLDR_MODULES_XTOS_HH */
|
729
boot/xtldr/modules/xtos_o/xtos.cc
Normal file
729
boot/xtldr/modules/xtos_o/xtos.cc
Normal file
@@ -0,0 +1,729 @@
|
||||
/**
|
||||
* PROJECT: ExectOS
|
||||
* COPYRIGHT: See COPYING.md in the top level directory
|
||||
* FILE: xtldr/modules/xtos/xtos.cc
|
||||
* DESCRIPTION: XTOS boot protocol support
|
||||
* DEVELOPERS: Rafal Kupiec <belliash@codingworkshop.eu.org>
|
||||
*/
|
||||
|
||||
#include <xtos.hh>
|
||||
|
||||
|
||||
/* XTOS module information */
|
||||
MODULE_AUTHOR(L"Rafal Kupiec <belliash@codingworkshop.eu.org>");
|
||||
MODULE_DESCRIPTION(L"XTOS boot protocol support");
|
||||
MODULE_DEPENDENCY(L"acpi framebuf pecoff");
|
||||
MODULE_LICENSE(L"GPLv3");
|
||||
MODULE_VERSION(L"0.1");
|
||||
|
||||
|
||||
/**
|
||||
* Starts the operating system according to the provided parameters using XTOS boot protocol.
|
||||
*
|
||||
* @param Parameters
|
||||
* Input parameters with detailed system configuration like boot device or kernel path.
|
||||
*
|
||||
* @return This routine returns a status code.
|
||||
*
|
||||
* @since XT 1.0
|
||||
*/
|
||||
XTCDECL
|
||||
EFI_STATUS
|
||||
Xtos::BootSystem(IN PXTBL_BOOT_PARAMETERS Parameters)
|
||||
{
|
||||
EFI_GUID PeCoffProtocolGuid = XT_PECOFF_IMAGE_PROTOCOL_GUID;
|
||||
EFI_HANDLE DiskHandle, ProtocolHandle;
|
||||
PEFI_FILE_HANDLE FsHandle, BootDir;
|
||||
PWCHAR SystemPath;
|
||||
EFI_STATUS Status;
|
||||
|
||||
/* Print debug message */
|
||||
XtLdrProtocol->Debug.Print(L"XTOS boot protocol activated\n");
|
||||
|
||||
/* Open the XT PE/COFF protocol */
|
||||
Status = XtLdrProtocol->Protocol.Open(&ProtocolHandle, (PVOID *)&PeCoffProtocol, &PeCoffProtocolGuid);
|
||||
if(Status != STATUS_EFI_SUCCESS)
|
||||
{
|
||||
/* Failed to open loader protocol */
|
||||
XtLdrProtocol->Debug.Print(L"ERROR: Unable to load PE/COFF image protocol\n");
|
||||
return STATUS_EFI_PROTOCOL_ERROR;
|
||||
}
|
||||
|
||||
/* Check device path */
|
||||
if(Parameters->DevicePath == NULLPTR)
|
||||
{
|
||||
/* No device path set */
|
||||
XtLdrProtocol->Debug.Print(L"ERROR: No device path provided, unable to boot system\n");
|
||||
return STATUS_EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
/* Check if system path is set */
|
||||
if(Parameters->SystemPath != NULLPTR)
|
||||
{
|
||||
/* Make sure system path begins with backslash, the only separator supported by EFI */
|
||||
if(Parameters->SystemPath[0] == '/')
|
||||
{
|
||||
/* Replace directory separator if needed */
|
||||
Parameters->SystemPath[0] = '\\';
|
||||
}
|
||||
|
||||
/* Validate system path */
|
||||
SystemPath = &Parameters->SystemPath[1];
|
||||
while(*SystemPath)
|
||||
{
|
||||
/* Make sure it does not point to any subdirectory and not contains special characters */
|
||||
if(((*SystemPath | 32) - 'a' >= 26) && ((*SystemPath - '0') >= 10))
|
||||
{
|
||||
/* Invalid path specified */
|
||||
XtLdrProtocol->Debug.Print(L"ERROR: System path does not point to the valid XTOS installation\n");
|
||||
return STATUS_EFI_INVALID_PARAMETER;
|
||||
}
|
||||
/* Check next character in the path */
|
||||
SystemPath++;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Fallback to '/ExectOS' by default */
|
||||
XtLdrProtocol->Debug.Print(L"WARNING: No system path set, falling back to defaults\n");
|
||||
Parameters->SystemPath = (PWCHAR)L"\\ExectOS";
|
||||
}
|
||||
|
||||
/* Check if kernel file is set */
|
||||
if(Parameters->KernelFile == NULLPTR)
|
||||
{
|
||||
/* No kernel filename set, fallback to default */
|
||||
XtLdrProtocol->Debug.Print(L"WARNING: No kernel file specified, falling back to defaults\n");
|
||||
Parameters->KernelFile = (PWCHAR)L"xtoskrnl.exe";
|
||||
}
|
||||
|
||||
/* Check if provided any kernel boot arguments */
|
||||
if(Parameters->Parameters == NULLPTR)
|
||||
{
|
||||
/* No argument supplied */
|
||||
Parameters->Parameters = (PWCHAR)L"";
|
||||
}
|
||||
|
||||
/* Print a debug message */
|
||||
XtLdrProtocol->Debug.Print(L"[XTOS] ARC Path: %S\n"
|
||||
L"[XTOS] System Path: %S\n"
|
||||
L"[XTOS] Kernel File: %S\n"
|
||||
L"[XTOS] Boot Arguments: %S\n",
|
||||
Parameters->ArcName, Parameters->SystemPath,
|
||||
Parameters->KernelFile, Parameters->Parameters);
|
||||
|
||||
/* Open EFI volume */
|
||||
Status = XtLdrProtocol->Disk.OpenVolume(Parameters->DevicePath, &DiskHandle, &FsHandle);
|
||||
if(Status != STATUS_EFI_SUCCESS)
|
||||
{
|
||||
/* Failed to open a volume */
|
||||
XtLdrProtocol->Debug.Print(L"ERROR: Unable to open boot volume\n");
|
||||
return Status;
|
||||
}
|
||||
|
||||
/* System path has to point to the boot directory */
|
||||
XtLdrProtocol->WideString.Concatenate(Parameters->SystemPath, (PWCHAR)L"\\Boot", 0);
|
||||
|
||||
/* Open XTOS system boot directory */
|
||||
Status = FsHandle->Open(FsHandle, &BootDir, Parameters->SystemPath, EFI_FILE_MODE_READ, 0);
|
||||
FsHandle->Close(FsHandle);
|
||||
|
||||
/* Check if system path directory opened successfully */
|
||||
if(Status == STATUS_EFI_NOT_FOUND)
|
||||
{
|
||||
/* Directory not found, nothing to load */
|
||||
XtLdrProtocol->Debug.Print(L"ERROR: System boot directory not found\n");
|
||||
|
||||
/* Close volume */
|
||||
XtLdrProtocol->Disk.CloseVolume(&DiskHandle);
|
||||
return Status;
|
||||
}
|
||||
else if(Status != STATUS_EFI_SUCCESS)
|
||||
{
|
||||
/* Failed to open directory */
|
||||
XtLdrProtocol->Debug.Print(L"ERROR: Unable to open system boot directory\n");
|
||||
XtLdrProtocol->Disk.CloseVolume(&DiskHandle);
|
||||
return Status;
|
||||
}
|
||||
|
||||
/* Start boot sequence */
|
||||
return RunBootSequence(BootDir, Parameters);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns information about frame buffer in XTOS compatible format.
|
||||
*
|
||||
* @param InformationBlock
|
||||
* A pointer to memory area containing XT structure where all the information will be stored.
|
||||
*
|
||||
* @return This routine does not return any value.
|
||||
*
|
||||
* @since XT 1.0
|
||||
*/
|
||||
XTCDECL
|
||||
VOID
|
||||
Xtos::GetDisplayInformation(OUT PSYSTEM_RESOURCE_FRAMEBUFFER FrameBufferResource,
|
||||
IN PEFI_PHYSICAL_ADDRESS FrameBufferBase,
|
||||
IN PULONG_PTR FrameBufferSize,
|
||||
IN PXTBL_FRAMEBUFFER_MODE_INFORMATION FrameBufferModeInfo)
|
||||
{
|
||||
/* Fill in frame buffer resource */
|
||||
FrameBufferResource->Header.PhysicalAddress = (PVOID)*FrameBufferBase;
|
||||
FrameBufferResource->Header.ResourceType = SystemResourceFrameBuffer;
|
||||
FrameBufferResource->Header.ResourceSize = sizeof(SYSTEM_RESOURCE_FRAMEBUFFER);
|
||||
FrameBufferResource->BufferSize = *FrameBufferSize;
|
||||
FrameBufferResource->Width = FrameBufferModeInfo->Width;
|
||||
FrameBufferResource->Height = FrameBufferModeInfo->Height;
|
||||
FrameBufferResource->Depth = FrameBufferModeInfo->Depth;
|
||||
FrameBufferResource->BitsPerPixel = FrameBufferModeInfo->BitsPerPixel;
|
||||
FrameBufferResource->PixelsPerScanLine = FrameBufferModeInfo->PixelsPerScanLine;
|
||||
FrameBufferResource->Pitch = FrameBufferModeInfo->Pitch;
|
||||
FrameBufferResource->Pixels.BlueShift = FrameBufferModeInfo->PixelInformation.BlueShift;
|
||||
FrameBufferResource->Pixels.BlueSize = FrameBufferModeInfo->PixelInformation.BlueSize;
|
||||
FrameBufferResource->Pixels.GreenShift = FrameBufferModeInfo->PixelInformation.GreenShift;
|
||||
FrameBufferResource->Pixels.GreenSize = FrameBufferModeInfo->PixelInformation.GreenSize;
|
||||
FrameBufferResource->Pixels.RedShift = FrameBufferModeInfo->PixelInformation.RedShift;
|
||||
FrameBufferResource->Pixels.RedSize = FrameBufferModeInfo->PixelInformation.RedSize;
|
||||
FrameBufferResource->Pixels.ReservedShift = FrameBufferModeInfo->PixelInformation.ReservedShift;
|
||||
FrameBufferResource->Pixels.ReservedSize = FrameBufferModeInfo->PixelInformation.ReservedSize;
|
||||
}
|
||||
|
||||
XTCDECL
|
||||
EFI_STATUS
|
||||
Xtos::GetMemoryDescriptorList(IN PXTBL_PAGE_MAPPING PageMap,
|
||||
IN PVOID *VirtualAddress,
|
||||
OUT PLIST_ENTRY MemoryDescriptorList)
|
||||
{
|
||||
EFI_PHYSICAL_ADDRESS Address;
|
||||
EFI_STATUS Status;
|
||||
ULONGLONG Pages;
|
||||
|
||||
Pages = (ULONGLONG)EFI_SIZE_TO_PAGES((PageMap->MapSize + 1) * sizeof(LOADER_MEMORY_DESCRIPTOR));
|
||||
|
||||
Status = XtLdrProtocol->Memory.AllocatePages(AllocateAnyPages, Pages, &Address);
|
||||
if(Status != STATUS_EFI_SUCCESS)
|
||||
{
|
||||
return Status;
|
||||
}
|
||||
|
||||
Status = XtLdrProtocol->Memory.MapVirtualMemory(PageMap, *VirtualAddress, (PVOID)Address, Pages, LoaderMemoryData);
|
||||
if(Status != STATUS_EFI_SUCCESS)
|
||||
{
|
||||
XtLdrProtocol->Memory.FreePages(Address, Pages);
|
||||
return Status;
|
||||
}
|
||||
|
||||
PVOID PhysicalBase = (PVOID)Address;
|
||||
|
||||
PLIST_ENTRY ListEntry;
|
||||
ListEntry = PageMap->MemoryMap.Flink;
|
||||
while(ListEntry != &PageMap->MemoryMap)
|
||||
{
|
||||
PXTBL_MEMORY_MAPPING MemoryMapping = CONTAIN_RECORD(ListEntry, XTBL_MEMORY_MAPPING, ListEntry);
|
||||
PLOADER_MEMORY_DESCRIPTOR MemoryDescriptor = (PLOADER_MEMORY_DESCRIPTOR)Address;
|
||||
|
||||
MemoryDescriptor->MemoryType = MemoryMapping->MemoryType;
|
||||
MemoryDescriptor->BasePage = (UINT_PTR)MemoryMapping->PhysicalAddress / EFI_PAGE_SIZE;
|
||||
MemoryDescriptor->PageCount = MemoryMapping->NumberOfPages;
|
||||
|
||||
XtLdrProtocol->LinkedList.InsertTail(MemoryDescriptorList, &MemoryDescriptor->ListEntry);
|
||||
|
||||
Address = Address + sizeof(LOADER_MEMORY_DESCRIPTOR);
|
||||
ListEntry = ListEntry->Flink;
|
||||
}
|
||||
|
||||
XtLdrProtocol->Memory.PhysicalListToVirtual(PageMap, MemoryDescriptorList, PhysicalBase, *VirtualAddress);
|
||||
|
||||
return STATUS_EFI_SUCCESS;
|
||||
}
|
||||
|
||||
XTCDECL
|
||||
EFI_STATUS
|
||||
Xtos::GetSystemResourcesList(IN PXTBL_PAGE_MAPPING PageMap,
|
||||
IN PVOID *VirtualAddress,
|
||||
OUT PLIST_ENTRY SystemResourcesList)
|
||||
{
|
||||
XTSTATUS Status;
|
||||
EFI_HANDLE ProtocolHandle;
|
||||
EFI_GUID AcpiGuid = XT_ACPI_PROTOCOL_GUID;
|
||||
EFI_GUID FrameBufGuid = XT_FRAMEBUFFER_PROTOCOL_GUID;
|
||||
PXTBL_ACPI_PROTOCOL AcpiProtocol;
|
||||
PXTBL_FRAMEBUFFER_PROTOCOL FrameBufProtocol;
|
||||
XTBL_FRAMEBUFFER_MODE_INFORMATION FbModeInfo;
|
||||
EFI_PHYSICAL_ADDRESS FbAddress;
|
||||
ULONG_PTR FbSize;
|
||||
UINT FrameBufferPages;
|
||||
PSYSTEM_RESOURCE_FRAMEBUFFER FrameBufferResource;
|
||||
PSYSTEM_RESOURCE_ACPI AcpiResource;
|
||||
ULONGLONG Pages;
|
||||
EFI_PHYSICAL_ADDRESS Address;
|
||||
PVOID PhysicalBase, VirtualBase;
|
||||
|
||||
Pages = (ULONGLONG)EFI_SIZE_TO_PAGES(sizeof(SYSTEM_RESOURCE_ACPI) + sizeof(SYSTEM_RESOURCE_FRAMEBUFFER));
|
||||
|
||||
Status = XtLdrProtocol->Memory.AllocatePages(AllocateAnyPages, Pages, &Address);
|
||||
if(Status != STATUS_EFI_SUCCESS)
|
||||
{
|
||||
return Status;
|
||||
}
|
||||
Status = XtLdrProtocol->Memory.MapVirtualMemory(PageMap, *VirtualAddress, (PVOID)Address, Pages, LoaderFirmwarePermanent);
|
||||
if(Status != STATUS_EFI_SUCCESS)
|
||||
{
|
||||
XtLdrProtocol->Memory.FreePages(Address, Pages);
|
||||
return Status;
|
||||
}
|
||||
|
||||
PhysicalBase = (PVOID)Address;
|
||||
VirtualBase = *VirtualAddress;
|
||||
|
||||
/* Calculate next valid virtual address */
|
||||
*VirtualAddress = (PUINT8)*VirtualAddress + (Pages * EFI_PAGE_SIZE);
|
||||
|
||||
AcpiResource = (PSYSTEM_RESOURCE_ACPI)Address;
|
||||
|
||||
XtLdrProtocol->Memory.ZeroMemory(AcpiResource, sizeof(SYSTEM_RESOURCE_ACPI));
|
||||
|
||||
/* Load FrameBuffer protocol */
|
||||
Status = XtLdrProtocol->Protocol.Open(&ProtocolHandle, (PVOID*)&AcpiProtocol, &AcpiGuid);
|
||||
if(Status != STATUS_EFI_SUCCESS)
|
||||
{
|
||||
return Status;
|
||||
}
|
||||
|
||||
AcpiResource->Header.ResourceType = SystemResourceAcpi;
|
||||
AcpiResource->Header.ResourceSize = sizeof(SYSTEM_RESOURCE_ACPI);
|
||||
|
||||
/* Get APIC and XSDP/RSDP addresses */
|
||||
AcpiProtocol->GetApicBase(&AcpiResource->ApicBase);
|
||||
AcpiProtocol->GetAcpiDescriptionPointer(&AcpiResource->Header.PhysicalAddress);
|
||||
|
||||
/* No need to map ACPI */
|
||||
AcpiResource->Header.VirtualAddress = 0;
|
||||
|
||||
XtLdrProtocol->LinkedList.InsertTail(SystemResourcesList, &AcpiResource->Header.ListEntry);
|
||||
|
||||
/* Close FrameBuffer protocol */
|
||||
XtLdrProtocol->Protocol.Close(&ProtocolHandle, &FrameBufGuid);
|
||||
|
||||
Address = Address + sizeof(SYSTEM_RESOURCE_ACPI);
|
||||
|
||||
FrameBufferResource = (PSYSTEM_RESOURCE_FRAMEBUFFER)Address;
|
||||
|
||||
XtLdrProtocol->Memory.ZeroMemory(FrameBufferResource, sizeof(SYSTEM_RESOURCE_FRAMEBUFFER));
|
||||
|
||||
/* Load FrameBuffer protocol */
|
||||
Status = XtLdrProtocol->Protocol.Open(&ProtocolHandle, (PVOID*)&FrameBufProtocol, &FrameBufGuid);
|
||||
if(Status == STATUS_EFI_SUCCESS)
|
||||
{
|
||||
/* Get FrameBuffer information */
|
||||
Status = FrameBufProtocol->GetDisplayInformation(&FbAddress, &FbSize, &FbModeInfo);
|
||||
if(Status == STATUS_EFI_SUCCESS)
|
||||
{
|
||||
|
||||
/* Store information about FrameBuffer device */
|
||||
GetDisplayInformation(FrameBufferResource, &FbAddress, &FbSize, &FbModeInfo);
|
||||
}
|
||||
}
|
||||
if(Status != STATUS_EFI_SUCCESS)
|
||||
{
|
||||
return Status;
|
||||
}
|
||||
|
||||
/* Calculate pages needed to map framebuffer */
|
||||
FrameBufferPages = EFI_SIZE_TO_PAGES(FbSize);
|
||||
|
||||
/* Rewrite framebuffer address by using virtual address */
|
||||
FrameBufferResource->Header.VirtualAddress = *VirtualAddress;
|
||||
|
||||
/* Map frame buffer memory */
|
||||
XtLdrProtocol->Memory.MapVirtualMemory(PageMap, FrameBufferResource->Header.VirtualAddress,
|
||||
FrameBufferResource->Header.PhysicalAddress,
|
||||
FrameBufferPages, LoaderFirmwarePermanent);
|
||||
|
||||
/* Close FrameBuffer protocol */
|
||||
XtLdrProtocol->Protocol.Close(&ProtocolHandle, &FrameBufGuid);
|
||||
|
||||
*VirtualAddress = (PUINT8)*VirtualAddress + (FrameBufferPages * EFI_PAGE_SIZE);
|
||||
|
||||
XtLdrProtocol->LinkedList.InsertTail(SystemResourcesList, &FrameBufferResource->Header.ListEntry);
|
||||
|
||||
XtLdrProtocol->Memory.PhysicalListToVirtual(PageMap, SystemResourcesList, PhysicalBase, VirtualBase);
|
||||
|
||||
return STATUS_EFI_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if APIC is present in the system and finds its base address.
|
||||
*
|
||||
* @param MemoryMappings
|
||||
* Supplies a pointer to linked list containing all memory mappings.
|
||||
*
|
||||
* @return This routine returns an EFI status code.
|
||||
*
|
||||
* @since XT 1.0
|
||||
*/
|
||||
XTCDECL
|
||||
EFI_STATUS
|
||||
Xtos::InitializeApicBase(IN PXTBL_PAGE_MAPPING PageMap)
|
||||
{
|
||||
EFI_GUID AcpiGuid = XT_ACPI_PROTOCOL_GUID;
|
||||
PXTBL_ACPI_PROTOCOL AcpiProtocol;
|
||||
EFI_HANDLE ProtocolHandle;
|
||||
PVOID ApicBaseAddress;
|
||||
EFI_STATUS Status;
|
||||
|
||||
/* Open ACPI protocol */
|
||||
Status = XtLdrProtocol->Protocol.Open(&ProtocolHandle, (PVOID*)&AcpiProtocol, &AcpiGuid);
|
||||
if(Status != STATUS_EFI_SUCCESS)
|
||||
{
|
||||
/* ACPI protocol not found */
|
||||
return Status;
|
||||
}
|
||||
|
||||
/* Get APIC base address */
|
||||
Status = AcpiProtocol->GetApicBase(&ApicBaseAddress);
|
||||
if(Status != STATUS_EFI_SUCCESS)
|
||||
{
|
||||
/* Failed to get APIC base address */
|
||||
return Status;
|
||||
}
|
||||
|
||||
/* Map APIC base address */
|
||||
XtLdrProtocol->Memory.MapVirtualMemory(PageMap, (PVOID)APIC_BASE, ApicBaseAddress, 1, LoaderFirmwarePermanent);
|
||||
return STATUS_EFI_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* Initializes and maps the kernel initialization block.
|
||||
*
|
||||
* @param MemoryMappings
|
||||
* Supplies a pointer to linked list containing all memory mappings.
|
||||
*
|
||||
* @param VirtualAddress
|
||||
* Supplies a pointer to the next valid, free and available virtual address.
|
||||
*
|
||||
* @return This routine returns a status code.
|
||||
*
|
||||
* @since XT 1.0
|
||||
*/
|
||||
XTCDECL
|
||||
EFI_STATUS
|
||||
Xtos::InitializeLoaderBlock(IN PXTBL_PAGE_MAPPING PageMap,
|
||||
IN PVOID *VirtualAddress,
|
||||
IN PXTBL_BOOT_PARAMETERS Parameters)
|
||||
{
|
||||
PKERNEL_INITIALIZATION_BLOCK LoaderBlock;
|
||||
EFI_PHYSICAL_ADDRESS Address;
|
||||
EFI_STATUS Status;
|
||||
UINT BlockPages;
|
||||
UINT ParametersSize;
|
||||
|
||||
/* Calculate size of parameters */
|
||||
ParametersSize = (XtLdrProtocol->WideString.Length(Parameters->Parameters, 0) + 1) * sizeof(WCHAR);
|
||||
|
||||
/* Calculate number of pages needed for initialization block */
|
||||
BlockPages = EFI_SIZE_TO_PAGES(sizeof(KERNEL_INITIALIZATION_BLOCK) + ParametersSize);
|
||||
|
||||
/* Allocate memory for kernel initialization block */
|
||||
Status = XtLdrProtocol->Memory.AllocatePages(AllocateAnyPages, BlockPages, &Address);
|
||||
if(Status != STATUS_EFI_SUCCESS)
|
||||
{
|
||||
/* Memory allocation failure */
|
||||
return Status;
|
||||
}
|
||||
|
||||
/* Initialize and zero-fill kernel initialization block */
|
||||
LoaderBlock = (PKERNEL_INITIALIZATION_BLOCK)(UINT_PTR)Address;
|
||||
XtLdrProtocol->Memory.ZeroMemory(LoaderBlock, sizeof(KERNEL_INITIALIZATION_BLOCK) + ParametersSize);
|
||||
|
||||
/* Set basic loader block properties */
|
||||
LoaderBlock->BlockSize = sizeof(KERNEL_INITIALIZATION_BLOCK);
|
||||
LoaderBlock->BlockVersion = INITIALIZATION_BLOCK_VERSION;
|
||||
LoaderBlock->ProtocolVersion = BOOT_PROTOCOL_VERSION;
|
||||
|
||||
/* Set LoaderInformation block properties */
|
||||
LoaderBlock->LoaderInformation.DbgPrint = (PVOID)XtLdrProtocol->Debug.Print;
|
||||
|
||||
/* Set FirmwareInformation block properties */
|
||||
LoaderBlock->FirmwareInformation.FirmwareType = SystemFirmwareEfi;
|
||||
// LoaderBlock->FirmwareInformation.EfiFirmware.EfiVersion = EfiSystemTable->Hdr.Revision;
|
||||
LoaderBlock->FirmwareInformation.EfiFirmware.EfiRuntimeServices = NULLPTR;
|
||||
|
||||
/* Copy parameters to kernel initialization block */
|
||||
LoaderBlock->KernelParameters = (PWCHAR)((UINT_PTR)*VirtualAddress + sizeof(KERNEL_INITIALIZATION_BLOCK));
|
||||
XtLdrProtocol->Memory.CopyMemory((PVOID)((UINT_PTR)LoaderBlock + sizeof(KERNEL_INITIALIZATION_BLOCK)),
|
||||
Parameters->Parameters,
|
||||
ParametersSize);
|
||||
|
||||
/* Map kernel initialization block */
|
||||
XtLdrProtocol->Memory.MapVirtualMemory(PageMap, *VirtualAddress, (PVOID)LoaderBlock,
|
||||
BlockPages, LoaderSystemBlock);
|
||||
|
||||
/* Calculate next valid virtual address */
|
||||
*VirtualAddress = (PUINT8)*VirtualAddress + (BlockPages * EFI_PAGE_SIZE);
|
||||
|
||||
XtLdrProtocol->LinkedList.InitializeHead(&LoaderBlock->SystemResourcesListHead);
|
||||
GetSystemResourcesList(PageMap, VirtualAddress, &LoaderBlock->SystemResourcesListHead);
|
||||
|
||||
/* Initialize memory descriptor list */
|
||||
XtLdrProtocol->LinkedList.InitializeHead(&LoaderBlock->MemoryDescriptorListHead);
|
||||
GetMemoryDescriptorList(PageMap, VirtualAddress, &LoaderBlock->MemoryDescriptorListHead);
|
||||
|
||||
/* Return success */
|
||||
return STATUS_EFI_SUCCESS;
|
||||
}
|
||||
|
||||
XTCDECL
|
||||
EFI_STATUS
|
||||
Xtos::InitializeModule(IN EFI_HANDLE ImageHandle,
|
||||
IN PEFI_SYSTEM_TABLE SystemTable)
|
||||
{
|
||||
EFI_GUID Guid = XT_XTOS_BOOT_PROTOCOL_GUID;
|
||||
EFI_STATUS Status;
|
||||
|
||||
/* Open the XTLDR protocol */
|
||||
Status = BlGetXtLdrProtocol(SystemTable, ImageHandle, &XtLdrProtocol);
|
||||
if(Status != STATUS_EFI_SUCCESS)
|
||||
{
|
||||
/* Failed to open loader protocol */
|
||||
return STATUS_EFI_PROTOCOL_ERROR;
|
||||
}
|
||||
|
||||
/* Set routines available via XTOS boot protocol */
|
||||
BootProtocol.BootSystem = Xtos::BootSystem;
|
||||
|
||||
/* Register XTOS boot protocol */
|
||||
XtLdrProtocol->Boot.RegisterProtocol(L"XTOS", &Guid);
|
||||
|
||||
/* Install XTOS protocol */
|
||||
return XtLdrProtocol->Protocol.Install(&BootProtocol, &Guid);
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads XTOS PE/COFF module.
|
||||
*
|
||||
* @param SystemDir
|
||||
* An EFI handle to the opened system directory containing a module that will be loaded.
|
||||
*
|
||||
* @param FileName
|
||||
* An on disk filename of the module that will be loaded.
|
||||
*
|
||||
* @param VirtualAddress
|
||||
* Optional virtual address pointing to the memory area where PE/COFF file will be loaded.
|
||||
*
|
||||
* @param MemoryType
|
||||
* Supplies the type of memory to be assigned to the memory descriptor.
|
||||
*
|
||||
* @param ImageContext
|
||||
* Supplies pointer to the memory area where loaded PE/COFF image context will be stored.
|
||||
*
|
||||
* @return This routine returns a status code.
|
||||
*
|
||||
* @since XT 1.0
|
||||
*/
|
||||
XTCDECL
|
||||
EFI_STATUS
|
||||
Xtos::LoadModule(IN PEFI_FILE_HANDLE SystemDir,
|
||||
IN PWCHAR FileName,
|
||||
IN PVOID VirtualAddress,
|
||||
IN LOADER_MEMORY_TYPE MemoryType,
|
||||
OUT PPECOFF_IMAGE_CONTEXT *ImageContext)
|
||||
{
|
||||
PEFI_FILE_HANDLE ModuleHandle;
|
||||
USHORT MachineType, SubSystem;
|
||||
EFI_STATUS Status;
|
||||
|
||||
/* Print debug message */
|
||||
XtLdrProtocol->Debug.Print(L"Loading %S ... \n", FileName);
|
||||
|
||||
/* Open module file */
|
||||
Status = SystemDir->Open(SystemDir, &ModuleHandle, FileName, EFI_FILE_MODE_READ, 0);
|
||||
if(Status != STATUS_EFI_SUCCESS)
|
||||
{
|
||||
/* Unable to open the file */
|
||||
XtLdrProtocol->Debug.Print(L"ERROR: Failed to open '%S'\n", FileName);
|
||||
return Status;
|
||||
}
|
||||
|
||||
/* Load the PE/COFF image file */
|
||||
Status = PeCoffProtocol->LoadImage(ModuleHandle, MemoryType, VirtualAddress, (PVOID*)ImageContext);
|
||||
if(Status != STATUS_EFI_SUCCESS)
|
||||
{
|
||||
/* Unable to load the file */
|
||||
XtLdrProtocol->Debug.Print(L"ERROR: Failed to load '%S'\n", FileName);
|
||||
return Status;
|
||||
}
|
||||
|
||||
/* Close image file */
|
||||
ModuleHandle->Close(ModuleHandle);
|
||||
|
||||
/* Check PE/COFF image machine type compatibility */
|
||||
PeCoffProtocol->GetMachineType(*ImageContext, &MachineType);
|
||||
if(MachineType != _ARCH_IMAGE_MACHINE_TYPE)
|
||||
{
|
||||
/* Machine type mismatch */
|
||||
XtLdrProtocol->Debug.Print(L"ERROR: Loaded incompatible PE/COFF image (machine type mismatch)\n");
|
||||
return STATUS_EFI_INCOMPATIBLE_VERSION;
|
||||
}
|
||||
|
||||
/* Check PE/COFF image subsystem */
|
||||
PeCoffProtocol->GetSubSystem(*ImageContext, &SubSystem);
|
||||
if(SubSystem != PECOFF_IMAGE_SUBSYSTEM_XT_NATIVE_KERNEL &&
|
||||
SubSystem != PECOFF_IMAGE_SUBSYSTEM_XT_NATIVE_APPLICATION &&
|
||||
SubSystem != PECOFF_IMAGE_SUBSYSTEM_XT_NATIVE_DRIVER)
|
||||
{
|
||||
XtLdrProtocol->Debug.Print(L"WARNING: Loaded PE/COFF image with non-XT subsystem set\n");
|
||||
}
|
||||
|
||||
/* Print debug message */
|
||||
XtLdrProtocol->Debug.Print(L"Loaded %S at PA: %P, VA: %P\n", FileName,
|
||||
(*ImageContext)->PhysicalAddress, (*ImageContext)->VirtualAddress);
|
||||
|
||||
/* Return success */
|
||||
return STATUS_EFI_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* This routine initiates an XTOS boot sequence.
|
||||
*
|
||||
* @param BootDir
|
||||
* An EFI handle to the XTOS boot directory.
|
||||
*
|
||||
* @param Parameters
|
||||
* Input parameters with detailed system configuration like boot device or kernel path.
|
||||
*
|
||||
* @return This routine returns a status code.
|
||||
*
|
||||
* @since XT 1.0
|
||||
*/
|
||||
XTCDECL
|
||||
EFI_STATUS
|
||||
Xtos::RunBootSequence(IN PEFI_FILE_HANDLE BootDir,
|
||||
IN PXTBL_BOOT_PARAMETERS Parameters)
|
||||
{
|
||||
EFI_GUID LoadedImageGuid = EFI_LOADED_IMAGE_PROTOCOL_GUID;
|
||||
EFI_GUID FrameBufGuid = XT_FRAMEBUFFER_PROTOCOL_GUID;
|
||||
PKERNEL_INITIALIZATION_BLOCK KernelParameters;
|
||||
PXTBL_FRAMEBUFFER_PROTOCOL FrameBufProtocol;
|
||||
PPECOFF_IMAGE_CONTEXT ImageContext = NULLPTR;
|
||||
PEFI_LOADED_IMAGE_PROTOCOL ImageProtocol;
|
||||
PVOID VirtualAddress, VirtualMemoryArea;
|
||||
PXT_ENTRY_POINT KernelEntryPoint;
|
||||
EFI_HANDLE ProtocolHandle;
|
||||
EFI_STATUS Status;
|
||||
XTBL_PAGE_MAPPING PageMap;
|
||||
|
||||
/* Initialize XTOS startup sequence */
|
||||
XtLdrProtocol->Debug.Print(L"Initializing XTOS startup sequence\n");
|
||||
|
||||
/* Load FrameBuffer protocol */
|
||||
Status = XtLdrProtocol->Protocol.Open(&ProtocolHandle, (PVOID*)&FrameBufProtocol, &FrameBufGuid);
|
||||
if(Status == STATUS_EFI_SUCCESS)
|
||||
{
|
||||
/* Make sure FrameBuffer is initialized */
|
||||
FrameBufProtocol->Initialize();
|
||||
FrameBufProtocol->SetScreenResolution(0, 0);
|
||||
}
|
||||
|
||||
/* Close FrameBuffer protocol */
|
||||
XtLdrProtocol->Protocol.Close(&ProtocolHandle, &FrameBufGuid);
|
||||
|
||||
/* Set base virtual memory area for the kernel mappings */
|
||||
VirtualMemoryArea = (PVOID)KSEG0_BASE;
|
||||
VirtualAddress = (PVOID)(KSEG0_BASE + KSEG0_KERNEL_BASE);
|
||||
|
||||
/* Initialize virtual memory mappings */
|
||||
XtLdrProtocol->Memory.InitializePageMap(&PageMap, DeterminePagingLevel(Parameters->Parameters), Size4K);
|
||||
|
||||
Status = XtLdrProtocol->Memory.MapEfiMemory(&PageMap, &VirtualMemoryArea, NULLPTR);
|
||||
if(Status != STATUS_EFI_SUCCESS)
|
||||
{
|
||||
return Status;
|
||||
}
|
||||
|
||||
/* Load the kernel */
|
||||
Status = LoadModule(BootDir, Parameters->KernelFile, VirtualAddress, LoaderSystemCode, &ImageContext);
|
||||
if(Status != STATUS_EFI_SUCCESS)
|
||||
{
|
||||
/* Failed to load the kernel */
|
||||
return Status;
|
||||
}
|
||||
|
||||
/* Add kernel image memory mapping */
|
||||
Status = XtLdrProtocol->Memory.MapVirtualMemory(&PageMap, ImageContext->VirtualAddress,
|
||||
ImageContext->PhysicalAddress, ImageContext->ImagePages,
|
||||
LoaderSystemCode);
|
||||
if(Status != STATUS_EFI_SUCCESS)
|
||||
{
|
||||
return Status;
|
||||
}
|
||||
|
||||
/* Set next valid virtual address right after the kernel */
|
||||
VirtualAddress = (PUINT8)VirtualAddress + (ImageContext->ImagePages * EFI_PAGE_SIZE);
|
||||
|
||||
/* Find and map APIC base address */
|
||||
Status = InitializeApicBase(&PageMap);
|
||||
if(Status != STATUS_EFI_SUCCESS)
|
||||
{
|
||||
/* Failed to setup kernel initialization block */
|
||||
XtLdrProtocol->Debug.Print(L"Failed to initialize APIC (Status Code: 0x%zX)\n", Status);
|
||||
return Status;
|
||||
}
|
||||
|
||||
/* Store virtual address of kernel initialization block for future kernel call */
|
||||
KernelParameters = (PKERNEL_INITIALIZATION_BLOCK)VirtualAddress;
|
||||
|
||||
/* Setup and map kernel initialization block */
|
||||
Status = InitializeLoaderBlock(&PageMap, &VirtualAddress, Parameters);
|
||||
if(Status != STATUS_EFI_SUCCESS)
|
||||
{
|
||||
/* Failed to setup kernel initialization block */
|
||||
XtLdrProtocol->Debug.Print(L"Failed to setup kernel initialization block (Status Code: 0x%zX)\n", Status);
|
||||
return Status;
|
||||
}
|
||||
|
||||
/* Get kernel entry point */
|
||||
PeCoffProtocol->GetEntryPoint(ImageContext, (PVOID*)&KernelEntryPoint);
|
||||
|
||||
/* Close boot directory handle */
|
||||
BootDir->Close(BootDir);
|
||||
|
||||
/* Enable paging */
|
||||
XtLdrProtocol->Protocol.Open(&ProtocolHandle, (PVOID*)&ImageProtocol, &LoadedImageGuid);
|
||||
Status = EnablePaging(&PageMap);
|
||||
if(Status != STATUS_EFI_SUCCESS)
|
||||
{
|
||||
/* Failed to enable paging */
|
||||
XtLdrProtocol->Debug.Print(L"Failed to enable paging (Status Code: 0x%zX)\n", Status);
|
||||
return Status;
|
||||
}
|
||||
|
||||
/* Call XTOS kernel */
|
||||
XtLdrProtocol->Debug.Print(L"Booting the XTOS kernel\n");
|
||||
KernelEntryPoint(KernelParameters);
|
||||
|
||||
/* Return success */
|
||||
return STATUS_EFI_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* This routine is the entry point of the XT EFI boot loader module.
|
||||
*
|
||||
* @param ImageHandle
|
||||
* Firmware-allocated handle that identifies the image.
|
||||
*
|
||||
* @param SystemTable
|
||||
* Provides the EFI system table.
|
||||
*
|
||||
* @return This routine returns status code.
|
||||
*
|
||||
* @since XT 1.0
|
||||
*/
|
||||
XTCDECL
|
||||
EFI_STATUS
|
||||
XtLdrModuleMain(IN EFI_HANDLE ImageHandle,
|
||||
IN PEFI_SYSTEM_TABLE SystemTable)
|
||||
{
|
||||
/* Initialize XTOS module */
|
||||
return Xtos::InitializeModule(ImageHandle, SystemTable);
|
||||
}
|
Reference in New Issue
Block a user