Move XTLDR under boot directory
This commit is contained in:
@@ -1,2 +1,3 @@
|
||||
add_subdirectory(bootdata)
|
||||
add_subdirectory(bootsect)
|
||||
add_subdirectory(xtldr)
|
||||
|
53
boot/xtldr/CMakeLists.txt
Normal file
53
boot/xtldr/CMakeLists.txt
Normal file
@@ -0,0 +1,53 @@
|
||||
# XT Boot Loader
|
||||
PROJECT(XTLDR)
|
||||
|
||||
# Build XTLDR modules
|
||||
add_subdirectory(modules)
|
||||
|
||||
# Specify include directories
|
||||
include_directories(
|
||||
${EXECTOS_SOURCE_DIR}/sdk/xtdk
|
||||
${XTLDR_SOURCE_DIR}/includes)
|
||||
|
||||
# Specify list of library source code files
|
||||
list(APPEND LIBXTLDR_SOURCE
|
||||
${XTLDR_SOURCE_DIR}/library/modproto.cc)
|
||||
|
||||
# Specify list of source code files
|
||||
list(APPEND XTLDR_SOURCE
|
||||
${XTLDR_SOURCE_DIR}/arch/${ARCH}/memory.cc
|
||||
${XTLDR_SOURCE_DIR}/bootutil.cc
|
||||
${XTLDR_SOURCE_DIR}/config.cc
|
||||
${XTLDR_SOURCE_DIR}/console.cc
|
||||
${XTLDR_SOURCE_DIR}/data.cc
|
||||
${XTLDR_SOURCE_DIR}/debug.cc
|
||||
${XTLDR_SOURCE_DIR}/efiutils.cc
|
||||
${XTLDR_SOURCE_DIR}/memory.cc
|
||||
${XTLDR_SOURCE_DIR}/protocol.cc
|
||||
${XTLDR_SOURCE_DIR}/shell.cc
|
||||
${XTLDR_SOURCE_DIR}/textui.cc
|
||||
${XTLDR_SOURCE_DIR}/volume.cc
|
||||
${XTLDR_SOURCE_DIR}/xtldr.cc)
|
||||
|
||||
# Link static XTLDR library
|
||||
add_library(libxtldr ${LIBXTLDR_SOURCE})
|
||||
|
||||
# Link bootloader executable
|
||||
add_executable(xtldr ${XTLDR_SOURCE})
|
||||
|
||||
# Add linker libraries
|
||||
target_link_libraries(xtldr libxtos)
|
||||
|
||||
# Set proper binary name and install target
|
||||
if(ARCH STREQUAL "i686")
|
||||
set(BINARY_NAME "bootia32")
|
||||
elseif(ARCH STREQUAL "amd64")
|
||||
set(BINARY_NAME "bootx64")
|
||||
endif()
|
||||
set_target_properties(xtldr PROPERTIES OUTPUT_NAME ${BINARY_NAME} SUFFIX .efi)
|
||||
set_install_target(xtldr efi/boot)
|
||||
|
||||
# Set loader entrypoint and subsystem
|
||||
set_entrypoint(xtldr "BlStartXtLoader")
|
||||
set_linker_map(xtldr TRUE)
|
||||
set_subsystem(xtldr efi_application)
|
14
boot/xtldr/README.md
Normal file
14
boot/xtldr/README.md
Normal file
@@ -0,0 +1,14 @@
|
||||
## XT Boot Loader (XTLDR)
|
||||
The XTLDR, or XTOS Boot Loader, is an EFI (Extensible Firmware Interface) boot loader specifically designed for XTOS.
|
||||
As an EFI boot loader, XTLDR operates exclusively with EFI-based hardware and is not compatible with non-EFI systems,
|
||||
like old and deprecated BIOS.
|
||||
|
||||
One of the notable features of XTLDR is its modular design. The boot loader is divided into different modules, with only
|
||||
the essential core being loaded during the boot process. This modular approach allows for a more efficient and
|
||||
streamlined boot experience, as only the necessary functionality is loaded, reducing the boot time and system resource
|
||||
usage.
|
||||
|
||||
XTLDR includes various modules that provide specific functionalities required for the boot process. For example, there is
|
||||
a module dedicated to supporting the XTOS boot protocol, which is the specific protocol used by XTOS for loading and
|
||||
executing the OS kernel. Additionally, there is a module for handling PE/COFF (Portable Executable) binaries, which is
|
||||
a commonly used format of executable files used by the XTOS.
|
372
boot/xtldr/arch/amd64/memory.cc
Normal file
372
boot/xtldr/arch/amd64/memory.cc
Normal file
@@ -0,0 +1,372 @@
|
||||
/**
|
||||
* PROJECT: ExectOS
|
||||
* COPYRIGHT: See COPYING.md in the top level directory
|
||||
* FILE: xtldr/arch/amd64/memory.cc
|
||||
* DESCRIPTION: XT Boot Loader AMD64 specific memory management
|
||||
* DEVELOPERS: Rafal Kupiec <belliash@codingworkshop.eu.org>
|
||||
* Aiken Harris <harraiken91@gmail.com>
|
||||
*/
|
||||
|
||||
#include <xtldr.hh>
|
||||
|
||||
|
||||
/**
|
||||
* Maps boot loader related code and builds page map.
|
||||
*
|
||||
* @param PageMap
|
||||
* Supplies a pointer to the page mapping structure.
|
||||
*
|
||||
* @param SelfMapAddress
|
||||
* Supplies a virtual address of the page tables.
|
||||
*
|
||||
* @return This routine returns a status code.
|
||||
*
|
||||
* @since XT 1.0
|
||||
*/
|
||||
XTCDECL
|
||||
EFI_STATUS
|
||||
Memory::BuildPageMap(IN PXTBL_PAGE_MAPPING PageMap,
|
||||
IN ULONG_PTR SelfMapAddress)
|
||||
{
|
||||
PLIST_ENTRY ListEntry, ModulesList, ModulesListEntry;
|
||||
PXTBL_MEMORY_MAPPING Mapping;
|
||||
PXTBL_MODULE_INFO ModuleInfo;
|
||||
EFI_PHYSICAL_ADDRESS Address;
|
||||
PVOID LoaderBase;
|
||||
ULONGLONG LoaderSize;
|
||||
EFI_STATUS Status;
|
||||
|
||||
/* Allocate pages for the Page Map */
|
||||
Status = AllocatePages(AllocateAnyPages, 1, &Address);
|
||||
if(Status != STATUS_EFI_SUCCESS)
|
||||
{
|
||||
/* Memory allocation failure */
|
||||
return Status;
|
||||
}
|
||||
|
||||
/* Assign and zero-fill memory used by page mappings */
|
||||
PageMap->PtePointer = (PVOID)(UINT_PTR)Address;
|
||||
RTL::Memory::ZeroMemory(PageMap->PtePointer, EFI_PAGE_SIZE);
|
||||
|
||||
/* Add page mapping itself to memory mapping */
|
||||
Status = Memory::SelfMapPml(PageMap, SelfMapAddress);
|
||||
if(Status != STATUS_EFI_SUCCESS)
|
||||
{
|
||||
/* PML mapping failed */
|
||||
return Status;
|
||||
}
|
||||
|
||||
/* Map the trampoline code area */
|
||||
Status = MapVirtualMemory(PageMap, (PVOID)MM_TRAMPOLINE_ADDRESS,(PVOID)MM_TRAMPOLINE_ADDRESS,
|
||||
1, LoaderFirmwareTemporary);
|
||||
if(Status != STATUS_EFI_SUCCESS)
|
||||
{
|
||||
/* Mapping trampoline code failed */
|
||||
return Status;
|
||||
}
|
||||
|
||||
/* Get list of XTLDR modules */
|
||||
ModulesList = Protocol::GetModulesList();
|
||||
ModulesListEntry = ModulesList->Flink;
|
||||
while(ModulesListEntry != ModulesList)
|
||||
{
|
||||
/* Get module info */
|
||||
ModuleInfo = CONTAIN_RECORD(ModulesListEntry, XTBL_MODULE_INFO, Flink);
|
||||
|
||||
/* Map module code */
|
||||
Status = MapVirtualMemory(PageMap, ModuleInfo->ModuleBase, ModuleInfo->ModuleBase,
|
||||
EFI_SIZE_TO_PAGES(ModuleInfo->ModuleSize), LoaderFirmwareTemporary);
|
||||
|
||||
/* Check if mapping succeeded */
|
||||
if(Status != STATUS_EFI_SUCCESS)
|
||||
{
|
||||
/* Mapping module code failed */
|
||||
return Status;
|
||||
}
|
||||
|
||||
/* Get next module */
|
||||
ModulesListEntry = ModulesListEntry->Flink;
|
||||
}
|
||||
|
||||
/* Get boot loader image information */
|
||||
XtLoader::GetLoaderImageInformation(&LoaderBase, &LoaderSize);
|
||||
|
||||
/* Make sure boot loader image base and size are set */
|
||||
if(LoaderBase && LoaderSize)
|
||||
{
|
||||
/* Map boot loader code as well */
|
||||
Status = MapVirtualMemory(PageMap, LoaderBase, LoaderBase,
|
||||
EFI_SIZE_TO_PAGES(LoaderSize), LoaderFirmwareTemporary);
|
||||
if(Status != STATUS_EFI_SUCCESS)
|
||||
{
|
||||
/* Mapping boot loader code failed */
|
||||
return Status;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Boot loader image information re not available */
|
||||
return STATUS_EFI_PROTOCOL_ERROR;
|
||||
}
|
||||
|
||||
/* Iterate through and map all the mappings*/
|
||||
Debug::Print(L"Mapping and dumping EFI memory:\n");
|
||||
ListEntry = PageMap->MemoryMap.Flink;
|
||||
while(ListEntry != &PageMap->MemoryMap)
|
||||
{
|
||||
/* Take mapping from the list */
|
||||
Mapping = CONTAIN_RECORD(ListEntry, XTBL_MEMORY_MAPPING, ListEntry);
|
||||
|
||||
/* Check if virtual address is set */
|
||||
if(Mapping->VirtualAddress)
|
||||
{
|
||||
/* Dump memory mapping */
|
||||
Debug::Print(L" Type=%02lu, PhysicalBase=%.16P, VirtualBase=%.16P, Pages=%llu\n", Mapping->MemoryType,
|
||||
Mapping->PhysicalAddress, Mapping->VirtualAddress, Mapping->NumberOfPages);
|
||||
|
||||
/* Map memory */
|
||||
Status = MapPage(PageMap, (UINT_PTR)Mapping->VirtualAddress,
|
||||
(UINT_PTR)Mapping->PhysicalAddress, Mapping->NumberOfPages);
|
||||
if(Status != STATUS_EFI_SUCCESS)
|
||||
{
|
||||
/* Memory mapping failed */
|
||||
return Status;
|
||||
}
|
||||
}
|
||||
|
||||
/* Take next element */
|
||||
ListEntry = ListEntry->Flink;
|
||||
}
|
||||
|
||||
/* Return success */
|
||||
return STATUS_EFI_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns next level of the Page Table.
|
||||
*
|
||||
* @param PageMap
|
||||
* Supplies a pointer to the page mapping structure.
|
||||
*
|
||||
* @param PageTable
|
||||
* Supplies a pointer to the current Page Table.
|
||||
*
|
||||
* @param Entry
|
||||
* Supplies an index of the current Page Table entry.
|
||||
*
|
||||
* @param NextPageTable
|
||||
* Supplies a pointer to the memory area where the next Page Table level is returned.
|
||||
*
|
||||
* @return This routine returns a status code.
|
||||
*
|
||||
* @since XT 1.0
|
||||
*/
|
||||
XTCDECL
|
||||
EFI_STATUS
|
||||
Memory::GetNextPageTable(IN PXTBL_PAGE_MAPPING PageMap,
|
||||
IN PVOID PageTable,
|
||||
IN SIZE_T Entry,
|
||||
OUT PVOID *NextPageTable)
|
||||
{
|
||||
EFI_PHYSICAL_ADDRESS Address;
|
||||
ULONGLONG PmlPointer = 0;
|
||||
PHARDWARE_PTE PmlTable;
|
||||
EFI_STATUS Status;
|
||||
|
||||
PmlTable = (PHARDWARE_PTE)PageTable;
|
||||
|
||||
/* Check if this is a valid table */
|
||||
if(PmlTable[Entry].Valid)
|
||||
{
|
||||
/* Get PML pointer */
|
||||
PmlPointer = PmlTable[Entry].PageFrameNumber;
|
||||
PmlPointer <<= EFI_PAGE_SHIFT;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Allocate pages for new PML entry */
|
||||
Status = AllocatePages(AllocateAnyPages, 1, &Address);
|
||||
if(Status != STATUS_EFI_SUCCESS)
|
||||
{
|
||||
/* Memory allocation failure */
|
||||
return Status;
|
||||
}
|
||||
|
||||
/* Add new memory mapping */
|
||||
Status = MapVirtualMemory(PageMap, NULLPTR, (PVOID)(UINT_PTR)Address, 1, LoaderMemoryData);
|
||||
if(Status != STATUS_EFI_SUCCESS)
|
||||
{
|
||||
/* Memory mapping failure */
|
||||
return Status;
|
||||
}
|
||||
|
||||
/* Fill allocated memory with zeros */
|
||||
RTL::Memory::ZeroMemory((PVOID)(ULONGLONG)Address, EFI_PAGE_SIZE);
|
||||
|
||||
/* Set paging entry settings */
|
||||
PmlTable[Entry].PageFrameNumber = Address / EFI_PAGE_SIZE;
|
||||
PmlTable[Entry].Valid = 1;
|
||||
PmlTable[Entry].Writable = 1;
|
||||
PmlPointer = (ULONGLONG)Address;
|
||||
}
|
||||
|
||||
/* Set next Page Map Level (PML) */
|
||||
*NextPageTable = (PVOID)(ULONGLONG)PmlPointer;
|
||||
|
||||
/* Return success */
|
||||
return STATUS_EFI_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* Does the actual virtual memory mapping.
|
||||
*
|
||||
* @param PageMap
|
||||
* Supplies a pointer to the page mapping structure.
|
||||
*
|
||||
* @param VirtualAddress
|
||||
* Supplies a virtual address of the mapping.
|
||||
*
|
||||
* @param PhysicalAddress
|
||||
* Supplies a physical address of the mapping.
|
||||
*
|
||||
* @param NumberOfPages
|
||||
* Supplies a number of the pages of the mapping.
|
||||
*
|
||||
* @return This routine returns a status code.
|
||||
*
|
||||
* @since XT 1.0
|
||||
*/
|
||||
XTCDECL
|
||||
EFI_STATUS
|
||||
Memory::MapPage(IN PXTBL_PAGE_MAPPING PageMap,
|
||||
IN ULONG_PTR VirtualAddress,
|
||||
IN ULONG_PTR PhysicalAddress,
|
||||
IN ULONG NumberOfPages)
|
||||
{
|
||||
PVOID Pml1, Pml2, Pml3, Pml4, Pml5;
|
||||
SIZE_T Pml1Entry, Pml2Entry, Pml3Entry, Pml4Entry, Pml5Entry;
|
||||
PHARDWARE_PTE PmlTable;
|
||||
SIZE_T PageFrameNumber;
|
||||
EFI_STATUS Status;
|
||||
|
||||
/* Set the Page Frame Number (PFN) */
|
||||
PageFrameNumber = PhysicalAddress >> EFI_PAGE_SHIFT;
|
||||
|
||||
/* Do the recursive mapping */
|
||||
while(NumberOfPages > 0)
|
||||
{
|
||||
/* Calculate the indices in the various Page Tables from the virtual address */
|
||||
Pml5Entry = (VirtualAddress & ((ULONGLONG)0x1FF << MM_P5I_SHIFT)) >> MM_P5I_SHIFT;
|
||||
Pml4Entry = (VirtualAddress & ((ULONGLONG)0x1FF << MM_PXI_SHIFT)) >> MM_PXI_SHIFT;
|
||||
Pml3Entry = (VirtualAddress & ((ULONGLONG)0x1FF << MM_PPI_SHIFT)) >> MM_PPI_SHIFT;
|
||||
Pml2Entry = (VirtualAddress & ((ULONGLONG)0x1FF << MM_PDI_SHIFT)) >> MM_PDI_SHIFT;
|
||||
Pml1Entry = (VirtualAddress & ((ULONGLONG)0x1FF << MM_PTI_SHIFT)) >> MM_PTI_SHIFT;
|
||||
|
||||
/* Check page map level */
|
||||
if(PageMap->PageMapLevel == 5)
|
||||
{
|
||||
/* Five level Page Map */
|
||||
Pml5 = PageMap->PtePointer;
|
||||
|
||||
/* Get PML4 */
|
||||
Status = GetNextPageTable(PageMap, Pml5, Pml5Entry, &Pml4);
|
||||
if(Status != STATUS_EFI_SUCCESS)
|
||||
{
|
||||
/* Memory mapping failure */
|
||||
return Status;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Four level Page Map */
|
||||
Pml4 = PageMap->PtePointer;
|
||||
}
|
||||
|
||||
/* Get PML3 */
|
||||
Status = GetNextPageTable(PageMap, Pml4, Pml4Entry, &Pml3);
|
||||
if(Status != STATUS_EFI_SUCCESS)
|
||||
{
|
||||
/* Memory mapping failure */
|
||||
return Status;
|
||||
}
|
||||
|
||||
/* Get PML 2 */
|
||||
Status = GetNextPageTable(PageMap, Pml3, Pml3Entry, &Pml2);
|
||||
if(Status != STATUS_EFI_SUCCESS)
|
||||
{
|
||||
/* Memory mapping failure */
|
||||
return Status;
|
||||
}
|
||||
|
||||
/* Get PML1 */
|
||||
Status = GetNextPageTable(PageMap, Pml2, Pml2Entry, &Pml1);
|
||||
if(Status != STATUS_EFI_SUCCESS)
|
||||
{
|
||||
/* Memory mapping failure */
|
||||
return Status;
|
||||
}
|
||||
|
||||
/* Set paging entry settings */
|
||||
PmlTable = (PHARDWARE_PTE)Pml1;
|
||||
RTL::Memory::ZeroMemory(&PmlTable[Pml1Entry], sizeof(HARDWARE_PTE));
|
||||
PmlTable[Pml1Entry].PageFrameNumber = PageFrameNumber;
|
||||
PmlTable[Pml1Entry].Valid = 1;
|
||||
PmlTable[Pml1Entry].Writable = 1;
|
||||
|
||||
/* Take next virtual address and PFN */
|
||||
VirtualAddress += EFI_PAGE_SIZE;
|
||||
PageFrameNumber++;
|
||||
|
||||
/* Decrease number of pages left */
|
||||
NumberOfPages--;
|
||||
}
|
||||
|
||||
/* Return success */
|
||||
return STATUS_EFI_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a recursive self mapping for all PML levels.
|
||||
*
|
||||
* @param PageMap
|
||||
* Supplies a pointer to the page mapping structure.
|
||||
*
|
||||
* @param SelfMapAddress
|
||||
* Supplies a virtual address of the page tables.
|
||||
*
|
||||
* @return This routine returns a status code.
|
||||
*
|
||||
* @since XT 1.0
|
||||
*/
|
||||
XTCDECL
|
||||
EFI_STATUS
|
||||
Memory::SelfMapPml(IN PXTBL_PAGE_MAPPING PageMap,
|
||||
IN ULONG_PTR SelfMapAddress)
|
||||
{
|
||||
PHARDWARE_PTE PmlBase;
|
||||
ULONGLONG PmlIndex;
|
||||
|
||||
/* Initialize PML base pointer */
|
||||
PmlBase = (PHARDWARE_PTE)PageMap->PtePointer;
|
||||
|
||||
/* Check page map level */
|
||||
if(PageMap->PageMapLevel == 5)
|
||||
{
|
||||
/* Calculate PML index based on provided self map address for PML5 */
|
||||
PmlIndex = (SelfMapAddress >> MM_P5I_SHIFT) & 0x1FF;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Calculate PML index based on provided self map address for PML4 */
|
||||
PmlIndex = (SelfMapAddress >> MM_PXI_SHIFT) & 0x1FF;
|
||||
}
|
||||
|
||||
/* Add self-mapping */
|
||||
RTL::Memory::ZeroMemory(&PmlBase[PmlIndex], sizeof(HARDWARE_PTE));
|
||||
PmlBase[PmlIndex].PageFrameNumber = (UINT_PTR)PageMap->PtePointer / EFI_PAGE_SIZE;
|
||||
PmlBase[PmlIndex].Valid = 1;
|
||||
PmlBase[PmlIndex].Writable = 1;
|
||||
|
||||
/* Return success */
|
||||
return STATUS_EFI_SUCCESS;
|
||||
}
|
461
boot/xtldr/arch/i686/memory.cc
Normal file
461
boot/xtldr/arch/i686/memory.cc
Normal file
@@ -0,0 +1,461 @@
|
||||
/**
|
||||
* PROJECT: ExectOS
|
||||
* COPYRIGHT: See COPYING.md in the top level directory
|
||||
* FILE: xtldr/arch/i686/memory.cc
|
||||
* DESCRIPTION: XT Boot Loader i686 specific memory management
|
||||
* DEVELOPERS: Rafal Kupiec <belliash@codingworkshop.eu.org>
|
||||
* Aiken Harris <harraiken91@gmail.com>
|
||||
*/
|
||||
|
||||
#include <xtldr.hh>
|
||||
|
||||
|
||||
/**
|
||||
* Maps boot loader related code and builds page map.
|
||||
*
|
||||
* @param PageMap
|
||||
* Supplies a pointer to the page mapping structure.
|
||||
*
|
||||
* @return This routine returns a status code.
|
||||
*
|
||||
* @since XT 1.0
|
||||
*/
|
||||
XTCDECL
|
||||
EFI_STATUS
|
||||
Memory::BuildPageMap(IN PXTBL_PAGE_MAPPING PageMap,
|
||||
IN ULONG_PTR SelfMapAddress)
|
||||
{
|
||||
PLIST_ENTRY ListEntry, ModulesList, ModulesListEntry;
|
||||
EFI_PHYSICAL_ADDRESS Address, DirectoryAddress;
|
||||
PXTBL_MODULE_INFO ModuleInfo;
|
||||
PXTBL_MEMORY_MAPPING Mapping;
|
||||
PVOID LoaderBase;
|
||||
ULONGLONG LoaderSize;
|
||||
EFI_STATUS Status;
|
||||
ULONG Index;
|
||||
|
||||
/* Check the page map level to determine which paging structure to create */
|
||||
if(PageMap->PageMapLevel == 3)
|
||||
{
|
||||
/* Allocate a page for the 3-level page map structure (PAE enabled) */
|
||||
Status = AllocatePages(AllocateAnyPages, 1, &Address);
|
||||
if(Status != STATUS_EFI_SUCCESS)
|
||||
{
|
||||
/* Memory allocation failed, cannot proceed with page map creation */
|
||||
return Status;
|
||||
}
|
||||
|
||||
/* Assign the allocated page to the page map and zero it out */
|
||||
PageMap->PtePointer = (PVOID)(UINT_PTR)Address;
|
||||
RTL::Memory::ZeroMemory(PageMap->PtePointer, EFI_PAGE_SIZE);
|
||||
|
||||
/* Allocate 4 pages for the Page Directories (PDs) */
|
||||
Status = AllocatePages(AllocateAnyPages, 4, &DirectoryAddress);
|
||||
if(Status != STATUS_EFI_SUCCESS)
|
||||
{
|
||||
/* Memory allocation failed, cannot proceed with page map creation */
|
||||
return Status;
|
||||
}
|
||||
|
||||
/* Zero-fill the allocated memory for the Page Directories */
|
||||
RTL::Memory::ZeroMemory((PVOID)DirectoryAddress, EFI_PAGE_SIZE * 4);
|
||||
|
||||
/* Fill the PDPT with pointers to the Page Directories */
|
||||
for(Index = 0; Index < 4; Index++)
|
||||
{
|
||||
RTL::Memory::ZeroMemory(&((PHARDWARE_MODERN_PTE)PageMap->PtePointer)[Index], sizeof(HARDWARE_MODERN_PTE));
|
||||
((PHARDWARE_MODERN_PTE)PageMap->PtePointer)[Index].PageFrameNumber = DirectoryAddress / EFI_PAGE_SIZE;
|
||||
((PHARDWARE_MODERN_PTE)PageMap->PtePointer)[Index].Valid = 1;
|
||||
DirectoryAddress += EFI_PAGE_SIZE;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Allocate a page for the 2-level page map structure (PAE disabled) */
|
||||
Status = AllocatePages(AllocateAnyPages, 1, &Address);
|
||||
if(Status != STATUS_EFI_SUCCESS)
|
||||
{
|
||||
/* Memory allocation failed, cannot proceed with page map creation */
|
||||
return Status;
|
||||
}
|
||||
|
||||
/* Assign the allocated page to the page map and zero it out */
|
||||
PageMap->PtePointer = (PVOID)(UINT_PTR)Address;
|
||||
RTL::Memory::ZeroMemory(PageMap->PtePointer, EFI_PAGE_SIZE);
|
||||
}
|
||||
|
||||
/* Add page mapping itself to memory mapping */
|
||||
Status = SelfMapPml(PageMap, SelfMapAddress);
|
||||
if(Status != STATUS_EFI_SUCCESS)
|
||||
{
|
||||
/* PML mapping failed */
|
||||
return Status;
|
||||
}
|
||||
|
||||
/* Map the trampoline code area */
|
||||
Status = MapVirtualMemory(PageMap, (PVOID)MM_TRAMPOLINE_ADDRESS,(PVOID)MM_TRAMPOLINE_ADDRESS,
|
||||
1, LoaderFirmwareTemporary);
|
||||
if(Status != STATUS_EFI_SUCCESS)
|
||||
{
|
||||
/* Mapping trampoline code failed */
|
||||
return Status;
|
||||
}
|
||||
|
||||
/* Get list of XTLDR modules */
|
||||
ModulesList = Protocol::GetModulesList();
|
||||
ModulesListEntry = ModulesList->Flink;
|
||||
while(ModulesListEntry != ModulesList)
|
||||
{
|
||||
/* Get module info */
|
||||
ModuleInfo = CONTAIN_RECORD(ModulesListEntry, XTBL_MODULE_INFO, Flink);
|
||||
|
||||
/* Map module code */
|
||||
Status = MapVirtualMemory(PageMap, ModuleInfo->ModuleBase, ModuleInfo->ModuleBase,
|
||||
EFI_SIZE_TO_PAGES(ModuleInfo->ModuleSize), LoaderFirmwareTemporary);
|
||||
|
||||
/* Check if mapping succeeded */
|
||||
if(Status != STATUS_EFI_SUCCESS)
|
||||
{
|
||||
/* Mapping module code failed */
|
||||
return Status;
|
||||
}
|
||||
|
||||
/* Get next module */
|
||||
ModulesListEntry = ModulesListEntry->Flink;
|
||||
}
|
||||
|
||||
/* Get boot loader image information */
|
||||
XtLoader::GetLoaderImageInformation(&LoaderBase, &LoaderSize);
|
||||
|
||||
/* Make sure boot loader image base and size are set */
|
||||
if(LoaderBase && LoaderSize)
|
||||
{
|
||||
/* Map boot loader code as well */
|
||||
Status = MapVirtualMemory(PageMap, LoaderBase, LoaderBase,
|
||||
EFI_SIZE_TO_PAGES(LoaderSize), LoaderFirmwareTemporary);
|
||||
if(Status != STATUS_EFI_SUCCESS)
|
||||
{
|
||||
/* Mapping boot loader code failed */
|
||||
return Status;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Boot loader image information re not available */
|
||||
return STATUS_EFI_PROTOCOL_ERROR;
|
||||
}
|
||||
|
||||
/* Iterate through and map all the mappings*/
|
||||
Debug::Print(L"Mapping and dumping EFI memory:\n");
|
||||
ListEntry = PageMap->MemoryMap.Flink;
|
||||
while(ListEntry != &PageMap->MemoryMap)
|
||||
{
|
||||
/* Take mapping from the list */
|
||||
Mapping = CONTAIN_RECORD(ListEntry, XTBL_MEMORY_MAPPING, ListEntry);
|
||||
|
||||
/* Check if virtual address is set */
|
||||
if(Mapping->VirtualAddress)
|
||||
{
|
||||
/* Dump memory mapping */
|
||||
Debug::Print(L" Type=%02lu, PhysicalBase=%.8P, VirtualBase=%.8P, Pages=%llu\n", Mapping->MemoryType,
|
||||
Mapping->PhysicalAddress, Mapping->VirtualAddress, Mapping->NumberOfPages);
|
||||
|
||||
/* Map memory */
|
||||
Status = MapPage(PageMap, (UINT_PTR)Mapping->VirtualAddress,
|
||||
(UINT_PTR)Mapping->PhysicalAddress, Mapping->NumberOfPages);
|
||||
if(Status != STATUS_EFI_SUCCESS)
|
||||
{
|
||||
/* Memory mapping failed */
|
||||
return Status;
|
||||
}
|
||||
}
|
||||
|
||||
/* Take next element */
|
||||
ListEntry = ListEntry->Flink;
|
||||
}
|
||||
|
||||
/* Return success */
|
||||
return STATUS_EFI_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns next level of the Page Table.
|
||||
*
|
||||
* @param PageMap
|
||||
* Supplies a pointer to the page mapping structure.
|
||||
*
|
||||
* @param PageTable
|
||||
* Supplies a pointer to the current Page Table.
|
||||
*
|
||||
* @param Entry
|
||||
* Supplies an index of the current Page Table entry.
|
||||
*
|
||||
* @param NextPageTable
|
||||
* Supplies a pointer to the memory area where the next Page Table level is returned.
|
||||
*
|
||||
* @return This routine returns a status code.
|
||||
*
|
||||
* @since XT 1.0
|
||||
*/
|
||||
XTCDECL
|
||||
EFI_STATUS
|
||||
Memory::GetNextPageTable(IN PXTBL_PAGE_MAPPING PageMap,
|
||||
IN PVOID PageTable,
|
||||
IN SIZE_T Entry,
|
||||
OUT PVOID *NextPageTable)
|
||||
{
|
||||
EFI_PHYSICAL_ADDRESS Address;
|
||||
ULONGLONG PmlPointer = 0;
|
||||
EFI_STATUS Status;
|
||||
PHARDWARE_LEGACY_PTE LegacyPmlTable;
|
||||
PHARDWARE_MODERN_PTE PmlTable;
|
||||
BOOLEAN ValidPte = FALSE;
|
||||
|
||||
/* Check page map level to determine PTE size */
|
||||
if(PageMap->PageMapLevel >= 3)
|
||||
{
|
||||
/* 64-bit PTE for PML3 (PAE enabled) */
|
||||
PmlTable = (PHARDWARE_MODERN_PTE)PageTable;
|
||||
if(PmlTable[Entry].Valid)
|
||||
{
|
||||
/* Get page frame number from page table entry */
|
||||
PmlPointer = PmlTable[Entry].PageFrameNumber;
|
||||
ValidPte = TRUE;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* 32-bit PTE for PML2 (PAE disabled) */
|
||||
LegacyPmlTable = (PHARDWARE_LEGACY_PTE)PageTable;
|
||||
if(LegacyPmlTable[Entry].Valid)
|
||||
{
|
||||
/* Get page frame number from page table entry */
|
||||
PmlPointer = LegacyPmlTable[Entry].PageFrameNumber;
|
||||
ValidPte = TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
/* Check if page table entry is valid */
|
||||
if(ValidPte)
|
||||
{
|
||||
/* Calculate the base address of the next page table */
|
||||
PmlPointer <<= EFI_PAGE_SHIFT;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Allocate pages for new PML entry */
|
||||
Status = AllocatePages(AllocateAnyPages, 1, &Address);
|
||||
if(Status != STATUS_EFI_SUCCESS)
|
||||
{
|
||||
/* Memory allocation failure */
|
||||
return Status;
|
||||
}
|
||||
|
||||
/* Add new memory mapping */
|
||||
Status = MapVirtualMemory(PageMap, NULLPTR, (PVOID)(UINT_PTR)Address, 1, LoaderMemoryData);
|
||||
if(Status != STATUS_EFI_SUCCESS)
|
||||
{
|
||||
/* Memory mapping failure */
|
||||
return Status;
|
||||
}
|
||||
|
||||
/* Fill allocated memory with zeros */
|
||||
RTL::Memory::ZeroMemory((PVOID)(ULONGLONG)Address, EFI_PAGE_SIZE);
|
||||
|
||||
/* Set paging entry settings based on level */
|
||||
if(PageMap->PageMapLevel >= 3)
|
||||
{
|
||||
/* 64-bit PTE for PML3 (PAE enabled) */
|
||||
PmlTable = (PHARDWARE_MODERN_PTE)PageTable;
|
||||
PmlTable[Entry].PageFrameNumber = Address / EFI_PAGE_SIZE;
|
||||
PmlTable[Entry].Valid = 1;
|
||||
PmlTable[Entry].Writable = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* 32-bit PTE for PML2 (PAE disabled) */
|
||||
LegacyPmlTable = (PHARDWARE_LEGACY_PTE)PageTable;
|
||||
LegacyPmlTable[Entry].PageFrameNumber = (UINT32)(Address / EFI_PAGE_SIZE);
|
||||
LegacyPmlTable[Entry].Valid = 1;
|
||||
LegacyPmlTable[Entry].Writable = 1;
|
||||
}
|
||||
|
||||
/* Return the address of the new page table */
|
||||
PmlPointer = (ULONGLONG)Address;
|
||||
}
|
||||
|
||||
/* Set next Page Map Level (PML) */
|
||||
*NextPageTable = (PVOID)(ULONGLONG)PmlPointer;
|
||||
|
||||
/* Return success */
|
||||
return STATUS_EFI_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* Does the actual virtual memory mapping.
|
||||
*
|
||||
* @param PageMap
|
||||
* Supplies a pointer to the page mapping structure.
|
||||
*
|
||||
* @param VirtualAddress
|
||||
* Supplies a virtual address of the mapping.
|
||||
*
|
||||
* @param PhysicalAddress
|
||||
* Supplies a physical address of the mapping.
|
||||
*
|
||||
* @param NumberOfPages
|
||||
* Supplies a number of the pages of the mapping.
|
||||
*
|
||||
* @return This routine returns a status code.
|
||||
*
|
||||
* @since XT 1.0
|
||||
*/
|
||||
XTCDECL
|
||||
EFI_STATUS
|
||||
Memory::MapPage(IN PXTBL_PAGE_MAPPING PageMap,
|
||||
IN ULONG_PTR VirtualAddress,
|
||||
IN ULONG_PTR PhysicalAddress,
|
||||
IN ULONG NumberOfPages)
|
||||
{
|
||||
SIZE_T PageFrameNumber;
|
||||
PVOID Pml1, Pml2, Pml3;
|
||||
SIZE_T Pml1Entry, Pml2Entry, Pml3Entry;
|
||||
PHARDWARE_LEGACY_PTE LegacyPmlTable;
|
||||
PHARDWARE_MODERN_PTE PmlTable;
|
||||
EFI_STATUS Status;
|
||||
|
||||
/* Set the Page Frame Number (PFN) */
|
||||
PageFrameNumber = PhysicalAddress >> EFI_PAGE_SHIFT;
|
||||
|
||||
/* Map all requested pages */
|
||||
while(NumberOfPages > 0)
|
||||
{
|
||||
/* Check the paging mode to use the correct page table structure */
|
||||
if(PageMap->PageMapLevel == 3)
|
||||
{
|
||||
/* Calculate the indices for PAE page tables */
|
||||
Pml3Entry = (VirtualAddress >> 30) & 0x3;
|
||||
Pml2Entry = (VirtualAddress >> 21) & 0x1FF;
|
||||
Pml1Entry = (VirtualAddress >> 12) & 0x1FF;
|
||||
|
||||
/* Get Page Directory Pointer Table (PML3) */
|
||||
Pml3 = PageMap->PtePointer;
|
||||
|
||||
/* Get Page Directory (PML2) */
|
||||
Status = GetNextPageTable(PageMap, Pml3, Pml3Entry, &Pml2);
|
||||
if(Status != STATUS_EFI_SUCCESS)
|
||||
{
|
||||
/* Failed to get the Page Table, abort mapping */
|
||||
return Status;
|
||||
}
|
||||
|
||||
/* Get Page Table (PML1) */
|
||||
Status = GetNextPageTable(PageMap, Pml2, Pml2Entry, &Pml1);
|
||||
if(Status != STATUS_EFI_SUCCESS)
|
||||
{
|
||||
/* Failed to get the Page Table, abort mapping */
|
||||
return Status;
|
||||
}
|
||||
|
||||
/* Set the 64-bit PTE entry */
|
||||
PmlTable = (PHARDWARE_MODERN_PTE)Pml1;
|
||||
RTL::Memory::ZeroMemory(&PmlTable[Pml1Entry], sizeof(HARDWARE_MODERN_PTE));
|
||||
PmlTable[Pml1Entry].PageFrameNumber = PageFrameNumber;
|
||||
PmlTable[Pml1Entry].Valid = 1;
|
||||
PmlTable[Pml1Entry].Writable = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Calculate the indices for non-PAE page tables */
|
||||
Pml2Entry = (VirtualAddress >> 22) & 0x3FF;
|
||||
Pml1Entry = (VirtualAddress >> 12) & 0x3FF;
|
||||
|
||||
/* Get Page Directory (PML2) */
|
||||
Pml2 = PageMap->PtePointer;
|
||||
|
||||
/* Get Page Table (PML1) */
|
||||
Status = GetNextPageTable(PageMap, Pml2, Pml2Entry, &Pml1);
|
||||
if(Status != STATUS_EFI_SUCCESS)
|
||||
{
|
||||
/* Failed to get the Page Table, abort mapping */
|
||||
return Status;
|
||||
}
|
||||
|
||||
/* Set the 32-bit PTE entry */
|
||||
LegacyPmlTable = (PHARDWARE_LEGACY_PTE)Pml1;
|
||||
RTL::Memory::ZeroMemory(&LegacyPmlTable[Pml1Entry], sizeof(HARDWARE_LEGACY_PTE));
|
||||
LegacyPmlTable[Pml1Entry].PageFrameNumber = (UINT32)PageFrameNumber;
|
||||
LegacyPmlTable[Pml1Entry].Valid = 1;
|
||||
LegacyPmlTable[Pml1Entry].Writable = 1;
|
||||
}
|
||||
|
||||
/* Take next virtual address and PFN */
|
||||
VirtualAddress += EFI_PAGE_SIZE;
|
||||
PageFrameNumber++;
|
||||
|
||||
/* Decrease number of pages left */
|
||||
NumberOfPages--;
|
||||
}
|
||||
|
||||
/* Return success */
|
||||
return STATUS_EFI_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a recursive self mapping for all PML levels.
|
||||
*
|
||||
* @param PageMap
|
||||
* Supplies a pointer to the page mapping structure.
|
||||
*
|
||||
* @param SelfMapAddress
|
||||
* Supplies a virtual address of the page tables.
|
||||
*
|
||||
* @return This routine returns a status code.
|
||||
*
|
||||
* @since XT 1.0
|
||||
*/
|
||||
XTCDECL
|
||||
EFI_STATUS
|
||||
Memory::SelfMapPml(IN PXTBL_PAGE_MAPPING PageMap,
|
||||
IN ULONG_PTR SelfMapAddress)
|
||||
{
|
||||
PHARDWARE_LEGACY_PTE LegacyPml;
|
||||
PHARDWARE_MODERN_PTE Pml;
|
||||
ULONGLONG PmlIndex;
|
||||
ULONG Index;
|
||||
|
||||
/* Check page map level */
|
||||
if(PageMap->PageMapLevel == 3)
|
||||
{
|
||||
/* Calculate PML index based on provided self map address */
|
||||
PmlIndex = (SelfMapAddress >> MM_PDI_SHIFT) & 0x1FF;
|
||||
|
||||
/* Get Page Directory */
|
||||
Pml = (PHARDWARE_MODERN_PTE)(((PHARDWARE_MODERN_PTE)PageMap->PtePointer)[SelfMapAddress >> MM_PPI_SHIFT].PageFrameNumber * EFI_PAGE_SIZE);
|
||||
|
||||
/* Add self-mapping for PML3 (PAE enabled) */
|
||||
for(Index = 0; Index < 4; Index++)
|
||||
{
|
||||
RTL::Memory::ZeroMemory(&Pml[PmlIndex + Index], sizeof(HARDWARE_MODERN_PTE));
|
||||
Pml[PmlIndex + Index].PageFrameNumber = ((PHARDWARE_MODERN_PTE)PageMap->PtePointer)[Index].PageFrameNumber;
|
||||
Pml[PmlIndex + Index].Valid = 1;
|
||||
Pml[PmlIndex + Index].Writable = 1;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
LegacyPml = (PHARDWARE_LEGACY_PTE)PageMap->PtePointer;
|
||||
|
||||
/* Calculate PML index based on provided self map address */
|
||||
PmlIndex = (SelfMapAddress >> MM_PDI_LEGACY_SHIFT);
|
||||
|
||||
/* Add self-mapping for PML2 (PAE disabled) */
|
||||
RTL::Memory::ZeroMemory(&LegacyPml[PmlIndex], sizeof(HARDWARE_LEGACY_PTE));
|
||||
LegacyPml[PmlIndex].PageFrameNumber = (UINT_PTR)PageMap->PtePointer / EFI_PAGE_SIZE;
|
||||
LegacyPml[PmlIndex].Valid = 1;
|
||||
LegacyPml[PmlIndex].Writable = 1;
|
||||
}
|
||||
|
||||
/* Return success */
|
||||
return STATUS_EFI_SUCCESS;
|
||||
}
|
87
boot/xtldr/bootutil.cc
Normal file
87
boot/xtldr/bootutil.cc
Normal file
@@ -0,0 +1,87 @@
|
||||
/**
|
||||
* PROJECT: ExectOS
|
||||
* COPYRIGHT: See COPYING.md in the top level directory
|
||||
* FILE: xtldr/bootutil.cc
|
||||
* DESCRIPTION: Helper functions used by the boot protocol during system startup
|
||||
* DEVELOPERS: Aiken Harris <harraiken91@gmail.com>
|
||||
*/
|
||||
|
||||
#include <xtldr.hh>
|
||||
|
||||
|
||||
/**
|
||||
* Checks if a specific option exists in the list of provided boot parameters.
|
||||
*
|
||||
* @param Parameters
|
||||
* A pointer to the wide-character string containing the boot parameters, separated by spaces.
|
||||
*
|
||||
* @param Needle
|
||||
* A pointer to the wide-character string representing the kernel option to find.
|
||||
*
|
||||
* @return This routine returns TRUE if the option is found, otherwise FALSE.
|
||||
*
|
||||
* @since XT 1.0
|
||||
*/
|
||||
XTCDECL
|
||||
BOOLEAN
|
||||
BootUtils::GetBooleanParameter(IN PCWSTR Parameters,
|
||||
IN PCWSTR Needle)
|
||||
{
|
||||
PCWSTR CurrentPosition, TokenEnd, TokenStart;
|
||||
SIZE_T NeedleLength, TokenLength;
|
||||
|
||||
/* Validate input data and ensure the option is not an empty string */
|
||||
if(Parameters == NULLPTR || Needle == NULLPTR || *Needle == L'\0')
|
||||
{
|
||||
/* One of the parameters was invalid */
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
CurrentPosition = Parameters;
|
||||
NeedleLength = RTL::WideString::WideStringLength(Needle, 0);
|
||||
|
||||
/* Iterate through the entire parameters string */
|
||||
while(*CurrentPosition != L'\0')
|
||||
{
|
||||
/* Skip any leading whitespace to find the start of the token */
|
||||
while(*CurrentPosition == L' ')
|
||||
{
|
||||
CurrentPosition++;
|
||||
}
|
||||
|
||||
/* Check if end of the string has been reached */
|
||||
if(*CurrentPosition == L'\0')
|
||||
{
|
||||
/* End of string reached, no more tokens */
|
||||
break;
|
||||
}
|
||||
|
||||
/* Identify the boundaries of the current token */
|
||||
TokenStart = CurrentPosition;
|
||||
TokenEnd = TokenStart;
|
||||
while(*TokenEnd != L'\0' && *TokenEnd != L' ')
|
||||
{
|
||||
TokenEnd++;
|
||||
}
|
||||
|
||||
/* Calculate the length of the token found */
|
||||
TokenLength = TokenEnd - TokenStart;
|
||||
|
||||
/* Compare the token length */
|
||||
if(TokenLength == NeedleLength)
|
||||
{
|
||||
/* Length matches, compare the strings */
|
||||
if(RTL::WideString::CompareWideStringInsensitive(TokenStart, Needle, NeedleLength) == 0)
|
||||
{
|
||||
/* A match was found */
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
/* Move the position past the current token to continue the search */
|
||||
CurrentPosition = TokenEnd;
|
||||
}
|
||||
|
||||
/* No match was found */
|
||||
return FALSE;
|
||||
}
|
1052
boot/xtldr/config.cc
Normal file
1052
boot/xtldr/config.cc
Normal file
File diff suppressed because it is too large
Load Diff
314
boot/xtldr/console.cc
Normal file
314
boot/xtldr/console.cc
Normal file
@@ -0,0 +1,314 @@
|
||||
/**
|
||||
* PROJECT: ExectOS
|
||||
* COPYRIGHT: See COPYING.md in the top level directory
|
||||
* FILE: xtldr/console.cc
|
||||
* DESCRIPTION: EFI console support
|
||||
* DEVELOPERS: Rafal Kupiec <belliash@codingworkshop.eu.org>
|
||||
*/
|
||||
|
||||
#include <xtldr.hh>
|
||||
|
||||
|
||||
/**
|
||||
* Clears a specified line on the UEFI text console.
|
||||
*
|
||||
* @param LineNo
|
||||
* Supplies a line number to clear.
|
||||
*
|
||||
* @return This routine does not return any value.
|
||||
*
|
||||
* @since XT 1.0
|
||||
*/
|
||||
XTCDECL
|
||||
VOID
|
||||
Console::ClearLine(IN ULONGLONG LineNo)
|
||||
{
|
||||
UINT_PTR Index, ResX, ResY;
|
||||
|
||||
/* Query console mode */
|
||||
QueryMode(&ResX, &ResY);
|
||||
|
||||
/* Set cursor position and clear line */
|
||||
SetCursorPosition(0, LineNo);
|
||||
for(Index = 0; Index < ResX; Index++)
|
||||
{
|
||||
/* Clear line */
|
||||
Write(L" ");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This routine clears the UEFI console screen.
|
||||
*
|
||||
* @return This routine does not return any value.
|
||||
*
|
||||
* @since XT 1.0
|
||||
*/
|
||||
XTCDECL
|
||||
VOID
|
||||
Console::ClearScreen()
|
||||
{
|
||||
/* Clear screen */
|
||||
XtLoader::GetEfiSystemTable()->ConOut->ClearScreen(XtLoader::GetEfiSystemTable()->ConOut);
|
||||
}
|
||||
|
||||
/**
|
||||
* Disables the cursor on the UEFI console.
|
||||
*
|
||||
* @return This routine does not return any value.
|
||||
*
|
||||
* @since XT 1.0
|
||||
*/
|
||||
XTCDECL
|
||||
VOID
|
||||
Console::DisableCursor()
|
||||
{
|
||||
XtLoader::GetEfiSystemTable()->ConOut->EnableCursor(XtLoader::GetEfiSystemTable()->ConOut, FALSE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Enables the cursor on the UEFI console.
|
||||
*
|
||||
* @return This routine does not return any value.
|
||||
*
|
||||
* @since XT 1.0
|
||||
*/
|
||||
XTCDECL
|
||||
VOID
|
||||
Console::EnableCursor()
|
||||
{
|
||||
XtLoader::GetEfiSystemTable()->ConOut->EnableCursor(XtLoader::GetEfiSystemTable()->ConOut, TRUE);
|
||||
}
|
||||
|
||||
/**
|
||||
* This routine initializes the EFI console.
|
||||
*
|
||||
* @return This routine returns status code.
|
||||
*
|
||||
* @since XT 1.0
|
||||
*/
|
||||
XTCDECL
|
||||
VOID
|
||||
Console::InitializeConsole()
|
||||
{
|
||||
/* Clear console buffers */
|
||||
XtLoader::GetEfiSystemTable()->ConIn->Reset(XtLoader::GetEfiSystemTable()->ConIn, TRUE);
|
||||
XtLoader::GetEfiSystemTable()->ConOut->Reset(XtLoader::GetEfiSystemTable()->ConOut, TRUE);
|
||||
XtLoader::GetEfiSystemTable()->StdErr->Reset(XtLoader::GetEfiSystemTable()->StdErr, TRUE);
|
||||
|
||||
/* Make sure that current console mode is 80x25 characters, as some broken EFI implementations might
|
||||
* set different mode that do not fit on the screen, causing a text to be displayed offscreen */
|
||||
if(XtLoader::GetEfiSystemTable()->ConOut->Mode->Mode != 0)
|
||||
{
|
||||
/* Set console mode to 0, which is standard, 80x25 text mode */
|
||||
SetMode(0);
|
||||
}
|
||||
|
||||
/* Clear screen and enable cursor */
|
||||
SetAttributes(EFI_TEXT_BGCOLOR_BLACK | EFI_TEXT_FGCOLOR_LIGHTGRAY);
|
||||
ClearScreen();
|
||||
EnableCursor();
|
||||
}
|
||||
|
||||
/**
|
||||
* This routine formats the input string and prints it out to the stdout and serial console.
|
||||
*
|
||||
* @param Format
|
||||
* The formatted string that is to be written to the output.
|
||||
*
|
||||
* @param ...
|
||||
* Depending on the format string, this routine might expect a sequence of additional arguments.
|
||||
*
|
||||
* @return This routine does not return any value.
|
||||
*
|
||||
* @since XT 1.0
|
||||
*/
|
||||
XTCDECL
|
||||
VOID
|
||||
Console::Print(IN PCWSTR Format,
|
||||
IN ...)
|
||||
{
|
||||
RTL_PRINT_CONTEXT ConsolePrintContext, SerialPrintContext;
|
||||
VA_LIST Arguments;
|
||||
|
||||
/* Initialise the print contexts */
|
||||
ConsolePrintContext.WriteWideCharacter = PutChar;
|
||||
SerialPrintContext.WriteWideCharacter = Debug::PutChar;
|
||||
|
||||
/* Initialise the va_list */
|
||||
VA_START(Arguments, Format);
|
||||
|
||||
/* Format and print the string to the stdout */
|
||||
RTL::WideString::FormatWideString(&ConsolePrintContext, (PWCHAR)Format, Arguments);
|
||||
|
||||
/* Print to serial console only if not running under OVMF */
|
||||
if(RTL::WideString::CompareWideString(XtLoader::GetEfiSystemTable()->FirmwareVendor, L"EDK II", 6) != 0)
|
||||
{
|
||||
/* Check if debugging enabled and if EFI serial port is fully initialized */
|
||||
if(DEBUG && Debug::SerialPortReady())
|
||||
{
|
||||
/* Format and print the string to the serial console */
|
||||
RTL::WideString::FormatWideString(&SerialPrintContext, (PWCHAR)Format, Arguments);
|
||||
}
|
||||
}
|
||||
|
||||
/* Clean up the va_list */
|
||||
VA_END(Arguments);
|
||||
}
|
||||
|
||||
/**
|
||||
* Writes a character to the default EFI console.
|
||||
*
|
||||
* @param Character
|
||||
* The integer promotion of the character to be written.
|
||||
*
|
||||
* @return This routine returns a status code.
|
||||
*
|
||||
* @since XT 1.0
|
||||
*/
|
||||
XTCDECL
|
||||
XTSTATUS
|
||||
Console::PutChar(IN WCHAR Character)
|
||||
{
|
||||
WCHAR Buffer[2];
|
||||
|
||||
/* Check if character is a newline ('\n') */
|
||||
if(Character == L'\n')
|
||||
{
|
||||
/* Print carriage return ('\r') as well */
|
||||
PutChar(L'\r');
|
||||
}
|
||||
|
||||
/* Write character to the screen console */
|
||||
Buffer[0] = Character;
|
||||
Buffer[1] = 0;
|
||||
XtLoader::GetEfiSystemTable()->ConOut->OutputString(XtLoader::GetEfiSystemTable()->ConOut, Buffer);
|
||||
|
||||
/* Return success */
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* Queries information concerning the output device’s supported text mode.
|
||||
*
|
||||
* @param ResX
|
||||
* Supplies a buffer to receive the horizontal resolution.
|
||||
*
|
||||
* @param ResY
|
||||
* Supplies a buffer to receive the vertical resolution.
|
||||
*
|
||||
* @return This routine does not return any value.
|
||||
*
|
||||
* @since XT 1.0
|
||||
*/
|
||||
XTCDECL
|
||||
VOID
|
||||
Console::QueryMode(OUT PUINT_PTR ResX,
|
||||
OUT PUINT_PTR ResY)
|
||||
{
|
||||
XtLoader::GetEfiSystemTable()->ConOut->QueryMode(XtLoader::GetEfiSystemTable()->ConOut,
|
||||
XtLoader::GetEfiSystemTable()->ConOut->Mode->Mode, ResX, ResY);
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads a keystroke from the input device.
|
||||
*
|
||||
* @param Key
|
||||
* Supplies a pointer to the EFI_INPUT_KEY structure that will receive the keystroke.
|
||||
*
|
||||
* @return This routine does not return any value.
|
||||
*
|
||||
* @since XT 1.0
|
||||
*/
|
||||
XTCDECL
|
||||
VOID
|
||||
Console::ReadKeyStroke(OUT PEFI_INPUT_KEY Key)
|
||||
{
|
||||
XtLoader::GetEfiSystemTable()->ConIn->ReadKeyStroke(XtLoader::GetEfiSystemTable()->ConIn, Key);
|
||||
}
|
||||
|
||||
/**
|
||||
* Resets the console input device and clears its input buffer.
|
||||
*
|
||||
* @return This routine does not return any value.
|
||||
*
|
||||
* @since XT 1.0
|
||||
*/
|
||||
XTCDECL
|
||||
VOID
|
||||
Console::ResetInputBuffer()
|
||||
{
|
||||
XtLoader::GetEfiSystemTable()->ConIn->Reset(XtLoader::GetEfiSystemTable()->ConIn, FALSE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the foreground and background colors.
|
||||
*
|
||||
* @param Attribute
|
||||
* Specifies the foreground and background colors (bits 0..3 are fg, and bits 4..6 are bg color).
|
||||
*
|
||||
* @return This routine does not return any value.
|
||||
*
|
||||
* @since XT 1.0
|
||||
*/
|
||||
XTCDECL
|
||||
VOID
|
||||
Console::SetAttributes(IN ULONGLONG Attributes)
|
||||
{
|
||||
XtLoader::GetEfiSystemTable()->ConOut->SetAttribute(XtLoader::GetEfiSystemTable()->ConOut, Attributes);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets new coordinates of the console cursor position.
|
||||
*
|
||||
* @param PosX
|
||||
* Specifies the new X coordinate of the cursor.
|
||||
*
|
||||
* @param PosY
|
||||
* Specifies the new Y coordinate of the cursor.
|
||||
*
|
||||
* @return This routine does not return any value.
|
||||
*
|
||||
* @since XT 1.0
|
||||
*/
|
||||
XTCDECL
|
||||
VOID
|
||||
Console::SetCursorPosition(IN ULONGLONG PosX,
|
||||
IN ULONGLONG PosY)
|
||||
{
|
||||
XtLoader::GetEfiSystemTable()->ConOut->SetCursorPosition(XtLoader::GetEfiSystemTable()->ConOut, PosX, PosY);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the output console device to the requested mode.
|
||||
*
|
||||
* @param Mode
|
||||
* Supplies a text mode number to set.
|
||||
*
|
||||
* @return This routine returns a status code.
|
||||
*
|
||||
* @since XT 1.0
|
||||
*/
|
||||
XTCDECL
|
||||
EFI_STATUS
|
||||
Console::SetMode(IN ULONGLONG Mode)
|
||||
{
|
||||
return XtLoader::GetEfiSystemTable()->ConOut->SetMode(XtLoader::GetEfiSystemTable()->ConOut, Mode);
|
||||
}
|
||||
|
||||
/**
|
||||
* Displays the string on the device at the current cursor location.
|
||||
*
|
||||
* @param String
|
||||
* The string to be displayed.
|
||||
*
|
||||
* @return This routine does not return any value.
|
||||
*
|
||||
* @since XT 1.0
|
||||
*/
|
||||
XTCDECL
|
||||
VOID
|
||||
Console::Write(IN PCWSTR String)
|
||||
{
|
||||
XtLoader::GetEfiSystemTable()->ConOut->OutputString(XtLoader::GetEfiSystemTable()->ConOut, (PWSTR)String);
|
||||
}
|
60
boot/xtldr/data.cc
Normal file
60
boot/xtldr/data.cc
Normal file
@@ -0,0 +1,60 @@
|
||||
/**
|
||||
* PROJECT: ExectOS
|
||||
* COPYRIGHT: See COPYING.md in the top level directory
|
||||
* FILE: xtldr/data.cc
|
||||
* DESCRIPTION: XT Boot Loader global and static data
|
||||
* DEVELOPERS: Rafal Kupiec <belliash@codingworkshop.eu.org>
|
||||
* Aiken Harris <harraiken91@gmail.com>
|
||||
*/
|
||||
|
||||
#include <xtldr.hh>
|
||||
|
||||
|
||||
/* XT Boot Loader menu list */
|
||||
PLIST_ENTRY Configuration::BootMenuList = NULLPTR;
|
||||
|
||||
/* XT Boot Loader configuration list */
|
||||
LIST_ENTRY Configuration::Config;
|
||||
|
||||
/* XT Boot Loader loaded configuration */
|
||||
LIST_ENTRY Configuration::ConfigSections;
|
||||
|
||||
/* List of user-editable boot options */
|
||||
PCWSTR Configuration::EditableConfigOptions[] = {
|
||||
L"BootModules", L"SystemType", L"SystemPath",
|
||||
L"KernelFile", L"InitrdFile", L"HalFile",
|
||||
L"Parameters", NULLPTR
|
||||
};
|
||||
|
||||
/* XT Boot Loader serial ports list */
|
||||
ULONG Debug::ComPortList[COMPORT_COUNT] = COMPORT_ADDRESS;
|
||||
|
||||
/* A list of enabled debug ports */
|
||||
ULONG Debug::EnabledDebugPorts;
|
||||
|
||||
/* XT Boot Loader serial port handle */
|
||||
CPPORT Debug::SerialPort;
|
||||
|
||||
/* XT Boot Loader registered boot protocol list */
|
||||
LIST_ENTRY Protocol::BootProtocols;
|
||||
|
||||
/* XT Boot Loader protocol */
|
||||
XTBL_LOADER_PROTOCOL Protocol::LoaderProtocol;
|
||||
|
||||
/* XT Boot Loader loaded modules list */
|
||||
LIST_ENTRY Protocol::LoadedModules;
|
||||
|
||||
/* List of available block devices */
|
||||
LIST_ENTRY Volume::EfiBlockDevices;
|
||||
|
||||
/* Pointer to the boot menu callback routine */
|
||||
PBL_XT_BOOT_MENU XtLoader::BootMenu = NULLPTR;
|
||||
|
||||
/* EFI Image Handle */
|
||||
EFI_HANDLE XtLoader::EfiImageHandle;
|
||||
|
||||
/* EFI System Table */
|
||||
PEFI_SYSTEM_TABLE XtLoader::EfiSystemTable;
|
||||
|
||||
/* XT Boot Loader status data */
|
||||
XTBL_STATUS XtLoader::LoaderStatus = {0};
|
402
boot/xtldr/debug.cc
Normal file
402
boot/xtldr/debug.cc
Normal file
@@ -0,0 +1,402 @@
|
||||
/**
|
||||
* PROJECT: ExectOS
|
||||
* COPYRIGHT: See COPYING.md in the top level directory
|
||||
* FILE: xtldr/debug.cc
|
||||
* DESCRIPTION: XT Boot Loader debugging support
|
||||
* DEVELOPERS: Rafal Kupiec <belliash@codingworkshop.eu.org>
|
||||
*/
|
||||
|
||||
#include <xtldr.hh>
|
||||
|
||||
|
||||
/**
|
||||
* Enables I/O space access to all serial controllers found on the PCI(E) root bridge.
|
||||
*
|
||||
* @return This routine returns a status code.
|
||||
*
|
||||
* @since XT 1.0
|
||||
*/
|
||||
XTCDECL
|
||||
EFI_STATUS
|
||||
Debug::ActivateSerialIOController()
|
||||
{
|
||||
EFI_GUID PciGuid = EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_GUID;
|
||||
PEFI_PCI_ROOT_BRIDGE_IO_PROTOCOL PciDev;
|
||||
USHORT Bus, Device, Function, Command;
|
||||
UINT_PTR Index, PciHandleSize;
|
||||
PEFI_HANDLE PciHandle = NULLPTR;
|
||||
PCI_COMMON_HEADER PciHeader;
|
||||
EFI_STATUS Status;
|
||||
ULONGLONG Address;
|
||||
|
||||
/* Allocate memory for single EFI_HANDLE, what should be enough in most cases */
|
||||
PciHandleSize = sizeof(EFI_HANDLE);
|
||||
Status = Memory::AllocatePool(PciHandleSize, (PVOID*)&PciHandle);
|
||||
if(Status != STATUS_EFI_SUCCESS)
|
||||
{
|
||||
/* Memory allocation failure */
|
||||
return Status;
|
||||
}
|
||||
|
||||
/* Get all instances of PciRootBridgeIo */
|
||||
Status = XtLoader::GetEfiSystemTable()->BootServices->LocateHandle(ByProtocol, &PciGuid, NULLPTR,
|
||||
&PciHandleSize, PciHandle);
|
||||
if(Status == STATUS_EFI_BUFFER_TOO_SMALL)
|
||||
{
|
||||
/* Reallocate more memory as requested by UEFI */
|
||||
Memory::FreePool(PciHandle);
|
||||
Status = Memory::AllocatePool(PciHandleSize, (PVOID*)&PciHandle);
|
||||
if(Status != STATUS_EFI_SUCCESS)
|
||||
{
|
||||
/* Memory reallocation failure */
|
||||
return Status;
|
||||
}
|
||||
|
||||
/* Second attempt to get instances of PciRootBridgeIo */
|
||||
Status = XtLoader::GetEfiSystemTable()->BootServices->LocateHandle(ByProtocol, &PciGuid, NULLPTR,
|
||||
&PciHandleSize, PciHandle);
|
||||
}
|
||||
|
||||
/* Make sure successfully obtained PciRootBridgeIo instances */
|
||||
if(Status != STATUS_EFI_SUCCESS)
|
||||
{
|
||||
/* Failed to get PciRootBridgeIo instances */
|
||||
return Status;
|
||||
}
|
||||
|
||||
/* Enumerate all devices for each handle, which decides a segment and a bus number range */
|
||||
for(Index = 0; Index < (PciHandleSize / sizeof(EFI_HANDLE)); Index++)
|
||||
{
|
||||
/* Get inferface from the protocol */
|
||||
Status = XtLoader::GetEfiSystemTable()->BootServices->HandleProtocol(PciHandle[Index], &PciGuid, (PVOID*)&PciDev);
|
||||
if(Status != STATUS_EFI_SUCCESS)
|
||||
{
|
||||
/* Failed to get interface */
|
||||
return Status;
|
||||
}
|
||||
|
||||
/* Enumerate whole PCI bridge */
|
||||
for(Bus = 0; Bus <= PCI_MAX_BRIDGE_NUMBER; Bus++)
|
||||
{
|
||||
/* Enumerate all devices for each bus */
|
||||
for(Device = 0; Device < PCI_MAX_DEVICES; Device++)
|
||||
{
|
||||
/* Enumerate all functions for each devices */
|
||||
for(Function = 0; Function < PCI_MAX_FUNCTION; Function++)
|
||||
{
|
||||
/* Read configuration space */
|
||||
Address = ((ULONGLONG)((((UINT_PTR) Bus) << 24) + (((UINT_PTR) Device) << 16) +
|
||||
(((UINT_PTR) Function) << 8) + ((UINT_PTR) 0)));
|
||||
PciDev->Pci.Read(PciDev, EfiPciIoWidthUint32, Address, sizeof (PciHeader) / sizeof (UINT), &PciHeader);
|
||||
|
||||
/* Check if device exists */
|
||||
if(PciHeader.VendorId == PCI_INVALID_VENDORID)
|
||||
{
|
||||
/* Skip non-existen device */
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Check if device is serial controller or multiport serial controller */
|
||||
if(PciHeader.BaseClass == 0x07 && (PciHeader.SubClass == 0x00 || PciHeader.SubClass == 0x02))
|
||||
{
|
||||
/* Enable I/O space access */
|
||||
Address |= 0x4;
|
||||
Command = PCI_ENABLE_IO_SPACE;
|
||||
Status = PciDev->Pci.Write(PciDev, EfiPciIoWidthUint16, Address, 1, &Command);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Return SUCCESS */
|
||||
return STATUS_EFI_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* This routine initializes the XTLDR debug console.
|
||||
*
|
||||
* @return This routine returns a status code.
|
||||
*
|
||||
* @since XT 1.0
|
||||
*/
|
||||
XTCDECL
|
||||
EFI_STATUS
|
||||
Debug::InitializeDebugConsole()
|
||||
{
|
||||
ULONG PortAddress, PortNumber, BaudRate;
|
||||
PWCHAR DebugConfiguration, DebugPort, LastPort;
|
||||
EFI_STATUS Status;
|
||||
|
||||
/* Set default serial port options */
|
||||
PortAddress = 0;
|
||||
PortNumber = 0;
|
||||
BaudRate = 0;
|
||||
|
||||
/* Get debug configuration */
|
||||
Configuration::GetValue(L"DEBUG", &DebugConfiguration);
|
||||
|
||||
/* Make sure any debug options are provided and debug console is not initialized yet */
|
||||
if(DebugConfiguration && EnabledDebugPorts == 0)
|
||||
{
|
||||
/* Find all debug ports */
|
||||
DebugPort = RTL::WideString::TokenizeWideString(DebugConfiguration, L";", &LastPort);
|
||||
|
||||
/* Iterate over all debug ports */
|
||||
while(DebugPort != NULLPTR)
|
||||
{
|
||||
/* Check what port is set for debugging */
|
||||
if(RTL::WideString::CompareWideStringInsensitive(DebugPort, L"COM", 3) == 0)
|
||||
{
|
||||
/* Read COM port number */
|
||||
DebugPort += 3;
|
||||
while(*DebugPort >= '0' && *DebugPort <= '9')
|
||||
{
|
||||
/* Get port number */
|
||||
PortNumber *= 10;
|
||||
PortNumber += *DebugPort - '0';
|
||||
DebugPort++;
|
||||
}
|
||||
|
||||
/* Check if custom COM port address supplied */
|
||||
if(PortNumber == 0 && RTL::WideString::CompareWideStringInsensitive(DebugPort, L":0x", 3) == 0)
|
||||
{
|
||||
/* COM port address provided */
|
||||
DebugPort += 3;
|
||||
while((*DebugPort >= '0' && *DebugPort <= '9') ||
|
||||
(*DebugPort >= 'A' && *DebugPort <= 'F') ||
|
||||
(*DebugPort >= 'a' && *DebugPort <= 'f'))
|
||||
{
|
||||
/* Get port address */
|
||||
PortAddress *= 16;
|
||||
if(*DebugPort >= '0' && *DebugPort <= '9')
|
||||
{
|
||||
PortAddress += *DebugPort - '0';
|
||||
}
|
||||
else if(*DebugPort >= 'A' && *DebugPort <= 'F')
|
||||
{
|
||||
PortAddress += *DebugPort - 'A' + 10;
|
||||
}
|
||||
else if(*DebugPort >= 'a' && *DebugPort <= 'f')
|
||||
{
|
||||
PortAddress += *DebugPort - 'a' + 10;
|
||||
}
|
||||
DebugPort++;
|
||||
}
|
||||
}
|
||||
|
||||
/* Look for additional COM port parameters */
|
||||
if(*DebugPort == ',')
|
||||
{
|
||||
/* Baud rate provided */
|
||||
DebugPort++;
|
||||
while(*DebugPort >= '0' && *DebugPort <= '9')
|
||||
{
|
||||
/* Get baud rate */
|
||||
BaudRate *= 10;
|
||||
BaudRate += *DebugPort - '0';
|
||||
DebugPort++;
|
||||
}
|
||||
}
|
||||
|
||||
/* Enable debug port */
|
||||
EnabledDebugPorts |= XTBL_DEBUGPORT_SERIAL;
|
||||
}
|
||||
else if(RTL::WideString::CompareWideStringInsensitive(DebugPort, L"SCREEN", 5) == 0)
|
||||
{
|
||||
/* Enable debug port */
|
||||
EnabledDebugPorts |= XTBL_DEBUGPORT_SCREEN;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Unsupported debug port specified */
|
||||
Console::Print(L"ERROR: Unsupported debug port ('%S') specified\n", DebugPort);
|
||||
EfiUtils::SleepExecution(3000);
|
||||
}
|
||||
|
||||
/* Take next debug port */
|
||||
DebugPort = RTL::WideString::TokenizeWideString(NULLPTR, L";", &LastPort);
|
||||
}
|
||||
|
||||
/* Check if serial debug port is enabled */
|
||||
if(EnabledDebugPorts & XTBL_DEBUGPORT_SERIAL)
|
||||
{
|
||||
/* Try to initialize COM port */
|
||||
Status = InitializeSerialPort(PortNumber, PortAddress, BaudRate);
|
||||
if(Status != STATUS_EFI_SUCCESS)
|
||||
{
|
||||
/* Remove serial debug port, as COM port initialization failed and return */
|
||||
EnabledDebugPorts &= ~XTBL_DEBUGPORT_SERIAL;
|
||||
return Status;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Return success */
|
||||
return STATUS_EFI_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* This routine initializes the serial debug console.
|
||||
*
|
||||
* @param PortNumber
|
||||
* Supplies a port number.
|
||||
*
|
||||
* @param PortAddress
|
||||
* Supplies an address of the COM port.
|
||||
*
|
||||
* @param BaudRate
|
||||
* Supplies an optional port baud rate.
|
||||
*
|
||||
* @return This routine returns a status code.
|
||||
*
|
||||
* @since XT 1.0
|
||||
*/
|
||||
XTCDECL
|
||||
EFI_STATUS
|
||||
Debug::InitializeSerialPort(IN ULONG PortNumber,
|
||||
IN ULONG PortAddress,
|
||||
IN ULONG BaudRate)
|
||||
{
|
||||
EFI_STATUS EfiStatus;
|
||||
XTSTATUS Status;
|
||||
|
||||
/* Check if custom COM port address supplied */
|
||||
if(!PortAddress)
|
||||
{
|
||||
/* We support only a pre-defined number of ports */
|
||||
if(PortNumber > COMPORT_COUNT)
|
||||
{
|
||||
/* Fail if wrong/unsupported port used */
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
/* Check if serial port is set */
|
||||
if(PortNumber == 0)
|
||||
{
|
||||
/* Use COM1 by default */
|
||||
PortNumber = 1;
|
||||
}
|
||||
|
||||
/* Set custom port address based on the port number and print debug message */
|
||||
PortAddress = ComPortList[PortNumber - 1];
|
||||
Console::Print(L"Initializing serial console at port COM%d\n", PortNumber);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Custom port address supplied, print debug message */
|
||||
Console::Print(L"Initializing serial console at COM port address: 0x%lX\n", PortAddress);
|
||||
}
|
||||
|
||||
/* Initialize COM port */
|
||||
Status = HL::ComPort::InitializeComPort(&SerialPort, (PUCHAR)UlongToPtr(PortAddress), BaudRate);
|
||||
|
||||
/* Port not found under supplied address */
|
||||
if(Status == STATUS_NOT_FOUND && PortAddress)
|
||||
{
|
||||
/* This might be PCI(E) serial controller, try to activate I/O space access first */
|
||||
EfiStatus = ActivateSerialIOController();
|
||||
if(EfiStatus == STATUS_EFI_SUCCESS)
|
||||
{
|
||||
/* Try to reinitialize COM port */
|
||||
Console::Print(L"Enabled I/O space access for all PCI(E) serial controllers found\n");
|
||||
Status = HL::ComPort::InitializeComPort(&SerialPort, (PUCHAR)UlongToPtr(PortAddress), BaudRate);
|
||||
}
|
||||
}
|
||||
|
||||
/* Check COM port initialization status code */
|
||||
if(Status != STATUS_SUCCESS)
|
||||
{
|
||||
/* Serial port initialization failed, mark as not ready */
|
||||
return STATUS_EFI_NOT_READY;
|
||||
}
|
||||
|
||||
/* Return success */
|
||||
return STATUS_EFI_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* This routine formats the input string and prints it out to the debug ports.
|
||||
*
|
||||
* @param Format
|
||||
* The formatted string that is to be written to the output.
|
||||
*
|
||||
* @param ...
|
||||
* Depending on the format string, this routine might expect a sequence of additional arguments.
|
||||
*
|
||||
* @return This routine does not return any value.
|
||||
*
|
||||
* @since XT 1.0
|
||||
*/
|
||||
XTCDECL
|
||||
VOID
|
||||
Debug::Print(IN PCWSTR Format,
|
||||
IN ...)
|
||||
{
|
||||
RTL_PRINT_CONTEXT ConsolePrintContext, SerialPrintContext;
|
||||
VA_LIST Arguments;
|
||||
|
||||
/* Check if debugging enabled and if EFI serial port is fully initialized */
|
||||
if(DEBUG)
|
||||
{
|
||||
/* Initialize the print contexts */
|
||||
ConsolePrintContext.WriteWideCharacter = Console::PutChar;
|
||||
SerialPrintContext.WriteWideCharacter = PutChar;
|
||||
|
||||
/* Initialise the va_list */
|
||||
VA_START(Arguments, Format);
|
||||
|
||||
/* Check if serial debug port is enabled */
|
||||
if((EnabledDebugPorts & XTBL_DEBUGPORT_SERIAL) && (SerialPort.Flags & COMPORT_FLAG_INIT))
|
||||
{
|
||||
/* Format and print the string to the serial console */
|
||||
RTL::WideString::FormatWideString(&SerialPrintContext, (PWCHAR)Format, Arguments);
|
||||
}
|
||||
|
||||
/* Check if screen debug port is enabled and Boot Services are still available */
|
||||
if((EnabledDebugPorts & XTBL_DEBUGPORT_SCREEN) && (XtLoader::GetBootServicesStatus() == TRUE))
|
||||
{
|
||||
/* Format and print the string to the screen */
|
||||
RTL::WideString::FormatWideString(&ConsolePrintContext, (PWCHAR)Format, Arguments);
|
||||
}
|
||||
|
||||
/* Clean up the va_list */
|
||||
VA_END(Arguments);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Writes a character to the serial console.
|
||||
*
|
||||
* @param Character
|
||||
* The integer promotion of the character to be written.
|
||||
*
|
||||
* @return This routine returns a status code.
|
||||
*
|
||||
* @since XT 1.0
|
||||
*/
|
||||
XTCDECL
|
||||
XTSTATUS
|
||||
Debug::PutChar(IN WCHAR Character)
|
||||
{
|
||||
WCHAR Buffer[2];
|
||||
|
||||
/* Write character to the serial console */
|
||||
Buffer[0] = Character;
|
||||
Buffer[1] = 0;
|
||||
return HL::ComPort::WriteComPort(&SerialPort, Buffer[0]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines if the serial port has been successfully initialized and is ready for communication.
|
||||
*
|
||||
* @return This routine returns TRUE if the serial port is initialized and ready, FALSE otherwise.
|
||||
*
|
||||
* @since XT 1.0
|
||||
*/
|
||||
XTCDECL
|
||||
BOOLEAN
|
||||
Debug::SerialPortReady()
|
||||
{
|
||||
return (SerialPort.Flags & COMPORT_FLAG_INIT);
|
||||
}
|
462
boot/xtldr/efiutils.cc
Normal file
462
boot/xtldr/efiutils.cc
Normal file
@@ -0,0 +1,462 @@
|
||||
/**
|
||||
* PROJECT: ExectOS
|
||||
* COPYRIGHT: See COPYING.md in the top level directory
|
||||
* FILE: xtldr/efiutils.cc
|
||||
* DESCRIPTION: EFI related routines for XT Boot Loader
|
||||
* DEVELOPERS: Rafal Kupiec <belliash@codingworkshop.eu.org>
|
||||
*/
|
||||
|
||||
#include <xtldr.hh>
|
||||
|
||||
|
||||
/**
|
||||
* Reboots into UEFI firmware setup interface.
|
||||
*
|
||||
* @return This routine returns a status code.
|
||||
*
|
||||
* @since XT 1.0
|
||||
*/
|
||||
XTCDECL
|
||||
EFI_STATUS
|
||||
EfiUtils::EnterFirmwareSetup()
|
||||
{
|
||||
EFI_GUID Guid = EFI_GLOBAL_VARIABLE_GUID;
|
||||
PULONGLONG SetupSupport = NULLPTR;
|
||||
ULONGLONG Indications;
|
||||
EFI_STATUS Status;
|
||||
|
||||
/* Check if booting into firmware interface is supported */
|
||||
Status = GetEfiVariable(&Guid, L"OsIndicationsSupported", (PVOID*)&SetupSupport);
|
||||
if(Status != STATUS_EFI_SUCCESS || !(*SetupSupport & EFI_OS_INDICATIONS_BOOT_TO_FW_UI))
|
||||
{
|
||||
/* Reboot into firmware setup is not supported */
|
||||
Debug::Print(L"WARNING: Reboot into firmware setup interface not supported\n");
|
||||
if(SetupSupport)
|
||||
{
|
||||
Memory::FreePool((PVOID)SetupSupport);
|
||||
}
|
||||
return STATUS_EFI_UNSUPPORTED;
|
||||
}
|
||||
|
||||
Memory::FreePool((PVOID)SetupSupport);
|
||||
|
||||
/* Get the value of OsIndications variable */
|
||||
Indications = 0;
|
||||
Status = GetEfiVariable(&Guid, L"OsIndications", (PVOID*)&Indications);
|
||||
|
||||
/* Enable FW setup on next boot */
|
||||
Indications |= EFI_OS_INDICATIONS_BOOT_TO_FW_UI;
|
||||
Status = SetEfiVariable(&Guid, L"OsIndications", (PVOID)&Indications, sizeof(Indications));
|
||||
if(Status != STATUS_EFI_SUCCESS)
|
||||
{
|
||||
/* Failed to update OsIndications variable */
|
||||
return Status;
|
||||
}
|
||||
|
||||
/* Reboot into firmware setup */
|
||||
RebootSystem();
|
||||
|
||||
/* Must not reach this point, just make the compiler happy */
|
||||
return STATUS_EFI_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* Exits EFI boot services.
|
||||
*
|
||||
* @return This routine returns status code.
|
||||
*
|
||||
* @since XT 1.0
|
||||
*/
|
||||
XTCDECL
|
||||
EFI_STATUS
|
||||
EfiUtils::ExitBootServices()
|
||||
{
|
||||
PEFI_MEMORY_MAP MemoryMap;
|
||||
EFI_STATUS Status;
|
||||
ULONG Counter;
|
||||
|
||||
/* Boot Services might be partially shutdown, so mark them as unavailable */
|
||||
XtLoader::DisableBootServices();
|
||||
|
||||
/* Allocate buffer for EFI memory map */
|
||||
Status = Memory::AllocatePool(sizeof(EFI_MEMORY_MAP), (PVOID*)&MemoryMap);
|
||||
if(Status != STATUS_EFI_SUCCESS)
|
||||
{
|
||||
/* Memory allocation failure */
|
||||
Debug::Print(L"ERROR: Memory allocation failure (Status Code: 0x%zX)\n", Status);
|
||||
return Status;
|
||||
}
|
||||
|
||||
/* Zero fill the buffer and initialize counter */
|
||||
RTL::Memory::ZeroMemory(MemoryMap, sizeof(EFI_MEMORY_MAP));
|
||||
Counter = 0xFF;
|
||||
|
||||
/* Attempt to exit boot services */
|
||||
while(Counter > 0)
|
||||
{
|
||||
/* Get memory map each time as it can change between two calls */
|
||||
Status = Memory::GetMemoryMap(MemoryMap);
|
||||
if(Status != STATUS_EFI_SUCCESS)
|
||||
{
|
||||
/* Failed to get new memory map */
|
||||
return Status;
|
||||
}
|
||||
|
||||
/* Exit boot services */
|
||||
Status = XtLoader::GetEfiSystemTable()->BootServices->ExitBootServices(XtLoader::GetEfiImageHandle(),
|
||||
MemoryMap->MapKey);
|
||||
if(Status == STATUS_EFI_SUCCESS)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
/* Decrement counter */
|
||||
Counter--;
|
||||
}
|
||||
|
||||
/* Return EFI status code */
|
||||
return Status;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the address of a reqested system configuration table.
|
||||
*
|
||||
* @param TableGuid
|
||||
* Supplies a GUID of the configuration table.
|
||||
*
|
||||
* @param Table
|
||||
* Supplies a pointer to the memory area where the table address will be stored.
|
||||
*
|
||||
* @return This routine returns a status code.
|
||||
*
|
||||
* @since XT 1.0
|
||||
*/
|
||||
XTCDECL
|
||||
EFI_STATUS
|
||||
EfiUtils::GetConfigurationTable(IN PEFI_GUID TableGuid,
|
||||
OUT PVOID *Table)
|
||||
{
|
||||
SIZE_T Index;
|
||||
|
||||
/* Iterate through all system configuration tables */
|
||||
for(Index = 0; Index < XtLoader::GetEfiSystemTable()->NumberOfTableEntries; Index++)
|
||||
{
|
||||
/* Check if this table matches requested table */
|
||||
if(RTL::Guid::CompareGuids((PGUID)&(XtLoader::GetEfiSystemTable()->ConfigurationTable[Index].VendorGuid),
|
||||
(PGUID)TableGuid))
|
||||
{
|
||||
/* Found requested table, return success */
|
||||
*Table = XtLoader::GetEfiSystemTable()->ConfigurationTable[Index].VendorTable;
|
||||
return STATUS_EFI_SUCCESS;
|
||||
}
|
||||
}
|
||||
|
||||
/* Table not found */
|
||||
*Table = NULLPTR;
|
||||
return STATUS_EFI_NOT_FOUND;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the value of the EFI variable.
|
||||
*
|
||||
* @param Vendor
|
||||
* Supplies a pointer to the unique vendor GUID.
|
||||
*
|
||||
* @param VariableName
|
||||
* Supplies a pointer to tge NULL-terminated string containing the variable name.
|
||||
*
|
||||
* @param VariableValue
|
||||
* Supplies a pointer to the buffer, where the variable value will be stored.
|
||||
*
|
||||
* @return This routine returns a status code.
|
||||
*
|
||||
* @since XT 1.0
|
||||
*/
|
||||
XTCDECL
|
||||
EFI_STATUS
|
||||
EfiUtils::GetEfiVariable(IN PEFI_GUID Vendor,
|
||||
IN PCWSTR VariableName,
|
||||
OUT PVOID *VariableValue)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
PVOID Buffer;
|
||||
UINT_PTR Size = 0;
|
||||
|
||||
/* Allocate a buffer for storing a variable's value */
|
||||
Size = EFI_MAXIMUM_VARIABLE_SIZE * sizeof(PWCHAR);
|
||||
Status = Memory::AllocatePool(Size, (PVOID*)&Buffer);
|
||||
if(Status != STATUS_EFI_SUCCESS)
|
||||
{
|
||||
/* Memory allocation failure */
|
||||
return Status;
|
||||
}
|
||||
|
||||
/* Attempt to get variable value */
|
||||
Status = XtLoader::GetEfiSystemTable()->RuntimeServices->GetVariable((PWCHAR)VariableName, Vendor, NULLPTR,
|
||||
&Size, Buffer);
|
||||
if(Status != STATUS_EFI_SUCCESS)
|
||||
{
|
||||
/* Failed to get variable, probably not found such one */
|
||||
return Status;
|
||||
}
|
||||
|
||||
/* Get variable value and return success */
|
||||
*VariableValue = Buffer;
|
||||
return STATUS_EFI_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a random value based on the initialized RNG buffer.
|
||||
*
|
||||
* @param RNGBuffer
|
||||
* Supplies a pointer to the RNG buffer.
|
||||
*
|
||||
* @return This routine returns a random value.
|
||||
*
|
||||
* @since XT 1.0
|
||||
*
|
||||
* @see https://en.wikipedia.org/wiki/Xorshift
|
||||
*/
|
||||
XTCDECL
|
||||
ULONGLONG
|
||||
EfiUtils::GetRandomValue(IN OUT PULONGLONG RNGBuffer)
|
||||
{
|
||||
/* Recalculate RNG buffer with XORSHIFT */
|
||||
*RNGBuffer ^= *RNGBuffer >> 12;
|
||||
*RNGBuffer ^= *RNGBuffer << 25;
|
||||
*RNGBuffer ^= *RNGBuffer >> 27;
|
||||
|
||||
/* Return random value */
|
||||
return *RNGBuffer * 0x2545F4914F6CDD1D;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether SecureBoot is enabled or not.
|
||||
*
|
||||
* @return Numeric representation of SecureBoot status (0 = Disabled, >0 = Enabled, <0 SetupMode).
|
||||
*
|
||||
* @since XT 1.0
|
||||
*/
|
||||
XTCDECL
|
||||
INT_PTR
|
||||
EfiUtils::GetSecureBootStatus()
|
||||
{
|
||||
EFI_GUID VarGuid = EFI_GLOBAL_VARIABLE_GUID;
|
||||
INT_PTR SecureBootStatus = 0;
|
||||
INT_PTR VarValue = 0;
|
||||
UINT_PTR Size;
|
||||
|
||||
Size = sizeof(INT_PTR);
|
||||
if(XtLoader::GetEfiSystemTable()->RuntimeServices->GetVariable((PWCHAR)L"SecureBoot", &VarGuid,
|
||||
NULLPTR, &Size, &VarValue) == STATUS_EFI_SUCCESS)
|
||||
{
|
||||
SecureBootStatus = VarValue;
|
||||
Size = sizeof(INT_PTR);
|
||||
if((XtLoader::GetEfiSystemTable()->RuntimeServices->GetVariable((PWCHAR)L"SetupMode", &VarGuid,
|
||||
NULLPTR, &Size, &VarValue) == STATUS_EFI_SUCCESS) && VarValue != 0)
|
||||
{
|
||||
SecureBootStatus = -1;
|
||||
}
|
||||
}
|
||||
|
||||
/* Return SecureBoot status */
|
||||
return SecureBootStatus;
|
||||
}
|
||||
|
||||
/**
|
||||
* Initializes the RNG buffer with random bytes from the default EFI RNG algorithm.
|
||||
*
|
||||
* @param RNGBuffer
|
||||
* Supplies a pointer to the RNG buffer.
|
||||
*
|
||||
* @return This routine returns a status code.
|
||||
*
|
||||
* @since XT 1.0
|
||||
*/
|
||||
XTCDECL
|
||||
EFI_STATUS
|
||||
EfiUtils::InitializeEntropy(PULONGLONG RNGBuffer)
|
||||
{
|
||||
EFI_GUID RngGuid = EFI_RNG_PROTOCOL_GUID;
|
||||
PEFI_RNG_PROTOCOL Rng;
|
||||
EFI_STATUS Status;
|
||||
ULONGLONG Seed;
|
||||
|
||||
/* Initialize variables */
|
||||
Rng = NULLPTR;
|
||||
Seed = 0;
|
||||
|
||||
/* Locate RNG protocol */
|
||||
Status = XtLoader::GetEfiSystemTable()->BootServices->LocateProtocol(&RngGuid, NULLPTR, (PVOID *)&Rng);
|
||||
if(Status != STATUS_EFI_SUCCESS)
|
||||
{
|
||||
/* Failed to locate RNG protocol, return status code */
|
||||
return Status;
|
||||
}
|
||||
|
||||
/* Get RNG value using the default algorithm */
|
||||
Status = Rng->GetRNG(Rng, NULLPTR, 8, (PUCHAR)&Seed);
|
||||
if(Status != STATUS_EFI_SUCCESS)
|
||||
{
|
||||
/* Failed to get RNG value, return status code */
|
||||
return Status;
|
||||
}
|
||||
|
||||
/* Initialize RNG state and return success */
|
||||
*RNGBuffer = Seed ? Seed : 1;
|
||||
return STATUS_EFI_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads an EFI image into memory.
|
||||
*
|
||||
* @param DevicePath
|
||||
* Specifies a device path from which the image is loaded.
|
||||
*
|
||||
* @param ImageData
|
||||
* Supplies a pointer to the memory are containing a copy of the EFI image.
|
||||
*
|
||||
* @param ImageSize
|
||||
* Supplies the size (in bytes) of the EFI image.
|
||||
*
|
||||
* @param ImageHandle
|
||||
* Supplies a pointer to the memory area, where an EFI_image handle will be stored.
|
||||
*
|
||||
* @return This routine returns a status code.
|
||||
*
|
||||
* @since XT 1.0
|
||||
*/
|
||||
XTCDECL
|
||||
EFI_STATUS
|
||||
EfiUtils::LoadEfiImage(IN PEFI_DEVICE_PATH_PROTOCOL DevicePath,
|
||||
IN PVOID ImageData,
|
||||
IN SIZE_T ImageSize,
|
||||
OUT PEFI_HANDLE ImageHandle)
|
||||
{
|
||||
/* Load EFI image */
|
||||
return XtLoader::GetEfiSystemTable()->BootServices->LoadImage(FALSE, XtLoader::GetEfiImageHandle(), DevicePath,
|
||||
ImageData, ImageSize, ImageHandle);
|
||||
}
|
||||
|
||||
/**
|
||||
* Reboots the machine.
|
||||
*
|
||||
* @return This routine returns a status code.
|
||||
*
|
||||
* @since XT 1.0
|
||||
*/
|
||||
XTCDECL
|
||||
EFI_STATUS
|
||||
EfiUtils::RebootSystem()
|
||||
{
|
||||
/* Reboot machine */
|
||||
return XtLoader::GetEfiSystemTable()->RuntimeServices->ResetSystem(EfiResetCold, STATUS_EFI_SUCCESS, 0, NULLPTR);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets a value of an EFI variable.
|
||||
*
|
||||
* @param Vendor
|
||||
* Supplies a pointer to the unique vendor GUID.
|
||||
*
|
||||
* @param VariableName
|
||||
* Supplies a pointer to tge NULL-terminated string containing the variable name.
|
||||
*
|
||||
* @param VariableValue
|
||||
* Supplies the contents of the variable.
|
||||
*
|
||||
* @param Size
|
||||
* Supplies the size of the variable data buffer.
|
||||
*
|
||||
* @return This routine returns a status code.
|
||||
*
|
||||
* @since XT 1.0
|
||||
*/
|
||||
XTCDECL
|
||||
EFI_STATUS
|
||||
EfiUtils::SetEfiVariable(IN PEFI_GUID Vendor,
|
||||
IN PCWSTR VariableName,
|
||||
IN PVOID VariableValue,
|
||||
IN UINT_PTR Size)
|
||||
{
|
||||
ULONG Attributes;
|
||||
|
||||
/* Set EFI variable */
|
||||
Attributes = EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS;
|
||||
return XtLoader::GetEfiSystemTable()->RuntimeServices->SetVariable((PWCHAR)VariableName, Vendor, Attributes,
|
||||
Size, VariableValue);
|
||||
}
|
||||
|
||||
/**
|
||||
* Shuts down the machine.
|
||||
*
|
||||
* @return This routine returns a status code.
|
||||
*
|
||||
* @since XT 1.0
|
||||
*/
|
||||
XTCDECL
|
||||
EFI_STATUS
|
||||
EfiUtils::ShutdownSystem()
|
||||
{
|
||||
/* Shutdown machine */
|
||||
return XtLoader::GetEfiSystemTable()->RuntimeServices->ResetSystem(EfiResetShutdown, STATUS_EFI_SUCCESS, 0, NULLPTR);
|
||||
}
|
||||
|
||||
/**
|
||||
* Puts the system to sleep for the specified number of milliseconds.
|
||||
*
|
||||
* @param Milliseconds
|
||||
* Supplies the number of milliseconds to sleep.
|
||||
*
|
||||
* @return This routine does not return any value.
|
||||
*
|
||||
* @since XT 1.0
|
||||
*/
|
||||
XTCDECL
|
||||
VOID
|
||||
EfiUtils::SleepExecution(IN ULONG_PTR Milliseconds)
|
||||
{
|
||||
XtLoader::GetEfiSystemTable()->BootServices->Stall(Milliseconds * 1000);
|
||||
}
|
||||
|
||||
/**
|
||||
* Executes a loaded EFI image entry point.
|
||||
*
|
||||
* @param ImageHandle
|
||||
* Provides a handle of loaded image, that will be started.
|
||||
*
|
||||
* @return This routine returns a status code.
|
||||
*
|
||||
* @since XT 1.0
|
||||
*/
|
||||
XTCDECL
|
||||
EFI_STATUS
|
||||
EfiUtils::StartEfiImage(IN EFI_HANDLE ImageHandle)
|
||||
{
|
||||
return XtLoader::GetEfiSystemTable()->BootServices->StartImage(ImageHandle, NULLPTR, NULLPTR);
|
||||
}
|
||||
|
||||
/**
|
||||
* Waits for one or more EFI events.
|
||||
*
|
||||
* @param NumberOfEvents
|
||||
* Supplies the number of events to wait for.
|
||||
*
|
||||
* @param Event
|
||||
* Supplies the array of events to wait for.
|
||||
*
|
||||
* @param Index
|
||||
* Receives the index of the event that was signaled.
|
||||
*
|
||||
* @return This routine returns status code.
|
||||
*
|
||||
* @since XT 1.0
|
||||
*/
|
||||
XTCDECL
|
||||
EFI_STATUS
|
||||
EfiUtils::WaitForEfiEvent(IN UINT_PTR NumberOfEvents,
|
||||
IN PEFI_EVENT Event,
|
||||
OUT PUINT_PTR Index)
|
||||
{
|
||||
return XtLoader::GetEfiSystemTable()->BootServices->WaitForEvent(NumberOfEvents, Event, Index);
|
||||
}
|
142
boot/xtldr/includes/libxtos.hh
Normal file
142
boot/xtldr/includes/libxtos.hh
Normal file
@@ -0,0 +1,142 @@
|
||||
/**
|
||||
* PROJECT: ExectOS
|
||||
* COPYRIGHT: See COPYING.md in the top level directory
|
||||
* FILE: xtldr/includes/libxtos.hh
|
||||
* DESCRIPTION: XT Loader to LIBXTOS interface
|
||||
* DEVELOPERS: Aiken Harris <harraiken91@gmail.com>
|
||||
*/
|
||||
|
||||
#ifndef __XTLDR_LIBXTOS_HH
|
||||
#define __XTLDR_LIBXTOS_HH
|
||||
|
||||
#include <xtblapi.h>
|
||||
|
||||
|
||||
/* Minimal forward references for AR classes used by XTLDR */
|
||||
namespace AR
|
||||
{
|
||||
class CpuFunc
|
||||
{
|
||||
public:
|
||||
STATIC XTCDECL BOOLEAN CpuId(IN OUT PCPUID_REGISTERS Registers);
|
||||
STATIC XTCDECL ULONG_PTR ReadControlRegister(IN USHORT ControlRegister);
|
||||
STATIC XTCDECL ULONGLONG ReadModelSpecificRegister(IN ULONG Register);
|
||||
STATIC XTCDECL VOID WriteControlRegister(IN USHORT ControlRegister,
|
||||
IN UINT_PTR Value);
|
||||
};
|
||||
|
||||
class ProcSup
|
||||
{
|
||||
public:
|
||||
STATIC XTAPI VOID GetTrampolineInformation(IN TRAMPOLINE_TYPE TrampolineType,
|
||||
OUT PVOID *TrampolineCode,
|
||||
OUT PULONG_PTR TrampolineSize);
|
||||
};
|
||||
}
|
||||
|
||||
/* Minimal forward references for HL classes used by XTLDR */
|
||||
namespace HL
|
||||
{
|
||||
class ComPort
|
||||
{
|
||||
public:
|
||||
STATIC XTCDECL XTSTATUS InitializeComPort(IN OUT PCPPORT Port,
|
||||
IN PUCHAR PortAddress,
|
||||
IN ULONG BaudRate);
|
||||
STATIC XTCDECL XTSTATUS WriteComPort(IN PCPPORT Port,
|
||||
IN UCHAR Byte);
|
||||
};
|
||||
|
||||
class IoPort
|
||||
{
|
||||
public:
|
||||
STATIC XTCDECL UCHAR ReadPort8(IN USHORT Port);
|
||||
STATIC XTCDECL USHORT ReadPort16(IN USHORT Port);
|
||||
STATIC XTCDECL ULONG ReadPort32(IN USHORT Port);
|
||||
STATIC XTCDECL VOID WritePort8(IN USHORT Port,
|
||||
IN UCHAR Value);
|
||||
STATIC XTCDECL VOID WritePort16(IN USHORT Port,
|
||||
IN USHORT Value);
|
||||
STATIC XTCDECL VOID WritePort32(IN USHORT Port,
|
||||
IN ULONG Value);
|
||||
};
|
||||
}
|
||||
|
||||
/* Minimal forward references for RTL classes used by XTLDR */
|
||||
namespace RTL
|
||||
{
|
||||
class Guid
|
||||
{
|
||||
public:
|
||||
STATIC XTAPI BOOLEAN CompareGuids(IN PGUID Guid1,
|
||||
IN PGUID Guid2);
|
||||
};
|
||||
|
||||
class LinkedList
|
||||
{
|
||||
public:
|
||||
STATIC XTCDECL VOID InitializeListHead(IN PLIST_ENTRY ListHead);
|
||||
STATIC XTCDECL VOID InsertHeadList(IN OUT PLIST_ENTRY ListHead,
|
||||
IN PLIST_ENTRY Entry);
|
||||
STATIC XTCDECL VOID InsertTailList(IN OUT PLIST_ENTRY ListHead,
|
||||
IN PLIST_ENTRY Entry);
|
||||
STATIC XTCDECL VOID RemoveEntryList(IN PLIST_ENTRY Entry);
|
||||
};
|
||||
|
||||
class Memory
|
||||
{
|
||||
public:
|
||||
STATIC XTAPI SIZE_T CompareMemory(IN PCVOID LeftBuffer,
|
||||
IN PCVOID RightBuffer,
|
||||
IN SIZE_T Length);
|
||||
STATIC XTAPI VOID CopyMemory(OUT PVOID Destination,
|
||||
IN PCVOID Source,
|
||||
IN SIZE_T Length);
|
||||
STATIC XTAPI VOID MoveMemory(OUT PVOID Destination,
|
||||
IN PCVOID Source,
|
||||
IN SIZE_T Length);
|
||||
STATIC XTAPI VOID SetMemory(OUT PVOID Destination,
|
||||
IN UCHAR Byte,
|
||||
IN SIZE_T Length);
|
||||
STATIC XTAPI VOID ZeroMemory(OUT PVOID Destination,
|
||||
IN SIZE_T Length);
|
||||
};
|
||||
|
||||
class String
|
||||
{
|
||||
public:
|
||||
STATIC XTAPI SIZE_T CompareString(IN PCSTR String1,
|
||||
IN PCSTR String2,
|
||||
IN SIZE_T Length);
|
||||
STATIC XTAPI SIZE_T StringLength(IN PCSTR String,
|
||||
IN SIZE_T MaxLength);
|
||||
STATIC XTAPI SIZE_T StringToWideString(OUT PWCHAR Destination,
|
||||
IN PCSTR *Source,
|
||||
IN SIZE_T Length);
|
||||
STATIC XTAPI PCHAR TrimString(IN PCHAR String);
|
||||
};
|
||||
|
||||
class WideString
|
||||
{
|
||||
public:
|
||||
STATIC XTAPI SIZE_T CompareWideString(IN PCWSTR String1,
|
||||
IN PCWSTR String2,
|
||||
IN SIZE_T Length);
|
||||
STATIC XTAPI SIZE_T CompareWideStringInsensitive(IN PCWSTR String1,
|
||||
IN PCWSTR String2,
|
||||
IN SIZE_T Length);
|
||||
STATIC XTAPI PWCHAR ConcatenateWideString(OUT PWCHAR Destination,
|
||||
IN PWCHAR Source,
|
||||
IN SIZE_T Count);
|
||||
STATIC XTAPI XTSTATUS FormatWideString(IN PRTL_PRINT_CONTEXT Context,
|
||||
IN PCWSTR Format,
|
||||
IN VA_LIST ArgumentList);
|
||||
STATIC XTAPI PWCHAR TokenizeWideString(IN PWCHAR String,
|
||||
IN PCWSTR Delimiter,
|
||||
IN OUT PWCHAR *SavePtr);
|
||||
STATIC XTAPI SIZE_T WideStringLength(IN PCWSTR String,
|
||||
IN SIZE_T MaxLength);
|
||||
};
|
||||
}
|
||||
|
||||
#endif /* __XTLDR_LIBXTOS_HH */
|
351
boot/xtldr/includes/xtldr.hh
Normal file
351
boot/xtldr/includes/xtldr.hh
Normal file
@@ -0,0 +1,351 @@
|
||||
/**
|
||||
* PROJECT: ExectOS
|
||||
* COPYRIGHT: See COPYING.md in the top level directory
|
||||
* FILE: xtldr/includes/xtldr.hh
|
||||
* DESCRIPTION: Top level header for XTLDR
|
||||
* DEVELOPERS: Rafal Kupiec <belliash@codingworkshop.eu.org>
|
||||
*/
|
||||
|
||||
#ifndef __XTLDR_XTLDR_HH
|
||||
#define __XTLDR_XTLDR_HH
|
||||
|
||||
#include <xtblapi.h>
|
||||
#include <xtver.h>
|
||||
|
||||
#include <libxtos.hh>
|
||||
|
||||
|
||||
class BootUtils
|
||||
{
|
||||
public:
|
||||
STATIC XTCDECL BOOLEAN GetBooleanParameter(IN PCWSTR Parameters,
|
||||
IN PCWSTR Needle);
|
||||
};
|
||||
|
||||
class Configuration
|
||||
{
|
||||
private:
|
||||
STATIC PLIST_ENTRY BootMenuList;
|
||||
STATIC LIST_ENTRY Config;
|
||||
STATIC LIST_ENTRY ConfigSections;
|
||||
STATIC PCWSTR EditableConfigOptions[];
|
||||
|
||||
public:
|
||||
STATIC XTCDECL BOOLEAN GetBooleanValue(IN PCWSTR ConfigName);
|
||||
STATIC XTCDECL EFI_STATUS GetBootOptionValue(IN PLIST_ENTRY Options,
|
||||
IN PCWSTR OptionName,
|
||||
OUT PWCHAR *OptionValue);
|
||||
STATIC XTCDECL VOID GetEditableOptions(OUT PCWSTR **OptionsArray,
|
||||
OUT PULONG OptionsCount);
|
||||
STATIC XTCDECL EFI_STATUS GetValue(IN PCWSTR ConfigName,
|
||||
OUT PWCHAR *ConfigValue);
|
||||
STATIC XTCDECL EFI_STATUS InitializeBootMenuList(IN ULONG MaxNameLength,
|
||||
OUT PXTBL_BOOTMENU_ITEM *MenuEntries,
|
||||
OUT PULONG EntriesCount,
|
||||
OUT PULONG DefaultId);
|
||||
STATIC XTCDECL VOID InitializeConfiguration();
|
||||
STATIC XTCDECL EFI_STATUS LoadConfiguration();
|
||||
STATIC XTCDECL EFI_STATUS ParseCommandLine();
|
||||
STATIC XTCDECL EFI_STATUS SetBootOptionValue(IN PLIST_ENTRY Options,
|
||||
IN PCWSTR OptionName,
|
||||
IN PCWSTR OptionValue);
|
||||
|
||||
private:
|
||||
STATIC XTCDECL EFI_STATUS ParseConfigFile(IN CONST PCHAR RawConfig,
|
||||
OUT PLIST_ENTRY Configuration);
|
||||
STATIC XTCDECL EFI_STATUS ReadConfigFile(IN PCWSTR ConfigDirectory,
|
||||
IN PCWSTR ConfigFile,
|
||||
OUT PCHAR *ConfigData);
|
||||
STATIC XTCDECL EFI_STATUS SetValue(IN PCWSTR ConfigName,
|
||||
IN PCWSTR ConfigValue);
|
||||
STATIC XTCDECL VOID UpdateConfiguration(IN PLIST_ENTRY NewConfig);
|
||||
};
|
||||
|
||||
class Console
|
||||
{
|
||||
public:
|
||||
STATIC XTCDECL VOID ClearLine(IN ULONGLONG LineNo);
|
||||
STATIC XTCDECL VOID ClearScreen();
|
||||
STATIC XTCDECL VOID DisableCursor();
|
||||
STATIC XTCDECL VOID EnableCursor();
|
||||
STATIC XTCDECL VOID InitializeConsole();
|
||||
STATIC XTCDECL VOID Print(IN PCWSTR Format,
|
||||
IN ...);
|
||||
STATIC XTCDECL XTSTATUS PutChar(IN WCHAR Character);
|
||||
STATIC XTCDECL VOID QueryMode(OUT PUINT_PTR ResX,
|
||||
OUT PUINT_PTR ResY);
|
||||
STATIC XTCDECL VOID ReadKeyStroke(OUT PEFI_INPUT_KEY Key);
|
||||
STATIC XTCDECL VOID ResetInputBuffer();
|
||||
STATIC XTCDECL VOID SetAttributes(IN ULONGLONG Attributes);
|
||||
STATIC XTCDECL VOID SetCursorPosition(IN ULONGLONG PosX,
|
||||
IN ULONGLONG PosY);
|
||||
STATIC XTCDECL VOID Write(IN PCWSTR String);
|
||||
|
||||
private:
|
||||
STATIC XTCDECL EFI_STATUS SetMode(IN ULONGLONG Mode);
|
||||
};
|
||||
|
||||
class Debug
|
||||
{
|
||||
private:
|
||||
STATIC ULONG ComPortList[COMPORT_COUNT];
|
||||
STATIC ULONG EnabledDebugPorts;
|
||||
STATIC CPPORT SerialPort;
|
||||
|
||||
public:
|
||||
STATIC XTCDECL EFI_STATUS InitializeDebugConsole();
|
||||
STATIC XTCDECL VOID Print(IN PCWSTR Format,
|
||||
IN ...);
|
||||
STATIC XTCDECL XTSTATUS PutChar(IN WCHAR Character);
|
||||
STATIC XTCDECL BOOLEAN SerialPortReady();
|
||||
|
||||
private:
|
||||
STATIC XTCDECL EFI_STATUS ActivateSerialIOController();
|
||||
STATIC XTCDECL EFI_STATUS InitializeSerialPort(IN ULONG PortNumber,
|
||||
IN ULONG PortAddress,
|
||||
IN ULONG BaudRate);
|
||||
};
|
||||
|
||||
class EfiUtils
|
||||
{
|
||||
public:
|
||||
STATIC XTCDECL EFI_STATUS EnterFirmwareSetup();
|
||||
STATIC XTCDECL EFI_STATUS ExitBootServices();
|
||||
STATIC XTCDECL EFI_STATUS GetConfigurationTable(IN PEFI_GUID TableGuid,
|
||||
OUT PVOID *Table);
|
||||
STATIC XTCDECL EFI_STATUS GetEfiVariable(IN PEFI_GUID Vendor,
|
||||
IN PCWSTR VariableName,
|
||||
OUT PVOID *VariableValue);
|
||||
STATIC XTCDECL ULONGLONG GetRandomValue(IN OUT PULONGLONG RNGBuffer);
|
||||
STATIC XTCDECL INT_PTR GetSecureBootStatus();
|
||||
STATIC XTCDECL EFI_STATUS InitializeEntropy(PULONGLONG RNGBuffer);
|
||||
STATIC XTCDECL EFI_STATUS LoadEfiImage(IN PEFI_DEVICE_PATH_PROTOCOL DevicePath,
|
||||
IN PVOID ImageData,
|
||||
IN SIZE_T ImageSize,
|
||||
OUT PEFI_HANDLE ImageHandle);
|
||||
STATIC XTCDECL EFI_STATUS RebootSystem();
|
||||
STATIC XTCDECL EFI_STATUS SetEfiVariable(IN PEFI_GUID Vendor,
|
||||
IN PCWSTR VariableName,
|
||||
IN PVOID VariableValue,
|
||||
IN UINT_PTR Size);
|
||||
STATIC XTCDECL EFI_STATUS ShutdownSystem();
|
||||
STATIC XTCDECL VOID SleepExecution(IN ULONG_PTR Milliseconds);
|
||||
STATIC XTCDECL EFI_STATUS StartEfiImage(IN EFI_HANDLE ImageHandle);
|
||||
STATIC XTCDECL EFI_STATUS WaitForEfiEvent(IN UINT_PTR NumberOfEvents,
|
||||
IN PEFI_EVENT Event,
|
||||
OUT PUINT_PTR Index);
|
||||
};
|
||||
|
||||
class Memory
|
||||
{
|
||||
public:
|
||||
STATIC XTCDECL EFI_STATUS AllocatePages(IN EFI_ALLOCATE_TYPE AllocationType,
|
||||
IN ULONGLONG NumberOfPages,
|
||||
OUT PEFI_PHYSICAL_ADDRESS Memory);
|
||||
STATIC XTCDECL EFI_STATUS AllocatePool(IN UINT_PTR Size,
|
||||
OUT PVOID *Memory);
|
||||
STATIC XTCDECL EFI_STATUS BuildPageMap(IN PXTBL_PAGE_MAPPING PageMap,
|
||||
IN ULONG_PTR SelfMapAddress);
|
||||
STATIC XTCDECL EFI_STATUS FreePages(IN ULONGLONG NumberOfPages,
|
||||
IN EFI_PHYSICAL_ADDRESS Memory);
|
||||
STATIC XTCDECL EFI_STATUS FreePool(IN PVOID Memory);
|
||||
STATIC XTCDECL VOID GetMappingsCount(IN PXTBL_PAGE_MAPPING PageMap,
|
||||
OUT PULONG NumberOfMappings);
|
||||
STATIC XTCDECL EFI_STATUS GetMemoryMap(OUT PEFI_MEMORY_MAP MemoryMap);
|
||||
STATIC XTCDECL PVOID GetVirtualAddress(IN PXTBL_PAGE_MAPPING PageMap,
|
||||
IN PVOID PhysicalAddress);
|
||||
STATIC XTCDECL VOID InitializePageMap(OUT PXTBL_PAGE_MAPPING PageMap,
|
||||
IN SHORT PageMapLevel,
|
||||
IN PAGE_SIZE PageSize);
|
||||
STATIC XTCDECL EFI_STATUS MapEfiMemory(IN OUT PXTBL_PAGE_MAPPING PageMap,
|
||||
IN OUT PVOID *MemoryMapAddress,
|
||||
IN PBL_GET_MEMTYPE_ROUTINE GetMemoryTypeRoutine);
|
||||
STATIC XTCDECL EFI_STATUS MapPage(IN PXTBL_PAGE_MAPPING PageMap,
|
||||
IN ULONG_PTR VirtualAddress,
|
||||
IN ULONG_PTR PhysicalAddress,
|
||||
IN ULONG NumberOfPages);
|
||||
STATIC XTCDECL EFI_STATUS MapVirtualMemory(IN OUT PXTBL_PAGE_MAPPING PageMap,
|
||||
IN PVOID VirtualAddress,
|
||||
IN PVOID PhysicalAddress,
|
||||
IN ULONGLONG NumberOfPages,
|
||||
IN LOADER_MEMORY_TYPE MemoryType);
|
||||
STATIC XTCDECL PVOID PhysicalAddressToVirtual(IN PVOID PhysicalAddress,
|
||||
IN PVOID PhysicalBase,
|
||||
IN PVOID VirtualBase);
|
||||
STATIC XTCDECL EFI_STATUS PhysicalListToVirtual(IN PXTBL_PAGE_MAPPING PageMap,
|
||||
IN OUT PLIST_ENTRY ListHead,
|
||||
IN PVOID PhysicalBase,
|
||||
IN PVOID VirtualBase);
|
||||
|
||||
private:
|
||||
STATIC XTCDECL LOADER_MEMORY_TYPE GetLoaderMemoryType(IN EFI_MEMORY_TYPE EfiMemoryType);
|
||||
STATIC XTCDECL EFI_STATUS GetNextPageTable(IN PXTBL_PAGE_MAPPING PageMap,
|
||||
IN PVOID PageTable,
|
||||
IN SIZE_T Entry,
|
||||
OUT PVOID *NextPageTable);
|
||||
STATIC XTCDECL EFI_STATUS SelfMapPml(IN PXTBL_PAGE_MAPPING PageMap,
|
||||
IN ULONG_PTR SelfMapAddress);
|
||||
};
|
||||
|
||||
class Protocol
|
||||
{
|
||||
private:
|
||||
STATIC LIST_ENTRY BootProtocols;
|
||||
STATIC XTBL_LOADER_PROTOCOL LoaderProtocol;
|
||||
STATIC LIST_ENTRY LoadedModules;
|
||||
|
||||
public:
|
||||
STATIC XTCDECL EFI_STATUS CloseProtocol(IN PEFI_HANDLE Handle,
|
||||
IN PEFI_GUID ProtocolGuid);
|
||||
STATIC XTCDECL EFI_STATUS FindBootProtocol(IN PCWSTR SystemType,
|
||||
OUT PEFI_GUID BootProtocolGuid);
|
||||
STATIC XTCDECL PLIST_ENTRY GetModulesList();
|
||||
STATIC XTCDECL EFI_STATUS InstallProtocol(IN PVOID Interface,
|
||||
IN PEFI_GUID Guid);
|
||||
STATIC XTCDECL VOID InitializeProtocol();
|
||||
STATIC XTCDECL EFI_STATUS InvokeBootProtocol(IN PWCHAR ShortName,
|
||||
IN PLIST_ENTRY OptionsList);
|
||||
STATIC XTCDECL EFI_STATUS LoadModule(IN PWCHAR ModuleName);
|
||||
STATIC XTCDECL EFI_STATUS LoadModules(IN PWCHAR ModulesList);
|
||||
STATIC XTCDECL EFI_STATUS LocateProtocolHandles(OUT PEFI_HANDLE *Handles,
|
||||
OUT PUINT_PTR Count,
|
||||
IN PEFI_GUID ProtocolGuid);
|
||||
STATIC XTCDECL EFI_STATUS OpenProtocol(OUT PEFI_HANDLE Handle,
|
||||
OUT PVOID *ProtocolHandler,
|
||||
IN PEFI_GUID ProtocolGuid);
|
||||
STATIC XTCDECL EFI_STATUS OpenProtocolHandle(IN EFI_HANDLE Handle,
|
||||
OUT PVOID *ProtocolHandler,
|
||||
IN PEFI_GUID ProtocolGuid);
|
||||
STATIC XTCDECL EFI_STATUS RegisterBootProtocol(IN PCWSTR SystemType,
|
||||
IN PEFI_GUID BootProtocolGuid);
|
||||
STATIC XTCDECL EFI_STATUS InstallXtLoaderProtocol();
|
||||
|
||||
private:
|
||||
STATIC XTCDECL EFI_STATUS GetModuleInformation(IN PWCHAR SectionData,
|
||||
IN ULONG SectionSize,
|
||||
OUT PXTBL_MODULE_INFO ModuleInfo);
|
||||
STATIC XTCDECL EFI_STATUS GetModuleInfoStrings(IN PWCHAR SectionData,
|
||||
IN ULONG SectionSize,
|
||||
OUT PWCHAR **ModInfo,
|
||||
OUT PULONG InfoCount);
|
||||
};
|
||||
|
||||
class Shell
|
||||
{
|
||||
public:
|
||||
STATIC XTCDECL VOID StartLoaderShell();
|
||||
|
||||
private:
|
||||
STATIC XTCDECL VOID PrintPrompt();
|
||||
};
|
||||
|
||||
class TextUi
|
||||
{
|
||||
public:
|
||||
STATIC XTCDECL VOID DisplayBootMenu();
|
||||
STATIC XTCDECL VOID DisplayErrorDialog(IN PCWSTR Caption,
|
||||
IN PCWSTR Message);
|
||||
STATIC XTCDECL VOID DisplayInfoDialog(IN PCWSTR Caption,
|
||||
IN PCWSTR Message);
|
||||
STATIC XTCDECL VOID DisplayInputDialog(IN PCWSTR Caption,
|
||||
IN PCWSTR Message,
|
||||
IN OUT PWCHAR *InputFieldText);
|
||||
STATIC XTCDECL XTBL_DIALOG_HANDLE DisplayProgressDialog(IN PCWSTR Caption,
|
||||
IN PCWSTR Message,
|
||||
IN UCHAR Percentage);
|
||||
STATIC XTCDECL VOID UpdateProgressBar(IN PXTBL_DIALOG_HANDLE Handle,
|
||||
IN PCWSTR Message,
|
||||
IN UCHAR Percentage);
|
||||
|
||||
private:
|
||||
STATIC XTCDECL VOID DetermineDialogBoxSize(IN OUT PXTBL_DIALOG_HANDLE Handle,
|
||||
IN PCWSTR Message);
|
||||
STATIC XTCDECL VOID DisplayEditMenu(IN PXTBL_BOOTMENU_ITEM MenuEntry);
|
||||
STATIC XTCDECL VOID DrawBootMenu(OUT PXTBL_DIALOG_HANDLE Handle);
|
||||
STATIC XTCDECL VOID DrawBootMenuEntry(IN PXTBL_DIALOG_HANDLE Handle,
|
||||
IN PWCHAR MenuEntry,
|
||||
IN UINT Position,
|
||||
IN BOOLEAN Highlighted);
|
||||
STATIC XTCDECL VOID DrawDialogBox(IN OUT PXTBL_DIALOG_HANDLE Handle,
|
||||
IN PCWSTR Caption,
|
||||
IN PCWSTR Message);
|
||||
STATIC XTCDECL VOID DrawButton(IN PXTBL_DIALOG_HANDLE Handle);
|
||||
STATIC XTCDECL VOID DrawInputField(IN PXTBL_DIALOG_HANDLE Handle,
|
||||
IN PWCHAR InputFieldText);
|
||||
STATIC XTCDECL VOID DrawMessage(IN PXTBL_DIALOG_HANDLE Handle,
|
||||
IN PCWSTR Message);
|
||||
STATIC XTCDECL VOID DrawProgressBar(IN PXTBL_DIALOG_HANDLE Handle,
|
||||
IN UCHAR Percentage);
|
||||
STATIC XTCDECL VOID DrawEditMenu(OUT PXTBL_DIALOG_HANDLE Handle);
|
||||
STATIC XTCDECL EFI_STATUS DrawEditMenuEntry(IN PXTBL_DIALOG_HANDLE Handle,
|
||||
IN PCWSTR OptionName,
|
||||
IN PCWSTR OptionValue,
|
||||
IN UINT Position,
|
||||
IN BOOLEAN Highlighted);
|
||||
};
|
||||
|
||||
class Volume
|
||||
{
|
||||
private:
|
||||
STATIC LIST_ENTRY EfiBlockDevices;
|
||||
|
||||
public:
|
||||
STATIC XTCDECL EFI_STATUS CloseVolume(IN PEFI_HANDLE VolumeHandle);
|
||||
STATIC XTCDECL EFI_STATUS EnumerateBlockDevices();
|
||||
STATIC XTCDECL EFI_STATUS FindDevicePath(IN PEFI_DEVICE_PATH_PROTOCOL FsHandle,
|
||||
IN CONST PWCHAR FileSystemPath,
|
||||
OUT PEFI_DEVICE_PATH_PROTOCOL* DevicePath);
|
||||
STATIC XTCDECL EFI_STATUS GetEfiPath(IN PWCHAR SystemPath,
|
||||
OUT PWCHAR *EfiPath);
|
||||
STATIC XTCDECL EFI_STATUS GetDevicePath(IN PWCHAR SystemPath,
|
||||
OUT PEFI_DEVICE_PATH_PROTOCOL *DevicePath,
|
||||
OUT PWCHAR *ArcName,
|
||||
OUT PWCHAR *Path);
|
||||
STATIC XTCDECL EFI_STATUS OpenVolume(IN PEFI_DEVICE_PATH_PROTOCOL DevicePath,
|
||||
OUT PEFI_HANDLE DiskHandle,
|
||||
OUT PEFI_FILE_HANDLE *FsHandle);
|
||||
STATIC XTCDECL EFI_STATUS ReadFile(IN PEFI_FILE_HANDLE DirHandle,
|
||||
IN PCWSTR FileName,
|
||||
OUT PVOID *FileData,
|
||||
OUT PSIZE_T FileSize);
|
||||
|
||||
|
||||
private:
|
||||
STATIC XTCDECL EFI_STATUS DiscoverEfiBlockDevices(OUT PLIST_ENTRY BlockDevices);
|
||||
STATIC XTCDECL EFI_STATUS DissectArcPath(IN PWCHAR SystemPath,
|
||||
OUT PWCHAR *ArcName,
|
||||
OUT PWCHAR *Path,
|
||||
OUT PUSHORT DriveType,
|
||||
OUT PULONG DriveNumber,
|
||||
OUT PULONG PartNumber);
|
||||
STATIC XTCDECL PEFI_DEVICE_PATH_PROTOCOL DuplicateDevicePath(IN PEFI_DEVICE_PATH_PROTOCOL DevicePath);
|
||||
STATIC XTCDECL EFI_STATUS FindLastBlockDeviceNode(IN PEFI_DEVICE_PATH_PROTOCOL DevicePath,
|
||||
OUT PEFI_DEVICE_PATH_PROTOCOL *LastNode);
|
||||
STATIC XTCDECL BOOLEAN FindParentBlockDevice(IN PLIST_ENTRY BlockDevices,
|
||||
IN PEFI_BLOCK_DEVICE_DATA ChildNode,
|
||||
OUT PEFI_BLOCK_DEVICE_DATA *ParentNode);
|
||||
};
|
||||
|
||||
class XtLoader
|
||||
{
|
||||
private:
|
||||
STATIC PBL_XT_BOOT_MENU BootMenu;
|
||||
STATIC EFI_HANDLE EfiImageHandle;
|
||||
STATIC PEFI_SYSTEM_TABLE EfiSystemTable;
|
||||
STATIC XTBL_STATUS LoaderStatus;
|
||||
|
||||
public:
|
||||
STATIC XTCDECL VOID DisableBootServices();
|
||||
STATIC XTCDECL BOOLEAN GetBootServicesStatus();
|
||||
STATIC XTCDECL EFI_HANDLE GetEfiImageHandle();
|
||||
STATIC XTCDECL PEFI_SYSTEM_TABLE GetEfiSystemTable();
|
||||
STATIC XTCDECL VOID GetLoaderImageInformation(PVOID *LoaderBase,
|
||||
PULONGLONG LoaderSize);
|
||||
STATIC XTCDECL INT_PTR GetSecureBootStatus();
|
||||
STATIC XTCDECL VOID InitializeBootLoader(IN EFI_HANDLE ImageHandle,
|
||||
IN PEFI_SYSTEM_TABLE SystemTable);
|
||||
STATIC XTCDECL VOID RegisterBootMenu(IN PVOID BootMenuRoutine);
|
||||
STATIC XTCDECL VOID ShowBootMenu();
|
||||
};
|
||||
|
||||
#endif /* __XTLDR_XTLDR_HH */
|
81
boot/xtldr/library/modproto.cc
Normal file
81
boot/xtldr/library/modproto.cc
Normal file
@@ -0,0 +1,81 @@
|
||||
/**
|
||||
* PROJECT: ExectOS
|
||||
* COPYRIGHT: See COPYING.md in the top level directory
|
||||
* FILE: xtldr/library/modproto.cc
|
||||
* DESCRIPTION: XT Boot Loader protocol support for XTLDR modules
|
||||
* DEVELOPERS: Rafal Kupiec <belliash@codingworkshop.eu.org>
|
||||
*/
|
||||
|
||||
#include <xtldr.hh>
|
||||
|
||||
|
||||
/**
|
||||
* Finds and opens the XT Boot Loader protocol. This routine should be called by module to access XTLDR protocol.
|
||||
*
|
||||
* @param SystemTable
|
||||
* Provides the EFI system table.
|
||||
*
|
||||
* @param ImageHandle
|
||||
* Firmware-allocated handle that identifies the image.
|
||||
*
|
||||
* @param ProtocolHandler
|
||||
* Receives the pointer to the XT Boot Loader protocol.
|
||||
*
|
||||
* @return This routine returns a status code.
|
||||
*
|
||||
* @since XT 1.0
|
||||
*/
|
||||
XTCLINK
|
||||
XTCDECL
|
||||
EFI_STATUS
|
||||
BlGetXtLdrProtocol(IN PEFI_SYSTEM_TABLE SystemTable,
|
||||
IN EFI_HANDLE ImageHandle,
|
||||
OUT PXTBL_LOADER_PROTOCOL *ProtocolHandler)
|
||||
{
|
||||
EFI_GUID ProtocolGuid = XT_BOOT_LOADER_PROTOCOL_GUID;
|
||||
PEFI_HANDLE Handles = NULLPTR;
|
||||
EFI_STATUS Status;
|
||||
UINT_PTR Count;
|
||||
UINT Index;
|
||||
|
||||
/* Try to locate the handles */
|
||||
Status = SystemTable->BootServices->LocateHandleBuffer(ByProtocol, &ProtocolGuid, NULLPTR, &Count, &Handles);
|
||||
if(Status != STATUS_EFI_SUCCESS)
|
||||
{
|
||||
/* Unable to get handles */
|
||||
return Status;
|
||||
}
|
||||
|
||||
/* Check if any handles returned */
|
||||
if(Count > 0)
|
||||
{
|
||||
/* Iterate through all given handles */
|
||||
for(Index = 0; Index < Count; Index++)
|
||||
{
|
||||
/* Try to open protocol */
|
||||
Status = SystemTable->BootServices->OpenProtocol(Handles[Index], &ProtocolGuid,
|
||||
(PVOID*)ProtocolHandler, ImageHandle, NULLPTR,
|
||||
EFI_OPEN_PROTOCOL_BY_HANDLE_PROTOCOL);
|
||||
|
||||
/* Check if successfully opened the loader protocol */
|
||||
if(Status == STATUS_EFI_SUCCESS)
|
||||
{
|
||||
/* Protocol found and successfully opened */
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Free handles */
|
||||
SystemTable->BootServices->FreePool(Handles);
|
||||
|
||||
/* Make sure the loaded protocol has been found */
|
||||
if(*ProtocolHandler == NULLPTR)
|
||||
{
|
||||
/* Protocol not found */
|
||||
return STATUS_EFI_NOT_FOUND;
|
||||
}
|
||||
|
||||
/* Return success */
|
||||
return STATUS_EFI_SUCCESS;
|
||||
}
|
746
boot/xtldr/memory.cc
Normal file
746
boot/xtldr/memory.cc
Normal file
@@ -0,0 +1,746 @@
|
||||
/**
|
||||
* PROJECT: ExectOS
|
||||
* COPYRIGHT: See COPYING.md in the top level directory
|
||||
* FILE: xtldr/memory.cc
|
||||
* DESCRIPTION: XT Boot Loader memory management
|
||||
* DEVELOPERS: Rafal Kupiec <belliash@codingworkshop.eu.org>
|
||||
*/
|
||||
|
||||
#include <xtldr.hh>
|
||||
|
||||
|
||||
/**
|
||||
* This routine allocates one or more 4KB pages.
|
||||
*
|
||||
* @param NumberOfPages
|
||||
* The number of contiguous 4KB pages to allocate.
|
||||
*
|
||||
* @param Memory
|
||||
* The pointer to a physical address.
|
||||
*
|
||||
* @return This routine returns a status code.
|
||||
*
|
||||
* @since XT 1.0
|
||||
*/
|
||||
XTCDECL
|
||||
EFI_STATUS
|
||||
Memory::AllocatePages(IN EFI_ALLOCATE_TYPE AllocationType,
|
||||
IN ULONGLONG NumberOfPages,
|
||||
OUT PEFI_PHYSICAL_ADDRESS Memory)
|
||||
{
|
||||
return XtLoader::GetEfiSystemTable()->BootServices->AllocatePages(AllocationType, EfiLoaderData,
|
||||
NumberOfPages, Memory);
|
||||
}
|
||||
|
||||
/**
|
||||
* This routine allocates a pool memory.
|
||||
*
|
||||
* @param Size
|
||||
* The number of bytes to allocate from the pool.
|
||||
*
|
||||
* @param Memory
|
||||
* The pointer to a physical address.
|
||||
*
|
||||
* @return This routine returns a status code.
|
||||
*
|
||||
* @since XT 1.0
|
||||
*/
|
||||
XTCDECL
|
||||
EFI_STATUS
|
||||
Memory::AllocatePool(IN UINT_PTR Size,
|
||||
OUT PVOID *Memory)
|
||||
{
|
||||
/* Allocate pool */
|
||||
return XtLoader::GetEfiSystemTable()->BootServices->AllocatePool(EfiLoaderData, Size, Memory);
|
||||
}
|
||||
|
||||
/**
|
||||
* This routine frees memory pages.
|
||||
*
|
||||
* @param NumberOfPages
|
||||
* The number of contiguous 4 KB pages to free.
|
||||
*
|
||||
* @param Memory
|
||||
* The base physical address of the pages to be freed.
|
||||
*
|
||||
* @return This routine returns a status code.
|
||||
*
|
||||
* @since XT 1.0
|
||||
*/
|
||||
XTCDECL
|
||||
EFI_STATUS
|
||||
Memory::FreePages(IN ULONGLONG NumberOfPages,
|
||||
IN EFI_PHYSICAL_ADDRESS Memory)
|
||||
{
|
||||
return XtLoader::GetEfiSystemTable()->BootServices->FreePages(Memory, NumberOfPages);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns pool memory to the system.
|
||||
*
|
||||
* @param Memory
|
||||
* The pointer to the buffer to free.
|
||||
*
|
||||
* @return This routine returns a status code.
|
||||
*
|
||||
* @since XT 1.0
|
||||
*/
|
||||
XTCDECL
|
||||
EFI_STATUS
|
||||
Memory::FreePool(IN PVOID Memory)
|
||||
{
|
||||
/* Free pool */
|
||||
return XtLoader::GetEfiSystemTable()->BootServices->FreePool(Memory);
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts EFI memory type to XTLDR memory type.
|
||||
*
|
||||
* @param EfiMemoryType
|
||||
* Specifies EFI memory type.
|
||||
*
|
||||
* @return This routine returns a mapped XTLDR memory type.
|
||||
*
|
||||
* @since XT 1.0
|
||||
*/
|
||||
XTCDECL
|
||||
LOADER_MEMORY_TYPE
|
||||
Memory::GetLoaderMemoryType(IN EFI_MEMORY_TYPE EfiMemoryType)
|
||||
{
|
||||
LOADER_MEMORY_TYPE MemoryType;
|
||||
|
||||
/* Check EFI memory type and convert to XTLDR memory type */
|
||||
switch(EfiMemoryType)
|
||||
{
|
||||
case EfiACPIMemoryNVS:
|
||||
case EfiACPIReclaimMemory:
|
||||
case EfiPalCode:
|
||||
case EfiReservedMemoryType:
|
||||
MemoryType = LoaderSpecialMemory;
|
||||
break;
|
||||
case EfiRuntimeServicesCode:
|
||||
case EfiRuntimeServicesData:
|
||||
case EfiMemoryMappedIO:
|
||||
case EfiMemoryMappedIOPortSpace:
|
||||
MemoryType = LoaderFirmwarePermanent;
|
||||
break;
|
||||
case EfiBootServicesData:
|
||||
case EfiLoaderCode:
|
||||
case EfiLoaderData:
|
||||
MemoryType = LoaderFirmwareTemporary;
|
||||
break;
|
||||
case EfiUnusableMemory:
|
||||
MemoryType = LoaderBad;
|
||||
break;
|
||||
default:
|
||||
MemoryType = LoaderFree;
|
||||
break;
|
||||
}
|
||||
|
||||
/* Return XTLDR memory type */
|
||||
return MemoryType;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the number of mappings in the page mapping structure.
|
||||
*
|
||||
* @param PageMap
|
||||
* Supplies a pointer to the page mapping structure.
|
||||
*
|
||||
* @param NumberOfMappings
|
||||
* Supplies a pointer to memory area where the number of mappings is returned.
|
||||
*
|
||||
* @return This routine does not return any value.
|
||||
*
|
||||
* @since XT 1.0
|
||||
*/
|
||||
XTCDECL
|
||||
VOID
|
||||
Memory::GetMappingsCount(IN PXTBL_PAGE_MAPPING PageMap,
|
||||
OUT PULONG NumberOfMappings)
|
||||
{
|
||||
/* Return number of mappings */
|
||||
*NumberOfMappings = PageMap->MapSize;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the memory descriptors which define a memory map of all the physical memory ranges reserved by the UEFI.
|
||||
*
|
||||
* @param MemoryMap
|
||||
* Supplies a pointer to the buffer where memory map will be written.
|
||||
*
|
||||
* @return This routine returns a status code.
|
||||
*
|
||||
* @since XT 1.0
|
||||
*/
|
||||
XTCDECL
|
||||
EFI_STATUS
|
||||
Memory::GetMemoryMap(OUT PEFI_MEMORY_MAP MemoryMap)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
|
||||
if(MemoryMap == NULLPTR)
|
||||
{
|
||||
return STATUS_EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
MemoryMap->Map = NULLPTR;
|
||||
MemoryMap->MapSize = 0;
|
||||
|
||||
/* Get memory map */
|
||||
do
|
||||
{
|
||||
/* Attempt do get EFI memory map */
|
||||
Status = XtLoader::GetEfiSystemTable()->BootServices->GetMemoryMap(&MemoryMap->MapSize,
|
||||
MemoryMap->Map,
|
||||
&MemoryMap->MapKey,
|
||||
&MemoryMap->DescriptorSize,
|
||||
&MemoryMap->DescriptorVersion);
|
||||
if(Status == STATUS_EFI_SUCCESS)
|
||||
{
|
||||
/* Go further if succeeded */
|
||||
break;
|
||||
}
|
||||
else if(Status != STATUS_EFI_BUFFER_TOO_SMALL)
|
||||
{
|
||||
/* Some error occurred */
|
||||
if(MemoryMap->Map)
|
||||
{
|
||||
/* Free allocated memory */
|
||||
FreePool(MemoryMap->Map);
|
||||
}
|
||||
return Status;
|
||||
}
|
||||
|
||||
/* Allocate the desired amount of memory */
|
||||
MemoryMap->MapSize += 2 * MemoryMap->DescriptorSize;
|
||||
AllocatePool(MemoryMap->MapSize, (PVOID *)&MemoryMap->Map);
|
||||
}
|
||||
while(Status == STATUS_EFI_BUFFER_TOO_SMALL);
|
||||
|
||||
/* Make sure memory map is set */
|
||||
if(MemoryMap->Map == NULLPTR)
|
||||
{
|
||||
/* Something went wrong */
|
||||
return STATUS_EFI_NO_MAPPING;
|
||||
}
|
||||
|
||||
/* Return success */
|
||||
return STATUS_EFI_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* Attempts to find a virtual address of the specified physical address in memory mappings.
|
||||
*
|
||||
* @param PageMap
|
||||
* Supplies a pointer to the page mapping structure.
|
||||
*
|
||||
* @param PhysicalAddress
|
||||
* Supplies a physical address to search for in the mappings.
|
||||
*
|
||||
* @return This routine returns a corresponding virtual address found in the mappings.
|
||||
*
|
||||
* @since XT 1.0
|
||||
*/
|
||||
XTCDECL
|
||||
PVOID
|
||||
Memory::GetVirtualAddress(IN PXTBL_PAGE_MAPPING PageMap,
|
||||
IN PVOID PhysicalAddress)
|
||||
{
|
||||
PXTBL_MEMORY_MAPPING Mapping;
|
||||
PLIST_ENTRY ListEntry;
|
||||
|
||||
/* Iterate over memory mappings in order to find descriptor containing a physical address */
|
||||
ListEntry = PageMap->MemoryMap.Flink;
|
||||
while(ListEntry != &PageMap->MemoryMap)
|
||||
{
|
||||
/* Get mapping from linked list */
|
||||
Mapping = CONTAIN_RECORD(ListEntry, XTBL_MEMORY_MAPPING, ListEntry);
|
||||
|
||||
/* Make sure any virtual address is set */
|
||||
if(Mapping->VirtualAddress)
|
||||
{
|
||||
/* Check if provided physical address is in range of this mapping */
|
||||
if(((UINT_PTR)PhysicalAddress >= (UINT_PTR)Mapping->PhysicalAddress) &&
|
||||
((UINT_PTR)PhysicalAddress < ((UINT_PTR)Mapping->PhysicalAddress + (Mapping->NumberOfPages * EFI_PAGE_SIZE))))
|
||||
{
|
||||
/* Calculate virtual address based on the mapping and return it */
|
||||
return (PVOID)(((UINT_PTR)PhysicalAddress - (UINT_PTR)Mapping->PhysicalAddress) + (UINT_PTR)Mapping->VirtualAddress);
|
||||
}
|
||||
}
|
||||
|
||||
/* Get next element from the list */
|
||||
ListEntry = ListEntry->Flink;
|
||||
}
|
||||
|
||||
/* Mapping not found, return 0 */
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Initializes the page mapping structures.
|
||||
*
|
||||
* @param PageMap
|
||||
* Supplies a pointer to the page mapping structure.
|
||||
*
|
||||
* @param PageMapLevel
|
||||
* Specifies a number of of paging structures levels.
|
||||
*
|
||||
* @param PageSize
|
||||
* Specifies a page size (currently it has no effect).
|
||||
*
|
||||
* @return This routine does not return any value.
|
||||
*
|
||||
* @since XT 1.0
|
||||
*/
|
||||
XTCDECL
|
||||
VOID
|
||||
Memory::InitializePageMap(OUT PXTBL_PAGE_MAPPING PageMap,
|
||||
IN SHORT PageMapLevel,
|
||||
IN PAGE_SIZE PageSize)
|
||||
{
|
||||
/* Initialize memory mappings */
|
||||
RTL::LinkedList::InitializeListHead(&PageMap->MemoryMap);
|
||||
PageMap->MapSize = 0;
|
||||
|
||||
/* Set page map size/level and memory map address */
|
||||
PageMap->PageMapLevel = PageMapLevel;
|
||||
PageMap->PageSize = PageSize;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds EFI memory mapping to the page mapping structure.
|
||||
*
|
||||
* @param PageMap
|
||||
* Supplies a pointer to the page mapping structure.
|
||||
*
|
||||
* @param MemoryMapAddress
|
||||
* Supplies a virtual address, where EFI memory will be mapped.
|
||||
*
|
||||
* @param GetMemoryTypeRoutine
|
||||
* Supplies a pointer to the routine which will be used to match EFI memory type to the OS memory type.
|
||||
*
|
||||
* @return This routine returns a status code.
|
||||
*
|
||||
* @since XT 1.0
|
||||
*/
|
||||
XTCDECL
|
||||
EFI_STATUS
|
||||
Memory::MapEfiMemory(IN OUT PXTBL_PAGE_MAPPING PageMap,
|
||||
IN OUT PVOID *MemoryMapAddress,
|
||||
IN PBL_GET_MEMTYPE_ROUTINE GetMemoryTypeRoutine)
|
||||
{
|
||||
PEFI_MEMORY_DESCRIPTOR Descriptor;
|
||||
LOADER_MEMORY_TYPE MemoryType;
|
||||
PEFI_MEMORY_MAP MemoryMap;
|
||||
SIZE_T DescriptorCount;
|
||||
PUCHAR VirtualAddress;
|
||||
EFI_STATUS Status;
|
||||
SIZE_T Index;
|
||||
|
||||
/* Set virtual address as specified in argument */
|
||||
VirtualAddress = (PUCHAR)*MemoryMapAddress;
|
||||
|
||||
/* Check if custom memory type routine is specified */
|
||||
if(GetMemoryTypeRoutine == NULLPTR)
|
||||
{
|
||||
/* Use default memory type routine */
|
||||
GetMemoryTypeRoutine = GetLoaderMemoryType;
|
||||
}
|
||||
|
||||
/* Allocate and zero-fill buffer for EFI memory map */
|
||||
AllocatePool(sizeof(EFI_MEMORY_MAP), (PVOID*)&MemoryMap);
|
||||
RTL::Memory::ZeroMemory(MemoryMap, sizeof(EFI_MEMORY_MAP));
|
||||
|
||||
/* Get EFI memory map */
|
||||
Status = GetMemoryMap(MemoryMap);
|
||||
if(Status != STATUS_EFI_SUCCESS)
|
||||
{
|
||||
/* Failed to get EFI memory map */
|
||||
return Status;
|
||||
}
|
||||
|
||||
/* Calculate descriptors count and get first one */
|
||||
Descriptor = MemoryMap->Map;
|
||||
DescriptorCount = MemoryMap->MapSize / MemoryMap->DescriptorSize;
|
||||
|
||||
/* Iterate through all descriptors from the memory map */
|
||||
for(Index = 0; Index < DescriptorCount; Index++)
|
||||
{
|
||||
/* Make sure descriptor does not start beyond lowest physical page */
|
||||
if(Descriptor->PhysicalStart <= MAXUINT_PTR)
|
||||
{
|
||||
/* Skip EFI reserved memory */
|
||||
if(Descriptor->Type == EfiReservedMemoryType)
|
||||
{
|
||||
/* Go to the next descriptor */
|
||||
Descriptor = (PEFI_MEMORY_DESCRIPTOR)((PUCHAR)Descriptor + MemoryMap->DescriptorSize);
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Check if preparing page map level 2 (non-PAE i686) */
|
||||
if(PageMap->PageMapLevel == 2)
|
||||
{
|
||||
/* Check if physical address starts beyond 4GB */
|
||||
if(Descriptor->PhysicalStart > 0xFFFFFFFF)
|
||||
{
|
||||
/* Go to the next descriptor */
|
||||
Descriptor = (PEFI_MEMORY_DESCRIPTOR)((PUCHAR)Descriptor + MemoryMap->DescriptorSize);
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Check if memory descriptor exceeds the lowest physical page */
|
||||
if(Descriptor->PhysicalStart + (Descriptor->NumberOfPages << EFI_PAGE_SHIFT) > MAXULONG)
|
||||
{
|
||||
/* Truncate memory descriptor to the 4GB */
|
||||
Descriptor->NumberOfPages = (((ULONGLONG)MAXULONG + 1) - Descriptor->PhysicalStart) >> EFI_PAGE_SHIFT;
|
||||
}
|
||||
}
|
||||
|
||||
/* Convert EFI memory type into XTLDR memory type */
|
||||
MemoryType = GetMemoryTypeRoutine((EFI_MEMORY_TYPE)Descriptor->Type);
|
||||
|
||||
/* Do memory mappings depending on memory type */
|
||||
if(MemoryType == LoaderFirmwareTemporary)
|
||||
{
|
||||
/* Map EFI firmware code */
|
||||
Status = MapVirtualMemory(PageMap, (PVOID)Descriptor->PhysicalStart,
|
||||
(PVOID)Descriptor->PhysicalStart, Descriptor->NumberOfPages, MemoryType);
|
||||
}
|
||||
else if(MemoryType != LoaderFree)
|
||||
{
|
||||
/* Add any non-free memory mapping */
|
||||
Status = MapVirtualMemory(PageMap, VirtualAddress, (PVOID)Descriptor->PhysicalStart,
|
||||
Descriptor->NumberOfPages, MemoryType);
|
||||
|
||||
/* Calculate next valid virtual address */
|
||||
VirtualAddress += Descriptor->NumberOfPages * EFI_PAGE_SIZE;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Map all other memory as loader free */
|
||||
Status = MapVirtualMemory(PageMap, NULLPTR, (PVOID)Descriptor->PhysicalStart,
|
||||
Descriptor->NumberOfPages, LoaderFree);
|
||||
}
|
||||
|
||||
/* Make sure memory mapping succeeded */
|
||||
if(Status != STATUS_EFI_SUCCESS)
|
||||
{
|
||||
/* Mapping failed */
|
||||
return Status;
|
||||
}
|
||||
}
|
||||
|
||||
/* Grab next descriptor */
|
||||
Descriptor = (PEFI_MEMORY_DESCRIPTOR)((PUCHAR)Descriptor + MemoryMap->DescriptorSize);
|
||||
}
|
||||
|
||||
/* Always map first page */
|
||||
Status = MapVirtualMemory(PageMap, NULLPTR, (PVOID)0, 1, LoaderFirmwarePermanent);
|
||||
if(Status != STATUS_EFI_SUCCESS)
|
||||
{
|
||||
/* Mapping failed */
|
||||
return Status;
|
||||
}
|
||||
|
||||
/* Map BIOS ROM and VRAM */
|
||||
Status = MapVirtualMemory(PageMap, NULLPTR, (PVOID)0xA0000, 0x60, LoaderFirmwarePermanent);
|
||||
if(Status != STATUS_EFI_SUCCESS)
|
||||
{
|
||||
/* Mapping failed */
|
||||
return Status;
|
||||
}
|
||||
|
||||
/* Store next valid virtual address and return success */
|
||||
*MemoryMapAddress = VirtualAddress;
|
||||
return STATUS_EFI_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a physical to virtual address mappings.
|
||||
*
|
||||
* @param PageMap
|
||||
* Supplies a pointer to the page mapping structure.
|
||||
*
|
||||
* @param VirtualAddress
|
||||
* Supplies a virtual address where the physical address should be mapped.
|
||||
*
|
||||
* @param PhysicalAddress
|
||||
* Supplies a physical address which will be mapped.
|
||||
*
|
||||
* @param NumberOfPages
|
||||
* Supplies a number of pages that will be mapped.
|
||||
*
|
||||
* @param MemoryType
|
||||
* Supplies the type of mapped memory that will be assigned to the memory descriptor.
|
||||
*
|
||||
* @return This routine returns a status code.
|
||||
*
|
||||
* @since XT 1.0
|
||||
*/
|
||||
XTCDECL
|
||||
EFI_STATUS
|
||||
Memory::MapVirtualMemory(IN OUT PXTBL_PAGE_MAPPING PageMap,
|
||||
IN PVOID VirtualAddress,
|
||||
IN PVOID PhysicalAddress,
|
||||
IN ULONGLONG NumberOfPages,
|
||||
IN LOADER_MEMORY_TYPE MemoryType)
|
||||
{
|
||||
PXTBL_MEMORY_MAPPING Mapping1, Mapping2, Mapping3;
|
||||
PVOID PhysicalAddressEnd, PhysicalAddress2End;
|
||||
PLIST_ENTRY ListEntry, MappingListEntry;
|
||||
SIZE_T NumberOfMappedPages;
|
||||
EFI_STATUS Status;
|
||||
|
||||
/* Allocate memory for new mapping */
|
||||
Status = AllocatePool(sizeof(XTBL_MEMORY_MAPPING), (PVOID *)&Mapping1);
|
||||
if(Status != STATUS_EFI_SUCCESS)
|
||||
{
|
||||
/* Memory allocation failure */
|
||||
return Status;
|
||||
}
|
||||
|
||||
/* Set mapping fields */
|
||||
Mapping1->PhysicalAddress = PhysicalAddress;
|
||||
Mapping1->VirtualAddress = VirtualAddress;
|
||||
Mapping1->NumberOfPages = NumberOfPages;
|
||||
Mapping1->MemoryType = MemoryType;
|
||||
|
||||
/* Calculate the end of the physical address */
|
||||
PhysicalAddressEnd = (PVOID)((ULONG_PTR)PhysicalAddress + (NumberOfPages * EFI_PAGE_SIZE) - 1);
|
||||
|
||||
/* Iterate through all the mappings already set to insert new mapping at the correct place */
|
||||
ListEntry = PageMap->MemoryMap.Flink;
|
||||
while(ListEntry != &PageMap->MemoryMap)
|
||||
{
|
||||
/* Take a mapping from the list and calculate its end of physical address */
|
||||
Mapping2 = CONTAIN_RECORD(ListEntry, XTBL_MEMORY_MAPPING, ListEntry);
|
||||
PhysicalAddress2End = (PVOID)((ULONG_PTR)Mapping2->PhysicalAddress + (Mapping2->NumberOfPages * EFI_PAGE_SIZE) - 1);
|
||||
|
||||
/* Check if new mapping is a subset of an existing mapping */
|
||||
if(Mapping1->PhysicalAddress >= Mapping2->PhysicalAddress && PhysicalAddressEnd <= PhysicalAddress2End)
|
||||
{
|
||||
/* Make sure it's memory type is the same */
|
||||
if(Mapping1->MemoryType == Mapping2->MemoryType)
|
||||
{
|
||||
/* It is already mapped */
|
||||
return STATUS_EFI_SUCCESS;
|
||||
}
|
||||
}
|
||||
|
||||
/* Check if they overlap */
|
||||
if(PhysicalAddressEnd > Mapping2->PhysicalAddress && PhysicalAddressEnd <= PhysicalAddress2End)
|
||||
{
|
||||
/* Make sure it's memory type is LoaderFree */
|
||||
if(Mapping2->MemoryType != LoaderFree)
|
||||
{
|
||||
/* LoaderFree memory type is strictly expected */
|
||||
return STATUS_EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
/* Calculate number of pages for this mapping */
|
||||
NumberOfMappedPages = ((PUCHAR)PhysicalAddress2End - (PUCHAR)PhysicalAddressEnd) / EFI_PAGE_SIZE;
|
||||
if(NumberOfMappedPages > 0)
|
||||
{
|
||||
/* Pages associated to the mapping, allocate memory for it */
|
||||
Status = AllocatePool(sizeof(XTBL_MEMORY_MAPPING), (PVOID*)&Mapping3);
|
||||
if(Status != STATUS_EFI_SUCCESS)
|
||||
{
|
||||
/* Memory allocation failure */
|
||||
return Status;
|
||||
}
|
||||
|
||||
/* Set mapping fields and insert it on the top */
|
||||
Mapping3->PhysicalAddress = (PUCHAR)PhysicalAddressEnd + 1;
|
||||
Mapping3->VirtualAddress = NULLPTR;
|
||||
Mapping3->NumberOfPages = NumberOfMappedPages;
|
||||
Mapping3->MemoryType = Mapping2->MemoryType;
|
||||
RTL::LinkedList::InsertHeadList(&Mapping2->ListEntry, &Mapping3->ListEntry);
|
||||
}
|
||||
|
||||
/* Calculate number of pages and the end of the physical address */
|
||||
Mapping2->NumberOfPages = ((PUCHAR)PhysicalAddressEnd + 1 -
|
||||
(PUCHAR)Mapping2->PhysicalAddress) / EFI_PAGE_SIZE;
|
||||
PhysicalAddress2End = (PVOID)((ULONG_PTR)Mapping2->PhysicalAddress + (Mapping2->NumberOfPages * EFI_PAGE_SIZE) - 1);
|
||||
}
|
||||
|
||||
/* Check if they overlap */
|
||||
if(Mapping1->PhysicalAddress > Mapping2->PhysicalAddress && Mapping1->PhysicalAddress < PhysicalAddress2End)
|
||||
{
|
||||
/* Make sure it's memory type is LoaderFree */
|
||||
if(Mapping2->MemoryType != LoaderFree)
|
||||
{
|
||||
/* LoaderFree memory type is strictly expected */
|
||||
return STATUS_EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
/* Calculate number of pages for this mapping */
|
||||
NumberOfMappedPages = ((PUCHAR)PhysicalAddress2End + 1 - (PUCHAR)Mapping1->PhysicalAddress) / EFI_PAGE_SIZE;
|
||||
if(NumberOfMappedPages > 0)
|
||||
{
|
||||
/* Pages associated to the mapping, allocate memory for it */
|
||||
Status = AllocatePool(sizeof(XTBL_MEMORY_MAPPING), (PVOID*)&Mapping3);
|
||||
if(Status != STATUS_EFI_SUCCESS)
|
||||
{
|
||||
/* Memory allocation failure */
|
||||
return Status;
|
||||
}
|
||||
|
||||
/* Set mapping fields and insert it on the top */
|
||||
Mapping3->PhysicalAddress = Mapping1->PhysicalAddress;
|
||||
Mapping3->VirtualAddress = NULLPTR;
|
||||
Mapping3->NumberOfPages = NumberOfMappedPages;
|
||||
Mapping3->MemoryType = Mapping2->MemoryType;
|
||||
RTL::LinkedList::InsertHeadList(&Mapping2->ListEntry, &Mapping3->ListEntry);
|
||||
}
|
||||
|
||||
/* Calculate number of pages and the end of the physical address */
|
||||
Mapping2->NumberOfPages = ((PUCHAR)Mapping1->PhysicalAddress -
|
||||
(PUCHAR)Mapping2->PhysicalAddress) / EFI_PAGE_SIZE;
|
||||
PhysicalAddress2End = (PVOID)((ULONG_PTR)Mapping2->PhysicalAddress + (Mapping2->NumberOfPages * EFI_PAGE_SIZE) - 1);
|
||||
}
|
||||
|
||||
/* Check if mapping is really needed */
|
||||
if((Mapping2->PhysicalAddress >= Mapping1->PhysicalAddress && PhysicalAddress2End <= PhysicalAddressEnd) ||
|
||||
(Mapping2->NumberOfPages == 0))
|
||||
{
|
||||
/* Make sure it's memory type is LoaderFree */
|
||||
if(Mapping2->MemoryType != LoaderFree)
|
||||
{
|
||||
/* LoaderFree memory type is strictly expected */
|
||||
return STATUS_EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
/* Store address of the next mapping */
|
||||
MappingListEntry = ListEntry->Flink;
|
||||
|
||||
/* Remove mapping from the list and free up it's memory */
|
||||
RTL::LinkedList::RemoveEntryList(&Mapping2->ListEntry);
|
||||
Status = FreePool(Mapping2);
|
||||
ListEntry = MappingListEntry;
|
||||
|
||||
/* Go to the next mapping */
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Determine physical address order */
|
||||
if(Mapping2->PhysicalAddress > Mapping1->PhysicalAddress)
|
||||
{
|
||||
/* Insert new mapping in front */
|
||||
RTL::LinkedList::InsertHeadList(Mapping2->ListEntry.Blink, &Mapping1->ListEntry);
|
||||
return STATUS_EFI_SUCCESS;
|
||||
}
|
||||
|
||||
/* Get next mapping from the list */
|
||||
ListEntry = ListEntry->Flink;
|
||||
}
|
||||
|
||||
/* Insert new mapping to the list and increase page map size */
|
||||
RTL::LinkedList::InsertTailList(&PageMap->MemoryMap, &Mapping1->ListEntry);
|
||||
PageMap->MapSize++;
|
||||
|
||||
/* Return success */
|
||||
return STATUS_EFI_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts physical address to virtual address based on physical base and virtual base.
|
||||
*
|
||||
* @param PhysicalAddress
|
||||
* Specifies physical address that will be converted to virtual address.
|
||||
*
|
||||
* @param PhysicalBase
|
||||
* Supplies a physical base address.
|
||||
*
|
||||
* @param VirtualBase
|
||||
* Supplies a virtual base address.
|
||||
*
|
||||
* @return This routine returns a mapped virtual address.
|
||||
*
|
||||
* @since XT 1.0
|
||||
*/
|
||||
XTCDECL
|
||||
PVOID
|
||||
Memory::PhysicalAddressToVirtual(IN PVOID PhysicalAddress,
|
||||
IN PVOID PhysicalBase,
|
||||
IN PVOID VirtualBase)
|
||||
{
|
||||
/* Convert physical address to virtual address */
|
||||
return (PUCHAR)VirtualBase + ((PUCHAR)PhysicalAddress - (PUCHAR)PhysicalBase);
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts whole linked list addressing from physical to virtual for future use after enabling paging.
|
||||
*
|
||||
* @param PageMap
|
||||
* Supplies a pointer to the page mapping structure.
|
||||
*
|
||||
* @param ListHead
|
||||
* Supplies a pointer to a structure that serves as the list header.
|
||||
*
|
||||
* @param PhysicalBase
|
||||
* Supplies a physical base address.
|
||||
*
|
||||
* @param VirtualBase
|
||||
* Supplies a virtual base address.
|
||||
*
|
||||
* @return This routine returns a status code.
|
||||
*
|
||||
* @since XT 1.0
|
||||
*/
|
||||
XTCDECL
|
||||
EFI_STATUS
|
||||
Memory::PhysicalListToVirtual(IN PXTBL_PAGE_MAPPING PageMap,
|
||||
IN OUT PLIST_ENTRY ListHead,
|
||||
IN PVOID PhysicalBase,
|
||||
IN PVOID VirtualBase)
|
||||
{
|
||||
PLIST_ENTRY ListEntry, NextEntry;
|
||||
|
||||
/* Make sure list is properly initialized */
|
||||
if(ListHead->Flink == 0 || ListHead->Blink == 0)
|
||||
{
|
||||
/* List not initialized, return error code */
|
||||
return STATUS_EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
/* Iterate through all elements */
|
||||
ListEntry = ListHead->Flink;
|
||||
while(ListEntry != ListHead)
|
||||
{
|
||||
/* Save physical address of the next element */
|
||||
NextEntry = ListEntry->Flink;
|
||||
|
||||
/* Convert the address of this element to VirtualAddress */
|
||||
if(ListEntry->Blink == ListHead)
|
||||
{
|
||||
/* Find virtual address of list head */
|
||||
ListEntry->Blink = (PLIST_ENTRY)GetVirtualAddress(PageMap, ListEntry->Blink);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Convert list entry */
|
||||
ListEntry->Blink = (PLIST_ENTRY)PhysicalAddressToVirtual(ListEntry->Blink, (PVOID)PhysicalBase, VirtualBase);
|
||||
}
|
||||
if(ListEntry->Flink == ListHead)
|
||||
{
|
||||
/* Convert list head */
|
||||
ListEntry->Flink = ListHead->Flink->Blink;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Convert list entry */
|
||||
ListEntry->Flink = (PLIST_ENTRY)PhysicalAddressToVirtual(ListEntry->Flink, (PVOID)PhysicalBase, VirtualBase);
|
||||
}
|
||||
|
||||
/* Get to the next element*/
|
||||
ListEntry = NextEntry;
|
||||
}
|
||||
|
||||
/* Convert list head */
|
||||
ListHead->Blink = (PLIST_ENTRY)PhysicalAddressToVirtual(ListHead->Blink, (PVOID)PhysicalBase, VirtualBase);
|
||||
ListHead->Flink = (PLIST_ENTRY)PhysicalAddressToVirtual(ListHead->Flink, (PVOID)PhysicalBase, VirtualBase);
|
||||
|
||||
/* Return success */
|
||||
return STATUS_EFI_SUCCESS;
|
||||
}
|
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);
|
||||
}
|
1112
boot/xtldr/protocol.cc
Normal file
1112
boot/xtldr/protocol.cc
Normal file
File diff suppressed because it is too large
Load Diff
50
boot/xtldr/shell.cc
Normal file
50
boot/xtldr/shell.cc
Normal file
@@ -0,0 +1,50 @@
|
||||
/**
|
||||
* PROJECT: ExectOS
|
||||
* COPYRIGHT: See COPYING.md in the top level directory
|
||||
* FILE: xtldr/shell.cc
|
||||
* DESCRIPTION: XT Boot Loader shell
|
||||
* DEVELOPERS: Rafal Kupiec <belliash@codingworkshop.eu.org>
|
||||
*/
|
||||
|
||||
#include <xtldr.hh>
|
||||
|
||||
|
||||
/**
|
||||
* Starts XTLDR shell.
|
||||
*
|
||||
* @return This routine does not return any value.
|
||||
*
|
||||
* @since XT 1.0
|
||||
*/
|
||||
XTCDECL
|
||||
VOID
|
||||
Shell::StartLoaderShell()
|
||||
{
|
||||
/* Initialize console */
|
||||
Console::InitializeConsole();
|
||||
|
||||
/* Print prompt */
|
||||
PrintPrompt();
|
||||
for(;;);
|
||||
}
|
||||
|
||||
/**
|
||||
* Prints XTLDR shell prompt.
|
||||
*
|
||||
* @return This routine does not return any value.
|
||||
*
|
||||
* @since XT 1.0
|
||||
*/
|
||||
XTCDECL
|
||||
VOID
|
||||
Shell::PrintPrompt()
|
||||
{
|
||||
/* Set prompt color */
|
||||
Console::SetAttributes(EFI_TEXT_BGCOLOR_BLACK | EFI_TEXT_FGCOLOR_YELLOW);
|
||||
|
||||
/* Print prompt */
|
||||
Console::Print(L"XTLDR> ");
|
||||
|
||||
/* Reset standard shell colors */
|
||||
Console::SetAttributes(EFI_TEXT_BGCOLOR_BLACK | EFI_TEXT_FGCOLOR_LIGHTGRAY);
|
||||
}
|
1815
boot/xtldr/textui.cc
Normal file
1815
boot/xtldr/textui.cc
Normal file
File diff suppressed because it is too large
Load Diff
1163
boot/xtldr/volume.cc
Normal file
1163
boot/xtldr/volume.cc
Normal file
File diff suppressed because it is too large
Load Diff
328
boot/xtldr/xtldr.cc
Normal file
328
boot/xtldr/xtldr.cc
Normal file
@@ -0,0 +1,328 @@
|
||||
/**
|
||||
* PROJECT: ExectOS
|
||||
* COPYRIGHT: See COPYING.md in the top level directory
|
||||
* FILE: xtldr/xtldr.cc
|
||||
* DESCRIPTION: XTOS UEFI Boot Loader
|
||||
* DEVELOPERS: Rafal Kupiec <belliash@codingworkshop.eu.org>
|
||||
*/
|
||||
|
||||
#include <xtldr.hh>
|
||||
|
||||
|
||||
/**
|
||||
* Disables access to EFI Boot Services.
|
||||
*
|
||||
* @return This routine does not return any value.
|
||||
*
|
||||
* @since XT 1.0
|
||||
*/
|
||||
XTCDECL
|
||||
VOID
|
||||
XtLoader::DisableBootServices()
|
||||
{
|
||||
LoaderStatus.BootServices = FALSE;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Queries the availability of EFI Boot Services.
|
||||
*
|
||||
* @return This routine returns TRUE if EFI Boot Services are available, FALSE otherwise.
|
||||
*
|
||||
* @since XT 1.0
|
||||
*/
|
||||
XTCDECL
|
||||
BOOLEAN
|
||||
XtLoader::GetBootServicesStatus()
|
||||
{
|
||||
return LoaderStatus.BootServices;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the EFI image handle.
|
||||
*
|
||||
* @return This routine returns a handle to the EFI-loaded image.
|
||||
*
|
||||
* @since XT 1.0
|
||||
*/
|
||||
XTCDECL
|
||||
EFI_HANDLE
|
||||
XtLoader::GetEfiImageHandle()
|
||||
{
|
||||
return XtLoader::EfiImageHandle;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the EFI system table pointer.
|
||||
*
|
||||
* @return This routine returns a pointer to the EFI system table.
|
||||
*
|
||||
* @since XT 1.0
|
||||
*/
|
||||
XTCDECL
|
||||
PEFI_SYSTEM_TABLE
|
||||
XtLoader::GetEfiSystemTable()
|
||||
{
|
||||
return XtLoader::EfiSystemTable;
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides base address and size of the XTLDR image.
|
||||
*
|
||||
* @param LoaderBase
|
||||
* Supplies a pointer to a variable that receives the base address of the XTLDR image.
|
||||
*
|
||||
* @param LoaderSize
|
||||
* Supplies a pointer to a variable that receives the size of the XTLDR image.
|
||||
*
|
||||
* @return This routine does not return any value.
|
||||
*
|
||||
* @since XT 1.0
|
||||
*/
|
||||
XTCDECL
|
||||
VOID
|
||||
XtLoader::GetLoaderImageInformation(PVOID *LoaderBase,
|
||||
PULONGLONG LoaderSize)
|
||||
{
|
||||
*LoaderBase = XtLoader::LoaderStatus.LoaderBase;
|
||||
*LoaderSize = XtLoader::LoaderStatus.LoaderSize;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the Secure Boot status.
|
||||
*
|
||||
* @return This routine returns SecureBoot status.
|
||||
*
|
||||
* @since XT 1.0
|
||||
*/
|
||||
XTCDECL
|
||||
INT_PTR
|
||||
XtLoader::GetSecureBootStatus()
|
||||
{
|
||||
return LoaderStatus.SecureBoot;
|
||||
}
|
||||
|
||||
/**
|
||||
* Initializes EFI Boot Loader (XTLDR).
|
||||
*
|
||||
* @return This routine does not return any value.
|
||||
*
|
||||
* @since XT 1.0
|
||||
*/
|
||||
XTCDECL
|
||||
VOID
|
||||
XtLoader::InitializeBootLoader(IN EFI_HANDLE ImageHandle,
|
||||
IN PEFI_SYSTEM_TABLE SystemTable)
|
||||
{
|
||||
EFI_GUID LipGuid = EFI_LOADED_IMAGE_PROTOCOL_GUID;
|
||||
PEFI_LOADED_IMAGE_PROTOCOL LoadedImage;
|
||||
EFI_HANDLE Handle;
|
||||
EFI_STATUS Status;
|
||||
|
||||
/* Set the system table and image handle */
|
||||
EfiImageHandle = ImageHandle;
|
||||
EfiSystemTable = SystemTable;
|
||||
|
||||
/* Set current XTLDR's EFI BootServices status */
|
||||
LoaderStatus.BootServices = TRUE;
|
||||
|
||||
/* Initialize console */
|
||||
Console::InitializeConsole();
|
||||
|
||||
/* Print XTLDR version */
|
||||
Console::Print(L"XTLDR boot loader v%s\n", XTOS_VERSION);
|
||||
|
||||
/* Initialize XTLDR protocol */
|
||||
Protocol::InitializeProtocol();
|
||||
|
||||
/* Initialize XTLDR configuration */
|
||||
Configuration::InitializeConfiguration();
|
||||
|
||||
/* Store SecureBoot status */
|
||||
LoaderStatus.SecureBoot = EfiUtils::GetSecureBootStatus();
|
||||
|
||||
/* Attempt to open EFI LoadedImage protocol */
|
||||
Status = Protocol::OpenProtocol(&Handle, (PVOID *)&LoadedImage, &LipGuid);
|
||||
if(Status == STATUS_EFI_SUCCESS)
|
||||
{
|
||||
/* Store boot loader image base and size */
|
||||
LoaderStatus.LoaderBase = LoadedImage->ImageBase;
|
||||
LoaderStatus.LoaderSize = LoadedImage->ImageSize;
|
||||
|
||||
/* Check if debug is enabled */
|
||||
if(DEBUG)
|
||||
{
|
||||
/* Protocol opened successfully, print useful debug information */
|
||||
Console::Print(L"\n---------- BOOTLOADER DEBUG ----------\n"
|
||||
L"Pointer Size : %d\n"
|
||||
L"Image Base Address : %P\n"
|
||||
L"Image Base Size : 0x%lX\n"
|
||||
L"Image Revision : 0x%lX\n"
|
||||
L"Secure Boot Status : %zd\n"
|
||||
L"--------------------------------------\n",
|
||||
sizeof(PVOID),
|
||||
LoadedImage->ImageBase,
|
||||
LoadedImage->ImageSize,
|
||||
LoadedImage->Revision,
|
||||
LoaderStatus.SecureBoot);
|
||||
EfiUtils::SleepExecution(3000);
|
||||
}
|
||||
|
||||
/* Close EFI LoadedImage protocol */
|
||||
Protocol::CloseProtocol(&Handle, &LipGuid);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers a boot menu callback routine, that will be used to display alternative boot menu.
|
||||
*
|
||||
* @param BootMenuRoutine
|
||||
* Supplies a pointer to the boot menu callback routine.
|
||||
*
|
||||
* @return This routine does not return any value.
|
||||
*
|
||||
* @since XT 1.0
|
||||
*/
|
||||
XTCDECL
|
||||
VOID
|
||||
XtLoader::RegisterBootMenu(IN PVOID BootMenuRoutine)
|
||||
{
|
||||
/* Set boot menu routine */
|
||||
BootMenu = (PBL_XT_BOOT_MENU)BootMenuRoutine;
|
||||
}
|
||||
|
||||
/**
|
||||
* Invokes either a custom boot menu handler, if one has been registered, or displays the default boot menu.
|
||||
*
|
||||
* @return This routine does not return any value.
|
||||
*
|
||||
* @since XT 1.0
|
||||
*/
|
||||
XTCDECL
|
||||
VOID
|
||||
XtLoader::ShowBootMenu()
|
||||
{
|
||||
/* Check if custom boot menu registered */
|
||||
if(BootMenu != NULLPTR)
|
||||
{
|
||||
/* Display alternative boot menu */
|
||||
BootMenu();
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Display default boot menu */
|
||||
TextUi::DisplayBootMenu();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This routine is the entry point of the XT EFI boot loader.
|
||||
*
|
||||
* @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
|
||||
BlStartXtLoader(IN EFI_HANDLE ImageHandle,
|
||||
IN PEFI_SYSTEM_TABLE SystemTable)
|
||||
{
|
||||
PWCHAR Modules;
|
||||
EFI_STATUS Status;
|
||||
|
||||
/* Initialize XTLDR and */
|
||||
XtLoader::InitializeBootLoader(ImageHandle, SystemTable);
|
||||
|
||||
/* Parse configuration options passed from UEFI shell */
|
||||
Status = Configuration::ParseCommandLine();
|
||||
if(Status != STATUS_EFI_SUCCESS)
|
||||
{
|
||||
/* Failed to parse command line options */
|
||||
TextUi::DisplayErrorDialog(L"XTLDR", L"Failed to parse command line parameters.");
|
||||
}
|
||||
|
||||
/* Attempt to early initialize debug console */
|
||||
if(DEBUG)
|
||||
{
|
||||
Status = Debug::InitializeDebugConsole();
|
||||
if(Status != STATUS_EFI_SUCCESS)
|
||||
{
|
||||
/* Initialization failed, notify user on stdout */
|
||||
TextUi::DisplayErrorDialog(L"XTLDR", L"Failed to initialize debug console.");
|
||||
}
|
||||
}
|
||||
|
||||
/* Load XTLDR configuration file */
|
||||
Status = Configuration::LoadConfiguration();
|
||||
if(Status != STATUS_EFI_SUCCESS)
|
||||
{
|
||||
/* Failed to load/parse config file */
|
||||
TextUi::DisplayErrorDialog(L"XTLDR", L"Failed to load and parse configuration file ");
|
||||
}
|
||||
|
||||
/* Reinitialize debug console if it was not initialized earlier */
|
||||
if(DEBUG)
|
||||
{
|
||||
Status = Debug::InitializeDebugConsole();
|
||||
if(Status != STATUS_EFI_SUCCESS)
|
||||
{
|
||||
/* Initialization failed, notify user on stdout */
|
||||
TextUi::DisplayErrorDialog(L"XTLDR", L"Failed to initialize debug console.");
|
||||
}
|
||||
}
|
||||
|
||||
/* Disable watchdog timer */
|
||||
Status = XtLoader::GetEfiSystemTable()->BootServices->SetWatchdogTimer(0, 0x10000, 0, NULLPTR);
|
||||
if(Status != STATUS_EFI_SUCCESS)
|
||||
{
|
||||
/* Failed to disable the timer, print message */
|
||||
Debug::Print(L"WARNING: Failed to disable watchdog timer (Status Code: 0x%zX)\n", Status);
|
||||
}
|
||||
|
||||
/* Install loader protocol */
|
||||
Status = Protocol::InstallXtLoaderProtocol();
|
||||
if(Status != STATUS_EFI_SUCCESS)
|
||||
{
|
||||
/* Failed to register loader protocol */
|
||||
Debug::Print(L"ERROR: Failed to register XTLDR loader protocol (Status Code: 0x%zX)\n", Status);
|
||||
return Status;
|
||||
}
|
||||
|
||||
/* Load all necessary modules */
|
||||
Configuration::GetValue(L"MODULES", &Modules);
|
||||
Status = Protocol::LoadModules(Modules);
|
||||
if(Status != STATUS_EFI_SUCCESS)
|
||||
{
|
||||
/* Failed to load modules */
|
||||
Debug::Print(L"ERROR: Failed to load XTLDR modules (Status Code: 0x%zX)\n", Status);
|
||||
TextUi::DisplayErrorDialog(L"XTLDR", L"Failed to load some XTLDR modules.");
|
||||
}
|
||||
|
||||
/* Discover and enumerate EFI block devices */
|
||||
Status = Volume::EnumerateBlockDevices();
|
||||
if(Status != STATUS_EFI_SUCCESS)
|
||||
{
|
||||
/* Failed to enumerate block devices */
|
||||
Debug::Print(L"ERROR: Failed to discover and enumerate block devices (Status Code: 0x%zX)\n", Status);
|
||||
return Status;
|
||||
}
|
||||
|
||||
/* Main boot loader loop */
|
||||
while(TRUE)
|
||||
{
|
||||
/* Show boot menu */
|
||||
XtLoader::ShowBootMenu();
|
||||
|
||||
/* Fallback to shell, if boot menu returned */
|
||||
Shell::StartLoaderShell();
|
||||
}
|
||||
|
||||
/* This point should be never reached, if this happen return error code */
|
||||
return STATUS_EFI_LOAD_ERROR;
|
||||
}
|
Reference in New Issue
Block a user