Replace obsolete bootloader code, since new one can already start XTOS kernel
This commit is contained in:
parent
297ac1acf6
commit
2f8820a021
@ -70,5 +70,5 @@ set_disk_image_size(128)
|
|||||||
|
|
||||||
# Build all subprojects
|
# Build all subprojects
|
||||||
add_subdirectory(bootdata)
|
add_subdirectory(bootdata)
|
||||||
add_subdirectory(xtldr2)
|
add_subdirectory(xtldr)
|
||||||
add_subdirectory(xtoskrnl)
|
add_subdirectory(xtoskrnl)
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
# XT Boot Loader
|
# XT Boot Manager
|
||||||
PROJECT(XTLDR)
|
PROJECT(XTLDR)
|
||||||
|
|
||||||
# Build XTLDR modules
|
# Build XTLDR modules
|
||||||
@ -9,19 +9,29 @@ include_directories(
|
|||||||
${EXECTOS_SOURCE_DIR}/sdk/xtdk
|
${EXECTOS_SOURCE_DIR}/sdk/xtdk
|
||||||
${XTLDR_SOURCE_DIR}/includes)
|
${XTLDR_SOURCE_DIR}/includes)
|
||||||
|
|
||||||
|
# Specify list of library source code files
|
||||||
|
list(APPEND LIBXTLDR_SOURCE
|
||||||
|
${XTLDR_SOURCE_DIR}/library/modproto.c)
|
||||||
|
|
||||||
# Specify list of source code files
|
# Specify list of source code files
|
||||||
list(APPEND XTLDR_SOURCE
|
list(APPEND XTLDR_SOURCE
|
||||||
${XTLDR_SOURCE_DIR}/${ARCH}/memory.c
|
${XTLDR_SOURCE_DIR}/config.c
|
||||||
${XTLDR_SOURCE_DIR}/blproto.c
|
|
||||||
${XTLDR_SOURCE_DIR}/console.c
|
${XTLDR_SOURCE_DIR}/console.c
|
||||||
${XTLDR_SOURCE_DIR}/efiutil.c
|
${XTLDR_SOURCE_DIR}/debug.c
|
||||||
|
${XTLDR_SOURCE_DIR}/efiutils.c
|
||||||
${XTLDR_SOURCE_DIR}/globals.c
|
${XTLDR_SOURCE_DIR}/globals.c
|
||||||
|
${XTLDR_SOURCE_DIR}/hardware.c
|
||||||
${XTLDR_SOURCE_DIR}/memory.c
|
${XTLDR_SOURCE_DIR}/memory.c
|
||||||
|
${XTLDR_SOURCE_DIR}/protocol.c
|
||||||
|
${XTLDR_SOURCE_DIR}/shell.c
|
||||||
${XTLDR_SOURCE_DIR}/string.c
|
${XTLDR_SOURCE_DIR}/string.c
|
||||||
${XTLDR_SOURCE_DIR}/system.c
|
${XTLDR_SOURCE_DIR}/textui.c
|
||||||
${XTLDR_SOURCE_DIR}/volume.c
|
${XTLDR_SOURCE_DIR}/volume.c
|
||||||
${XTLDR_SOURCE_DIR}/xtldr.c)
|
${XTLDR_SOURCE_DIR}/xtldr.c)
|
||||||
|
|
||||||
|
# Link static XTLDR library
|
||||||
|
add_library(libxtldr ${LIBXTLDR_SOURCE})
|
||||||
|
|
||||||
# Link bootloader executable
|
# Link bootloader executable
|
||||||
add_executable(xtldr ${XTLDR_SOURCE})
|
add_executable(xtldr ${XTLDR_SOURCE})
|
||||||
|
|
||||||
@ -38,6 +48,7 @@ set_target_properties(xtldr PROPERTIES OUTPUT_NAME ${BINARY_NAME} SUFFIX .efi)
|
|||||||
set_install_target(xtldr efi/boot)
|
set_install_target(xtldr efi/boot)
|
||||||
|
|
||||||
# Set loader entrypoint and subsystem
|
# Set loader entrypoint and subsystem
|
||||||
set_imagebase(xtldr ${BASEADDRESS_XTLDR})
|
|
||||||
set_entrypoint(xtldr "BlStartXtLoader")
|
set_entrypoint(xtldr "BlStartXtLoader")
|
||||||
|
set_imagebase(xtldr ${BASEADDRESS_XTLDR})
|
||||||
|
set_linker_map(xtldr TRUE)
|
||||||
set_subsystem(xtldr efi_application)
|
set_subsystem(xtldr efi_application)
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
## XT Loader (XTLDR)
|
## XT Boot Manager (XTLDR)
|
||||||
The XTLDR, or XTOS Boot Loader, is an EFI (Extensible Firmware Interface) boot loader specifically designed for XTOS.
|
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,
|
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.
|
like old and deprecated BIOS.
|
||||||
|
@ -1,310 +0,0 @@
|
|||||||
/**
|
|
||||||
* PROJECT: ExectOS
|
|
||||||
* COPYRIGHT: See COPYING.md in the top level directory
|
|
||||||
* FILE: xtldr/amd64/memory.c
|
|
||||||
* DESCRIPTION: EFI memory management for AMD64 target
|
|
||||||
* DEVELOPERS: Rafal Kupiec <belliash@codingworkshop.eu.org>
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <xtbl.h>
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Builds the actual memory mapping page table and enables paging. This routine exits EFI boot services as well.
|
|
||||||
*
|
|
||||||
* @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.
|
|
||||||
*
|
|
||||||
* @param ImageProtocol
|
|
||||||
* A pointer to the EFI loaded image protocol with information about where in memory the loader code was placed.
|
|
||||||
*
|
|
||||||
* @param PtePointer
|
|
||||||
* Supplies a pointer to memory area containing a Page Table Entries (PTE).
|
|
||||||
*
|
|
||||||
* @return This routine returns a status code.
|
|
||||||
*
|
|
||||||
* @since XT 1.0
|
|
||||||
*/
|
|
||||||
XTCDECL
|
|
||||||
EFI_STATUS
|
|
||||||
BlEnablePaging(IN PLIST_ENTRY MemoryMappings,
|
|
||||||
IN PVOID VirtualAddress,
|
|
||||||
IN PEFI_LOADED_IMAGE_PROTOCOL ImageProtocol,
|
|
||||||
IN PVOID *PtePointer)
|
|
||||||
{
|
|
||||||
PLOADER_MEMORY_MAPPING Mapping;
|
|
||||||
EFI_PHYSICAL_ADDRESS Address;
|
|
||||||
PEFI_MEMORY_MAP MemoryMap;
|
|
||||||
PLIST_ENTRY ListEntry;
|
|
||||||
EFI_STATUS Status;
|
|
||||||
|
|
||||||
/* Allocate pages for PML4 */
|
|
||||||
Status = BlEfiMemoryAllocatePages(1, &Address);
|
|
||||||
if(Status != STATUS_EFI_SUCCESS)
|
|
||||||
{
|
|
||||||
/* Memory allocation failure */
|
|
||||||
return Status;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Assign and zero-fill memory used by page mappings */
|
|
||||||
*PtePointer = (PVOID)(UINT_PTR)Address;
|
|
||||||
RtlZeroMemory(*PtePointer, EFI_PAGE_SIZE);
|
|
||||||
|
|
||||||
/* Map XTLDR code */
|
|
||||||
Status = BlAddVirtualMemoryMapping(MemoryMappings, ImageProtocol->ImageBase, ImageProtocol->ImageBase,
|
|
||||||
EFI_SIZE_TO_PAGES(ImageProtocol->ImageSize), LoaderFirmwareTemporary);
|
|
||||||
if(Status != STATUS_EFI_SUCCESS)
|
|
||||||
{
|
|
||||||
/* Mapping the boot loader code failed */
|
|
||||||
return Status;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Add page mapping itself to memory mapping */
|
|
||||||
Status = BlAddVirtualMemoryMapping(MemoryMappings, NULL, *PtePointer, 1, LoaderMemoryData);
|
|
||||||
if(Status != STATUS_EFI_SUCCESS)
|
|
||||||
{
|
|
||||||
/* Mapping PML4 failed */
|
|
||||||
return Status;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Iterate through and map all the mappings*/
|
|
||||||
BlDbgPrint(L"Mapping and dumping EFI memory:\n");
|
|
||||||
ListEntry = MemoryMappings->Flink;
|
|
||||||
while(ListEntry != MemoryMappings)
|
|
||||||
{
|
|
||||||
/* Take mapping from the list */
|
|
||||||
Mapping = CONTAIN_RECORD(ListEntry, LOADER_MEMORY_MAPPING, ListEntry);
|
|
||||||
|
|
||||||
/* Check if virtual address is set */
|
|
||||||
if(Mapping->VirtualAddress)
|
|
||||||
{
|
|
||||||
/* Dump memory mapping */
|
|
||||||
BlDbgPrint(L" Type=%02lu, PhysicalBase=0x%016lx, VirtualBase=0x%016lx, Pages=%lu\n", Mapping->MemoryType,
|
|
||||||
Mapping->PhysicalAddress, Mapping->VirtualAddress, Mapping->NumberOfPages);
|
|
||||||
|
|
||||||
/* Map memory */
|
|
||||||
Status = BlMapVirtualMemory(MemoryMappings, (UINT_PTR)Mapping->VirtualAddress,
|
|
||||||
(UINT_PTR)Mapping->PhysicalAddress, Mapping->NumberOfPages, PtePointer);
|
|
||||||
if(Status != STATUS_EFI_SUCCESS)
|
|
||||||
{
|
|
||||||
/* Memory mapping failed */
|
|
||||||
return Status;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Take next element */
|
|
||||||
ListEntry = ListEntry->Flink;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Map zero page as well */
|
|
||||||
BlMapVirtualMemory(MemoryMappings, 0, 0, 1, PtePointer);
|
|
||||||
|
|
||||||
/* Allocate and zero-fill buffer for EFI memory map */
|
|
||||||
BlEfiMemoryAllocatePool(sizeof(EFI_MEMORY_MAP), (PVOID*)&MemoryMap);
|
|
||||||
RtlZeroMemory(MemoryMap, sizeof(EFI_MEMORY_MAP));
|
|
||||||
|
|
||||||
/* Get EFI memory map and prepare for exiting boot services */
|
|
||||||
BlDbgPrint(L"Exiting EFI boot services\n");
|
|
||||||
Status = BlGetMemoryMap(MemoryMap);
|
|
||||||
if(Status != STATUS_EFI_SUCCESS)
|
|
||||||
{
|
|
||||||
/* Unable to get memory map */
|
|
||||||
return Status;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Exit EFI Boot Services */
|
|
||||||
Status = EfiSystemTable->BootServices->ExitBootServices(EfiImageHandle, MemoryMap->MapKey);
|
|
||||||
if(Status != STATUS_EFI_SUCCESS)
|
|
||||||
{
|
|
||||||
/* Retry as UEFI spec says to do it twice */
|
|
||||||
Status = EfiSystemTable->BootServices->ExitBootServices(EfiImageHandle, MemoryMap->MapKey);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Check if exitted boot services successfully */
|
|
||||||
if(Status != STATUS_EFI_SUCCESS)
|
|
||||||
{
|
|
||||||
/* Failed to exit boot services */
|
|
||||||
BlDbgPrint(L"Failed to exit boot services (Status code: %lx)\n", Status);
|
|
||||||
return STATUS_EFI_ABORTED;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Write PML4 to CR3 */
|
|
||||||
ArWriteControlRegister(3, (UINT_PTR)*PtePointer);
|
|
||||||
|
|
||||||
/* Return success */
|
|
||||||
return STATUS_EFI_SUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This routine does the actual virtual memory mapping.
|
|
||||||
*
|
|
||||||
* @param MemoryMappings
|
|
||||||
* Supplies a pointer to linked list containing all memory mappings.
|
|
||||||
*
|
|
||||||
* @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.
|
|
||||||
*
|
|
||||||
* @param PaeExtension
|
|
||||||
* Specifies whether Physical Address Extension (PAE) is supported by the hardware. Not used on AMD64.
|
|
||||||
*
|
|
||||||
* @param PtePointer
|
|
||||||
* Supplies a pointer to an array of pointers to page table entries.
|
|
||||||
*
|
|
||||||
* @return This routine returns a status code.
|
|
||||||
*
|
|
||||||
* @since XT 1.0
|
|
||||||
*/
|
|
||||||
XTCDECL
|
|
||||||
EFI_STATUS
|
|
||||||
BlMapVirtualMemory(IN PLIST_ENTRY MemoryMappings,
|
|
||||||
IN UINT_PTR VirtualAddress,
|
|
||||||
IN UINT_PTR PhysicalAddress,
|
|
||||||
IN UINT NumberOfPages,
|
|
||||||
IN OUT PVOID *PtePointer)
|
|
||||||
{
|
|
||||||
PHARDWARE_PTE PageDirectoryPointTable, PageDirectory, PageTable;
|
|
||||||
UINT Pml4Index, PdpIndex, PdIndex, PtIndex;
|
|
||||||
EFI_PHYSICAL_ADDRESS Address;
|
|
||||||
UINT_PTR PageFrameNumber;
|
|
||||||
EFI_STATUS Status;
|
|
||||||
UINT64 Pointer;
|
|
||||||
|
|
||||||
/* Set the PFN */
|
|
||||||
PageFrameNumber = PhysicalAddress >> EFI_PAGE_SHIFT;
|
|
||||||
|
|
||||||
/* Do the recursive mapping */
|
|
||||||
while(NumberOfPages > 0)
|
|
||||||
{
|
|
||||||
/* Calculate indices from a virtual address */
|
|
||||||
Pml4Index = (VirtualAddress >> 39) & 0x1FF;
|
|
||||||
PdpIndex = (VirtualAddress >> 30) & 0x1FF;
|
|
||||||
PdIndex = (VirtualAddress >> 21) & 0x1FF;
|
|
||||||
PtIndex = (VirtualAddress >> 12) & 0x1FF;
|
|
||||||
|
|
||||||
/* Validate Page Map Level 4 (PML4) */
|
|
||||||
if(!((PHARDWARE_PTE)(*PtePointer))[Pml4Index].Valid)
|
|
||||||
{
|
|
||||||
/* Allocate pages for the PDPT */
|
|
||||||
Status = BlEfiMemoryAllocatePages(1, &Address);
|
|
||||||
if (Status != STATUS_EFI_SUCCESS) {
|
|
||||||
/* Memory allocation failure */
|
|
||||||
return Status;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Add new memory mapping */
|
|
||||||
Status = BlAddVirtualMemoryMapping(MemoryMappings, NULL, (PVOID)(UINT_PTR)Address, 1, LoaderMemoryData);
|
|
||||||
if(Status != STATUS_EFI_SUCCESS) {
|
|
||||||
/* Memory mapping failed */
|
|
||||||
return Status;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Fill allocated memory with zeros */
|
|
||||||
RtlZeroMemory((PVOID)(UINT_PTR)Address, EFI_PAGE_SIZE);
|
|
||||||
|
|
||||||
/* Set paging entry settings */
|
|
||||||
((PHARDWARE_PTE)(*PtePointer))[Pml4Index].PageFrameNumber = Address / EFI_PAGE_SIZE;
|
|
||||||
((PHARDWARE_PTE)(*PtePointer))[Pml4Index].Valid = 1;
|
|
||||||
((PHARDWARE_PTE)(*PtePointer))[Pml4Index].Write = 1;
|
|
||||||
PageDirectoryPointTable = (PHARDWARE_PTE)(UINT_PTR)Address;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
/* Find Page Directory Point Table (PDPT) */
|
|
||||||
Pointer = ((PHARDWARE_PTE)(*PtePointer))[Pml4Index].PageFrameNumber;
|
|
||||||
Pointer <<= EFI_PAGE_SHIFT;
|
|
||||||
PageDirectoryPointTable = (PHARDWARE_PTE)(UINT_PTR)Pointer;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Validate Page Directory Point Table (PDPT)*/
|
|
||||||
if(!PageDirectoryPointTable[PdpIndex].Valid)
|
|
||||||
{
|
|
||||||
/* Allocate pages for the PD */
|
|
||||||
Status = BlEfiMemoryAllocatePages(1, &Address);
|
|
||||||
if (Status != STATUS_EFI_SUCCESS) {
|
|
||||||
/* Memory allocation failure */
|
|
||||||
return Status;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Add new memory mapping */
|
|
||||||
Status = BlAddVirtualMemoryMapping(MemoryMappings, NULL, (PVOID)(UINT_PTR)Address, 1, LoaderMemoryData);
|
|
||||||
if (Status != STATUS_EFI_SUCCESS) {
|
|
||||||
/* Memory mapping failed */
|
|
||||||
return Status;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Fill allocated memory with zeros */
|
|
||||||
RtlZeroMemory((PVOID)(UINT_PTR)Address, EFI_PAGE_SIZE);
|
|
||||||
|
|
||||||
/* Set paging entry settings */
|
|
||||||
PageDirectoryPointTable[PdpIndex].PageFrameNumber = Address / EFI_PAGE_SIZE;
|
|
||||||
PageDirectoryPointTable[PdpIndex].Valid = 1;
|
|
||||||
PageDirectoryPointTable[PdpIndex].Write = 1;
|
|
||||||
PageDirectory = (PHARDWARE_PTE)(UINT_PTR)Address;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
/* Find Page Directory (PD) */
|
|
||||||
Pointer = PageDirectoryPointTable[PdpIndex].PageFrameNumber;
|
|
||||||
Pointer <<= EFI_PAGE_SHIFT;
|
|
||||||
PageDirectory = (PHARDWARE_PTE)(UINT_PTR)Pointer;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Validate Page Directory (PD)*/
|
|
||||||
if(!PageDirectory[PdIndex].Valid)
|
|
||||||
{
|
|
||||||
/* Allocate pages for the PT */
|
|
||||||
Status = BlEfiMemoryAllocatePages(1, &Address);
|
|
||||||
if (Status != STATUS_EFI_SUCCESS) {
|
|
||||||
/* Memory allocation failure */
|
|
||||||
return Status;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Add new memory mapping */
|
|
||||||
Status = BlAddVirtualMemoryMapping(MemoryMappings, NULL, (PVOID)(UINT_PTR)Address, 1, LoaderMemoryData);
|
|
||||||
if (Status != STATUS_EFI_SUCCESS) {
|
|
||||||
/* Memory mapping failed */
|
|
||||||
return Status;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Fill allocated memory with zeros */
|
|
||||||
RtlZeroMemory((PVOID)(UINT_PTR)Address, EFI_PAGE_SIZE);
|
|
||||||
|
|
||||||
/* Set paging entry settings */
|
|
||||||
PageDirectory[PdIndex].PageFrameNumber = Address / EFI_PAGE_SIZE;
|
|
||||||
PageDirectory[PdIndex].Valid = 1;
|
|
||||||
PageDirectory[PdIndex].Write = 1;
|
|
||||||
PageTable = (PHARDWARE_PTE)(UINT_PTR)Address;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
/* Find Page Table (PT) */
|
|
||||||
Pointer = PageDirectory[PdIndex].PageFrameNumber;
|
|
||||||
Pointer <<= EFI_PAGE_SHIFT;
|
|
||||||
PageTable = (PHARDWARE_PTE)(UINT_PTR)Pointer;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Set paging entry settings */
|
|
||||||
PageTable[PtIndex].PageFrameNumber = PageFrameNumber;
|
|
||||||
PageTable[PtIndex].Valid = 1;
|
|
||||||
PageTable[PtIndex].Write = 1;
|
|
||||||
|
|
||||||
/* Take next virtual address and PFN */
|
|
||||||
VirtualAddress += EFI_PAGE_SIZE;
|
|
||||||
PageFrameNumber++;
|
|
||||||
|
|
||||||
/* Decrease number of pages left */
|
|
||||||
NumberOfPages--;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Return success */
|
|
||||||
return STATUS_EFI_SUCCESS;
|
|
||||||
}
|
|
@ -1,96 +0,0 @@
|
|||||||
/**
|
|
||||||
* PROJECT: ExectOS
|
|
||||||
* COPYRIGHT: See COPYING.md in the top level directory
|
|
||||||
* FILE: xtldr/blproto.c
|
|
||||||
* DESCRIPTION: EFI XTLDR protocol API
|
|
||||||
* DEVELOPERS: Rafal Kupiec <belliash@codingworkshop.eu.org>
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <xtbl.h>
|
|
||||||
#include <blproto.h>
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This routine locates and opens the XT boot loader protocol.
|
|
||||||
*
|
|
||||||
* @param LdrProtocol
|
|
||||||
* Supplies the address where a pointer to the loader protocol is returned.
|
|
||||||
*
|
|
||||||
* @return This routine returns status code.
|
|
||||||
*
|
|
||||||
* @since XT 1.0
|
|
||||||
*/
|
|
||||||
XTCDECL
|
|
||||||
EFI_STATUS
|
|
||||||
BlGetXtLoaderProtocol(OUT PXT_BOOT_LOADER_PROTOCOL *LdrProtocol)
|
|
||||||
{
|
|
||||||
EFI_GUID Guid = XT_BOOT_LOADER_PROTOCOL_GUID;
|
|
||||||
|
|
||||||
/* Load XTLDR protocol */
|
|
||||||
return BlLoadXtProtocol((PVOID *)LdrProtocol, &Guid);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This routine locates and opens the requested XT protocol.
|
|
||||||
*
|
|
||||||
* @param ProtocolHandler
|
|
||||||
* Supplies the address where a pointer to the opened protocol is returned.
|
|
||||||
*
|
|
||||||
* @param ProtocolGuid
|
|
||||||
* Supplies a pointer to the unique protocol GUID.
|
|
||||||
*
|
|
||||||
* @return This routine returns status code.
|
|
||||||
*
|
|
||||||
* @since XT 1.0
|
|
||||||
*/
|
|
||||||
XTCDECL
|
|
||||||
EFI_STATUS
|
|
||||||
BlLoadXtProtocol(OUT PVOID *ProtocolHandler,
|
|
||||||
IN PEFI_GUID ProtocolGuid)
|
|
||||||
{
|
|
||||||
PEFI_HANDLE Handles = NULL;
|
|
||||||
EFI_STATUS Status;
|
|
||||||
UINT_PTR Count;
|
|
||||||
UINT Index;
|
|
||||||
|
|
||||||
/* Try to locate the handles */
|
|
||||||
Status = EfiSystemTable->BootServices->LocateHandleBuffer(ByProtocol, ProtocolGuid, NULL, &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 = EfiSystemTable->BootServices->OpenProtocol(Handles[Index], ProtocolGuid,
|
|
||||||
ProtocolHandler, EfiImageHandle, NULL,
|
|
||||||
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 */
|
|
||||||
EfiSystemTable->BootServices->FreePool(Handles);
|
|
||||||
|
|
||||||
/* Make sure the loaded protocol has been found */
|
|
||||||
if(*ProtocolHandler == NULL)
|
|
||||||
{
|
|
||||||
/* Protocol not found */
|
|
||||||
return STATUS_EFI_NOT_FOUND;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Return success */
|
|
||||||
return STATUS_EFI_SUCCESS;
|
|
||||||
}
|
|
260
xtldr/console.c
260
xtldr/console.c
@ -6,9 +6,37 @@
|
|||||||
* DEVELOPERS: Rafal Kupiec <belliash@codingworkshop.eu.org>
|
* DEVELOPERS: Rafal Kupiec <belliash@codingworkshop.eu.org>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <xtbl.h>
|
#include <xtldr.h>
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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
|
||||||
|
BlClearConsoleLine(IN ULONGLONG LineNo)
|
||||||
|
{
|
||||||
|
UINT_PTR Index, ResX, ResY;
|
||||||
|
|
||||||
|
/* Query console mode */
|
||||||
|
BlQueryConsoleMode(&ResX, &ResY);
|
||||||
|
|
||||||
|
/* Set cursor position and clear line */
|
||||||
|
BlSetCursorPosition(0, LineNo);
|
||||||
|
for(Index = 0; Index < ResX; Index++)
|
||||||
|
{
|
||||||
|
/* Clear line */
|
||||||
|
BlConsoleWrite(L" ");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This routine clears the UEFI console screen.
|
* This routine clears the UEFI console screen.
|
||||||
*
|
*
|
||||||
@ -18,34 +46,205 @@
|
|||||||
*/
|
*/
|
||||||
XTCDECL
|
XTCDECL
|
||||||
VOID
|
VOID
|
||||||
BlConsoleClearScreen()
|
BlClearConsoleScreen()
|
||||||
{
|
{
|
||||||
|
/* Clear screen */
|
||||||
EfiSystemTable->ConOut->ClearScreen(EfiSystemTable->ConOut);
|
EfiSystemTable->ConOut->ClearScreen(EfiSystemTable->ConOut);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This routine initializes the EFI console.
|
* Disables the cursor on the UEFI console.
|
||||||
*
|
*
|
||||||
* @return This routine returns status code.
|
* @return This routine does not return any value.
|
||||||
*
|
*
|
||||||
* @since XT 1.0
|
* @since XT 1.0
|
||||||
*/
|
*/
|
||||||
XTCDECL
|
XTCDECL
|
||||||
VOID
|
VOID
|
||||||
BlConsoleInitialize()
|
BlDisableConsoleCursor()
|
||||||
{
|
{
|
||||||
/* Clear console buffers */
|
EfiSystemTable->ConOut->EnableCursor(EfiSystemTable->ConOut, FALSE);
|
||||||
EfiSystemTable->ConIn->Reset(EfiSystemTable->ConIn, TRUE);
|
}
|
||||||
EfiSystemTable->ConOut->Reset(EfiSystemTable->ConOut, TRUE);
|
|
||||||
EfiSystemTable->StdErr->Reset(EfiSystemTable->StdErr, TRUE);
|
|
||||||
|
|
||||||
/* Clear screen */
|
/**
|
||||||
BlConsoleClearScreen();
|
* Enables the cursor on the UEFI console.
|
||||||
|
*
|
||||||
/* Enable cursor */
|
* @return This routine does not return any value.
|
||||||
|
*
|
||||||
|
* @since XT 1.0
|
||||||
|
*/
|
||||||
|
XTCDECL
|
||||||
|
VOID
|
||||||
|
BlEnableConsoleCursor()
|
||||||
|
{
|
||||||
EfiSystemTable->ConOut->EnableCursor(EfiSystemTable->ConOut, TRUE);
|
EfiSystemTable->ConOut->EnableCursor(EfiSystemTable->ConOut, TRUE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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
|
||||||
|
BlConsolePrint(IN PUINT16 Format,
|
||||||
|
IN ...)
|
||||||
|
{
|
||||||
|
VA_LIST Arguments;
|
||||||
|
|
||||||
|
/* Initialise the va_list */
|
||||||
|
VA_START(Arguments, Format);
|
||||||
|
|
||||||
|
/* Format and print the string to the stdout */
|
||||||
|
BlpStringPrint(BlpConsolePrintChar, Format, Arguments);
|
||||||
|
|
||||||
|
/* Print to serial console only if not running under OVMF */
|
||||||
|
if(RtlCompareWideString(EfiSystemTable->FirmwareVendor, L"EDK II", 6) != 0)
|
||||||
|
{
|
||||||
|
/* Check if debugging enabled and if EFI serial port is fully initialized */
|
||||||
|
if(DEBUG && (BlpStatus.SerialPort.Flags & COMPORT_FLAG_INIT))
|
||||||
|
{
|
||||||
|
/* Format and print the string to the serial console */
|
||||||
|
BlpStringPrint(BlpDebugPutChar, Format, Arguments);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Clean up the va_list */
|
||||||
|
VA_END(Arguments);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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
|
||||||
|
BlConsoleWrite(IN PUSHORT String)
|
||||||
|
{
|
||||||
|
EfiSystemTable->ConOut->OutputString(EfiSystemTable->ConOut, String);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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
|
||||||
|
BlQueryConsoleMode(OUT PUINT_PTR ResX,
|
||||||
|
OUT PUINT_PTR ResY)
|
||||||
|
{
|
||||||
|
EfiSystemTable->ConOut->QueryMode(EfiSystemTable->ConOut, EfiSystemTable->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
|
||||||
|
BlReadKeyStroke(OUT PEFI_INPUT_KEY Key)
|
||||||
|
{
|
||||||
|
EfiSystemTable->ConIn->ReadKeyStroke(EfiSystemTable->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
|
||||||
|
BlResetConsoleInputBuffer()
|
||||||
|
{
|
||||||
|
EfiSystemTable->ConIn->Reset(EfiSystemTable->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
|
||||||
|
BlSetConsoleAttributes(IN ULONGLONG Attributes)
|
||||||
|
{
|
||||||
|
EfiSystemTable->ConOut->SetAttribute(EfiSystemTable->ConOut, Attributes);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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
|
||||||
|
BlSetConsoleMode(IN ULONGLONG Mode)
|
||||||
|
{
|
||||||
|
return EfiSystemTable->ConOut->SetMode(EfiSystemTable->ConOut, Mode);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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
|
||||||
|
BlSetCursorPosition(IN ULONGLONG PosX,
|
||||||
|
IN ULONGLONG PosY)
|
||||||
|
{
|
||||||
|
EfiSystemTable->ConOut->SetCursorPosition(EfiSystemTable->ConOut, PosX, PosY);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Writes a character to the default EFI console.
|
* Writes a character to the default EFI console.
|
||||||
*
|
*
|
||||||
@ -58,7 +257,7 @@ BlConsoleInitialize()
|
|||||||
*/
|
*/
|
||||||
XTCDECL
|
XTCDECL
|
||||||
VOID
|
VOID
|
||||||
BlConsolePutChar(IN USHORT Character)
|
BlpConsolePrintChar(IN USHORT Character)
|
||||||
{
|
{
|
||||||
USHORT Buffer[2];
|
USHORT Buffer[2];
|
||||||
|
|
||||||
@ -67,3 +266,32 @@ BlConsolePutChar(IN USHORT Character)
|
|||||||
Buffer[1] = 0;
|
Buffer[1] = 0;
|
||||||
EfiSystemTable->ConOut->OutputString(EfiSystemTable->ConOut, Buffer);
|
EfiSystemTable->ConOut->OutputString(EfiSystemTable->ConOut, Buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This routine initializes the EFI console.
|
||||||
|
*
|
||||||
|
* @return This routine returns status code.
|
||||||
|
*
|
||||||
|
* @since XT 1.0
|
||||||
|
*/
|
||||||
|
XTCDECL
|
||||||
|
VOID
|
||||||
|
BlpInitializeConsole()
|
||||||
|
{
|
||||||
|
/* Clear console buffers */
|
||||||
|
EfiSystemTable->ConIn->Reset(EfiSystemTable->ConIn, TRUE);
|
||||||
|
EfiSystemTable->ConOut->Reset(EfiSystemTable->ConOut, TRUE);
|
||||||
|
EfiSystemTable->StdErr->Reset(EfiSystemTable->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(EfiSystemTable->ConOut->Mode->Mode != 0)
|
||||||
|
{
|
||||||
|
/* Set console mode to 0, which is standard, 80x25 text mode */
|
||||||
|
BlSetConsoleMode(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Clear screen and enable cursor */
|
||||||
|
BlClearConsoleScreen();
|
||||||
|
BlEnableConsoleCursor();
|
||||||
|
}
|
||||||
|
364
xtldr/efiutil.c
364
xtldr/efiutil.c
@ -1,364 +0,0 @@
|
|||||||
/**
|
|
||||||
* PROJECT: ExectOS
|
|
||||||
* COPYRIGHT: See COPYING.md in the top level directory
|
|
||||||
* FILE: xtldr/efiutil.c
|
|
||||||
* DESCRIPTION: EFI utilities
|
|
||||||
* DEVELOPERS: Rafal Kupiec <belliash@codingworkshop.eu.org>
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <xtbl.h>
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 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
|
|
||||||
BlActivateSerialControllerIO()
|
|
||||||
{
|
|
||||||
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 = NULL;
|
|
||||||
PCI_COMMON_HEADER PciHeader;
|
|
||||||
EFI_STATUS Status;
|
|
||||||
UINT64 Address;
|
|
||||||
|
|
||||||
/* Allocate memory for single EFI_HANDLE, what should be enough in most cases */
|
|
||||||
PciHandleSize = sizeof(EFI_HANDLE);
|
|
||||||
Status = BlEfiMemoryAllocatePool(PciHandleSize, (PVOID*)&PciHandle);
|
|
||||||
if(Status != STATUS_EFI_SUCCESS)
|
|
||||||
{
|
|
||||||
/* Memory allocation failure */
|
|
||||||
return Status;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Get all instances of PciRootBridgeIo */
|
|
||||||
Status = EfiSystemTable->BootServices->LocateHandle(ByProtocol, &PciGuid, NULL, &PciHandleSize, PciHandle);
|
|
||||||
if(Status == STATUS_EFI_BUFFER_TOO_SMALL)
|
|
||||||
{
|
|
||||||
/* Reallocate more memory as requested by UEFI */
|
|
||||||
BlEfiMemoryFreePool(PciHandle);
|
|
||||||
Status = BlEfiMemoryAllocatePool(PciHandleSize, (PVOID*)&PciHandle);
|
|
||||||
if(Status != STATUS_EFI_SUCCESS)
|
|
||||||
{
|
|
||||||
/* Memory reallocation failure */
|
|
||||||
return Status;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Second attempt to get instances of PciRootBridgeIo */
|
|
||||||
Status = EfiSystemTable->BootServices->LocateHandle(ByProtocol, &PciGuid, NULL, &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 = EfiSystemTable->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 = ((UINT64)((((UINT_PTR) Bus) << 24) + (((UINT_PTR) Device) << 16) +
|
|
||||||
(((UINT_PTR) Function) << 8) + ((UINT_PTR) 0)));
|
|
||||||
PciDev->Pci.Read(PciDev, 2, Address, sizeof (PciHeader) / sizeof (UINT32), &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, 1, Address, 1, &Command);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Return SUCCESS */
|
|
||||||
return STATUS_EFI_SUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This routine initializes the COM port debug console.
|
|
||||||
*
|
|
||||||
* @return This routine returns a status code.
|
|
||||||
*
|
|
||||||
* @since XT 1.0
|
|
||||||
*/
|
|
||||||
XTCDECL
|
|
||||||
EFI_STATUS
|
|
||||||
BlComPortInitialize()
|
|
||||||
{
|
|
||||||
EFI_GUID LIPGuid = EFI_LOADED_IMAGE_PROTOCOL_GUID;
|
|
||||||
PEFI_LOADED_IMAGE_PROTOCOL LoadedImage;
|
|
||||||
ULONG PortAddress, PortNumber, BaudRate;
|
|
||||||
PWCHAR Argument, CommandLine, LastArg;
|
|
||||||
EFI_STATUS EfiStatus;
|
|
||||||
XTSTATUS Status;
|
|
||||||
|
|
||||||
/* Set default serial port options */
|
|
||||||
PortAddress = 0;
|
|
||||||
PortNumber = 0;
|
|
||||||
BaudRate = 0;
|
|
||||||
|
|
||||||
/* Handle loaded image protocol */
|
|
||||||
EfiStatus = EfiSystemTable->BootServices->HandleProtocol(EfiImageHandle, &LIPGuid, (PVOID *)&LoadedImage);
|
|
||||||
if(EfiStatus == STATUS_EFI_SUCCESS)
|
|
||||||
{
|
|
||||||
|
|
||||||
/* Check if launched from UEFI shell */
|
|
||||||
if(LoadedImage && LoadedImage->LoadOptions)
|
|
||||||
{
|
|
||||||
/* Store arguments passed from UEFI shell */
|
|
||||||
CommandLine = (PWCHAR)LoadedImage->LoadOptions;
|
|
||||||
|
|
||||||
/* Find command in command line */
|
|
||||||
Argument = RtlTokenizeWideString(CommandLine, L" ", &LastArg);
|
|
||||||
|
|
||||||
/* Iterate over all arguments passed to boot loader */
|
|
||||||
while(Argument != NULL)
|
|
||||||
{
|
|
||||||
/* Check if this is DEBUG parameter */
|
|
||||||
if(RtlCompareWideString(Argument, L"DEBUG=", 6) == 0)
|
|
||||||
{
|
|
||||||
/* Skip to the argument value */
|
|
||||||
Argument += 6;
|
|
||||||
|
|
||||||
/* Make sure COM port is being used */
|
|
||||||
if(RtlCompareWideString(Argument, L"COM", 3))
|
|
||||||
{
|
|
||||||
/* Invalid debug port specified */
|
|
||||||
BlEfiPrint(L"ERROR: Invalid debug port specified, falling back to defaults\n");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Read COM port number */
|
|
||||||
Argument += 3;
|
|
||||||
while(*Argument >= '0' && *Argument <= '9')
|
|
||||||
{
|
|
||||||
/* Get port number */
|
|
||||||
PortNumber *= 10;
|
|
||||||
PortNumber += *Argument - '0';
|
|
||||||
Argument++;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Check if custom COM port address supplied */
|
|
||||||
if(PortNumber == 0 && RtlCompareWideString(Argument, L":0x", 3) == 0)
|
|
||||||
{
|
|
||||||
/* COM port address provided */
|
|
||||||
Argument += 3;
|
|
||||||
while((*Argument >= '0' && *Argument <= '9') ||
|
|
||||||
(*Argument >= 'A' && *Argument <= 'F') ||
|
|
||||||
(*Argument >= 'a' && *Argument <= 'f'))
|
|
||||||
{
|
|
||||||
/* Get port address */
|
|
||||||
PortAddress *= 16;
|
|
||||||
if(*Argument >= '0' && *Argument <= '9')
|
|
||||||
{
|
|
||||||
PortAddress += *Argument - '0';
|
|
||||||
}
|
|
||||||
else if(*Argument >= 'A' && *Argument <= 'F')
|
|
||||||
{
|
|
||||||
PortAddress += *Argument - 'A' + 10;
|
|
||||||
}
|
|
||||||
else if(*Argument >= 'a' && *Argument <= 'f')
|
|
||||||
{
|
|
||||||
PortAddress += *Argument - 'a' + 10;
|
|
||||||
}
|
|
||||||
Argument++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Look for additional COM port parameters */
|
|
||||||
if(*Argument == ',')
|
|
||||||
{
|
|
||||||
/* Baud rate provided */
|
|
||||||
Argument++;
|
|
||||||
while(*Argument >= '0' && *Argument <= '9')
|
|
||||||
{
|
|
||||||
/* Get baud rate */
|
|
||||||
BaudRate *= 10;
|
|
||||||
BaudRate += *Argument - '0';
|
|
||||||
Argument++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* No need to check next arguments */
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Take next argument */
|
|
||||||
Argument = RtlTokenizeWideString(NULL, L" ", &LastArg);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Print debug message depending on port settings */
|
|
||||||
if(PortAddress)
|
|
||||||
{
|
|
||||||
BlEfiPrint(L"Initializing serial console at COM port address: 0x%lx\n", PortAddress);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
BlEfiPrint(L"Initializing serial console at port COM%d\n", PortNumber);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Initialize COM port */
|
|
||||||
Status = HlInitializeComPort(&EfiSerialPort, PortNumber, 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 = BlActivateSerialControllerIO();
|
|
||||||
if(EfiStatus == STATUS_EFI_SUCCESS)
|
|
||||||
{
|
|
||||||
/* Try to reinitialize COM port */
|
|
||||||
BlEfiPrint(L"Enabled I/O space access for all PCI(E) serial controllers found\n");
|
|
||||||
Status = HlInitializeComPort(&EfiSerialPort, PortNumber, 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;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Writes a character to the serial console.
|
|
||||||
*
|
|
||||||
* @param Character
|
|
||||||
* The integer promotion of the character to be written.
|
|
||||||
*
|
|
||||||
* @return This routine does not return any value.
|
|
||||||
*
|
|
||||||
* @since XT 1.0
|
|
||||||
*/
|
|
||||||
XTCDECL
|
|
||||||
VOID
|
|
||||||
BlComPortPutChar(IN USHORT Character)
|
|
||||||
{
|
|
||||||
USHORT Buffer[2];
|
|
||||||
|
|
||||||
/* Write character to the serial console */
|
|
||||||
Buffer[0] = Character;
|
|
||||||
Buffer[1] = 0;
|
|
||||||
|
|
||||||
HlComPortPutByte(&EfiSerialPort, Buffer[0]);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This routine formats the input string and prints it out to the 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
|
|
||||||
BlDbgPrint(IN PUINT16 Format,
|
|
||||||
IN ...)
|
|
||||||
{
|
|
||||||
VA_LIST Arguments;
|
|
||||||
|
|
||||||
/* Check if debugging enabled and if EFI serial port is fully initialized */
|
|
||||||
if(DEBUG && (EfiSerialPort.Flags & COMPORT_FLAG_INIT))
|
|
||||||
{
|
|
||||||
/* Initialise the va_list */
|
|
||||||
VA_START(Arguments, Format);
|
|
||||||
|
|
||||||
/* Format and print the string to the serial console */
|
|
||||||
BlStringPrint(BlComPortPutChar, Format, Arguments);
|
|
||||||
|
|
||||||
/* Clean up the va_list */
|
|
||||||
VA_END(Arguments);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 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
|
|
||||||
*
|
|
||||||
* @todo Check if GOP is active and use it instead of default conout protocol
|
|
||||||
*/
|
|
||||||
XTCDECL
|
|
||||||
VOID
|
|
||||||
BlEfiPrint(IN PUINT16 Format,
|
|
||||||
IN ...)
|
|
||||||
{
|
|
||||||
VA_LIST Arguments;
|
|
||||||
|
|
||||||
/* Initialise the va_list */
|
|
||||||
VA_START(Arguments, Format);
|
|
||||||
|
|
||||||
/* Format and print the string to the stdout */
|
|
||||||
BlStringPrint(BlConsolePutChar, Format, Arguments);
|
|
||||||
|
|
||||||
/* Print to serial console only if not running under OVMF */
|
|
||||||
if(RtlCompareWideString(EfiSystemTable->FirmwareVendor, L"EDK II", 6) != 0)
|
|
||||||
{
|
|
||||||
/* Check if debugging enabled and if EFI serial port is fully initialized */
|
|
||||||
if(DEBUG && (EfiSerialPort.Flags & COMPORT_FLAG_INIT))
|
|
||||||
{
|
|
||||||
/* Format and print the string to the serial console */
|
|
||||||
BlStringPrint(BlComPortPutChar, Format, Arguments);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Clean up the va_list */
|
|
||||||
VA_END(Arguments);
|
|
||||||
}
|
|
@ -6,26 +6,38 @@
|
|||||||
* DEVELOPERS: Rafal Kupiec <belliash@codingworkshop.eu.org>
|
* DEVELOPERS: Rafal Kupiec <belliash@codingworkshop.eu.org>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <xtbl.h>
|
#include <xtldr.h>
|
||||||
|
|
||||||
|
|
||||||
|
/* XT Boot Loader registered boot protocol list */
|
||||||
|
LIST_ENTRY BlpBootProtocols;
|
||||||
|
|
||||||
|
/* XT Boot Loader configuration list */
|
||||||
|
LIST_ENTRY BlpConfig;
|
||||||
|
|
||||||
|
/* XT Boot Loader loaded configuration */
|
||||||
|
LIST_ENTRY BlpConfigSections;
|
||||||
|
|
||||||
|
/* XT Boot Loader hex table */
|
||||||
|
STATIC PUINT16 BlpHexTable = L"0123456789ABCDEF";
|
||||||
|
|
||||||
|
/* XT Boot Loader protocol */
|
||||||
|
XTBL_LOADER_PROTOCOL BlpLdrProtocol;
|
||||||
|
|
||||||
|
/* XT Boot Loader loaded modules list */
|
||||||
|
LIST_ENTRY BlpLoadedModules;
|
||||||
|
|
||||||
|
/* XT Boot Loader menu list */
|
||||||
|
PLIST_ENTRY BlpMenuList = NULL;
|
||||||
|
|
||||||
|
/* XT Boot Loader status data */
|
||||||
|
XTBL_STATUS BlpStatus = {0};
|
||||||
|
|
||||||
/* List of available block devices */
|
/* List of available block devices */
|
||||||
LIST_ENTRY EfiBlockDevices;
|
LIST_ENTRY EfiBlockDevices;
|
||||||
|
|
||||||
/* XT Boot Loader hex table */
|
|
||||||
STATIC PUINT16 EfiHexTable = L"0123456789ABCDEF";
|
|
||||||
|
|
||||||
/* EFI Image Handle */
|
/* EFI Image Handle */
|
||||||
EFI_HANDLE EfiImageHandle;
|
EFI_HANDLE EfiImageHandle;
|
||||||
|
|
||||||
/* XT Boot Loader protocol */
|
|
||||||
XT_BOOT_LOADER_PROTOCOL EfiLdrProtocol;
|
|
||||||
|
|
||||||
/* EFI System Table */
|
/* EFI System Table */
|
||||||
PEFI_SYSTEM_TABLE EfiSystemTable;
|
PEFI_SYSTEM_TABLE EfiSystemTable;
|
||||||
|
|
||||||
/* EFI Secure Boot status */
|
|
||||||
INT_PTR EfiSecureBoot;
|
|
||||||
|
|
||||||
/* Serial port configuration */
|
|
||||||
CPPORT EfiSerialPort;
|
|
||||||
|
@ -1,334 +0,0 @@
|
|||||||
/**
|
|
||||||
* PROJECT: ExectOS
|
|
||||||
* COPYRIGHT: See COPYING.md in the top level directory
|
|
||||||
* FILE: xtldr/i686/memory.c
|
|
||||||
* DESCRIPTION: EFI memory management for i686 target
|
|
||||||
* DEVELOPERS: Rafal Kupiec <belliash@codingworkshop.eu.org>
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <xtbl.h>
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Builds the actual memory mapping page table and enables paging. This routine exits EFI boot services as well.
|
|
||||||
*
|
|
||||||
* @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.
|
|
||||||
*
|
|
||||||
* @param ImageProtocol
|
|
||||||
* A pointer to the EFI loaded image protocol with information about where in memory the loader code was placed.
|
|
||||||
*
|
|
||||||
* @param PtePointer
|
|
||||||
* Supplies a pointer to memory area containing a Page Table Entries (PTE).
|
|
||||||
*
|
|
||||||
* @return This routine returns a status code.
|
|
||||||
*
|
|
||||||
* @since XT 1.0
|
|
||||||
*/
|
|
||||||
XTCDECL
|
|
||||||
EFI_STATUS
|
|
||||||
BlEnablePaging(IN PLIST_ENTRY MemoryMappings,
|
|
||||||
IN PVOID VirtualAddress,
|
|
||||||
IN PEFI_LOADED_IMAGE_PROTOCOL ImageProtocol,
|
|
||||||
IN PVOID *PtePointer)
|
|
||||||
{
|
|
||||||
UINT_PTR PhysicalAddress, DescriptorCount;
|
|
||||||
EFI_PHYSICAL_ADDRESS Address, PDPTAddress = 0;
|
|
||||||
PCPUID_REGISTERS CpuRegisters = NULL;
|
|
||||||
PEFI_MEMORY_DESCRIPTOR Descriptor;
|
|
||||||
PLOADER_MEMORY_MAPPING Mapping;
|
|
||||||
PEFI_MEMORY_MAP MemoryMap;
|
|
||||||
PLIST_ENTRY ListEntry;
|
|
||||||
EFI_STATUS Status;
|
|
||||||
UINT Index;
|
|
||||||
|
|
||||||
/* Prepare CPUID registers */
|
|
||||||
CpuRegisters->Leaf = CPUID_GET_CPU_FEATURES;
|
|
||||||
CpuRegisters->SubLeaf = 0;
|
|
||||||
CpuRegisters->Eax = 0;
|
|
||||||
CpuRegisters->Ebx = 0;
|
|
||||||
CpuRegisters->Ecx = 0;
|
|
||||||
CpuRegisters->Edx = 0;
|
|
||||||
|
|
||||||
/* Get CPUID */
|
|
||||||
ArCpuId(CpuRegisters);
|
|
||||||
|
|
||||||
/* Store PAE status from the CPUID results */
|
|
||||||
if(!(CpuRegisters->Edx & CPUID_FEATURES_EDX_PAE))
|
|
||||||
{
|
|
||||||
/* No PAE support */
|
|
||||||
BlDbgPrint(L"ERROR: PAE extension not supported by the CPU\n");
|
|
||||||
return STATUS_EFI_UNSUPPORTED;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Allocate and zero-fill buffer for EFI memory map */
|
|
||||||
BlEfiMemoryAllocatePool(sizeof(EFI_MEMORY_MAP), (PVOID*)&MemoryMap);
|
|
||||||
RtlZeroMemory(MemoryMap, sizeof(EFI_MEMORY_MAP));
|
|
||||||
|
|
||||||
/* Get EFI memory map */
|
|
||||||
Status = BlGetMemoryMap(MemoryMap);
|
|
||||||
if(Status != STATUS_EFI_SUCCESS)
|
|
||||||
{
|
|
||||||
/* Unable to get memory map */
|
|
||||||
return Status;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Calculate descriptors count and get first one */
|
|
||||||
Descriptor = MemoryMap->Map;
|
|
||||||
DescriptorCount = MemoryMap->MapSize / MemoryMap->DescriptorSize;
|
|
||||||
|
|
||||||
/* Calculate physical address based on KSEG0 base */
|
|
||||||
PhysicalAddress = (UINT_PTR)VirtualAddress - KSEG0_BASE;
|
|
||||||
|
|
||||||
/* Iterate over all descriptors from memory map to find satisfying address for PDPT */
|
|
||||||
for(Index = 0; Index < DescriptorCount; Index++)
|
|
||||||
{
|
|
||||||
/* Check descriptor if it can be used to store PDPT */
|
|
||||||
if((Descriptor->PhysicalStart + ((Descriptor->NumberOfPages - 1) * EFI_PAGE_SIZE) >= PhysicalAddress) &&
|
|
||||||
(Descriptor->Type == EfiConventionalMemory))
|
|
||||||
{
|
|
||||||
/* Use highest address possible */
|
|
||||||
if(PhysicalAddress >= Descriptor->PhysicalStart)
|
|
||||||
{
|
|
||||||
/* Use physical address */
|
|
||||||
PDPTAddress = PhysicalAddress;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
/* Use descriptor physical start as PDPT address */
|
|
||||||
PDPTAddress = Descriptor->PhysicalStart;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Allocate pages for the PDPT address */
|
|
||||||
Status = BlEfiMemoryAllocatePages(1, &PDPTAddress);
|
|
||||||
if(Status != STATUS_EFI_SUCCESS) {
|
|
||||||
return Status;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Get next descriptor */
|
|
||||||
Descriptor = (EFI_MEMORY_DESCRIPTOR*)((UINT8*)Descriptor + MemoryMap->DescriptorSize);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Make sure PDPT address found */
|
|
||||||
if(PDPTAddress == 0)
|
|
||||||
{
|
|
||||||
/* No suitable area for PDPT found in EFI memory map */
|
|
||||||
return STATUS_EFI_NOT_FOUND;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Set virtual address based on new PDPT address mapped to KSEG0 base */
|
|
||||||
VirtualAddress = (PVOID)(UINT_PTR)(PDPTAddress + EFI_PAGE_SIZE + KSEG0_BASE);
|
|
||||||
|
|
||||||
/* Set base page frame number */
|
|
||||||
Address = 0x100000;
|
|
||||||
|
|
||||||
/* Allocate pages for the PFN */
|
|
||||||
Status = BlEfiMemoryAllocatePages(4, &Address);
|
|
||||||
if(Status != STATUS_EFI_SUCCESS)
|
|
||||||
{
|
|
||||||
/* Memory allocation failure */
|
|
||||||
return Status;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Set and zero memory used by page mappings and CR3 */
|
|
||||||
*PtePointer = (PVOID)(UINT_PTR)PDPTAddress;
|
|
||||||
RtlZeroMemory(*PtePointer, EFI_PAGE_SIZE);
|
|
||||||
RtlZeroMemory((PVOID)Address, EFI_PAGE_SIZE * 4);
|
|
||||||
|
|
||||||
/* Set the page directory into the PDPT and mark it present */
|
|
||||||
for(Index = 0; Index < 4; Index++)
|
|
||||||
{
|
|
||||||
/* Set paging entry settings */
|
|
||||||
((PHARDWARE_PTE)*PtePointer)[Index].PageFrameNumber = Address / EFI_PAGE_SIZE;
|
|
||||||
((PHARDWARE_PTE)*PtePointer)[Index].Valid = 1;
|
|
||||||
|
|
||||||
/* Next valid PFN address */
|
|
||||||
Address += EFI_PAGE_SIZE;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Map XTLDR code */
|
|
||||||
Status = BlAddVirtualMemoryMapping(MemoryMappings, ImageProtocol->ImageBase, ImageProtocol->ImageBase,
|
|
||||||
EFI_SIZE_TO_PAGES(ImageProtocol->ImageSize), LoaderFirmwareTemporary);
|
|
||||||
if(Status != STATUS_EFI_SUCCESS)
|
|
||||||
{
|
|
||||||
/* Mapping the boot loader code failed */
|
|
||||||
return Status;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Add page mapping itself to memory mapping */
|
|
||||||
Status = BlAddVirtualMemoryMapping(MemoryMappings, NULL, *PtePointer, 1, LoaderMemoryData);
|
|
||||||
if(Status != STATUS_EFI_SUCCESS)
|
|
||||||
{
|
|
||||||
/* Mapping PD failed */
|
|
||||||
return Status;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Iterate through and map all the mappings */
|
|
||||||
BlDbgPrint(L"Mapping and dumping EFI memory:\n");
|
|
||||||
ListEntry = MemoryMappings->Flink;
|
|
||||||
while(ListEntry != MemoryMappings)
|
|
||||||
{
|
|
||||||
/* Take mapping from the list */
|
|
||||||
Mapping = CONTAIN_RECORD(ListEntry, LOADER_MEMORY_MAPPING, ListEntry);
|
|
||||||
|
|
||||||
/* Check if virtual address is set */
|
|
||||||
if(Mapping->VirtualAddress)
|
|
||||||
{
|
|
||||||
/* Dump memory mapping */
|
|
||||||
BlDbgPrint(L" Type=%02lu, PhysicalBase=0x%08lx, VirtualBase=0x%08lx, Pages=%lu\n", Mapping->MemoryType,
|
|
||||||
Mapping->PhysicalAddress, Mapping->VirtualAddress, Mapping->NumberOfPages);
|
|
||||||
|
|
||||||
/* Map memory */
|
|
||||||
Status = BlMapVirtualMemory(MemoryMappings, (UINT_PTR)Mapping->VirtualAddress,
|
|
||||||
(UINT_PTR)Mapping->PhysicalAddress, Mapping->NumberOfPages, PtePointer);
|
|
||||||
if(Status != STATUS_EFI_SUCCESS)
|
|
||||||
{
|
|
||||||
/* Memory mapping failed */
|
|
||||||
return Status;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Take next element */
|
|
||||||
ListEntry = ListEntry->Flink;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Map zero page as well */
|
|
||||||
BlMapVirtualMemory(MemoryMappings, 0, 0, 1, PtePointer);
|
|
||||||
|
|
||||||
/* Zero-fill buffer for EFI memory map */
|
|
||||||
RtlZeroMemory(MemoryMap, sizeof(EFI_MEMORY_MAP));
|
|
||||||
|
|
||||||
/* Get EFI memory map and prepare for exiting boot services */
|
|
||||||
BlDbgPrint(L"Exiting EFI boot services\n");
|
|
||||||
Status = BlGetMemoryMap(MemoryMap);
|
|
||||||
if(Status != STATUS_EFI_SUCCESS)
|
|
||||||
{
|
|
||||||
/* Unable to get memory map */
|
|
||||||
return Status;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Exit EFI Boot Services */
|
|
||||||
Status = EfiSystemTable->BootServices->ExitBootServices(EfiImageHandle, MemoryMap->MapKey);
|
|
||||||
if(Status != STATUS_EFI_SUCCESS)
|
|
||||||
{
|
|
||||||
/* Retry as UEFI spec says to do it twice */
|
|
||||||
Status = EfiSystemTable->BootServices->ExitBootServices(EfiImageHandle, MemoryMap->MapKey);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Check if exitted boot services successfully */
|
|
||||||
if(Status != STATUS_EFI_SUCCESS)
|
|
||||||
{
|
|
||||||
/* Failed to exit boot services */
|
|
||||||
BlDbgPrint(L"Failed to exit boot services (Status code: %lx)\n", Status);
|
|
||||||
return STATUS_EFI_ABORTED;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Enable Physical Address Extension (PAE) */
|
|
||||||
ArWriteControlRegister(4, ArReadControlRegister(4) | CR4_PAE);
|
|
||||||
|
|
||||||
/* Write page mappings to CR3 */
|
|
||||||
ArWriteControlRegister(3, (UINT_PTR)*PtePointer);
|
|
||||||
|
|
||||||
/* Enable paging */
|
|
||||||
ArWriteControlRegister(0, ArReadControlRegister(0) | CR0_PG);
|
|
||||||
|
|
||||||
/* Return success */
|
|
||||||
return STATUS_EFI_SUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This routine does the actual virtual memory mapping.
|
|
||||||
*
|
|
||||||
* @param MemoryMappings
|
|
||||||
* Supplies a pointer to linked list containing all memory mappings.
|
|
||||||
*
|
|
||||||
* @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.
|
|
||||||
*
|
|
||||||
* @param PaeExtension
|
|
||||||
* Specifies whether Physical Address Extension (PAE) is supported by the hardware.
|
|
||||||
*
|
|
||||||
* @param PtePointer
|
|
||||||
* Supplies a pointer to an array of pointers to page table entries.
|
|
||||||
*
|
|
||||||
* @return This routine returns a status code.
|
|
||||||
*
|
|
||||||
* @since XT 1.0
|
|
||||||
*/
|
|
||||||
XTCDECL
|
|
||||||
EFI_STATUS
|
|
||||||
BlMapVirtualMemory(IN PLIST_ENTRY MemoryMappings,
|
|
||||||
IN UINT_PTR VirtualAddress,
|
|
||||||
IN UINT_PTR PhysicalAddress,
|
|
||||||
IN UINT NumberOfPages,
|
|
||||||
IN OUT PVOID *PtePointer)
|
|
||||||
{
|
|
||||||
EFI_PHYSICAL_ADDRESS Address;
|
|
||||||
UINT_PTR PageFrameNumber;
|
|
||||||
PHARDWARE_PTE PageTable, PageDirectory;
|
|
||||||
EFI_STATUS Status;
|
|
||||||
unsigned int PdIndex, PtIndex;
|
|
||||||
|
|
||||||
/* Set the PFN */
|
|
||||||
PageFrameNumber = PhysicalAddress >> EFI_PAGE_SHIFT;
|
|
||||||
|
|
||||||
/* Do the recursive mapping */
|
|
||||||
while(NumberOfPages > 0)
|
|
||||||
{
|
|
||||||
/* Find Page Directory and calculate indices from a virtual address */
|
|
||||||
PageDirectory = (PHARDWARE_PTE)(UINT_PTR)(((PHARDWARE_PTE)(*PtePointer))[VirtualAddress >> 30].PageFrameNumber * EFI_PAGE_SIZE);
|
|
||||||
PdIndex = (VirtualAddress >> 21) & 0x1FF;
|
|
||||||
PtIndex = (VirtualAddress & 0x1FF000) >> 12;
|
|
||||||
|
|
||||||
/* Validate Page Directory */
|
|
||||||
if(!PageDirectory[PdIndex].Valid) {
|
|
||||||
/* Allocate pages for new page table */
|
|
||||||
Status = BlEfiMemoryAllocatePages(1, &Address);
|
|
||||||
if(Status != STATUS_EFI_SUCCESS) {
|
|
||||||
/* Memory allocation failure */
|
|
||||||
return Status;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Fill allocated memory with zeros */
|
|
||||||
RtlZeroMemory((PVOID)(UINT_PTR)Address, EFI_PAGE_SIZE);
|
|
||||||
|
|
||||||
/* Set paging entry settings */
|
|
||||||
PageDirectory[PdIndex].PageFrameNumber = Address / EFI_PAGE_SIZE;
|
|
||||||
PageDirectory[PdIndex].Valid = 1;
|
|
||||||
PageDirectory[PdIndex].Write = 1;
|
|
||||||
|
|
||||||
/* Set page table */
|
|
||||||
PageTable = (PHARDWARE_PTE)(UINT_PTR)Address;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
/* Set page table */
|
|
||||||
PageTable = (PHARDWARE_PTE)(UINT_PTR)(PageDirectory[PdIndex].PageFrameNumber * EFI_PAGE_SIZE);
|
|
||||||
}
|
|
||||||
/* Set page table settings */
|
|
||||||
PageTable[PtIndex].PageFrameNumber = PageFrameNumber;
|
|
||||||
PageTable[PtIndex].Valid = 1;
|
|
||||||
PageTable[PtIndex].Write = 1;
|
|
||||||
|
|
||||||
/* Take next virtual address and PFN */
|
|
||||||
VirtualAddress += EFI_PAGE_SIZE;
|
|
||||||
PageFrameNumber++;
|
|
||||||
|
|
||||||
/* Decrease number of pages left */
|
|
||||||
NumberOfPages--;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Return success */
|
|
||||||
return STATUS_EFI_SUCCESS;
|
|
||||||
}
|
|
@ -1,22 +0,0 @@
|
|||||||
/**
|
|
||||||
* PROJECT: ExectOS
|
|
||||||
* COPYRIGHT: See COPYING.md in the top level directory
|
|
||||||
* FILE: xtldr/includes/bldefs.h
|
|
||||||
* DESCRIPTION: Definitions for the XT boot loader
|
|
||||||
* DEVELOPERS: Rafal Kupiec <belliash@codingworkshop.eu.org>
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef __XTLDR_BLDEFS_H
|
|
||||||
#define __XTLDR_BLDEFS_H
|
|
||||||
|
|
||||||
#include <xtkmapi.h>
|
|
||||||
|
|
||||||
|
|
||||||
/* EFI XT boot devices */
|
|
||||||
#define XT_BOOT_DEVICE_UNKNOWN 0x00
|
|
||||||
#define XT_BOOT_DEVICE_CDROM 0x01
|
|
||||||
#define XT_BOOT_DEVICE_FLOPPY 0x02
|
|
||||||
#define XT_BOOT_DEVICE_HARDDISK 0x03
|
|
||||||
#define XT_BOOT_DEVICE_RAMDISK 0x04
|
|
||||||
|
|
||||||
#endif /* __XTLDR_BLDEFS_H */
|
|
@ -1,94 +0,0 @@
|
|||||||
/**
|
|
||||||
* PROJECT: ExectOS
|
|
||||||
* COPYRIGHT: See COPYING.md in the top level directory
|
|
||||||
* FILE: xtldr/includes/blmod.h
|
|
||||||
* DESCRIPTION: Top level header for XTLDR modules support
|
|
||||||
* DEVELOPERS: Rafal Kupiec <belliash@codingworkshop.eu.org>
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef __XTLDR_BLMOD_H
|
|
||||||
#define __XTLDR_BLMOD_H
|
|
||||||
|
|
||||||
#include <xtkmapi.h>
|
|
||||||
#include <bldefs.h>
|
|
||||||
#include <blproto.h>
|
|
||||||
|
|
||||||
|
|
||||||
/* Structures forward declarations */
|
|
||||||
typedef struct _XT_BOOT_PROTOCOL XT_BOOT_PROTOCOL, *PXT_BOOT_PROTOCOL;
|
|
||||||
typedef struct _XT_BOOT_PROTOCOL_PARAMETERS XT_BOOT_PROTOCOL_PARAMETERS, *PXT_BOOT_PROTOCOL_PARAMETERS;
|
|
||||||
typedef struct _XT_PECOFFF_IMAGE_PROTOCOL XT_PECOFF_IMAGE_PROTOCOL, *PXT_PECOFF_IMAGE_PROTOCOL;
|
|
||||||
|
|
||||||
/* Pointers to the routines provided by the modules */
|
|
||||||
typedef EFI_STATUS (*PXT_BOOTPROTO_BOOT_SYSTEM)(IN PXT_BOOT_PROTOCOL_PARAMETERS Parameters);
|
|
||||||
typedef VOID (*PXT_FRAMEBUFFER_GET_DISPLAY_DRIVER)(OUT PWCHAR *DriverName);
|
|
||||||
typedef VOID (*PXT_FRAMEBUFFER_GET_DISPLAY_INFORMATION)(OUT PLOADER_GRAPHICS_INFORMATION_BLOCK InformationBlock);
|
|
||||||
typedef EFI_STATUS (*PXT_FRAMEBUFFER_INITIALIZE)();
|
|
||||||
typedef VOID (*PXT_FRAMEBUFFER_PRINT_DISPLAY_INFORMATION)();
|
|
||||||
typedef EFI_STATUS (*PXT_PECOFF_GET_ENTRY_POINT)(IN PPECOFF_IMAGE_CONTEXT Image, OUT PVOID *EntryPoint);
|
|
||||||
typedef EFI_STATUS (*PXT_PECOFF_GET_MACHINE_TYPE)(IN PPECOFF_IMAGE_CONTEXT Image, OUT PUSHORT MachineType);
|
|
||||||
typedef EFI_STATUS (*PXT_PECOFF_GET_SUBSYSTEM)(IN PPECOFF_IMAGE_CONTEXT Image, OUT PUSHORT SubSystem);
|
|
||||||
typedef EFI_STATUS (*PXT_PECOFF_LOAD_IMAGE)(IN PEFI_FILE_HANDLE FileHandle, IN LOADER_MEMORY_TYPE MemoryType,
|
|
||||||
IN PVOID VirtualAddress, OUT PPECOFF_IMAGE_CONTEXT *Image);
|
|
||||||
typedef EFI_STATUS (*PXT_PECOFF_RELOCATE_IMAGE)(IN PPECOFF_IMAGE_CONTEXT Image, IN EFI_VIRTUAL_ADDRESS Address);
|
|
||||||
|
|
||||||
|
|
||||||
/* XT common boot protocols */
|
|
||||||
typedef struct _XT_BOOT_PROTOCOL
|
|
||||||
{
|
|
||||||
PXT_BOOTPROTO_BOOT_SYSTEM BootSystem;
|
|
||||||
} XT_BOOT_PROTOCOL, *PXT_BOOT_PROTOCOL;
|
|
||||||
|
|
||||||
/* XT common boot protocol parameters */
|
|
||||||
typedef struct _XT_BOOT_PROTOCOL_PARAMETERS
|
|
||||||
{
|
|
||||||
PEFI_DEVICE_PATH_PROTOCOL DevicePath;
|
|
||||||
PWCHAR ArcName;
|
|
||||||
PWCHAR SystemPath;
|
|
||||||
PWCHAR KernelFile;
|
|
||||||
PWCHAR InitrdFile;
|
|
||||||
PWCHAR HalFile;
|
|
||||||
PWCHAR Arguments;
|
|
||||||
} XT_BOOT_PROTOCOL_PARAMETERS, *PXT_BOOT_PROTOCOL_PARAMETERS;
|
|
||||||
|
|
||||||
/* XT framebuffer support protocol */
|
|
||||||
typedef struct _XT_FRAMEBUFFER_PROTOCOL
|
|
||||||
{
|
|
||||||
PXT_FRAMEBUFFER_GET_DISPLAY_DRIVER GetDisplayDriver;
|
|
||||||
PXT_FRAMEBUFFER_GET_DISPLAY_INFORMATION GetDisplayInformation;
|
|
||||||
PXT_FRAMEBUFFER_INITIALIZE Initialize;
|
|
||||||
PXT_FRAMEBUFFER_PRINT_DISPLAY_INFORMATION PrintDisplayInformation;
|
|
||||||
} XT_FRAMEBUFFER_PROTOCOL, *PXT_FRAMEBUFFER_PROTOCOL;
|
|
||||||
|
|
||||||
/* XT framebuffer information structure definition */
|
|
||||||
typedef struct _XT_FRAMEBUFFER_INFORMATION
|
|
||||||
{
|
|
||||||
BOOLEAN Initialized;
|
|
||||||
EFI_GRAPHICS_PROTOCOL Protocol;
|
|
||||||
union
|
|
||||||
{
|
|
||||||
PEFI_GRAPHICS_OUTPUT_PROTOCOL GOP;
|
|
||||||
PEFI_UNIVERSAL_GRAPHICS_ADAPTER_PROTOCOL UGA;
|
|
||||||
} Adapter;
|
|
||||||
UINT HorizontalResolution;
|
|
||||||
UINT VerticalResolution;
|
|
||||||
UINT BitsPerPixel;
|
|
||||||
UINT BytesPerPixel;
|
|
||||||
UINT PixelsPerScanLine;
|
|
||||||
UINT Pitch;
|
|
||||||
EFI_GRAPHICS_PIXEL_FORMAT PixelFormat;
|
|
||||||
EFI_PHYSICAL_ADDRESS FrameBufferBase;
|
|
||||||
ULONG_PTR FrameBufferSize;
|
|
||||||
} XT_FRAMEBUFFER_INFORMATION, *PXT_FRAMEBUFFER_INFORMATION;
|
|
||||||
|
|
||||||
/* EFI XT PE/COFF Image Protocol */
|
|
||||||
typedef struct _XT_PECOFFF_IMAGE_PROTOCOL
|
|
||||||
{
|
|
||||||
PXT_PECOFF_GET_ENTRY_POINT GetEntryPoint;
|
|
||||||
PXT_PECOFF_GET_MACHINE_TYPE GetMachineType;
|
|
||||||
PXT_PECOFF_GET_SUBSYSTEM GetSubSystem;
|
|
||||||
PXT_PECOFF_LOAD_IMAGE Load;
|
|
||||||
PXT_PECOFF_RELOCATE_IMAGE Relocate;
|
|
||||||
} XT_PECOFF_IMAGE_PROTOCOL, *PXT_PECOFF_IMAGE_PROTOCOL;
|
|
||||||
|
|
||||||
#endif /* __XTLDR_BLMOD_H */
|
|
@ -1,62 +0,0 @@
|
|||||||
/**
|
|
||||||
* PROJECT: ExectOS
|
|
||||||
* COPYRIGHT: See COPYING.md in the top level directory
|
|
||||||
* FILE: xtldr/includes/blproto.h
|
|
||||||
* DESCRIPTION: XTLDR boot loader protocol support
|
|
||||||
* DEVELOPERS: Rafal Kupiec <belliash@codingworkshop.eu.org>
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef __XTLDR_BLPROTO_H
|
|
||||||
#define __XTLDR_BLPROTO_H
|
|
||||||
|
|
||||||
#include <xtkmapi.h>
|
|
||||||
#include <bldefs.h>
|
|
||||||
|
|
||||||
|
|
||||||
/* Loader protocol routine pointers */
|
|
||||||
typedef EFI_STATUS (*PBL_ADD_VIRTUAL_MEMORY_MAPPING)(IN PLIST_ENTRY MemoryMappings, IN PVOID VirtualAddress, IN PVOID PhysicalAddress, IN UINT NumberOfPages, IN LOADER_MEMORY_TYPE MemoryType);
|
|
||||||
typedef EFI_STATUS (*PBL_ALLOCATE_PAGES)(IN UINT64 Size, OUT PEFI_PHYSICAL_ADDRESS Memory);
|
|
||||||
typedef EFI_STATUS (*PBL_ALLOCATE_POOL)(IN UINT_PTR Size, OUT PVOID *Memory);
|
|
||||||
typedef EFI_STATUS (*PBL_ENABLE_PAGING)(IN PLIST_ENTRY MemoryMappings, IN PVOID VirtualAddress, IN PEFI_LOADED_IMAGE_PROTOCOL ImageProtocol, IN PVOID *PtePointer);
|
|
||||||
typedef EFI_STATUS (*PBL_FREE_PAGES)(IN UINT64 Size, IN EFI_PHYSICAL_ADDRESS Memory);
|
|
||||||
typedef EFI_STATUS (*PBL_FREE_POOL)(IN PVOID Memory);
|
|
||||||
typedef EFI_STATUS (*PBL_GET_MEMORY_MAP)(OUT PEFI_MEMORY_MAP MemoryMap);
|
|
||||||
typedef EFI_STATUS (*PBL_GET_VIRTUAL_ADDRESS)(IN PLIST_ENTRY MemoryMappings, IN PVOID PhysicalAddress, OUT PVOID *VirtualAddress);
|
|
||||||
typedef EFI_STATUS (*PBL_INIT_VIRTUAL_MEMORY)(IN OUT PLIST_ENTRY MemoryMappings, IN OUT PVOID *MemoryMapAddress);
|
|
||||||
typedef EFI_STATUS (*PBL_MAP_VIRTUAL_MEMORY)(IN PLIST_ENTRY MemoryMappings, IN UINT_PTR VirtualAddress, IN UINT_PTR PhysicalAddress, IN UINT NumberOfPages, IN OUT PVOID *PtePointer);
|
|
||||||
typedef VOID (*PBL_GET_STACK)(OUT PVOID *Stack);
|
|
||||||
typedef VOID (*PBL_DBG_PRINT)(IN PUINT16 Format, IN ...);
|
|
||||||
typedef VOID (*PBL_EFI_PRINT)(IN PUINT16 Format, IN ...);
|
|
||||||
typedef EFI_STATUS (*PBL_CLOSE_VOLUME)(IN PEFI_HANDLE VolumeHandle);
|
|
||||||
typedef EFI_STATUS (*PBL_OPEN_VOLUME)(IN PEFI_DEVICE_PATH_PROTOCOL DevicePath, OUT PEFI_HANDLE DiskHandle, OUT PEFI_FILE_HANDLE *FsHandle);
|
|
||||||
|
|
||||||
/* EFI XT Boot Loader Protocol */
|
|
||||||
typedef struct _XT_BOOT_LOADER_PROTOCOL
|
|
||||||
{
|
|
||||||
PBL_ADD_VIRTUAL_MEMORY_MAPPING AddVirtualMemoryMapping;
|
|
||||||
PBL_ALLOCATE_PAGES AllocatePages;
|
|
||||||
PBL_ALLOCATE_POOL AllocatePool;
|
|
||||||
PBL_FREE_PAGES FreePages;
|
|
||||||
PBL_FREE_POOL FreePool;
|
|
||||||
PBL_ENABLE_PAGING EnablePaging;
|
|
||||||
PBL_GET_MEMORY_MAP GetMemoryMap;
|
|
||||||
PBL_GET_VIRTUAL_ADDRESS GetVirtualAddress;
|
|
||||||
PBL_INIT_VIRTUAL_MEMORY InitializeVirtualMemory;
|
|
||||||
PBL_MAP_VIRTUAL_MEMORY MapVirtualMemory;
|
|
||||||
PBL_DBG_PRINT DbgPrint;
|
|
||||||
PBL_EFI_PRINT EfiPrint;
|
|
||||||
PBL_CLOSE_VOLUME CloseVolume;
|
|
||||||
PBL_OPEN_VOLUME OpenVolume;
|
|
||||||
} XT_BOOT_LOADER_PROTOCOL, *PXT_BOOT_LOADER_PROTOCOL;
|
|
||||||
|
|
||||||
/* Loader protocol related routines forward references */
|
|
||||||
XTCDECL
|
|
||||||
EFI_STATUS
|
|
||||||
BlGetXtLoaderProtocol(OUT PXT_BOOT_LOADER_PROTOCOL *LdrProtocol);
|
|
||||||
|
|
||||||
XTCDECL
|
|
||||||
EFI_STATUS
|
|
||||||
BlLoadXtProtocol(OUT PVOID *ProtocolHandler,
|
|
||||||
IN PEFI_GUID ProtocolGuid);
|
|
||||||
|
|
||||||
#endif /* __XTLDR_BLPROTO_H */
|
|
@ -1,264 +0,0 @@
|
|||||||
/**
|
|
||||||
* PROJECT: ExectOS
|
|
||||||
* COPYRIGHT: See COPYING.md in the top level directory
|
|
||||||
* FILE: xtldr/includes/xtbl.h
|
|
||||||
* DESCRIPTION: Top level header for XTLDR
|
|
||||||
* DEVELOPERS: Rafal Kupiec <belliash@codingworkshop.eu.org>
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef __XTLDR_XTBL_H
|
|
||||||
#define __XTLDR_XTBL_H
|
|
||||||
|
|
||||||
#include <xtkmapi.h>
|
|
||||||
#include <xtver.h>
|
|
||||||
#include <blmod.h>
|
|
||||||
|
|
||||||
|
|
||||||
/* List of available block devices */
|
|
||||||
EXTERN LIST_ENTRY EfiBlockDevices;
|
|
||||||
|
|
||||||
/* XT Boot Loader hex table */
|
|
||||||
EXTERN PUINT16 EfiHexTable;
|
|
||||||
|
|
||||||
/* EFI Image Handle */
|
|
||||||
EXTERN EFI_HANDLE EfiImageHandle;
|
|
||||||
|
|
||||||
/* XT Boot Loader protocol */
|
|
||||||
EXTERN XT_BOOT_LOADER_PROTOCOL EfiLdrProtocol;
|
|
||||||
|
|
||||||
/* EFI System Table */
|
|
||||||
EXTERN PEFI_SYSTEM_TABLE EfiSystemTable;
|
|
||||||
|
|
||||||
/* EFI Secure Boot status */
|
|
||||||
EXTERN INT_PTR EfiSecureBoot;
|
|
||||||
|
|
||||||
/* New bootloader stack */
|
|
||||||
EXTERN PVOID EfiLoaderStack;
|
|
||||||
|
|
||||||
/* Serial port configuration */
|
|
||||||
EXTERN CPPORT EfiSerialPort;
|
|
||||||
|
|
||||||
XTCDECL
|
|
||||||
EFI_STATUS
|
|
||||||
BlActivateSerialControllerIO();
|
|
||||||
|
|
||||||
XTCDECL
|
|
||||||
EFI_STATUS
|
|
||||||
BlAddVirtualMemoryMapping(IN PLIST_ENTRY MemoryMappings,
|
|
||||||
IN PVOID VirtualAddress,
|
|
||||||
IN PVOID PhysicalAddress,
|
|
||||||
IN UINT NumberOfPages,
|
|
||||||
IN LOADER_MEMORY_TYPE MemoryType);
|
|
||||||
|
|
||||||
XTCDECL
|
|
||||||
EFI_STATUS
|
|
||||||
BlCloseVolume(IN PEFI_HANDLE VolumeHandle);
|
|
||||||
|
|
||||||
XTCDECL
|
|
||||||
EFI_STATUS
|
|
||||||
BlComPortInitialize();
|
|
||||||
|
|
||||||
XTCDECL
|
|
||||||
VOID
|
|
||||||
BlComPortPutChar(IN USHORT Character);
|
|
||||||
|
|
||||||
XTCDECL
|
|
||||||
VOID
|
|
||||||
BlConsoleClearScreen();
|
|
||||||
|
|
||||||
XTCDECL
|
|
||||||
VOID
|
|
||||||
BlConsoleInitialize();
|
|
||||||
|
|
||||||
XTCDECL
|
|
||||||
VOID
|
|
||||||
BlConsolePutChar(IN USHORT Character);
|
|
||||||
|
|
||||||
XTCDECL
|
|
||||||
LOADER_MEMORY_TYPE
|
|
||||||
BlConvertEfiMemoryType(IN EFI_MEMORY_TYPE EfiMemoryType);
|
|
||||||
|
|
||||||
XTCDECL
|
|
||||||
VOID
|
|
||||||
BlDbgPrint(IN PUINT16 Format,
|
|
||||||
IN ...);
|
|
||||||
|
|
||||||
XTCDECL
|
|
||||||
INT_PTR
|
|
||||||
BlEfiGetSecureBootStatus();
|
|
||||||
|
|
||||||
XTCDECL
|
|
||||||
EFI_STATUS
|
|
||||||
BlEfiGetSystemConfigurationTable(IN PEFI_GUID TableGuid,
|
|
||||||
OUT PVOID *Table);
|
|
||||||
|
|
||||||
XTCDECL
|
|
||||||
EFI_STATUS
|
|
||||||
BlEfiMemoryAllocatePages(IN UINT64 Size,
|
|
||||||
OUT PEFI_PHYSICAL_ADDRESS Memory);
|
|
||||||
|
|
||||||
XTCDECL
|
|
||||||
EFI_STATUS
|
|
||||||
BlEfiMemoryAllocatePool(IN UINT_PTR Size,
|
|
||||||
OUT PVOID *Memory);
|
|
||||||
|
|
||||||
XTCDECL
|
|
||||||
EFI_STATUS
|
|
||||||
BlEfiMemoryFreePages(IN UINT64 Size,
|
|
||||||
IN EFI_PHYSICAL_ADDRESS Memory);
|
|
||||||
|
|
||||||
XTCDECL
|
|
||||||
EFI_STATUS
|
|
||||||
BlEfiMemoryFreePool(IN PVOID Memory);
|
|
||||||
|
|
||||||
XTCDECL
|
|
||||||
VOID
|
|
||||||
BlEfiPrint(IN PUINT16 Format,
|
|
||||||
IN ...);
|
|
||||||
|
|
||||||
XTCDECL
|
|
||||||
EFI_STATUS
|
|
||||||
BlEnablePaging(IN PLIST_ENTRY MemoryMappings,
|
|
||||||
IN PVOID VirtualAddress,
|
|
||||||
IN PEFI_LOADED_IMAGE_PROTOCOL ImageProtocol,
|
|
||||||
IN PVOID *PtePointer);
|
|
||||||
|
|
||||||
XTCDECL
|
|
||||||
EFI_STATUS
|
|
||||||
BlEnumerateEfiBlockDevices();
|
|
||||||
|
|
||||||
XTCDECL
|
|
||||||
EFI_STATUS
|
|
||||||
BlFindVolumeDevicePath(IN PEFI_DEVICE_PATH_PROTOCOL FsHandle,
|
|
||||||
IN CONST PWCHAR FileSystemPath,
|
|
||||||
OUT PEFI_DEVICE_PATH_PROTOCOL* DevicePath);
|
|
||||||
|
|
||||||
XTCDECL
|
|
||||||
EFI_STATUS
|
|
||||||
BlGetMemoryMap(OUT PEFI_MEMORY_MAP MemoryMap);
|
|
||||||
|
|
||||||
XTCDECL
|
|
||||||
EFI_STATUS
|
|
||||||
BlGetVirtualAddress(IN PLIST_ENTRY MemoryMappings,
|
|
||||||
IN PVOID PhysicalAddress,
|
|
||||||
OUT PVOID *VirtualAddress);
|
|
||||||
|
|
||||||
XTCDECL
|
|
||||||
EFI_STATUS
|
|
||||||
BlGetVolumeDevicePath(IN PUCHAR SystemPath,
|
|
||||||
OUT PEFI_DEVICE_PATH_PROTOCOL *DevicePath,
|
|
||||||
OUT PUCHAR *ArcName,
|
|
||||||
OUT PUCHAR *Path);
|
|
||||||
|
|
||||||
XTCDECL
|
|
||||||
EFI_STATUS
|
|
||||||
BlInitializeVirtualMemory(IN OUT PLIST_ENTRY MemoryMappings,
|
|
||||||
IN OUT PVOID *MemoryMapAddress);
|
|
||||||
|
|
||||||
XTCDECL
|
|
||||||
EFI_STATUS
|
|
||||||
BlLoadEfiModules();
|
|
||||||
|
|
||||||
XTCDECL
|
|
||||||
EFI_STATUS
|
|
||||||
BlLoadXtSystem();
|
|
||||||
|
|
||||||
XTCDECL
|
|
||||||
EFI_STATUS
|
|
||||||
BlMapVirtualMemory(IN PLIST_ENTRY MemoryMappings,
|
|
||||||
IN UINT_PTR VirtualAddress,
|
|
||||||
IN UINT_PTR PhysicalAddress,
|
|
||||||
IN UINT NumberOfPages,
|
|
||||||
IN OUT PVOID *PtePointer);
|
|
||||||
|
|
||||||
XTCDECL
|
|
||||||
EFI_STATUS
|
|
||||||
BlOpenVolume(IN PEFI_DEVICE_PATH_PROTOCOL DevicePath,
|
|
||||||
OUT PEFI_HANDLE DiskHandle,
|
|
||||||
OUT PEFI_FILE_HANDLE *FsHandle);
|
|
||||||
|
|
||||||
XTCDECL
|
|
||||||
EFI_STATUS
|
|
||||||
BlRegisterXtLoaderProtocol();
|
|
||||||
|
|
||||||
XTCDECL
|
|
||||||
EFI_STATUS
|
|
||||||
BlStartXtLoader(IN EFI_HANDLE ImageHandle,
|
|
||||||
IN PEFI_SYSTEM_TABLE SystemTable);
|
|
||||||
|
|
||||||
XTCDECL
|
|
||||||
INT
|
|
||||||
BlStringCompareInsensitive(IN PUCHAR String1,
|
|
||||||
IN PUCHAR String2);
|
|
||||||
|
|
||||||
XTCDECL
|
|
||||||
VOID
|
|
||||||
BlStringPrint(IN VOID PutChar(IN USHORT Character),
|
|
||||||
IN PUINT16 Format,
|
|
||||||
IN VA_LIST Arguments);
|
|
||||||
|
|
||||||
XTCDECL
|
|
||||||
EFI_STATUS
|
|
||||||
BlpDiscoverEfiBlockDevices(OUT PLIST_ENTRY BlockDevices);
|
|
||||||
|
|
||||||
XTCDECL
|
|
||||||
EFI_STATUS
|
|
||||||
BlpDissectVolumeArcPath(IN PUCHAR SystemPath,
|
|
||||||
OUT PUCHAR *ArcName,
|
|
||||||
OUT PUCHAR *Path,
|
|
||||||
OUT PUSHORT DriveType,
|
|
||||||
OUT PULONG DriveNumber,
|
|
||||||
OUT PULONG PartNumber);
|
|
||||||
|
|
||||||
XTCDECL
|
|
||||||
PEFI_DEVICE_PATH_PROTOCOL
|
|
||||||
BlpDuplicateDevicePath(IN PEFI_DEVICE_PATH_PROTOCOL DevicePath);
|
|
||||||
|
|
||||||
XTCDECL
|
|
||||||
EFI_STATUS
|
|
||||||
BlpFindLastEfiBlockDeviceNode(IN PEFI_DEVICE_PATH_PROTOCOL DevicePath,
|
|
||||||
OUT PEFI_DEVICE_PATH_PROTOCOL *LastNode);
|
|
||||||
|
|
||||||
XTCDECL
|
|
||||||
BOOLEAN
|
|
||||||
BlpFindParentEfiBlockDevice(IN PLIST_ENTRY BlockDevices,
|
|
||||||
IN PEFI_BLOCK_DEVICE_DATA ChildNode,
|
|
||||||
OUT PEFI_BLOCK_DEVICE_DATA ParentNode);
|
|
||||||
|
|
||||||
XTCDECL
|
|
||||||
VOID
|
|
||||||
BlpStringFormat(IN VOID PutChar(IN USHORT Character),
|
|
||||||
IN PUINT16 Format,
|
|
||||||
IN ...);
|
|
||||||
|
|
||||||
XTCDECL
|
|
||||||
VOID
|
|
||||||
BlpStringPrintSigned32(IN VOID PutChar(IN USHORT Character),
|
|
||||||
IN INT32 Number,
|
|
||||||
IN UINT32 Base);
|
|
||||||
|
|
||||||
XTCDECL
|
|
||||||
VOID
|
|
||||||
BlpStringPrintSigned64(IN VOID PutChar(IN USHORT Character),
|
|
||||||
IN INT_PTR Number,
|
|
||||||
IN UINT_PTR Base);
|
|
||||||
|
|
||||||
XTCDECL
|
|
||||||
VOID
|
|
||||||
BlpStringPrintUnsigned32(IN VOID PutChar(IN USHORT Character),
|
|
||||||
IN UINT32 Number,
|
|
||||||
IN UINT32 Base,
|
|
||||||
IN UINT32 Padding);
|
|
||||||
|
|
||||||
XTCDECL
|
|
||||||
VOID
|
|
||||||
BlpStringPrintUnsigned64(IN VOID PutChar(IN USHORT Character),
|
|
||||||
IN UINT_PTR Number,
|
|
||||||
IN UINT_PTR Base,
|
|
||||||
IN UINT_PTR Padding);
|
|
||||||
|
|
||||||
XTCDECL
|
|
||||||
UINT64
|
|
||||||
BlpStringReadPadding(IN PUINT16 *Format);
|
|
||||||
|
|
||||||
#endif /* __XTLDR_XTBL_H */
|
|
495
xtldr/memory.c
495
xtldr/memory.c
@ -2,315 +2,13 @@
|
|||||||
* PROJECT: ExectOS
|
* PROJECT: ExectOS
|
||||||
* COPYRIGHT: See COPYING.md in the top level directory
|
* COPYRIGHT: See COPYING.md in the top level directory
|
||||||
* FILE: xtldr/memory.c
|
* FILE: xtldr/memory.c
|
||||||
* DESCRIPTION: EFI memory management
|
* DESCRIPTION: XT Boot Loader memory management
|
||||||
* DEVELOPERS: Rafal Kupiec <belliash@codingworkshop.eu.org>
|
* DEVELOPERS: Rafal Kupiec <belliash@codingworkshop.eu.org>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <xtbl.h>
|
#include <xtldr.h>
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Adds a physical to virtual address mapping to the linked list for future processing.
|
|
||||||
*
|
|
||||||
* @param MemoryMapping
|
|
||||||
* Supplies the head of the memory mapping list.
|
|
||||||
*
|
|
||||||
* @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 which will be mapped.
|
|
||||||
*
|
|
||||||
* @param MemoryType
|
|
||||||
* Supplies the type of memory that will be assigned to the memory descriptor.
|
|
||||||
*
|
|
||||||
* @return This routine returns a status code.
|
|
||||||
*
|
|
||||||
* @since XT 1.0
|
|
||||||
*/
|
|
||||||
XTCDECL
|
|
||||||
EFI_STATUS
|
|
||||||
BlAddVirtualMemoryMapping(IN PLIST_ENTRY MemoryMappings,
|
|
||||||
IN PVOID VirtualAddress,
|
|
||||||
IN PVOID PhysicalAddress,
|
|
||||||
IN UINT NumberOfPages,
|
|
||||||
IN LOADER_MEMORY_TYPE MemoryType)
|
|
||||||
{
|
|
||||||
PLOADER_MEMORY_MAPPING Mapping1, Mapping2, Mapping3;
|
|
||||||
PVOID PhysicalAddressEnd, PhysicalAddress2End;
|
|
||||||
PLIST_ENTRY ListEntry, MappingListEntry;
|
|
||||||
SIZE_T NumberOfMappedPages;
|
|
||||||
EFI_STATUS Status;
|
|
||||||
|
|
||||||
/* Allocate memory for new mapping */
|
|
||||||
Status = BlEfiMemoryAllocatePool(sizeof(LOADER_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 = (PUINT8)PhysicalAddress + (NumberOfPages * EFI_PAGE_SIZE) - 1;
|
|
||||||
|
|
||||||
/* Iterate through all the mappings already set to insert new mapping at the correct place */
|
|
||||||
ListEntry = MemoryMappings->Flink;
|
|
||||||
while(ListEntry != MemoryMappings)
|
|
||||||
{
|
|
||||||
/* Take a mapping from the list and calculate its end of physical address */
|
|
||||||
Mapping2 = CONTAIN_RECORD(ListEntry, LOADER_MEMORY_MAPPING, ListEntry);
|
|
||||||
PhysicalAddress2End = (PUINT8)Mapping2->PhysicalAddress + (Mapping2->NumberOfPages * EFI_PAGE_SIZE) - 1 ;
|
|
||||||
|
|
||||||
/* 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 = ((PUINT8)PhysicalAddress2End - (PUINT8)PhysicalAddressEnd) / EFI_PAGE_SIZE;
|
|
||||||
if(NumberOfMappedPages > 0)
|
|
||||||
{
|
|
||||||
/* Pages associated to the mapping, allocate memory for it */
|
|
||||||
Status = BlEfiMemoryAllocatePool(sizeof(LOADER_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 = (PUINT8)PhysicalAddressEnd + 1;
|
|
||||||
Mapping3->VirtualAddress = NULL;
|
|
||||||
Mapping3->NumberOfPages = NumberOfMappedPages;
|
|
||||||
Mapping3->MemoryType = Mapping2->MemoryType;
|
|
||||||
RtlInsertHeadList(&Mapping2->ListEntry, &Mapping3->ListEntry);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Calculate number of pages and the end of the physical address */
|
|
||||||
Mapping2->NumberOfPages = ((PUINT8)PhysicalAddressEnd + 1 -
|
|
||||||
(PUINT8)Mapping2->PhysicalAddress) / EFI_PAGE_SIZE;
|
|
||||||
PhysicalAddress2End = (PUINT8)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 = ((PUINT8)PhysicalAddress2End + 1 - (PUINT8)Mapping1->PhysicalAddress) / EFI_PAGE_SIZE;
|
|
||||||
if(NumberOfMappedPages > 0)
|
|
||||||
{
|
|
||||||
/* Pages associated to the mapping, allocate memory for it */
|
|
||||||
Status = BlEfiMemoryAllocatePool(sizeof(LOADER_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 = NULL;
|
|
||||||
Mapping3->NumberOfPages = NumberOfMappedPages;
|
|
||||||
Mapping3->MemoryType = Mapping2->MemoryType;
|
|
||||||
RtlInsertHeadList(&Mapping2->ListEntry, &Mapping3->ListEntry);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Calculate number of pages and the end of the physical address */
|
|
||||||
Mapping2->NumberOfPages = ((PUINT8)Mapping1->PhysicalAddress -
|
|
||||||
(PUINT8)Mapping2->PhysicalAddress) / EFI_PAGE_SIZE;
|
|
||||||
PhysicalAddress2End = (PUINT8)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 */
|
|
||||||
RtlRemoveEntryList(&Mapping2->ListEntry);
|
|
||||||
BlEfiMemoryFreePool(Mapping2);
|
|
||||||
ListEntry = MappingListEntry;
|
|
||||||
|
|
||||||
/* Go to the next mapping */
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Determine phsical address order */
|
|
||||||
if(Mapping2->PhysicalAddress > Mapping1->PhysicalAddress)
|
|
||||||
{
|
|
||||||
/* Insert new mapping in front */
|
|
||||||
RtlInsertHeadList(Mapping2->ListEntry.Blink, &Mapping1->ListEntry);
|
|
||||||
return STATUS_EFI_SUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Get next mapping from the list */
|
|
||||||
ListEntry = ListEntry->Flink;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Insert new mapping to the end of the list and return success */
|
|
||||||
RtlInsertTailList(MemoryMappings, &Mapping1->ListEntry);
|
|
||||||
return STATUS_EFI_SUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Converts an EFI memory type into an XTOS memory type.
|
|
||||||
*
|
|
||||||
* @param EfiMemoryType
|
|
||||||
* Supplies the EFI memory type.
|
|
||||||
*
|
|
||||||
* @return Returns a conversion of the memory type.
|
|
||||||
*
|
|
||||||
* @since XT 1.0
|
|
||||||
*/
|
|
||||||
XTCDECL
|
|
||||||
LOADER_MEMORY_TYPE
|
|
||||||
BlConvertEfiMemoryType(IN EFI_MEMORY_TYPE EfiMemoryType)
|
|
||||||
{
|
|
||||||
LOADER_MEMORY_TYPE MemoryType;
|
|
||||||
|
|
||||||
/* Check EFI memory type and convert to XTOS memory type */
|
|
||||||
switch(EfiMemoryType)
|
|
||||||
{
|
|
||||||
case EfiACPIMemoryNVS:
|
|
||||||
case EfiACPIReclaimMemory:
|
|
||||||
case EfiPalCode:
|
|
||||||
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 XTOS memory type */
|
|
||||||
return MemoryType;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This routine allocates one or more 4KB pages.
|
|
||||||
*
|
|
||||||
* @param Pages
|
|
||||||
* 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
|
|
||||||
BlEfiMemoryAllocatePages(IN UINT64 Pages,
|
|
||||||
OUT PEFI_PHYSICAL_ADDRESS Memory)
|
|
||||||
{
|
|
||||||
return EfiSystemTable->BootServices->AllocatePages(AllocateAnyPages, EfiLoaderData, Pages, 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
|
|
||||||
BlEfiMemoryAllocatePool(IN UINT_PTR Size,
|
|
||||||
OUT PVOID *Memory)
|
|
||||||
{
|
|
||||||
/* Allocate pool */
|
|
||||||
return EfiSystemTable->BootServices->AllocatePool(EfiLoaderData, Size, Memory);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This routine frees memory pages.
|
|
||||||
*
|
|
||||||
* @param Pages
|
|
||||||
* 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
|
|
||||||
BlEfiMemoryFreePages(IN UINT64 Pages,
|
|
||||||
IN EFI_PHYSICAL_ADDRESS Memory)
|
|
||||||
{
|
|
||||||
return EfiSystemTable->BootServices->FreePages(Memory, Pages);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 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
|
|
||||||
BlEfiMemoryFreePool(IN PVOID Memory)
|
|
||||||
{
|
|
||||||
/* Free pool */
|
|
||||||
return EfiSystemTable->BootServices->FreePool(Memory);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the memory descriptors which define a memory map of all the physical memory ranges reserved by the UEFI.
|
* Returns the memory descriptors which define a memory map of all the physical memory ranges reserved by the UEFI.
|
||||||
*
|
*
|
||||||
@ -352,14 +50,14 @@ BlGetMemoryMap(OUT PEFI_MEMORY_MAP MemoryMap)
|
|||||||
if(MemoryMap->Map)
|
if(MemoryMap->Map)
|
||||||
{
|
{
|
||||||
/* Free allocated memory */
|
/* Free allocated memory */
|
||||||
BlEfiMemoryFreePool(MemoryMap->Map);
|
BlMemoryFreePool(MemoryMap->Map);
|
||||||
}
|
}
|
||||||
return Status;
|
return Status;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Allocate the desired amount of memory */
|
/* Allocate the desired amount of memory */
|
||||||
MemoryMap->MapSize += 2 * MemoryMap->DescriptorSize;
|
MemoryMap->MapSize += 2 * MemoryMap->DescriptorSize;
|
||||||
BlEfiMemoryAllocatePool(MemoryMap->MapSize, (PVOID *)&MemoryMap->Map);
|
BlMemoryAllocatePool(MemoryMap->MapSize, (PVOID *)&MemoryMap->Map);
|
||||||
}
|
}
|
||||||
while(Status == STATUS_EFI_BUFFER_TOO_SMALL);
|
while(Status == STATUS_EFI_BUFFER_TOO_SMALL);
|
||||||
|
|
||||||
@ -375,16 +73,13 @@ BlGetMemoryMap(OUT PEFI_MEMORY_MAP MemoryMap)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Attempts to find a virtual address of the specified physical address in memory mappings.
|
* This routine allocates one or more 4KB pages.
|
||||||
*
|
*
|
||||||
* @param MemoryMappings
|
* @param Pages
|
||||||
* Supplies a pointer to linked list containing all memory mappings.
|
* The number of contiguous 4KB pages to allocate.
|
||||||
*
|
*
|
||||||
* @param PhysicalAddress
|
* @param Memory
|
||||||
* Supplies a physical address to search for in the mappings.
|
* The pointer to a physical address.
|
||||||
*
|
|
||||||
* @param VirtualAddress
|
|
||||||
* Supplies a buffer, where mapped virtual address of the found mapping will be stored.
|
|
||||||
*
|
*
|
||||||
* @return This routine returns a status code.
|
* @return This routine returns a status code.
|
||||||
*
|
*
|
||||||
@ -392,58 +87,20 @@ BlGetMemoryMap(OUT PEFI_MEMORY_MAP MemoryMap)
|
|||||||
*/
|
*/
|
||||||
XTCDECL
|
XTCDECL
|
||||||
EFI_STATUS
|
EFI_STATUS
|
||||||
BlGetVirtualAddress(IN PLIST_ENTRY MemoryMappings,
|
BlMemoryAllocatePages(IN UINT64 Pages,
|
||||||
IN PVOID PhysicalAddress,
|
OUT PEFI_PHYSICAL_ADDRESS Memory)
|
||||||
OUT PVOID *VirtualAddress)
|
|
||||||
{
|
{
|
||||||
PLOADER_MEMORY_MAPPING Mapping;
|
return EfiSystemTable->BootServices->AllocatePages(AllocateAnyPages, EfiLoaderData, Pages, Memory);
|
||||||
PLIST_ENTRY ListEntry;
|
|
||||||
|
|
||||||
/* NULLify virtual address */
|
|
||||||
*VirtualAddress = NULL;
|
|
||||||
|
|
||||||
/* Iterate over memory mappings in order to find descriptor containing a physical address */
|
|
||||||
ListEntry = MemoryMappings->Flink;
|
|
||||||
while(ListEntry != MemoryMappings)
|
|
||||||
{
|
|
||||||
/* Get mapping from linked list */
|
|
||||||
Mapping = CONTAIN_RECORD(ListEntry, LOADER_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((PhysicalAddress >= Mapping->PhysicalAddress) &&
|
|
||||||
(PhysicalAddress < Mapping->PhysicalAddress + (Mapping->NumberOfPages * EFI_PAGE_SIZE)))
|
|
||||||
{
|
|
||||||
/* Calculate virtual address based on the mapping */
|
|
||||||
*VirtualAddress = PhysicalAddress - Mapping->PhysicalAddress + Mapping->VirtualAddress;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Get next element from the list */
|
|
||||||
ListEntry = ListEntry->Flink;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* If virtual address is still NULL, then mapping was not found */
|
|
||||||
if(*VirtualAddress == NULL)
|
|
||||||
{
|
|
||||||
/* Mapping not found */
|
|
||||||
return STATUS_EFI_NOT_FOUND;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Mapping found, return success */
|
|
||||||
return STATUS_EFI_SUCCESS;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Initializes virtual memory by adding known and general mappings.
|
* This routine allocates a pool memory.
|
||||||
*
|
*
|
||||||
* @param MemoryMappings
|
* @param Size
|
||||||
* Supplies a pointer to linked list containing all memory mappings.
|
* The number of bytes to allocate from the pool.
|
||||||
*
|
*
|
||||||
* @param MemoryMapAddress
|
* @param Memory
|
||||||
* Supplies an address of the mapped virtual memory area.
|
* The pointer to a physical address.
|
||||||
*
|
*
|
||||||
* @return This routine returns a status code.
|
* @return This routine returns a status code.
|
||||||
*
|
*
|
||||||
@ -451,80 +108,48 @@ BlGetVirtualAddress(IN PLIST_ENTRY MemoryMappings,
|
|||||||
*/
|
*/
|
||||||
XTCDECL
|
XTCDECL
|
||||||
EFI_STATUS
|
EFI_STATUS
|
||||||
BlInitializeVirtualMemory(IN OUT PLIST_ENTRY MemoryMappings,
|
BlMemoryAllocatePool(IN UINT_PTR Size,
|
||||||
IN OUT PVOID *MemoryMapAddress)
|
OUT PVOID *Memory)
|
||||||
{
|
{
|
||||||
PEFI_MEMORY_DESCRIPTOR Descriptor;
|
/* Allocate pool */
|
||||||
LOADER_MEMORY_TYPE MemoryType;
|
return EfiSystemTable->BootServices->AllocatePool(EfiLoaderData, Size, Memory);
|
||||||
PEFI_MEMORY_MAP MemoryMap;
|
}
|
||||||
SIZE_T DescriptorCount;
|
|
||||||
PUCHAR VirtualAddress;
|
/**
|
||||||
EFI_STATUS Status;
|
* This routine frees memory pages.
|
||||||
SIZE_T Index;
|
*
|
||||||
|
* @param Pages
|
||||||
/* Set initial virtual address */
|
* The number of contiguous 4 KB pages to free.
|
||||||
VirtualAddress = *MemoryMapAddress;
|
*
|
||||||
|
* @param Memory
|
||||||
/* Allocate and zero-fill buffer for EFI memory map */
|
* The base physical address of the pages to be freed.
|
||||||
BlEfiMemoryAllocatePool(sizeof(EFI_MEMORY_MAP), (PVOID*)&MemoryMap);
|
*
|
||||||
RtlZeroMemory(MemoryMap, sizeof(EFI_MEMORY_MAP));
|
* @return This routine returns a status code.
|
||||||
|
*
|
||||||
/* Get EFI memory map */
|
* @since XT 1.0
|
||||||
Status = BlGetMemoryMap(MemoryMap);
|
*/
|
||||||
if(Status != STATUS_EFI_SUCCESS)
|
XTCDECL
|
||||||
{
|
EFI_STATUS
|
||||||
return Status;
|
BlMemoryFreePages(IN UINT64 Pages,
|
||||||
}
|
IN EFI_PHYSICAL_ADDRESS Memory)
|
||||||
|
{
|
||||||
/* Calculate descriptors count and get first one */
|
return EfiSystemTable->BootServices->FreePages(Memory, Pages);
|
||||||
Descriptor = MemoryMap->Map;
|
}
|
||||||
DescriptorCount = MemoryMap->MapSize / MemoryMap->DescriptorSize;
|
|
||||||
|
/**
|
||||||
/* Iterate through all descriptors from the memory map */
|
* Returns pool memory to the system.
|
||||||
for(Index = 0; Index < DescriptorCount; Index++)
|
*
|
||||||
{
|
* @param Memory
|
||||||
/* Make sure descriptor does not go beyond lowest physical page */
|
* The pointer to the buffer to free.
|
||||||
if((Descriptor->PhysicalStart + (Descriptor->NumberOfPages * EFI_PAGE_SIZE)) <= (UINT_PTR)-1)
|
*
|
||||||
{
|
* @return This routine returns a status code.
|
||||||
/* Convert EFI memory type into XTOS memory type */
|
*
|
||||||
MemoryType = BlConvertEfiMemoryType(Descriptor->Type);
|
* @since XT 1.0
|
||||||
|
*/
|
||||||
/* Do memory mappings depending on memory type */
|
XTCDECL
|
||||||
if(MemoryType == LoaderFirmwareTemporary)
|
EFI_STATUS
|
||||||
{
|
BlMemoryFreePool(IN PVOID Memory)
|
||||||
/* Map EFI firmware code */
|
{
|
||||||
Status = BlAddVirtualMemoryMapping(MemoryMappings, (PVOID)Descriptor->PhysicalStart,
|
/* Free pool */
|
||||||
(PVOID)Descriptor->PhysicalStart, Descriptor->NumberOfPages, MemoryType);
|
return EfiSystemTable->BootServices->FreePool(Memory);
|
||||||
}
|
|
||||||
else if(MemoryType != LoaderFree)
|
|
||||||
{
|
|
||||||
/* Add any non-free memory mapping */
|
|
||||||
Status = BlAddVirtualMemoryMapping(MemoryMappings, 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 = BlAddVirtualMemoryMapping(MemoryMappings, NULL, (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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Store next valid virtual address and return success */
|
|
||||||
*MemoryMapAddress = VirtualAddress;
|
|
||||||
return STATUS_EFI_SUCCESS;
|
|
||||||
}
|
}
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
add_subdirectory(framebuf)
|
add_subdirectory(dummy)
|
||||||
add_subdirectory(pecoff)
|
add_subdirectory(fb_o)
|
||||||
add_subdirectory(xtos)
|
add_subdirectory(pecoff_o)
|
||||||
|
add_subdirectory(xtos_o)
|
||||||
|
@ -1,28 +0,0 @@
|
|||||||
# XT Boot Loader
|
|
||||||
PROJECT(XTLDR_FRAMEBUF)
|
|
||||||
|
|
||||||
# Specify include directories
|
|
||||||
include_directories(
|
|
||||||
${EXECTOS_SOURCE_DIR}/sdk/xtdk
|
|
||||||
${XTLDR_SOURCE_DIR}/includes
|
|
||||||
${XTLDR_FRAMEBUF_SOURCE_DIR}/includes)
|
|
||||||
|
|
||||||
# Specify list of source code files
|
|
||||||
list(APPEND XTLDR_FRAMEBUF_SOURCE
|
|
||||||
${XTLDR_SOURCE_DIR}/blproto.c
|
|
||||||
${XTLDR_FRAMEBUF_SOURCE_DIR}/framebuf.c
|
|
||||||
${XTLDR_FRAMEBUF_SOURCE_DIR}/gop.c)
|
|
||||||
|
|
||||||
# Link bootloader executable
|
|
||||||
add_executable(framebuf ${XTLDR_FRAMEBUF_SOURCE})
|
|
||||||
|
|
||||||
# Add linker libraries
|
|
||||||
target_link_libraries(framebuf libxtos)
|
|
||||||
|
|
||||||
# Set proper binary name and install target
|
|
||||||
set_target_properties(framebuf PROPERTIES SUFFIX .efi)
|
|
||||||
set_install_target(framebuf efi/boot/xtldr)
|
|
||||||
|
|
||||||
# Set module entrypoint and subsystem
|
|
||||||
set_entrypoint(framebuf "BlXtLdrModuleMain")
|
|
||||||
set_subsystem(framebuf efi_boot_service_driver)
|
|
@ -1,277 +0,0 @@
|
|||||||
/**
|
|
||||||
* PROJECT: ExectOS
|
|
||||||
* COPYRIGHT: See COPYING.md in the top level directory
|
|
||||||
* FILE: xtldr/modules/framebuf/framebuf.c
|
|
||||||
* DESCRIPTION: Boot loader framebuffer support
|
|
||||||
* DEVELOPERS: Rafal Kupiec <belliash@codingworkshop.eu.org>
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <framebuf.h>
|
|
||||||
|
|
||||||
|
|
||||||
/* EFI Image Handle */
|
|
||||||
EFI_HANDLE EfiImageHandle;
|
|
||||||
|
|
||||||
/* EFI System Table */
|
|
||||||
PEFI_SYSTEM_TABLE EfiSystemTable;
|
|
||||||
|
|
||||||
/* EFI XT Loader Protocol */
|
|
||||||
PXT_BOOT_LOADER_PROTOCOL XtLdrProtocol;
|
|
||||||
|
|
||||||
/* XT FrameBuffer Information */
|
|
||||||
XT_FRAMEBUFFER_INFORMATION FrameBufferInfo;
|
|
||||||
|
|
||||||
/* XT FrameBuffer Protocol */
|
|
||||||
XT_FRAMEBUFFER_PROTOCOL XtFramebufferProtocol;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Provides a current FrameBuffer driver name.
|
|
||||||
*
|
|
||||||
* @param DriverName
|
|
||||||
* Supplies a pointer to the memory area where FB driver name will be stored.
|
|
||||||
*
|
|
||||||
* @return This routine does not return any value.
|
|
||||||
*
|
|
||||||
* @since XT 1.0
|
|
||||||
*/
|
|
||||||
XTCDECL
|
|
||||||
VOID
|
|
||||||
FbGetDisplayDriver(OUT PWCHAR *DriverName)
|
|
||||||
{
|
|
||||||
switch(FrameBufferInfo.Protocol)
|
|
||||||
{
|
|
||||||
case GOP:
|
|
||||||
*DriverName = L"GOP";
|
|
||||||
break;
|
|
||||||
case UGA:
|
|
||||||
*DriverName = L"UGA";
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
*DriverName = L"NONE";
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 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
|
|
||||||
FbGetDisplayInformation(OUT PLOADER_GRAPHICS_INFORMATION_BLOCK InformationBlock)
|
|
||||||
{
|
|
||||||
InformationBlock->Initialized = FrameBufferInfo.Initialized;
|
|
||||||
InformationBlock->Protocol = FrameBufferInfo.Protocol;
|
|
||||||
InformationBlock->Address = (PVOID)(ULONG_PTR)FrameBufferInfo.FrameBufferBase;
|
|
||||||
InformationBlock->BufferSize = FrameBufferInfo.FrameBufferSize;
|
|
||||||
InformationBlock->Width = FrameBufferInfo.HorizontalResolution;
|
|
||||||
InformationBlock->Height = FrameBufferInfo.VerticalResolution;
|
|
||||||
InformationBlock->BitsPerPixel = FrameBufferInfo.BitsPerPixel;
|
|
||||||
InformationBlock->PixelsPerScanLine = FrameBufferInfo.PixelsPerScanLine;
|
|
||||||
InformationBlock->Pitch = FrameBufferInfo.Pitch;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Initializes FrameBuffer device on GOP and UGA compatible adapters.
|
|
||||||
*
|
|
||||||
* @return This routine returns a status code.
|
|
||||||
*
|
|
||||||
* @since XT 1.0
|
|
||||||
*/
|
|
||||||
XTCDECL
|
|
||||||
EFI_STATUS
|
|
||||||
FbInitializeDisplay()
|
|
||||||
{
|
|
||||||
EFI_GUID GopGuid = EFI_GRAPHICS_OUTPUT_PROTOCOL_GUID;
|
|
||||||
EFI_GUID UgaGuid = EFI_UNIVERSAL_GRAPHICS_ADAPTER_PROTOCOL_GUID;
|
|
||||||
UINT32 Parameter1, Parameter2;
|
|
||||||
EFI_STATUS Status;
|
|
||||||
|
|
||||||
/* Check if framebuffer already initialized */
|
|
||||||
if(!FrameBufferInfo.Initialized)
|
|
||||||
{
|
|
||||||
/* Initialize framebuffer */
|
|
||||||
XtLdrProtocol->DbgPrint(L"Initializing framebuffer device\n");
|
|
||||||
FrameBufferInfo.Protocol = NONE;
|
|
||||||
FrameBufferInfo.Initialized = FALSE;
|
|
||||||
|
|
||||||
/* Check if GOP already in use */
|
|
||||||
Status = EfiSystemTable->BootServices->HandleProtocol(EfiSystemTable->ConsoleOutHandle, &GopGuid,
|
|
||||||
(PVOID*)&FrameBufferInfo.Adapter.GOP);
|
|
||||||
if(Status != STATUS_EFI_SUCCESS)
|
|
||||||
{
|
|
||||||
/* Locate GOP protocol */
|
|
||||||
Status = EfiSystemTable->BootServices->LocateProtocol(&GopGuid, NULL, (PVOID *)&FrameBufferInfo.Adapter.GOP);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Check if Graphics Output Protocol is available */
|
|
||||||
if(Status == STATUS_EFI_SUCCESS)
|
|
||||||
{
|
|
||||||
/* Found GOP */
|
|
||||||
XtLdrProtocol->DbgPrint(L"Found GOP compatible display adapter\n");
|
|
||||||
|
|
||||||
/* Set framebuffer parameters */
|
|
||||||
FrameBufferInfo.HorizontalResolution = FrameBufferInfo.Adapter.GOP->Mode->Info->HorizontalResolution;
|
|
||||||
FrameBufferInfo.VerticalResolution = FrameBufferInfo.Adapter.GOP->Mode->Info->VerticalResolution;
|
|
||||||
FrameBufferInfo.BitsPerPixel = GoppGetBitsPerPixel();
|
|
||||||
FrameBufferInfo.BytesPerPixel = FrameBufferInfo.BitsPerPixel >> 3;
|
|
||||||
FrameBufferInfo.PixelsPerScanLine = FrameBufferInfo.Adapter.GOP->Mode->Info->PixelsPerScanLine;
|
|
||||||
FrameBufferInfo.PixelFormat = FrameBufferInfo.Adapter.GOP->Mode->Info->PixelFormat;
|
|
||||||
FrameBufferInfo.Pitch = FrameBufferInfo.PixelsPerScanLine * (FrameBufferInfo.BitsPerPixel / 8);
|
|
||||||
FrameBufferInfo.FrameBufferBase = FrameBufferInfo.Adapter.GOP->Mode->FrameBufferBase;
|
|
||||||
FrameBufferInfo.FrameBufferSize = FrameBufferInfo.Adapter.GOP->Mode->FrameBufferSize;
|
|
||||||
FrameBufferInfo.Protocol = GOP;
|
|
||||||
FrameBufferInfo.Initialized = TRUE;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
/* GOP is unavailable */
|
|
||||||
FrameBufferInfo.Adapter.GOP = NULL;
|
|
||||||
|
|
||||||
/* Check if UGA already in use */
|
|
||||||
Status = EfiSystemTable->BootServices->HandleProtocol(EfiSystemTable->ConsoleOutHandle, &UgaGuid,
|
|
||||||
(PVOID*)&FrameBufferInfo.Adapter.UGA);
|
|
||||||
if(Status != STATUS_EFI_SUCCESS)
|
|
||||||
{
|
|
||||||
/* Locate UGA protocol */
|
|
||||||
Status = EfiSystemTable->BootServices->LocateProtocol(&UgaGuid, NULL,
|
|
||||||
(PVOID*)&FrameBufferInfo.Adapter.UGA);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Check if Universal Graphics Adapter is available */
|
|
||||||
if(Status == STATUS_EFI_SUCCESS)
|
|
||||||
{
|
|
||||||
/* Found UGA */
|
|
||||||
XtLdrProtocol->DbgPrint(L"Found UGA compatible display adapter\n");
|
|
||||||
|
|
||||||
/* Get current mode */
|
|
||||||
Status = FrameBufferInfo.Adapter.UGA->GetMode(FrameBufferInfo.Adapter.UGA,
|
|
||||||
&FrameBufferInfo.HorizontalResolution,
|
|
||||||
&FrameBufferInfo.VerticalResolution,
|
|
||||||
&Parameter1, &Parameter2);
|
|
||||||
if(Status != STATUS_EFI_SUCCESS)
|
|
||||||
{
|
|
||||||
/* Unable to get current UGA mode */
|
|
||||||
XtLdrProtocol->DbgPrint(L"Failed to get current UGA mode (Status code: %lx)\n", Status);
|
|
||||||
FrameBufferInfo.Adapter.UGA = NULL;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
/* Set framebuffer parameters */
|
|
||||||
FrameBufferInfo.BitsPerPixel = 32;
|
|
||||||
FrameBufferInfo.BytesPerPixel = 4;
|
|
||||||
FrameBufferInfo.PixelsPerScanLine = FrameBufferInfo.HorizontalResolution;
|
|
||||||
FrameBufferInfo.PixelFormat = PixelBlueGreenRedReserved8BitPerColor;
|
|
||||||
FrameBufferInfo.Pitch = FrameBufferInfo.PixelsPerScanLine * (FrameBufferInfo.BitsPerPixel / 8);
|
|
||||||
FrameBufferInfo.FrameBufferBase = 0;
|
|
||||||
FrameBufferInfo.FrameBufferSize = FrameBufferInfo.HorizontalResolution *
|
|
||||||
FrameBufferInfo.VerticalResolution *
|
|
||||||
FrameBufferInfo.BytesPerPixel + 1024;
|
|
||||||
FrameBufferInfo.Protocol = UGA;
|
|
||||||
|
|
||||||
/* Temporarily set this to FALSE, as we don't set FB base and we cannot use it anyway */
|
|
||||||
FrameBufferInfo.Initialized = FALSE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Make sure framebuffer initialized properly */
|
|
||||||
if(!FrameBufferInfo.Initialized)
|
|
||||||
{
|
|
||||||
/* GOP and UGA unavailable */
|
|
||||||
XtLdrProtocol->DbgPrint(L"No display adapter found\n");
|
|
||||||
return STATUS_EFI_NOT_FOUND;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Return success */
|
|
||||||
return STATUS_SUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Prints important information about framebuffer.
|
|
||||||
*
|
|
||||||
* @return This routine does not return any value.
|
|
||||||
*
|
|
||||||
* @since XT 1.0
|
|
||||||
*/
|
|
||||||
XTCDECL
|
|
||||||
VOID
|
|
||||||
FbPrintDisplayInformation()
|
|
||||||
{
|
|
||||||
PWCHAR DriverName;
|
|
||||||
|
|
||||||
/* Make sure frame buffer is initialized */
|
|
||||||
if(!FrameBufferInfo.Initialized)
|
|
||||||
{
|
|
||||||
/* No FrameBuffer */
|
|
||||||
XtLdrProtocol->DbgPrint(L"No display adapters initialized, unable to print video information\n");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Get display driver name */
|
|
||||||
FbGetDisplayDriver(&DriverName);
|
|
||||||
|
|
||||||
/* Print video information */
|
|
||||||
XtLdrProtocol->DbgPrint(L"XTLDR Framebuffer information:\n"
|
|
||||||
L" FrameBuffer Address: 0x%lx\n"
|
|
||||||
L" FrameBuffer Size: %lu\n"
|
|
||||||
L" FrameBuffer Driver: %S\n"
|
|
||||||
L" Current Resolution: %ux%ux%u\n"
|
|
||||||
L" Pixel Format: %u\n"
|
|
||||||
L" Pixels Per ScanLine: %u\n",
|
|
||||||
FrameBufferInfo.FrameBufferBase, FrameBufferInfo.FrameBufferSize, DriverName,
|
|
||||||
FrameBufferInfo.HorizontalResolution, FrameBufferInfo.VerticalResolution,
|
|
||||||
FrameBufferInfo.BitsPerPixel, FrameBufferInfo.PixelFormat,
|
|
||||||
FrameBufferInfo.PixelsPerScanLine);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 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
|
|
||||||
BlXtLdrModuleMain(IN EFI_HANDLE ImageHandle,
|
|
||||||
IN PEFI_SYSTEM_TABLE SystemTable)
|
|
||||||
{
|
|
||||||
EFI_GUID Guid = XT_FRAMEBUFFER_PROTOCOL_GUID;
|
|
||||||
EFI_HANDLE Handle = NULL;
|
|
||||||
EFI_STATUS Status;
|
|
||||||
|
|
||||||
/* Set the system table and image handle */
|
|
||||||
EfiImageHandle = ImageHandle;
|
|
||||||
EfiSystemTable = SystemTable;
|
|
||||||
|
|
||||||
/* Open the XTLDR protocol */
|
|
||||||
Status = BlGetXtLoaderProtocol(&XtLdrProtocol);
|
|
||||||
if(Status != STATUS_EFI_SUCCESS)
|
|
||||||
{
|
|
||||||
/* Failed to open loader protocol */
|
|
||||||
return STATUS_EFI_PROTOCOL_ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
XtFramebufferProtocol.GetDisplayDriver = FbGetDisplayDriver;
|
|
||||||
XtFramebufferProtocol.GetDisplayInformation = FbGetDisplayInformation;
|
|
||||||
XtFramebufferProtocol.Initialize = FbInitializeDisplay;
|
|
||||||
XtFramebufferProtocol.PrintDisplayInformation = FbPrintDisplayInformation;
|
|
||||||
|
|
||||||
/* Register XTOS boot protocol */
|
|
||||||
return EfiSystemTable->BootServices->InstallProtocolInterface(&Handle, &Guid, EFI_NATIVE_INTERFACE,
|
|
||||||
&XtFramebufferProtocol);
|
|
||||||
}
|
|
@ -1,51 +0,0 @@
|
|||||||
/**
|
|
||||||
* PROJECT: ExectOS
|
|
||||||
* COPYRIGHT: See COPYING.md in the top level directory
|
|
||||||
* FILE: xtldr/modules/framebuf/gop.c
|
|
||||||
* DESCRIPTION: Graphical Output Protocol (GOP) support
|
|
||||||
* DEVELOPERS: Rafal Kupiec <belliash@codingworkshop.eu.org>
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <framebuf.h>
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns a number of bits per pixel (BPP) in the current video mode.
|
|
||||||
*
|
|
||||||
* @return A number of bits per pixel.
|
|
||||||
*
|
|
||||||
* @since XT 1.0
|
|
||||||
*/
|
|
||||||
XTCDECL
|
|
||||||
UINT32
|
|
||||||
GoppGetBitsPerPixel()
|
|
||||||
{
|
|
||||||
UINT32 BitsPerPixel, CompoundMask;
|
|
||||||
|
|
||||||
switch(FrameBufferInfo.Adapter.GOP->Mode->Info->PixelFormat)
|
|
||||||
{
|
|
||||||
case PixelBlueGreenRedReserved8BitPerColor:
|
|
||||||
case PixelRedGreenBlueReserved8BitPerColor:
|
|
||||||
case PixelBltOnly:
|
|
||||||
BitsPerPixel = 32;
|
|
||||||
break;
|
|
||||||
case PixelBitMask:
|
|
||||||
BitsPerPixel = 32;
|
|
||||||
CompoundMask = FrameBufferInfo.Adapter.GOP->Mode->Info->PixelInformation.RedMask |
|
|
||||||
FrameBufferInfo.Adapter.GOP->Mode->Info->PixelInformation.GreenMask |
|
|
||||||
FrameBufferInfo.Adapter.GOP->Mode->Info->PixelInformation.BlueMask |
|
|
||||||
FrameBufferInfo.Adapter.GOP->Mode->Info->PixelInformation.ReservedMask;
|
|
||||||
while((CompoundMask & (1 << 31)) == 0)
|
|
||||||
{
|
|
||||||
BitsPerPixel--;
|
|
||||||
CompoundMask <<= 1;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
BitsPerPixel = 0;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Return bpp */
|
|
||||||
return BitsPerPixel;
|
|
||||||
}
|
|
@ -1,44 +0,0 @@
|
|||||||
/**
|
|
||||||
* PROJECT: ExectOS
|
|
||||||
* COPYRIGHT: See COPYING.md in the top level directory
|
|
||||||
* FILE: xtldr/modules/framebuf/includes/framebuf.h
|
|
||||||
* DESCRIPTION: Framebuffer support module header file
|
|
||||||
* DEVELOPERS: Rafal Kupiec <belliash@codingworkshop.eu.org>
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef __XTLDR_MODULES_FRAMEBUF_H
|
|
||||||
#define __XTLDR_MODULES_FRAMEBUF_H
|
|
||||||
|
|
||||||
#include <blmod.h>
|
|
||||||
|
|
||||||
|
|
||||||
/* XT FrameBuffer Information */
|
|
||||||
EXTERN XT_FRAMEBUFFER_INFORMATION FrameBufferInfo;
|
|
||||||
|
|
||||||
/* FrameBuffer support protocol related routines forward references */
|
|
||||||
XTCDECL
|
|
||||||
VOID
|
|
||||||
FbGetDisplayDriver(OUT PWCHAR *DriverName);
|
|
||||||
|
|
||||||
XTCDECL
|
|
||||||
VOID
|
|
||||||
FbGetDisplayInformation(OUT PLOADER_GRAPHICS_INFORMATION_BLOCK InformationBlock);
|
|
||||||
|
|
||||||
XTCDECL
|
|
||||||
EFI_STATUS
|
|
||||||
FbInitializeDisplay();
|
|
||||||
|
|
||||||
XTCDECL
|
|
||||||
VOID
|
|
||||||
FbPrintDisplayInformation();
|
|
||||||
|
|
||||||
XTCDECL
|
|
||||||
UINT32
|
|
||||||
GoppGetBitsPerPixel();
|
|
||||||
|
|
||||||
XTCDECL
|
|
||||||
EFI_STATUS
|
|
||||||
BlXtLdrModuleMain(IN EFI_HANDLE ImageHandle,
|
|
||||||
IN PEFI_SYSTEM_TABLE SystemTable);
|
|
||||||
|
|
||||||
#endif /* __XTLDR_MODULES_FRAMEBUF_H */
|
|
@ -1,27 +0,0 @@
|
|||||||
# XT Boot Loader
|
|
||||||
PROJECT(XTLDR_PECOFF)
|
|
||||||
|
|
||||||
# Specify include directories
|
|
||||||
include_directories(
|
|
||||||
${EXECTOS_SOURCE_DIR}/sdk/xtdk
|
|
||||||
${XTLDR_SOURCE_DIR}/includes
|
|
||||||
${XTLDR_PECOFF_SOURCE_DIR}/includes)
|
|
||||||
|
|
||||||
# Specify list of source code files
|
|
||||||
list(APPEND XTLDR_PECOFF_SOURCE
|
|
||||||
${XTLDR_SOURCE_DIR}/blproto.c
|
|
||||||
${XTLDR_PECOFF_SOURCE_DIR}/pecoff.c)
|
|
||||||
|
|
||||||
# Link bootloader executable
|
|
||||||
add_executable(pecoff ${XTLDR_PECOFF_SOURCE})
|
|
||||||
|
|
||||||
# Add linker libraries
|
|
||||||
target_link_libraries(pecoff libxtos)
|
|
||||||
|
|
||||||
# Set proper binary name and install target
|
|
||||||
set_target_properties(pecoff PROPERTIES SUFFIX .efi)
|
|
||||||
set_install_target(pecoff efi/boot/xtldr)
|
|
||||||
|
|
||||||
# Set module entrypoint and subsystem
|
|
||||||
set_entrypoint(pecoff "BlXtLdrModuleMain")
|
|
||||||
set_subsystem(pecoff efi_boot_service_driver)
|
|
@ -1,58 +0,0 @@
|
|||||||
/**
|
|
||||||
* PROJECT: ExectOS
|
|
||||||
* COPYRIGHT: See COPYING.md in the top level directory
|
|
||||||
* FILE: xtldr/modules/pecoff/includes/pecoff.h
|
|
||||||
* DESCRIPTION: PE/COFF executable file format support header
|
|
||||||
* DEVELOPERS: Rafal Kupiec <belliash@codingworkshop.eu.org>
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef __XTLDR_MODULES_PECOFF_H
|
|
||||||
#define __XTLDR_MODULES_PECOFF_H
|
|
||||||
|
|
||||||
#include <blmod.h>
|
|
||||||
|
|
||||||
|
|
||||||
/* PE/COFF image protocol related routines forward references */
|
|
||||||
XTCDECL
|
|
||||||
EFI_STATUS
|
|
||||||
PeGetEntryPoint(IN PPECOFF_IMAGE_CONTEXT Image,
|
|
||||||
OUT PVOID *EntryPoint);
|
|
||||||
|
|
||||||
XTCDECL
|
|
||||||
EFI_STATUS
|
|
||||||
PeGetMachineType(IN PPECOFF_IMAGE_CONTEXT Image,
|
|
||||||
OUT PUSHORT MachineType);
|
|
||||||
|
|
||||||
XTCDECL
|
|
||||||
EFI_STATUS
|
|
||||||
PeGetSubSystem(IN PPECOFF_IMAGE_CONTEXT Image,
|
|
||||||
OUT PUSHORT SubSystem);
|
|
||||||
|
|
||||||
XTCDECL
|
|
||||||
EFI_STATUS
|
|
||||||
PeLoadImage(IN PEFI_FILE_HANDLE FileHandle,
|
|
||||||
IN LOADER_MEMORY_TYPE MemoryType,
|
|
||||||
IN PVOID VirtualAddress,
|
|
||||||
OUT PPECOFF_IMAGE_CONTEXT *Image);
|
|
||||||
|
|
||||||
XTCDECL
|
|
||||||
EFI_STATUS
|
|
||||||
PeRelocateImage(IN PPECOFF_IMAGE_CONTEXT Image,
|
|
||||||
IN EFI_VIRTUAL_ADDRESS Address);
|
|
||||||
|
|
||||||
XTCDECL
|
|
||||||
EFI_STATUS
|
|
||||||
PepRelocateLoadedImage(IN PPECOFF_IMAGE_CONTEXT Image);
|
|
||||||
|
|
||||||
XTCDECL
|
|
||||||
EFI_STATUS
|
|
||||||
PepValidateImageHeaders(IN PPECOFF_IMAGE_DOS_HEADER DosHeader,
|
|
||||||
IN PPECOFF_IMAGE_PE_HEADER PeHeader,
|
|
||||||
IN SIZE_T FileSize);
|
|
||||||
|
|
||||||
XTCDECL
|
|
||||||
EFI_STATUS
|
|
||||||
BlXtLdrModuleMain(IN EFI_HANDLE ImageHandle,
|
|
||||||
IN PEFI_SYSTEM_TABLE SystemTable);
|
|
||||||
|
|
||||||
#endif /* __XTLDR_MODULES_PECOFF_H */
|
|
@ -1,608 +0,0 @@
|
|||||||
/**
|
|
||||||
* PROJECT: ExectOS
|
|
||||||
* COPYRIGHT: See COPYING.md in the top level directory
|
|
||||||
* FILE: xtldr/modules/pecoff/pecoff.c
|
|
||||||
* DESCRIPTION: PE/COFF executable file format support
|
|
||||||
* DEVELOPERS: Rafal Kupiec <belliash@codingworkshop.eu.org>
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <pecoff.h>
|
|
||||||
|
|
||||||
|
|
||||||
/* EFI Image Handle */
|
|
||||||
EFI_HANDLE EfiImageHandle;
|
|
||||||
|
|
||||||
/* EFI System Table */
|
|
||||||
PEFI_SYSTEM_TABLE EfiSystemTable;
|
|
||||||
|
|
||||||
/* EFI XT Loader Protocol */
|
|
||||||
PXT_BOOT_LOADER_PROTOCOL XtLdrProtocol;
|
|
||||||
|
|
||||||
/* XTOS PE/COFF Image Protocol */
|
|
||||||
XT_PECOFF_IMAGE_PROTOCOL XtPeCoffProtocol;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the address of the entry point.
|
|
||||||
*
|
|
||||||
* @param Image
|
|
||||||
* A pointer to the PE/COFF context structure representing the loaded image.
|
|
||||||
*
|
|
||||||
* @param EntryPoint
|
|
||||||
* 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
|
|
||||||
PeGetEntryPoint(IN PPECOFF_IMAGE_CONTEXT Image,
|
|
||||||
OUT PVOID *EntryPoint)
|
|
||||||
{
|
|
||||||
/* Validate input data */
|
|
||||||
if(!Image || !Image->PeHeader)
|
|
||||||
{
|
|
||||||
/* Invalid parameter passed */
|
|
||||||
return STATUS_EFI_INVALID_PARAMETER;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Get entry point and return success */
|
|
||||||
*EntryPoint = (PUINT8)Image->VirtualAddress + Image->PeHeader->OptionalHeader.AddressOfEntryPoint;
|
|
||||||
return STATUS_EFI_SUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the machine type of the PE/COFF image.
|
|
||||||
*
|
|
||||||
* @param Image
|
|
||||||
* A pointer to the PE/COFF context structure representing the loaded image.
|
|
||||||
*
|
|
||||||
* @param MachineType
|
|
||||||
* 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
|
|
||||||
PeGetMachineType(IN PPECOFF_IMAGE_CONTEXT Image,
|
|
||||||
OUT PUSHORT MachineType)
|
|
||||||
{
|
|
||||||
/* 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 information about subsystem that is required to run PE/COFF image.
|
|
||||||
*
|
|
||||||
* @param Image
|
|
||||||
* A pointer to the PE/COFF context structure representing the loaded image.
|
|
||||||
*
|
|
||||||
* @param SubSystem
|
|
||||||
* 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
|
|
||||||
PeGetSubSystem(IN PPECOFF_IMAGE_CONTEXT Image,
|
|
||||||
OUT PUSHORT SubSystem)
|
|
||||||
{
|
|
||||||
/* Validate input data */
|
|
||||||
if(!Image || !Image->PeHeader)
|
|
||||||
{
|
|
||||||
/* Invalid parameter passed */
|
|
||||||
return STATUS_EFI_INVALID_PARAMETER;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Get image subsystem and return success */
|
|
||||||
*SubSystem = Image->PeHeader->OptionalHeader.Subsystem;
|
|
||||||
return STATUS_EFI_SUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 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 status code.
|
|
||||||
*
|
|
||||||
* @since XT 1.0
|
|
||||||
*/
|
|
||||||
XTCDECL
|
|
||||||
EFI_STATUS
|
|
||||||
PeLoadImage(IN PEFI_FILE_HANDLE FileHandle,
|
|
||||||
IN LOADER_MEMORY_TYPE MemoryType,
|
|
||||||
IN PVOID VirtualAddress,
|
|
||||||
OUT PPECOFF_IMAGE_CONTEXT *Image)
|
|
||||||
{
|
|
||||||
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->AllocatePool(ReadSize, (PVOID *)&FileInfo);
|
|
||||||
if(Status != STATUS_EFI_SUCCESS)
|
|
||||||
{
|
|
||||||
/* Memory allocation failure */
|
|
||||||
XtLdrProtocol->DbgPrint(L"ERROR: Memory pool allocation failure\n");
|
|
||||||
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->FreePool(&FileInfo);
|
|
||||||
Status = XtLdrProtocol->AllocatePool(ReadSize, (PVOID *)&FileInfo);
|
|
||||||
if(Status != STATUS_EFI_SUCCESS)
|
|
||||||
{
|
|
||||||
/* Memory allocation failure */
|
|
||||||
XtLdrProtocol->DbgPrint(L"ERROR: Memory pool allocation failure\n");
|
|
||||||
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->DbgPrint(L"ERROR: Failed to get file information\n");
|
|
||||||
return Status;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Allocate memory for storing image data */
|
|
||||||
Status = XtLdrProtocol->AllocatePool(sizeof(PECOFF_IMAGE_CONTEXT), (PVOID *)&ImageData);
|
|
||||||
if(Status != STATUS_EFI_SUCCESS)
|
|
||||||
{
|
|
||||||
/* Memory allocation failure */
|
|
||||||
XtLdrProtocol->DbgPrint(L"ERROR: Memory pool allocation failure\n");
|
|
||||||
return Status;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Store file size and memory type, nullify data and free up memory */
|
|
||||||
ImageData->Data = NULL;
|
|
||||||
ImageData->FileSize = FileInfo->FileSize;
|
|
||||||
ImageData->MemoryType = MemoryType;
|
|
||||||
XtLdrProtocol->FreePool(FileInfo);
|
|
||||||
|
|
||||||
/* Calculate number of pages */
|
|
||||||
Pages = EFI_SIZE_TO_PAGES(ImageData->FileSize);
|
|
||||||
|
|
||||||
/* Allocate pages */
|
|
||||||
Status = XtLdrProtocol->AllocatePages(Pages, &Address);
|
|
||||||
if(Status != STATUS_EFI_SUCCESS)
|
|
||||||
{
|
|
||||||
/* Pages allocation failure */
|
|
||||||
XtLdrProtocol->DbgPrint(L"ERROR: Pages allocation failure\n");
|
|
||||||
XtLdrProtocol->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->DbgPrint(L"ERROR: Unable to read PE/COFF image file\n");
|
|
||||||
XtLdrProtocol->FreePages(Pages, (EFI_PHYSICAL_ADDRESS)(UINT_PTR)Data);
|
|
||||||
XtLdrProtocol->FreePool(ImageData);
|
|
||||||
return Status;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Extract DOS and PE headers */
|
|
||||||
ImageData->DosHeader = (PPECOFF_IMAGE_DOS_HEADER)Data;
|
|
||||||
ImageData->PeHeader = (PPECOFF_IMAGE_PE_HEADER)((PUINT8)Data + ImageData->DosHeader->e_lfanew);
|
|
||||||
|
|
||||||
/* Validate headers */
|
|
||||||
Status = PepValidateImageHeaders(ImageData->DosHeader, ImageData->PeHeader, ImageData->FileSize);
|
|
||||||
if(Status != STATUS_EFI_SUCCESS)
|
|
||||||
{
|
|
||||||
/* Header validation failed, probably broken or invalid PE/COFF image */
|
|
||||||
XtLdrProtocol->DbgPrint(L"ERROR: Invalid PE/COFF image headers\n");
|
|
||||||
XtLdrProtocol->FreePages(Pages, (EFI_PHYSICAL_ADDRESS)(UINT_PTR)Data);
|
|
||||||
XtLdrProtocol->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->DbgPrint(L"ERROR: Non-executable PE/COFF image loaded\n");
|
|
||||||
XtLdrProtocol->FreePages(Pages, (EFI_PHYSICAL_ADDRESS)(UINT_PTR)Data);
|
|
||||||
XtLdrProtocol->FreePool(ImageData);
|
|
||||||
return STATUS_EFI_LOAD_ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Store image size and calculate number of image pages */
|
|
||||||
ImageData->ImageSize = ImageData->PeHeader->OptionalHeader.SizeOfImage;
|
|
||||||
ImageData->ImagePages = EFI_SIZE_TO_PAGES(ImageData->ImageSize);
|
|
||||||
|
|
||||||
/* Allocate image pages */
|
|
||||||
Status = XtLdrProtocol->AllocatePages(ImageData->ImagePages, &Address);
|
|
||||||
if(Status != STATUS_EFI_SUCCESS)
|
|
||||||
{
|
|
||||||
/* Pages reallocation failure */
|
|
||||||
XtLdrProtocol->DbgPrint(L"ERROR: Pages reallocation failure\n");
|
|
||||||
XtLdrProtocol->FreePool(ImageData);
|
|
||||||
return Status;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Store image data and virtual address */
|
|
||||||
ImageData->Data = (PUINT8)(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;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Copy all sections */
|
|
||||||
RtlCopyMemory(ImageData->Data, Data, ImageData->PeHeader->OptionalHeader.SizeOfHeaders);
|
|
||||||
|
|
||||||
/* Find section header */
|
|
||||||
SectionHeader = (PPECOFF_IMAGE_SECTION_HEADER)((PUCHAR)&ImageData->PeHeader->OptionalHeader +
|
|
||||||
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 */
|
|
||||||
RtlCopyMemory((PUINT8)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 */
|
|
||||||
RtlZeroMemory((PUINT8)ImageData->Data + SectionHeader[Index].VirtualAddress + SectionSize,
|
|
||||||
SectionHeader[Index].Misc.VirtualSize - SectionSize);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Free pages */
|
|
||||||
XtLdrProtocol->FreePages((EFI_PHYSICAL_ADDRESS)(UINT_PTR)Data, Pages);
|
|
||||||
|
|
||||||
/* Perform relocation fixups */
|
|
||||||
Status = PepRelocateLoadedImage(ImageData);
|
|
||||||
if(Status != STATUS_EFI_SUCCESS)
|
|
||||||
{
|
|
||||||
/* Failed to relocate image */
|
|
||||||
XtLdrProtocol->DbgPrint(L"ERROR: PE/COFF image relocation failed\n");
|
|
||||||
return Status;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Store image data */
|
|
||||||
*Image = ImageData;
|
|
||||||
|
|
||||||
/* Return SUCCESS */
|
|
||||||
return STATUS_EFI_SUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Relocates PE/COFF image to the specified address.
|
|
||||||
*
|
|
||||||
* @param Image
|
|
||||||
* A pointer to the PE/COFF context structure representing the loaded image.
|
|
||||||
*
|
|
||||||
* @param Address
|
|
||||||
* Destination address of memory region, where image should be relocated.
|
|
||||||
*
|
|
||||||
* @return This routine returns status code.
|
|
||||||
*
|
|
||||||
* @since XT 1.0
|
|
||||||
*/
|
|
||||||
XTCDECL
|
|
||||||
EFI_STATUS
|
|
||||||
PeRelocateImage(IN PPECOFF_IMAGE_CONTEXT Image,
|
|
||||||
IN EFI_VIRTUAL_ADDRESS Address)
|
|
||||||
{
|
|
||||||
UINT64 ImageBase, OldVirtualAddress;
|
|
||||||
EFI_STATUS Status;
|
|
||||||
|
|
||||||
/* Store original virtual address */
|
|
||||||
OldVirtualAddress = (UINT_PTR)Image->VirtualAddress;
|
|
||||||
|
|
||||||
/* Check PE/COFF image type */
|
|
||||||
if(Image->PeHeader->OptionalHeader.Magic == PECOFF_IMAGE_PE_OPTIONAL_HDR64_MAGIC)
|
|
||||||
{
|
|
||||||
/* This is 64-bit PE32+, store its image base address */
|
|
||||||
ImageBase = Image->PeHeader->OptionalHeader.ImageBase64;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
/* This is 32-bit PE32, store its image base address */
|
|
||||||
ImageBase = Image->PeHeader->OptionalHeader.ImageBase32;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Overwrite virtual address and relocate image once again */
|
|
||||||
Image->VirtualAddress = (PVOID)(Address - OldVirtualAddress + ImageBase);
|
|
||||||
Status = PepRelocateLoadedImage(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
|
|
||||||
* 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
|
|
||||||
PepRelocateLoadedImage(IN PPECOFF_IMAGE_CONTEXT Image)
|
|
||||||
{
|
|
||||||
PPECOFF_IMAGE_BASE_RELOCATION RelocationDir, RelocationEnd;
|
|
||||||
PPECOFF_IMAGE_DATA_DIRECTORY DataDirectory;
|
|
||||||
USHORT Offset, Type, Count;
|
|
||||||
PUSHORT TypeOffset;
|
|
||||||
UINT64 ImageBase;
|
|
||||||
PUINT32 Address;
|
|
||||||
PUINT64 LongPtr;
|
|
||||||
PUINT ShortPtr;
|
|
||||||
|
|
||||||
/* Make sure image is not stripped */
|
|
||||||
if(Image->PeHeader->FileHeader.Characteristics & PECOFF_IMAGE_FILE_RELOCS_STRIPPED)
|
|
||||||
{
|
|
||||||
/* No relocation information found */
|
|
||||||
XtLdrProtocol->DbgPrint(L"WARNING: PE/COFF image is stripped and contains no information about relocations\n");
|
|
||||||
return STATUS_EFI_SUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Set relocation data directory */
|
|
||||||
DataDirectory = &Image->PeHeader->OptionalHeader.DataDirectory[PECOFF_IMAGE_DIRECTORY_ENTRY_BASERELOC];
|
|
||||||
|
|
||||||
/* Check if loaded image should be relocated */
|
|
||||||
if(Image->PeHeader->OptionalHeader.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;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Check PE/COFF image type */
|
|
||||||
if(Image->PeHeader->OptionalHeader.Magic == PECOFF_IMAGE_PE_OPTIONAL_HDR64_MAGIC)
|
|
||||||
{
|
|
||||||
/* This is 64-bit PE32+, store its image base address */
|
|
||||||
ImageBase = Image->PeHeader->OptionalHeader.ImageBase64;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
/* This is 32-bit PE32, store its image base address */
|
|
||||||
ImageBase = Image->PeHeader->OptionalHeader.ImageBase32;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 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) >= 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 = (PUINT32)((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;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Validates a PE/COFF image headers.
|
|
||||||
*
|
|
||||||
* @param DosHeader
|
|
||||||
* Pointer to the memory area with DOS header stored.
|
|
||||||
*
|
|
||||||
* @param PeHeader
|
|
||||||
* Pointer to the memory area with PE header stored.
|
|
||||||
*
|
|
||||||
* @param FileSize
|
|
||||||
* A PE/COFF image file size.
|
|
||||||
*
|
|
||||||
* @return This routine returns a status code.
|
|
||||||
*
|
|
||||||
* @since XT 1.0
|
|
||||||
*/
|
|
||||||
XTCDECL
|
|
||||||
EFI_STATUS
|
|
||||||
PepValidateImageHeaders(IN PPECOFF_IMAGE_DOS_HEADER DosHeader,
|
|
||||||
IN PPECOFF_IMAGE_PE_HEADER PeHeader,
|
|
||||||
IN SIZE_T FileSize)
|
|
||||||
{
|
|
||||||
/* Validate file size */
|
|
||||||
if(FileSize < sizeof(PECOFF_IMAGE_DOS_HEADER))
|
|
||||||
{
|
|
||||||
XtLdrProtocol->DbgPrint(L"WARNING: PE/COFF image shorter than DOS header\n");
|
|
||||||
return STATUS_EFI_END_OF_FILE;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Validate DOS header */
|
|
||||||
if(DosHeader->e_magic != PECOFF_IMAGE_DOS_SIGNATURE)
|
|
||||||
{
|
|
||||||
XtLdrProtocol->DbgPrint(L"WARNING: Invalid DOS signature found\n");
|
|
||||||
return STATUS_EFI_INCOMPATIBLE_VERSION;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Validate PE header */
|
|
||||||
if(PeHeader->Signature != PECOFF_IMAGE_NT_SIGNATURE && PeHeader->Signature != PECOFF_IMAGE_XT_SIGNATURE)
|
|
||||||
{
|
|
||||||
XtLdrProtocol->DbgPrint(L"WARNING: Invalid NT/XT signature found\n");
|
|
||||||
return STATUS_EFI_INCOMPATIBLE_VERSION;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Validate optional header */
|
|
||||||
if(PeHeader->OptionalHeader.Magic != PECOFF_IMAGE_PE_OPTIONAL_HDR32_MAGIC &&
|
|
||||||
PeHeader->OptionalHeader.Magic != PECOFF_IMAGE_PE_OPTIONAL_HDR64_MAGIC)
|
|
||||||
{
|
|
||||||
XtLdrProtocol->DbgPrint(L"WARNING: Invalid optional header signature found\n");
|
|
||||||
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 status code.
|
|
||||||
*
|
|
||||||
* @since XT 1.0
|
|
||||||
*/
|
|
||||||
XTCDECL
|
|
||||||
EFI_STATUS
|
|
||||||
BlXtLdrModuleMain(IN EFI_HANDLE ImageHandle,
|
|
||||||
IN PEFI_SYSTEM_TABLE SystemTable)
|
|
||||||
{
|
|
||||||
EFI_GUID Guid = XT_PECOFF_IMAGE_PROTOCOL_GUID;
|
|
||||||
EFI_HANDLE Handle = NULL;
|
|
||||||
EFI_STATUS Status;
|
|
||||||
|
|
||||||
/* Set the system table and image handle */
|
|
||||||
EfiImageHandle = ImageHandle;
|
|
||||||
EfiSystemTable = SystemTable;
|
|
||||||
|
|
||||||
/* Open the XTLDR protocol */
|
|
||||||
Status = BlGetXtLoaderProtocol(&XtLdrProtocol);
|
|
||||||
if(Status != STATUS_EFI_SUCCESS)
|
|
||||||
{
|
|
||||||
/* Failed to open loader protocol */
|
|
||||||
return STATUS_EFI_PROTOCOL_ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Set routines available via PE/COFF image protocol */
|
|
||||||
XtPeCoffProtocol.GetEntryPoint = PeGetEntryPoint;
|
|
||||||
XtPeCoffProtocol.GetMachineType = PeGetMachineType;
|
|
||||||
XtPeCoffProtocol.GetSubSystem = PeGetSubSystem;
|
|
||||||
XtPeCoffProtocol.Load = PeLoadImage;
|
|
||||||
XtPeCoffProtocol.Relocate = PeRelocateImage;
|
|
||||||
|
|
||||||
/* Register PE/COFF protocol */
|
|
||||||
return EfiSystemTable->BootServices->InstallProtocolInterface(&Handle, &Guid, EFI_NATIVE_INTERFACE,
|
|
||||||
&XtPeCoffProtocol);
|
|
||||||
}
|
|
@ -1,27 +0,0 @@
|
|||||||
# XT Boot Loader
|
|
||||||
PROJECT(XTLDR_XTOS)
|
|
||||||
|
|
||||||
# Specify include directories
|
|
||||||
include_directories(
|
|
||||||
${EXECTOS_SOURCE_DIR}/sdk/xtdk
|
|
||||||
${XTLDR_SOURCE_DIR}/includes
|
|
||||||
${XTLDR_XTOS_SOURCE_DIR}/includes)
|
|
||||||
|
|
||||||
# Specify list of source code files
|
|
||||||
list(APPEND XTLDR_XTOS_SOURCE
|
|
||||||
${XTLDR_SOURCE_DIR}/blproto.c
|
|
||||||
${XTLDR_XTOS_SOURCE_DIR}/xtos.c)
|
|
||||||
|
|
||||||
# Link bootloader executable
|
|
||||||
add_executable(xtos ${XTLDR_XTOS_SOURCE})
|
|
||||||
|
|
||||||
# Add linker libraries
|
|
||||||
target_link_libraries(xtos libxtos)
|
|
||||||
|
|
||||||
# Set proper binary name and install target
|
|
||||||
set_target_properties(xtos PROPERTIES SUFFIX .efi)
|
|
||||||
set_install_target(xtos efi/boot/xtldr)
|
|
||||||
|
|
||||||
# Set module entrypoint and subsystem
|
|
||||||
set_entrypoint(xtos "BlXtLdrModuleMain")
|
|
||||||
set_subsystem(xtos efi_boot_service_driver)
|
|
@ -1,54 +0,0 @@
|
|||||||
/**
|
|
||||||
* PROJECT: ExectOS
|
|
||||||
* COPYRIGHT: See COPYING.md in the top level directory
|
|
||||||
* FILE: xtldr/modules/xtos/includes/xtos.h
|
|
||||||
* DESCRIPTION: XTOS boot protocol support header
|
|
||||||
* DEVELOPERS: Rafal Kupiec <belliash@codingworkshop.eu.org>
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef __XTLDR_MODULES_XTOS_H
|
|
||||||
#define __XTLDR_MODULES_XTOS_H
|
|
||||||
|
|
||||||
#include <blmod.h>
|
|
||||||
|
|
||||||
|
|
||||||
/* EFI XT Loader Protocol */
|
|
||||||
EXTERN PXT_BOOT_LOADER_PROTOCOL XtLdrProtocol;
|
|
||||||
|
|
||||||
/* XTOS kernel entry point */
|
|
||||||
typedef VOID (XTAPI *PXT_ENTRY_POINT)(IN PKERNEL_INITIALIZATION_BLOCK BootParameters);
|
|
||||||
|
|
||||||
/* XTOS boot protocol related routines forward references */
|
|
||||||
XTCDECL
|
|
||||||
EFI_STATUS
|
|
||||||
XtBootSystem(IN PXT_BOOT_PROTOCOL_PARAMETERS Parameters);
|
|
||||||
|
|
||||||
XTCDECL
|
|
||||||
EFI_STATUS
|
|
||||||
XtpBootSequence(IN PEFI_FILE_HANDLE BootDir,
|
|
||||||
IN PXT_BOOT_PROTOCOL_PARAMETERS Parameters);
|
|
||||||
|
|
||||||
|
|
||||||
XTCDECL
|
|
||||||
EFI_STATUS
|
|
||||||
XtpInitializeApicBase(IN PLIST_ENTRY MemoryMappings);
|
|
||||||
|
|
||||||
XTCDECL
|
|
||||||
EFI_STATUS
|
|
||||||
XtpInitializeLoaderBlock(IN PLIST_ENTRY MemoryMappings,
|
|
||||||
IN PVOID *VirtualAddress);
|
|
||||||
|
|
||||||
XTCDECL
|
|
||||||
EFI_STATUS
|
|
||||||
XtpLoadModule(IN PEFI_FILE_HANDLE BootDir,
|
|
||||||
IN PWCHAR FileName,
|
|
||||||
IN PVOID VirtualAddress,
|
|
||||||
IN LOADER_MEMORY_TYPE MemoryType,
|
|
||||||
OUT PPECOFF_IMAGE_CONTEXT *ImageContext);
|
|
||||||
|
|
||||||
XTCDECL
|
|
||||||
EFI_STATUS
|
|
||||||
BlXtLdrModuleMain(IN EFI_HANDLE ImageHandle,
|
|
||||||
IN PEFI_SYSTEM_TABLE SystemTable);
|
|
||||||
|
|
||||||
#endif /* __XTLDR_MODULES_XTOS_H */
|
|
@ -1,548 +0,0 @@
|
|||||||
/**
|
|
||||||
* PROJECT: ExectOS
|
|
||||||
* COPYRIGHT: See COPYING.md in the top level directory
|
|
||||||
* FILE: xtldr/modules/xtos/xtos.c
|
|
||||||
* DESCRIPTION: XTOS boot protocol support
|
|
||||||
* DEVELOPERS: Rafal Kupiec <belliash@codingworkshop.eu.org>
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <xtos.h>
|
|
||||||
|
|
||||||
|
|
||||||
/* EFI Image Handle */
|
|
||||||
EFI_HANDLE EfiImageHandle;
|
|
||||||
|
|
||||||
/* EFI System Table */
|
|
||||||
PEFI_SYSTEM_TABLE EfiSystemTable;
|
|
||||||
|
|
||||||
/* EFI XT Loader Protocol */
|
|
||||||
PXT_BOOT_LOADER_PROTOCOL XtLdrProtocol;
|
|
||||||
|
|
||||||
/* XTOS PE/COFF Image Protocol */
|
|
||||||
PXT_PECOFF_IMAGE_PROTOCOL XtPeCoffProtocol;
|
|
||||||
|
|
||||||
/* XTOS Boot Protocol */
|
|
||||||
XT_BOOT_PROTOCOL XtBootProtocol;
|
|
||||||
|
|
||||||
/* XTOS Page Map */
|
|
||||||
PVOID XtPageMap;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 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
|
|
||||||
XtBootSystem(IN PXT_BOOT_PROTOCOL_PARAMETERS Parameters)
|
|
||||||
{
|
|
||||||
EFI_GUID PeCoffProtocolGuid = XT_PECOFF_IMAGE_PROTOCOL_GUID;
|
|
||||||
EFI_HANDLE DiskHandle;
|
|
||||||
PEFI_FILE_HANDLE FsHandle, BootDir;
|
|
||||||
PWCHAR SystemPath;
|
|
||||||
EFI_STATUS Status;
|
|
||||||
|
|
||||||
/* Print debug message */
|
|
||||||
XtLdrProtocol->DbgPrint(L"XTOS boot protocol activated\n");
|
|
||||||
|
|
||||||
/* Open the XT PE/COFF protocol */
|
|
||||||
Status = BlLoadXtProtocol((PVOID *)&XtPeCoffProtocol, &PeCoffProtocolGuid);
|
|
||||||
if(Status != STATUS_EFI_SUCCESS)
|
|
||||||
{
|
|
||||||
/* Failed to open loader protocol */
|
|
||||||
XtLdrProtocol->DbgPrint(L"ERROR: Unable to load PE/COFF image protocol\n");
|
|
||||||
return STATUS_EFI_PROTOCOL_ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Check device path */
|
|
||||||
if(Parameters->DevicePath == NULL)
|
|
||||||
{
|
|
||||||
/* No device path set */
|
|
||||||
XtLdrProtocol->DbgPrint(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 != NULL)
|
|
||||||
{
|
|
||||||
/* 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->DbgPrint(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->DbgPrint(L"WARNING: No system path set, falling back to defaults\n");
|
|
||||||
Parameters->SystemPath = L"\\ExectOS";
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Check if kernel file is set */
|
|
||||||
if(Parameters->KernelFile == NULL)
|
|
||||||
{
|
|
||||||
/* No kernel filename set, fallback to default */
|
|
||||||
XtLdrProtocol->DbgPrint(L"WARNING: No kernel file specified, falling back to defaults\n");
|
|
||||||
Parameters->KernelFile = L"xtoskrnl.exe";
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Check if provided any kernel boot arguments */
|
|
||||||
if(Parameters->Arguments == NULL)
|
|
||||||
{
|
|
||||||
/* No argument supplied */
|
|
||||||
Parameters->Arguments = L"";
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Print a debug message */
|
|
||||||
XtLdrProtocol->DbgPrint(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->Arguments);
|
|
||||||
|
|
||||||
/* Open EFI volume */
|
|
||||||
Status = XtLdrProtocol->OpenVolume(NULL, &DiskHandle, &FsHandle);
|
|
||||||
if(Status != STATUS_EFI_SUCCESS)
|
|
||||||
{
|
|
||||||
/* Failed to open a volume */
|
|
||||||
XtLdrProtocol->DbgPrint(L"ERROR: Unable to open boot volume\n");
|
|
||||||
return Status;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* System path has to point to the boot directory */
|
|
||||||
RtlConcatenateWideString(Parameters->SystemPath, 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->DbgPrint(L"ERROR: System boot directory not found\n");
|
|
||||||
|
|
||||||
/* Close volume */
|
|
||||||
XtLdrProtocol->CloseVolume(DiskHandle);
|
|
||||||
return Status;
|
|
||||||
}
|
|
||||||
else if(Status != STATUS_EFI_SUCCESS)
|
|
||||||
{
|
|
||||||
/* Failed to open directory */
|
|
||||||
XtLdrProtocol->DbgPrint(L"ERROR: Unable to open system boot directory\n");
|
|
||||||
XtLdrProtocol->CloseVolume(DiskHandle);
|
|
||||||
return Status;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Start boot sequence */
|
|
||||||
return XtpBootSequence(BootDir, Parameters);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 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
|
|
||||||
XtpBootSequence(IN PEFI_FILE_HANDLE BootDir,
|
|
||||||
IN PXT_BOOT_PROTOCOL_PARAMETERS Parameters)
|
|
||||||
{
|
|
||||||
EFI_GUID LoadedImageGuid = EFI_LOADED_IMAGE_PROTOCOL_GUID;
|
|
||||||
PKERNEL_INITIALIZATION_BLOCK KernelParameters;
|
|
||||||
PPECOFF_IMAGE_CONTEXT ImageContext = NULL;
|
|
||||||
PEFI_LOADED_IMAGE_PROTOCOL ImageProtocol;
|
|
||||||
PVOID VirtualAddress, VirtualMemoryArea;
|
|
||||||
PXT_ENTRY_POINT KernelEntryPoint;
|
|
||||||
LIST_ENTRY MemoryMappings;
|
|
||||||
EFI_STATUS Status;
|
|
||||||
|
|
||||||
/* Initialize XTOS startup sequence */
|
|
||||||
XtLdrProtocol->DbgPrint(L"Initializing XTOS startup sequence\n");
|
|
||||||
|
|
||||||
/* Set base virtual memory area for the kernel mappings */
|
|
||||||
VirtualMemoryArea = (PVOID)KSEG0_BASE;
|
|
||||||
VirtualAddress = (PVOID)(KSEG0_BASE + KSEG0_KERNEL_BASE);
|
|
||||||
|
|
||||||
/* Initialize memory mapping linked list */
|
|
||||||
RtlInitializeListHead(&MemoryMappings);
|
|
||||||
|
|
||||||
/* Initialize virtual memory mappings */
|
|
||||||
Status = XtLdrProtocol->InitializeVirtualMemory(&MemoryMappings, &VirtualMemoryArea);
|
|
||||||
if(Status != STATUS_EFI_SUCCESS)
|
|
||||||
{
|
|
||||||
/* Failed to initialize virtual memory */
|
|
||||||
return Status;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Load the kernel */
|
|
||||||
Status = XtpLoadModule(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->AddVirtualMemoryMapping(&MemoryMappings, ImageContext->VirtualAddress,
|
|
||||||
ImageContext->PhysicalAddress, ImageContext->ImagePages, 0);
|
|
||||||
if(Status != STATUS_EFI_SUCCESS)
|
|
||||||
{
|
|
||||||
return Status;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Set next valid virtual address right after the kernel */
|
|
||||||
VirtualAddress += ImageContext->ImagePages * EFI_PAGE_SIZE;
|
|
||||||
|
|
||||||
/* Store virtual address of kernel initialization block for future kernel call */
|
|
||||||
KernelParameters = (PKERNEL_INITIALIZATION_BLOCK)VirtualAddress;
|
|
||||||
|
|
||||||
/* Setup and map kernel initialization block */
|
|
||||||
Status = XtpInitializeLoaderBlock(&MemoryMappings, &VirtualAddress);
|
|
||||||
if(Status != STATUS_EFI_SUCCESS)
|
|
||||||
{
|
|
||||||
/* Failed to setup kernel initialization block */
|
|
||||||
XtLdrProtocol->DbgPrint(L"Failed to setup kernel initialization block (Status Code: %lx)\n", Status);
|
|
||||||
return Status;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Find and map APIC base address */
|
|
||||||
Status = XtpInitializeApicBase(&MemoryMappings);
|
|
||||||
if(Status != STATUS_EFI_SUCCESS)
|
|
||||||
{
|
|
||||||
/* Failed to setup kernel initialization block */
|
|
||||||
XtLdrProtocol->DbgPrint(L"Failed to initialize APIC (Status Code: %lx)\n", Status);
|
|
||||||
return Status;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Get kernel entry point */
|
|
||||||
XtPeCoffProtocol->GetEntryPoint(ImageContext, (PVOID)&KernelEntryPoint);
|
|
||||||
|
|
||||||
/* Close boot directory handle */
|
|
||||||
BootDir->Close(BootDir);
|
|
||||||
|
|
||||||
/* Enable paging */
|
|
||||||
EfiSystemTable->BootServices->HandleProtocol(EfiImageHandle, &LoadedImageGuid, (PVOID*)&ImageProtocol);
|
|
||||||
Status = XtLdrProtocol->EnablePaging(&MemoryMappings, VirtualAddress, ImageProtocol, &XtPageMap);
|
|
||||||
if(Status != STATUS_EFI_SUCCESS)
|
|
||||||
{
|
|
||||||
/* Failed to enable paging */
|
|
||||||
XtLdrProtocol->DbgPrint(L"Failed to enable paging (Status Code: %lx)\n", Status);
|
|
||||||
return Status;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Call XTOS kernel */
|
|
||||||
XtLdrProtocol->DbgPrint(L"Booting the XTOS kernel\n");
|
|
||||||
KernelEntryPoint(KernelParameters);
|
|
||||||
|
|
||||||
/* Return success */
|
|
||||||
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
|
|
||||||
XtpInitializeApicBase(IN PLIST_ENTRY MemoryMappings)
|
|
||||||
{
|
|
||||||
PCPUID_REGISTERS CpuRegisters = NULL;
|
|
||||||
PVOID ApicBaseAddress;
|
|
||||||
|
|
||||||
/* Get CPU features list */
|
|
||||||
CpuRegisters->Leaf = CPUID_GET_CPU_FEATURES;
|
|
||||||
CpuRegisters->SubLeaf = 0;
|
|
||||||
CpuRegisters->Eax = 0;
|
|
||||||
CpuRegisters->Ebx = 0;
|
|
||||||
CpuRegisters->Ecx = 0;
|
|
||||||
CpuRegisters->Edx = 0;
|
|
||||||
ArCpuId(CpuRegisters);
|
|
||||||
|
|
||||||
/* Check if APIC is present */
|
|
||||||
if((CpuRegisters->Edx & CPUID_FEATURES_EDX_APIC) == 0)
|
|
||||||
{
|
|
||||||
/* APIC is not supported by the CPU */
|
|
||||||
return STATUS_EFI_UNSUPPORTED;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Get APIC base address */
|
|
||||||
ApicBaseAddress = (PVOID)((UINT_PTR)ArReadModelSpecificRegister(0x1B) & 0xFFFFF000);
|
|
||||||
|
|
||||||
/* Map APIC base address */
|
|
||||||
XtLdrProtocol->AddVirtualMemoryMapping(MemoryMappings, (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
|
|
||||||
XtpInitializeLoaderBlock(IN PLIST_ENTRY MemoryMappings,
|
|
||||||
IN PVOID *VirtualAddress)
|
|
||||||
{
|
|
||||||
EFI_GUID FrameBufGuid = XT_FRAMEBUFFER_PROTOCOL_GUID;
|
|
||||||
PXT_FRAMEBUFFER_PROTOCOL FrameBufProtocol;
|
|
||||||
PKERNEL_INITIALIZATION_BLOCK LoaderBlock;
|
|
||||||
EFI_PHYSICAL_ADDRESS Address;
|
|
||||||
PVOID RuntimeServices;
|
|
||||||
EFI_STATUS Status;
|
|
||||||
UINT BlockPages, FrameBufferPages;
|
|
||||||
|
|
||||||
/* Calculate number of pages needed for initialization block */
|
|
||||||
BlockPages = EFI_SIZE_TO_PAGES(sizeof(KERNEL_INITIALIZATION_BLOCK));
|
|
||||||
|
|
||||||
/* Allocate memory for kernel initialization block */
|
|
||||||
Status = XtLdrProtocol->AllocatePages(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;
|
|
||||||
RtlZeroMemory(LoaderBlock, sizeof(KERNEL_INITIALIZATION_BLOCK));
|
|
||||||
|
|
||||||
/* 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 = XtLdrProtocol->DbgPrint;
|
|
||||||
|
|
||||||
/* Load FrameBuffer protocol */
|
|
||||||
Status = BlLoadXtProtocol((PVOID *)&FrameBufProtocol, &FrameBufGuid);
|
|
||||||
if(Status == STATUS_EFI_SUCCESS)
|
|
||||||
{
|
|
||||||
/* Make sure FrameBuffer is initialized */
|
|
||||||
FrameBufProtocol->Initialize();
|
|
||||||
FrameBufProtocol->PrintDisplayInformation();
|
|
||||||
|
|
||||||
/* Store information about FrameBuffer device */
|
|
||||||
FrameBufProtocol->GetDisplayInformation(&LoaderBlock->LoaderInformation.FrameBuffer);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
/* No FrameBuffer available */
|
|
||||||
LoaderBlock->LoaderInformation.FrameBuffer.Initialized = FALSE;
|
|
||||||
LoaderBlock->LoaderInformation.FrameBuffer.Protocol = NONE;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Attempt to find virtual address of the EFI Runtime Services */
|
|
||||||
Status = XtLdrProtocol->GetVirtualAddress(MemoryMappings, &EfiSystemTable->RuntimeServices->Hdr, &RuntimeServices);
|
|
||||||
if(Status == STATUS_EFI_SUCCESS)
|
|
||||||
{
|
|
||||||
/* Set FirmwareInformation block properties */
|
|
||||||
LoaderBlock->FirmwareInformation.FirmwareType = SystemFirmwareEfi;
|
|
||||||
LoaderBlock->FirmwareInformation.EfiFirmware.EfiVersion = EfiSystemTable->Hdr.Revision;
|
|
||||||
LoaderBlock->FirmwareInformation.EfiFirmware.EfiRuntimeServices = RuntimeServices;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
/* Set invalid firmware type to indicate that kernel cannot rely on FirmwareInformation block */
|
|
||||||
LoaderBlock->FirmwareInformation.FirmwareType = SystemFirmwareInvalid;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Map kernel initialization block */
|
|
||||||
XtLdrProtocol->AddVirtualMemoryMapping(MemoryMappings, *VirtualAddress, (PVOID)LoaderBlock,
|
|
||||||
BlockPages, LoaderSystemBlock);
|
|
||||||
|
|
||||||
/* Calculate next valid virtual address */
|
|
||||||
*VirtualAddress += (UINT_PTR)(BlockPages * EFI_PAGE_SIZE);
|
|
||||||
|
|
||||||
/* Check if framebuffer initialized */
|
|
||||||
if(LoaderBlock->LoaderInformation.FrameBuffer.Initialized)
|
|
||||||
{
|
|
||||||
/* Calculate pages needed to map framebuffer */
|
|
||||||
FrameBufferPages = EFI_SIZE_TO_PAGES(LoaderBlock->LoaderInformation.FrameBuffer.BufferSize);
|
|
||||||
|
|
||||||
/* Map frame buffer memory */
|
|
||||||
XtLdrProtocol->AddVirtualMemoryMapping(MemoryMappings, *VirtualAddress,
|
|
||||||
LoaderBlock->LoaderInformation.FrameBuffer.Address,
|
|
||||||
FrameBufferPages, LoaderFirmwarePermanent);
|
|
||||||
|
|
||||||
/* Rewrite framebuffer address by using virtual address */
|
|
||||||
LoaderBlock->LoaderInformation.FrameBuffer.Address = *VirtualAddress;
|
|
||||||
|
|
||||||
/* Calcualate next valid virtual address */
|
|
||||||
*VirtualAddress += (UINT_PTR)(FrameBufferPages * EFI_PAGE_SIZE);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Return success */
|
|
||||||
return STATUS_EFI_SUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 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
|
|
||||||
XtpLoadModule(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->DbgPrint(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->DbgPrint(L"ERROR: Failed to open '%S'\n", FileName);
|
|
||||||
return Status;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Load the PE/COFF image file */
|
|
||||||
Status = XtPeCoffProtocol->Load(ModuleHandle, MemoryType, VirtualAddress, ImageContext);
|
|
||||||
if(Status != STATUS_EFI_SUCCESS)
|
|
||||||
{
|
|
||||||
/* Unable to load the file */
|
|
||||||
XtLdrProtocol->DbgPrint(L"ERROR: Failed to load '%S'\n", FileName);
|
|
||||||
return Status;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Close image file */
|
|
||||||
ModuleHandle->Close(ModuleHandle);
|
|
||||||
|
|
||||||
/* Check PE/COFF image machine type compatibility */
|
|
||||||
XtPeCoffProtocol->GetMachineType(*ImageContext, &MachineType);
|
|
||||||
if(MachineType != _ARCH_IMAGE_MACHINE_TYPE)
|
|
||||||
{
|
|
||||||
/* Machine type mismatch */
|
|
||||||
XtLdrProtocol->DbgPrint(L"ERROR: Loaded incompatible PE/COFF image (machine type mismatch)\n");
|
|
||||||
return STATUS_EFI_INCOMPATIBLE_VERSION;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Check PE/COFF image subsystem */
|
|
||||||
XtPeCoffProtocol->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->DbgPrint(L"WARNING: Loaded PE/COFF image with non-XT subsystem set\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Print debug message */
|
|
||||||
XtLdrProtocol->DbgPrint(L"Loaded %S at PA: 0x%lx, VA: 0x%lx\n", FileName,
|
|
||||||
(*ImageContext)->PhysicalAddress, (*ImageContext)->VirtualAddress);
|
|
||||||
|
|
||||||
/* 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
|
|
||||||
BlXtLdrModuleMain(IN EFI_HANDLE ImageHandle,
|
|
||||||
IN PEFI_SYSTEM_TABLE SystemTable)
|
|
||||||
{
|
|
||||||
EFI_GUID Guid = XT_XTOS_BOOT_PROTOCOL_GUID;
|
|
||||||
EFI_HANDLE Handle = NULL;
|
|
||||||
EFI_STATUS Status;
|
|
||||||
|
|
||||||
/* Set the system table and image handle */
|
|
||||||
EfiImageHandle = ImageHandle;
|
|
||||||
EfiSystemTable = SystemTable;
|
|
||||||
|
|
||||||
/* Open the XTLDR protocol */
|
|
||||||
Status = BlGetXtLoaderProtocol(&XtLdrProtocol);
|
|
||||||
if(Status != STATUS_EFI_SUCCESS)
|
|
||||||
{
|
|
||||||
/* Failed to open loader protocol */
|
|
||||||
return STATUS_EFI_PROTOCOL_ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Set routines available via XTOS boot protocol */
|
|
||||||
XtBootProtocol.BootSystem = XtBootSystem;
|
|
||||||
|
|
||||||
/* Register XTOS boot protocol */
|
|
||||||
return EfiSystemTable->BootServices->InstallProtocolInterface(&Handle, &Guid, EFI_NATIVE_INTERFACE,
|
|
||||||
&XtBootProtocol);
|
|
||||||
}
|
|
190
xtldr/string.c
190
xtldr/string.c
@ -2,73 +2,17 @@
|
|||||||
* PROJECT: ExectOS
|
* PROJECT: ExectOS
|
||||||
* COPYRIGHT: See COPYING.md in the top level directory
|
* COPYRIGHT: See COPYING.md in the top level directory
|
||||||
* FILE: xtldr/string.c
|
* FILE: xtldr/string.c
|
||||||
* DESCRIPTION: EFI string operations support
|
* DESCRIPTION: EFI string manipulation support
|
||||||
* DEVELOPERS: Rafal Kupiec <belliash@codingworkshop.eu.org>
|
* DEVELOPERS: Rafal Kupiec <belliash@codingworkshop.eu.org>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <xtbl.h>
|
#include <xtldr.h>
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Compares two strings without sensitivity to case.
|
|
||||||
*
|
|
||||||
* @param String1
|
|
||||||
* First string to be compared.
|
|
||||||
*
|
|
||||||
* @param String2
|
|
||||||
* Second string to be compared.
|
|
||||||
*
|
|
||||||
* @return This routine returns a value indicating the relationship between the two strings.
|
|
||||||
*
|
|
||||||
* @since XT 1.0
|
|
||||||
*/
|
|
||||||
XTCDECL
|
|
||||||
INT
|
|
||||||
BlStringCompareInsensitive(IN PUCHAR String1,
|
|
||||||
IN PUCHAR String2)
|
|
||||||
{
|
|
||||||
UCHAR Character1;
|
|
||||||
UCHAR Character2;
|
|
||||||
ULONG Index = 0;
|
|
||||||
|
|
||||||
/* Iterate through the strings */
|
|
||||||
while(String1[Index] != '\0' && String2[Index] != '\0')
|
|
||||||
{
|
|
||||||
/* Get the characters */
|
|
||||||
Character1 = String1[Index];
|
|
||||||
Character2 = String2[Index];
|
|
||||||
|
|
||||||
/* Lowercase string1 character if needed */
|
|
||||||
if(String1[Index] >= 'A' && String1[Index] <= 'Z')
|
|
||||||
{
|
|
||||||
Character1 = String1[Index] - 'A' + 'a';
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Lowercase string2 character if needed */
|
|
||||||
if(String2[Index] >= 'A' && String2[Index] <= 'Z')
|
|
||||||
{
|
|
||||||
Character2 = String2[Index] - 'A' + 'a';
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Compare the characters */
|
|
||||||
if(Character1 != Character2)
|
|
||||||
{
|
|
||||||
/* Strings are not equal */
|
|
||||||
return Character1 > Character2 ? 1 : -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Get next character */
|
|
||||||
Index++;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Strings are equal */
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This routine formats the input string and prints it using specified routine.
|
* This routine formats the input string and prints it using specified routine.
|
||||||
*
|
*
|
||||||
* @param PutChar
|
* @param PrintCharRoutine
|
||||||
* Pointer to the routine that writes an input data to specific device.
|
* Pointer to the routine that writes an input data to specific device.
|
||||||
*
|
*
|
||||||
* @param Format
|
* @param Format
|
||||||
@ -83,9 +27,9 @@ BlStringCompareInsensitive(IN PUCHAR String1,
|
|||||||
*/
|
*/
|
||||||
XTCDECL
|
XTCDECL
|
||||||
VOID
|
VOID
|
||||||
BlStringPrint(IN VOID PutChar(IN USHORT Character),
|
BlpStringPrint(IN IN BLPRINTCHAR PrintCharRoutine,
|
||||||
IN PUINT16 Format,
|
IN PUINT16 Format,
|
||||||
IN VA_LIST Arguments)
|
IN VA_LIST Arguments)
|
||||||
{
|
{
|
||||||
PEFI_GUID Guid;
|
PEFI_GUID Guid;
|
||||||
PUCHAR String;
|
PUCHAR String;
|
||||||
@ -102,20 +46,20 @@ BlStringPrint(IN VOID PutChar(IN USHORT Character),
|
|||||||
{
|
{
|
||||||
case L'b':
|
case L'b':
|
||||||
/* Boolean */
|
/* Boolean */
|
||||||
BlpStringFormat(PutChar, L"%s", VA_ARG(Arguments, INT32) ? "TRUE" : "FALSE");
|
BlpStringFormat(PrintCharRoutine, L"%s", VA_ARG(Arguments, INT32) ? "TRUE" : "FALSE");
|
||||||
break;
|
break;
|
||||||
case L'c':
|
case L'c':
|
||||||
/* Character */
|
/* Character */
|
||||||
PutChar(VA_ARG(Arguments, INT));
|
PrintCharRoutine(VA_ARG(Arguments, INT));
|
||||||
break;
|
break;
|
||||||
case L'd':
|
case L'd':
|
||||||
/* Signed 32-bit integer */
|
/* Signed 32-bit integer */
|
||||||
BlpStringPrintSigned32(PutChar, VA_ARG(Arguments, INT32), 10);
|
BlpStringPrintSigned32(PrintCharRoutine, VA_ARG(Arguments, INT32), 10);
|
||||||
break;
|
break;
|
||||||
case L'g':
|
case L'g':
|
||||||
/* EFI GUID */
|
/* EFI GUID */
|
||||||
Guid = VA_ARG(Arguments, PEFI_GUID);
|
Guid = VA_ARG(Arguments, PEFI_GUID);
|
||||||
BlpStringFormat(PutChar, L"%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x", Guid->Data1,
|
BlpStringFormat(PrintCharRoutine, L"%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x", Guid->Data1,
|
||||||
Guid->Data2, Guid->Data3, Guid->Data4[0], Guid->Data4[1], Guid->Data4[2],
|
Guid->Data2, Guid->Data3, Guid->Data4[0], Guid->Data4[1], Guid->Data4[2],
|
||||||
Guid->Data4[3], Guid->Data4[4], Guid->Data4[5], Guid->Data4[6], Guid->Data4[7]);
|
Guid->Data4[3], Guid->Data4[4], Guid->Data4[5], Guid->Data4[6], Guid->Data4[7]);
|
||||||
break;
|
break;
|
||||||
@ -125,48 +69,48 @@ BlStringPrint(IN VOID PutChar(IN USHORT Character),
|
|||||||
{
|
{
|
||||||
case L'd':
|
case L'd':
|
||||||
/* Signed 64-bit integer */
|
/* Signed 64-bit integer */
|
||||||
BlpStringPrintSigned64(PutChar, VA_ARG(Arguments, INT_PTR), 10);
|
BlpStringPrintSigned64(PrintCharRoutine, VA_ARG(Arguments, INT_PTR), 10);
|
||||||
break;
|
break;
|
||||||
case L'u':
|
case L'u':
|
||||||
/* Unsigned 64-bit integer */
|
/* Unsigned 64-bit integer */
|
||||||
BlpStringPrintUnsigned64(PutChar, VA_ARG(Arguments, UINT_PTR), 10, 0);
|
BlpStringPrintUnsigned64(PrintCharRoutine, VA_ARG(Arguments, UINT_PTR), 10, 0);
|
||||||
break;
|
break;
|
||||||
case L'x':
|
case L'x':
|
||||||
/* Unsigned 64-bit hexadecimal integer */
|
/* Unsigned 64-bit hexadecimal integer */
|
||||||
BlpStringPrintUnsigned64(PutChar, VA_ARG(Arguments, UINT_PTR), 16, 0);
|
BlpStringPrintUnsigned64(PrintCharRoutine, VA_ARG(Arguments, UINT_PTR), 16, 0);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
/* Unknown by default */
|
/* Unknown by default */
|
||||||
PutChar(L'?');
|
PrintCharRoutine(L'?');
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case L'p':
|
case L'p':
|
||||||
/* Pointer address */
|
/* Pointer address */
|
||||||
BlpStringPrintUnsigned64(PutChar, VA_ARG(Arguments, UINT_PTR), 16, 0);
|
BlpStringPrintUnsigned64(PrintCharRoutine, VA_ARG(Arguments, UINT_PTR), 16, 0);
|
||||||
break;
|
break;
|
||||||
case L's':
|
case L's':
|
||||||
/* String of characters */
|
/* String of characters */
|
||||||
String = VA_ARG(Arguments, PUCHAR);
|
String = VA_ARG(Arguments, PUCHAR);
|
||||||
while(*String)
|
while(*String)
|
||||||
{
|
{
|
||||||
PutChar(*String++);
|
PrintCharRoutine(*String++);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case L'S':
|
case L'S':
|
||||||
WideString = VA_ARG(Arguments, PWCHAR);
|
WideString = VA_ARG(Arguments, PWCHAR);
|
||||||
while(*WideString)
|
while(*WideString)
|
||||||
{
|
{
|
||||||
PutChar((UCHAR)*WideString++);
|
PrintCharRoutine((UCHAR)*WideString++);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case L'u':
|
case L'u':
|
||||||
/* Unsigned 32-bit integer */
|
/* Unsigned 32-bit integer */
|
||||||
BlpStringPrintUnsigned32(PutChar, VA_ARG(Arguments, UINT32), 10, 0);
|
BlpStringPrintUnsigned32(PrintCharRoutine, VA_ARG(Arguments, UINT32), 10, 0);
|
||||||
break;
|
break;
|
||||||
case L'x':
|
case L'x':
|
||||||
/* Unsigned 32-bit hexadecimal integer */
|
/* Unsigned 32-bit hexadecimal integer */
|
||||||
BlpStringPrintUnsigned32(PutChar, VA_ARG(Arguments, UINT32), 16, 0);
|
BlpStringPrintUnsigned32(PrintCharRoutine, VA_ARG(Arguments, UINT32), 16, 0);
|
||||||
break;
|
break;
|
||||||
case L'0':
|
case L'0':
|
||||||
/* Zero padded numbers */
|
/* Zero padded numbers */
|
||||||
@ -176,7 +120,7 @@ BlStringPrint(IN VOID PutChar(IN USHORT Character),
|
|||||||
{
|
{
|
||||||
case L'd':
|
case L'd':
|
||||||
/* Zero-padded, signed 32-bit integer */
|
/* Zero-padded, signed 32-bit integer */
|
||||||
BlpStringPrintSigned32(PutChar, VA_ARG(Arguments, INT32), 10);
|
BlpStringPrintSigned32(PrintCharRoutine, VA_ARG(Arguments, INT32), 10);
|
||||||
break;
|
break;
|
||||||
case L'l':
|
case L'l':
|
||||||
/* 64-bit numbers */
|
/* 64-bit numbers */
|
||||||
@ -184,43 +128,43 @@ BlStringPrint(IN VOID PutChar(IN USHORT Character),
|
|||||||
{
|
{
|
||||||
case L'd':
|
case L'd':
|
||||||
/* Zero-padded, signed 64-bit integer */
|
/* Zero-padded, signed 64-bit integer */
|
||||||
BlpStringPrintSigned64(PutChar, VA_ARG(Arguments, INT_PTR), 10);
|
BlpStringPrintSigned64(PrintCharRoutine, VA_ARG(Arguments, INT_PTR), 10);
|
||||||
break;
|
break;
|
||||||
case L'u':
|
case L'u':
|
||||||
/* Zero-padded, unsigned 64-bit integer */
|
/* Zero-padded, unsigned 64-bit integer */
|
||||||
BlpStringPrintUnsigned64(PutChar, VA_ARG(Arguments, UINT_PTR), 10, PaddingCount);
|
BlpStringPrintUnsigned64(PrintCharRoutine, VA_ARG(Arguments, UINT_PTR), 10, PaddingCount);
|
||||||
break;
|
break;
|
||||||
case L'x':
|
case L'x':
|
||||||
/* Zero-padded, unsigned 64-bit hexadecimal integer */
|
/* Zero-padded, unsigned 64-bit hexadecimal integer */
|
||||||
BlpStringPrintUnsigned64(PutChar, VA_ARG(Arguments, UINT_PTR), 16, PaddingCount);
|
BlpStringPrintUnsigned64(PrintCharRoutine, VA_ARG(Arguments, UINT_PTR), 16, PaddingCount);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
/* Unknown by default */
|
/* Unknown by default */
|
||||||
PutChar(L'?');
|
PrintCharRoutine(L'?');
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case L'u':
|
case L'u':
|
||||||
/* Zero-padded, unsigned 32-bit integer */
|
/* Zero-padded, unsigned 32-bit integer */
|
||||||
BlpStringPrintUnsigned32(PutChar, VA_ARG(Arguments, UINT32), 10, PaddingCount);
|
BlpStringPrintUnsigned32(PrintCharRoutine, VA_ARG(Arguments, UINT32), 10, PaddingCount);
|
||||||
break;
|
break;
|
||||||
case L'x':
|
case L'x':
|
||||||
/* Zero-padded, unsigned 32-bit hexadecimal integer */
|
/* Zero-padded, unsigned 32-bit hexadecimal integer */
|
||||||
BlpStringPrintUnsigned32(PutChar, VA_ARG(Arguments, UINT32), 16, PaddingCount);
|
BlpStringPrintUnsigned32(PrintCharRoutine, VA_ARG(Arguments, UINT32), 16, PaddingCount);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
/* Unknown by default */
|
/* Unknown by default */
|
||||||
PutChar(L'?');
|
PrintCharRoutine(L'?');
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case L'%':
|
case L'%':
|
||||||
/* Percent character */
|
/* Percent character */
|
||||||
PutChar(L'%');
|
PrintCharRoutine(L'%');
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
/* Unknown by default */
|
/* Unknown by default */
|
||||||
PutChar(L'?');
|
PrintCharRoutine(L'?');
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@ -229,12 +173,12 @@ BlStringPrint(IN VOID PutChar(IN USHORT Character),
|
|||||||
break;
|
break;
|
||||||
case L'\n':
|
case L'\n':
|
||||||
/* New line together with carriage return */
|
/* New line together with carriage return */
|
||||||
PutChar(L'\r');
|
PrintCharRoutine(L'\r');
|
||||||
PutChar(L'\n');
|
PrintCharRoutine(L'\n');
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
/* Put character by default */
|
/* Put character by default */
|
||||||
PutChar(*Format);
|
PrintCharRoutine(*Format);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -243,7 +187,7 @@ BlStringPrint(IN VOID PutChar(IN USHORT Character),
|
|||||||
/**
|
/**
|
||||||
* This routine formats the input string and prints it using specified routine.
|
* This routine formats the input string and prints it using specified routine.
|
||||||
*
|
*
|
||||||
* @param PutChar
|
* @param PrintCharRoutine
|
||||||
* Pointer to the routine that writes an input data to specific device.
|
* Pointer to the routine that writes an input data to specific device.
|
||||||
*
|
*
|
||||||
* @param Format
|
* @param Format
|
||||||
@ -258,7 +202,7 @@ BlStringPrint(IN VOID PutChar(IN USHORT Character),
|
|||||||
*/
|
*/
|
||||||
XTCDECL
|
XTCDECL
|
||||||
VOID
|
VOID
|
||||||
BlpStringFormat(IN VOID PutChar(IN USHORT Character),
|
BlpStringFormat(IN BLPRINTCHAR PrintCharRoutine,
|
||||||
IN PUINT16 Format,
|
IN PUINT16 Format,
|
||||||
IN ...)
|
IN ...)
|
||||||
{
|
{
|
||||||
@ -268,7 +212,7 @@ BlpStringFormat(IN VOID PutChar(IN USHORT Character),
|
|||||||
VA_START(Arguments, Format);
|
VA_START(Arguments, Format);
|
||||||
|
|
||||||
/* Format and print the string to the desired output */
|
/* Format and print the string to the desired output */
|
||||||
BlStringPrint(PutChar, Format, Arguments);
|
BlpStringPrint(PrintCharRoutine, Format, Arguments);
|
||||||
|
|
||||||
/* Clean up the va_list */
|
/* Clean up the va_list */
|
||||||
VA_END(Arguments);
|
VA_END(Arguments);
|
||||||
@ -277,7 +221,7 @@ BlpStringFormat(IN VOID PutChar(IN USHORT Character),
|
|||||||
/**
|
/**
|
||||||
* This routine converts 32-bit integer as string and prints it using specified routine.
|
* This routine converts 32-bit integer as string and prints it using specified routine.
|
||||||
*
|
*
|
||||||
* @param PutChar
|
* @param PrintCharRoutine
|
||||||
* Pointer to the routine that writes an input data to specific device.
|
* Pointer to the routine that writes an input data to specific device.
|
||||||
*
|
*
|
||||||
* @param Number
|
* @param Number
|
||||||
@ -292,25 +236,25 @@ BlpStringFormat(IN VOID PutChar(IN USHORT Character),
|
|||||||
*/
|
*/
|
||||||
XTCDECL
|
XTCDECL
|
||||||
VOID
|
VOID
|
||||||
BlpStringPrintSigned32(IN VOID PutChar(IN USHORT Character),
|
BlpStringPrintSigned32(IN BLPRINTCHAR PrintCharRoutine,
|
||||||
IN INT32 Number,
|
IN INT Number,
|
||||||
IN UINT32 Base)
|
IN UINT Base)
|
||||||
{
|
{
|
||||||
/* Print - (minus) if this is negative value */
|
/* Print - (minus) if this is negative value */
|
||||||
if(Number < 0)
|
if(Number < 0)
|
||||||
{
|
{
|
||||||
PutChar(L'-');
|
PrintCharRoutine(L'-');
|
||||||
Number *= -1;
|
Number *= -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Print the integer value */
|
/* Print the integer value */
|
||||||
BlpStringPrintUnsigned32(PutChar, Number, Base, 0);
|
BlpStringPrintUnsigned32(PrintCharRoutine, Number, Base, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This routine converts 64-bit integer as string and prints it using specified routine.
|
* This routine converts 64-bit integer as string and prints it using specified routine.
|
||||||
*
|
*
|
||||||
* @param PutChar
|
* @param PrintCharRoutine
|
||||||
* Pointer to the routine that writes an input data to specific device.
|
* Pointer to the routine that writes an input data to specific device.
|
||||||
*
|
*
|
||||||
* @param Number
|
* @param Number
|
||||||
@ -325,25 +269,25 @@ BlpStringPrintSigned32(IN VOID PutChar(IN USHORT Character),
|
|||||||
*/
|
*/
|
||||||
XTCDECL
|
XTCDECL
|
||||||
VOID
|
VOID
|
||||||
BlpStringPrintSigned64(IN VOID PutChar(IN USHORT Character),
|
BlpStringPrintSigned64(IN BLPRINTCHAR PrintCharRoutine,
|
||||||
IN INT_PTR Number,
|
IN INT_PTR Number,
|
||||||
IN UINT_PTR Base)
|
IN UINT_PTR Base)
|
||||||
{
|
{
|
||||||
/* Print - (minus) if this is negative value */
|
/* Print - (minus) if this is negative value */
|
||||||
if(Number < 0)
|
if(Number < 0)
|
||||||
{
|
{
|
||||||
PutChar(L'-');
|
PrintCharRoutine(L'-');
|
||||||
Number *= -1;
|
Number *= -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Print the integer value */
|
/* Print the integer value */
|
||||||
BlpStringPrintUnsigned64(PutChar, Number, Base, 0);
|
BlpStringPrintUnsigned64(PrintCharRoutine, Number, Base, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This routine converts 32-bit unsigned integer as string and prints it using specified routine.
|
* This routine converts 32-bit unsigned integer as string and prints it using specified routine.
|
||||||
*
|
*
|
||||||
* @param PutChar
|
* @param PrintCharRoutine
|
||||||
* Pointer to the routine that writes an input data to specific device.
|
* Pointer to the routine that writes an input data to specific device.
|
||||||
*
|
*
|
||||||
* @param Number
|
* @param Number
|
||||||
@ -361,23 +305,27 @@ BlpStringPrintSigned64(IN VOID PutChar(IN USHORT Character),
|
|||||||
*/
|
*/
|
||||||
XTCDECL
|
XTCDECL
|
||||||
VOID
|
VOID
|
||||||
BlpStringPrintUnsigned32(IN VOID PutChar(IN USHORT Character),
|
BlpStringPrintUnsigned32(IN BLPRINTCHAR PrintCharRoutine,
|
||||||
IN UINT32 Number,
|
IN UINT Number,
|
||||||
IN UINT32 Base,
|
IN UINT Base,
|
||||||
IN UINT32 Padding)
|
IN UINT Padding)
|
||||||
{
|
{
|
||||||
UINT32 Buffer[20];
|
UINT Buffer[20];
|
||||||
PUINT32 Pointer = Buffer + ARRAY_SIZE(Buffer);
|
UINT NumberLength;
|
||||||
|
PUINT Pointer;
|
||||||
|
|
||||||
|
/* Set pointer to the end of buffer */
|
||||||
|
Pointer = Buffer + ARRAY_SIZE(Buffer);
|
||||||
|
|
||||||
/* Convert value to specified base system */
|
/* Convert value to specified base system */
|
||||||
*--Pointer = 0;
|
*--Pointer = 0;
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
*--Pointer = EfiHexTable[Number % Base];
|
*--Pointer = BlpHexTable[Number % Base];
|
||||||
} while(Pointer >= Buffer && (Number /= Base));
|
} while(Pointer >= Buffer && (Number /= Base));
|
||||||
|
|
||||||
/* Calculate number length */
|
/* Calculate number length */
|
||||||
UINT32 NumberLength = ARRAY_SIZE(Buffer) - (Pointer - Buffer) - 1;
|
NumberLength = ARRAY_SIZE(Buffer) - (Pointer - Buffer) - 1;
|
||||||
|
|
||||||
/* Check if leading zeros are needed */
|
/* Check if leading zeros are needed */
|
||||||
if(NumberLength < Padding)
|
if(NumberLength < Padding)
|
||||||
@ -386,21 +334,21 @@ BlpStringPrintUnsigned32(IN VOID PutChar(IN USHORT Character),
|
|||||||
while(Padding--)
|
while(Padding--)
|
||||||
{
|
{
|
||||||
/* Write leading zeroes */
|
/* Write leading zeroes */
|
||||||
PutChar(L'0');
|
PrintCharRoutine(L'0');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Print value to the console */
|
/* Print value to the console */
|
||||||
for(; *Pointer; ++Pointer)
|
for(; *Pointer; ++Pointer)
|
||||||
{
|
{
|
||||||
PutChar(*Pointer);
|
PrintCharRoutine(*Pointer);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This routine converts 64-bit unsigned integer as string and prints it using specified routine.
|
* This routine converts 64-bit unsigned integer as string and prints it using specified routine.
|
||||||
*
|
*
|
||||||
* @param PutChar
|
* @param PrintCharRoutine
|
||||||
* Pointer to the routine that writes an input data to specific device.
|
* Pointer to the routine that writes an input data to specific device.
|
||||||
*
|
*
|
||||||
* @param Number
|
* @param Number
|
||||||
@ -418,23 +366,27 @@ BlpStringPrintUnsigned32(IN VOID PutChar(IN USHORT Character),
|
|||||||
*/
|
*/
|
||||||
XTCDECL
|
XTCDECL
|
||||||
VOID
|
VOID
|
||||||
BlpStringPrintUnsigned64(IN VOID PutChar(IN USHORT Character),
|
BlpStringPrintUnsigned64(IN BLPRINTCHAR PrintCharRoutine,
|
||||||
IN UINT_PTR Number,
|
IN UINT_PTR Number,
|
||||||
IN UINT_PTR Base,
|
IN UINT_PTR Base,
|
||||||
IN UINT_PTR Padding)
|
IN UINT_PTR Padding)
|
||||||
{
|
{
|
||||||
UINT16 Buffer[20];
|
UINT16 Buffer[20];
|
||||||
PUINT16 Pointer = Buffer + ARRAY_SIZE(Buffer);
|
UINT_PTR NumberLength;
|
||||||
|
PUINT16 Pointer;
|
||||||
|
|
||||||
|
/* Set pointer to the end of buffer */
|
||||||
|
Pointer = Buffer + ARRAY_SIZE(Buffer);
|
||||||
|
|
||||||
/* Convert value to specified base system */
|
/* Convert value to specified base system */
|
||||||
*--Pointer = 0;
|
*--Pointer = 0;
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
*--Pointer = EfiHexTable[Number % Base];
|
*--Pointer = BlpHexTable[Number % Base];
|
||||||
} while(Pointer >= Buffer && (Number /= Base));
|
} while(Pointer >= Buffer && (Number /= Base));
|
||||||
|
|
||||||
/* Calculate number length */
|
/* Calculate number length */
|
||||||
UINT_PTR NumberLength = ARRAY_SIZE(Buffer) - (Pointer - Buffer) - 1;
|
NumberLength = ARRAY_SIZE(Buffer) - (Pointer - Buffer) - 1;
|
||||||
|
|
||||||
/* Check if leading zeros are needed */
|
/* Check if leading zeros are needed */
|
||||||
if(NumberLength < Padding)
|
if(NumberLength < Padding)
|
||||||
@ -443,14 +395,14 @@ BlpStringPrintUnsigned64(IN VOID PutChar(IN USHORT Character),
|
|||||||
while(Padding--)
|
while(Padding--)
|
||||||
{
|
{
|
||||||
/* Write leading zeroes */
|
/* Write leading zeroes */
|
||||||
PutChar(L'0');
|
PrintCharRoutine(L'0');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Print value to the console */
|
/* Print value to the console */
|
||||||
for(; *Pointer; ++Pointer)
|
for(; *Pointer; ++Pointer)
|
||||||
{
|
{
|
||||||
PutChar(*Pointer);
|
PrintCharRoutine(*Pointer);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,77 +0,0 @@
|
|||||||
/**
|
|
||||||
* PROJECT: ExectOS
|
|
||||||
* COPYRIGHT: See COPYING.md in the top level directory
|
|
||||||
* FILE: xtldr/system.c
|
|
||||||
* DESCRIPTION: EFI system information
|
|
||||||
* DEVELOPERS: Rafal Kupiec <belliash@codingworkshop.eu.org>
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <xtbl.h>
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This routine 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
|
|
||||||
BlEfiGetSecureBootStatus()
|
|
||||||
{
|
|
||||||
EFI_GUID VarGuid = EFI_GLOBAL_VARIABLE_GUID;
|
|
||||||
INT_PTR SecureBootStatus = 0;
|
|
||||||
UCHAR VarValue = 0;
|
|
||||||
UINT_PTR Size;
|
|
||||||
|
|
||||||
Size = sizeof(VarValue);
|
|
||||||
if(EfiSystemTable->RuntimeServices->GetVariable(L"SecureBoot", &VarGuid,
|
|
||||||
NULL, &Size, &VarValue) == STATUS_EFI_SUCCESS)
|
|
||||||
{
|
|
||||||
SecureBootStatus = (INT_PTR)VarValue;
|
|
||||||
|
|
||||||
if((EfiSystemTable->RuntimeServices->GetVariable(L"SetupMode", &VarGuid,
|
|
||||||
NULL, &Size, &VarValue) == STATUS_EFI_SUCCESS) && VarValue != 0)
|
|
||||||
{
|
|
||||||
SecureBootStatus = -1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Return SecureBoot status */
|
|
||||||
return SecureBootStatus;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Read system configuration from a specified table.
|
|
||||||
*
|
|
||||||
* @param TableGuid
|
|
||||||
* Supplies a pointer to the GUID to search for.
|
|
||||||
*
|
|
||||||
* @param Table
|
|
||||||
* Supplies a pointer that will point to the configuration table.
|
|
||||||
*
|
|
||||||
* @return This routine returns a status code.
|
|
||||||
*
|
|
||||||
* @since XT 1.0
|
|
||||||
*/
|
|
||||||
XTCDECL
|
|
||||||
EFI_STATUS
|
|
||||||
BlEfiGetSystemConfigurationTable(IN PEFI_GUID TableGuid,
|
|
||||||
OUT PVOID *Table)
|
|
||||||
{
|
|
||||||
SIZE_T Size = sizeof(EFI_GUID);
|
|
||||||
UINT_PTR Index;
|
|
||||||
|
|
||||||
for(Index = 0; Index < EfiSystemTable->NumberOfTableEntries; Index++)
|
|
||||||
{
|
|
||||||
if(RtlCompareMemory((PVOID)&EfiSystemTable->ConfigurationTable[Index].VendorGuid, TableGuid, Size) == Size)
|
|
||||||
{
|
|
||||||
*Table = EfiSystemTable->ConfigurationTable[Index].VendorTable;
|
|
||||||
return STATUS_EFI_SUCCESS;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Table not found */
|
|
||||||
return STATUS_EFI_NOT_FOUND;
|
|
||||||
}
|
|
239
xtldr/volume.c
239
xtldr/volume.c
@ -6,7 +6,7 @@
|
|||||||
* DEVELOPERS: Rafal Kupiec <belliash@codingworkshop.eu.org>
|
* DEVELOPERS: Rafal Kupiec <belliash@codingworkshop.eu.org>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <xtbl.h>
|
#include <xtldr.h>
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -45,7 +45,7 @@ BlCloseVolume(IN PEFI_HANDLE VolumeHandle)
|
|||||||
*/
|
*/
|
||||||
XTCDECL
|
XTCDECL
|
||||||
EFI_STATUS
|
EFI_STATUS
|
||||||
BlEnumerateEfiBlockDevices()
|
BlEnumerateBlockDevices()
|
||||||
{
|
{
|
||||||
PEFI_DEVICE_PATH_PROTOCOL LastNode = NULL;
|
PEFI_DEVICE_PATH_PROTOCOL LastNode = NULL;
|
||||||
PEFI_BLOCK_DEVICE_DATA ParentNode = NULL;
|
PEFI_BLOCK_DEVICE_DATA ParentNode = NULL;
|
||||||
@ -70,7 +70,7 @@ BlEnumerateEfiBlockDevices()
|
|||||||
Status = BlpDiscoverEfiBlockDevices(&BlockDevices);
|
Status = BlpDiscoverEfiBlockDevices(&BlockDevices);
|
||||||
if(Status != STATUS_EFI_SUCCESS)
|
if(Status != STATUS_EFI_SUCCESS)
|
||||||
{
|
{
|
||||||
BlDbgPrint(L"ERROR: Failed to discover EFI block devices (status code: %lx)\n", Status);
|
BlDebugPrint(L"ERROR: Failed to discover EFI block devices (Status Code: 0x%lx)\n", Status);
|
||||||
return Status;
|
return Status;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -82,16 +82,16 @@ BlEnumerateEfiBlockDevices()
|
|||||||
BlockDeviceData = CONTAIN_RECORD(ListEntry, EFI_BLOCK_DEVICE_DATA, ListEntry);
|
BlockDeviceData = CONTAIN_RECORD(ListEntry, EFI_BLOCK_DEVICE_DATA, ListEntry);
|
||||||
|
|
||||||
/* Find last node */
|
/* Find last node */
|
||||||
Status = BlpFindLastEfiBlockDeviceNode(BlockDeviceData->DevicePath, &LastNode);
|
Status = BlpFindLastBlockDeviceNode(BlockDeviceData->DevicePath, &LastNode);
|
||||||
if(Status != STATUS_EFI_SUCCESS)
|
if(Status != STATUS_EFI_SUCCESS)
|
||||||
{
|
{
|
||||||
BlDbgPrint(L"WARNING: Block device last node not found\n");
|
BlDebugPrint(L"WARNING: Block device last node not found\n");
|
||||||
ListEntry = ListEntry->Flink;
|
ListEntry = ListEntry->Flink;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Set drive type to 'unknown' by default */
|
/* Set drive type to 'unknown' by default */
|
||||||
DriveType = XT_BOOT_DEVICE_UNKNOWN;
|
DriveType = XTBL_BOOT_DEVICE_UNKNOWN;
|
||||||
|
|
||||||
/* Check last node type */
|
/* Check last node type */
|
||||||
if(LastNode->Type == EFI_ACPI_DEVICE_PATH && LastNode->SubType == EFI_ACPI_DP)
|
if(LastNode->Type == EFI_ACPI_DEVICE_PATH && LastNode->SubType == EFI_ACPI_DP)
|
||||||
@ -102,12 +102,12 @@ BlEnumerateEfiBlockDevices()
|
|||||||
{
|
{
|
||||||
/* Floppy drive found */
|
/* Floppy drive found */
|
||||||
Media = BlockDeviceData->BlockIo->Media;
|
Media = BlockDeviceData->BlockIo->Media;
|
||||||
DriveType = XT_BOOT_DEVICE_FLOPPY;
|
DriveType = XTBL_BOOT_DEVICE_FLOPPY;
|
||||||
DriveNumber = FDCount++;
|
DriveNumber = FDCount++;
|
||||||
PartitionNumber = 0;
|
PartitionNumber = 0;
|
||||||
|
|
||||||
/* Print debug message */
|
/* Print debug message */
|
||||||
BlDbgPrint(L"Found Floppy Disk (DiskNumber: %lu, MediaPresent: %u, RO: %u)\n",
|
BlDebugPrint(L"Found Floppy Disk (DiskNumber: %lu, MediaPresent: %u, RO: %u)\n",
|
||||||
DriveNumber, Media->MediaPresent, Media->ReadOnly);
|
DriveNumber, Media->MediaPresent, Media->ReadOnly);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -118,12 +118,12 @@ BlEnumerateEfiBlockDevices()
|
|||||||
{
|
{
|
||||||
/* Optical drive found */
|
/* Optical drive found */
|
||||||
Media = BlockDeviceData->BlockIo->Media;
|
Media = BlockDeviceData->BlockIo->Media;
|
||||||
DriveType = XT_BOOT_DEVICE_CDROM;
|
DriveType = XTBL_BOOT_DEVICE_CDROM;
|
||||||
DriveNumber = CDCount++;
|
DriveNumber = CDCount++;
|
||||||
PartitionNumber = 0;
|
PartitionNumber = 0;
|
||||||
|
|
||||||
/* Print debug message */
|
/* Print debug message */
|
||||||
BlDbgPrint(L"Found CD-ROM drive (DriveNumber: %lu, MediaPresent: %u, RemovableMedia: %u, RO: %u)\n",
|
BlDebugPrint(L"Found CD-ROM drive (DriveNumber: %lu, MediaPresent: %u, RemovableMedia: %u, RO: %u)\n",
|
||||||
DriveNumber, Media->MediaPresent, Media->RemovableMedia, Media->ReadOnly);
|
DriveNumber, Media->MediaPresent, Media->RemovableMedia, Media->ReadOnly);
|
||||||
}
|
}
|
||||||
else if(LastNode->SubType == EFI_MEDIA_HARDDRIVE_DP)
|
else if(LastNode->SubType == EFI_MEDIA_HARDDRIVE_DP)
|
||||||
@ -131,13 +131,13 @@ BlEnumerateEfiBlockDevices()
|
|||||||
/* Hard disk partition found */
|
/* Hard disk partition found */
|
||||||
Media = BlockDeviceData->BlockIo->Media;
|
Media = BlockDeviceData->BlockIo->Media;
|
||||||
HDPath = (PEFI_HARDDRIVE_DEVICE_PATH)LastNode;
|
HDPath = (PEFI_HARDDRIVE_DEVICE_PATH)LastNode;
|
||||||
DriveType = XT_BOOT_DEVICE_HARDDISK;
|
DriveType = XTBL_BOOT_DEVICE_HARDDISK;
|
||||||
DriveNumber = (HDPath->PartitionNumber == 1) ? HDCount++ : HDCount - 1;
|
DriveNumber = (HDPath->PartitionNumber == 1) ? HDCount++ : HDCount - 1;
|
||||||
PartitionNumber = HDPath->PartitionNumber;
|
PartitionNumber = HDPath->PartitionNumber;
|
||||||
PartitionGuid = (PEFI_GUID)HDPath->Signature;
|
PartitionGuid = (PEFI_GUID)HDPath->Signature;
|
||||||
|
|
||||||
/* Print debug message */
|
/* Print debug message */
|
||||||
BlDbgPrint(L"Found Hard Disk partition (DiskNumber: %lu, PartNumber: %lu, "
|
BlDebugPrint(L"Found Hard Disk partition (DiskNumber: %lu, PartNumber: %lu, "
|
||||||
L"MBRType: %u, GUID: {%g}, PartSize: %luB)\n",
|
L"MBRType: %u, GUID: {%g}, PartSize: %luB)\n",
|
||||||
DriveNumber, PartitionNumber, HDPath->MBRType,
|
DriveNumber, PartitionNumber, HDPath->MBRType,
|
||||||
PartitionGuid, HDPath->PartitionSize * Media->BlockSize);
|
PartitionGuid, HDPath->PartitionSize * Media->BlockSize);
|
||||||
@ -146,30 +146,30 @@ BlEnumerateEfiBlockDevices()
|
|||||||
{
|
{
|
||||||
/* RAM disk found */
|
/* RAM disk found */
|
||||||
Media = BlockDeviceData->BlockIo->Media;
|
Media = BlockDeviceData->BlockIo->Media;
|
||||||
DriveType = XT_BOOT_DEVICE_RAMDISK;
|
DriveType = XTBL_BOOT_DEVICE_RAMDISK;
|
||||||
DriveNumber = RDCount++;
|
DriveNumber = RDCount++;
|
||||||
PartitionNumber = 0;
|
PartitionNumber = 0;
|
||||||
|
|
||||||
/* Print debug message */
|
/* Print debug message */
|
||||||
BlDbgPrint(L"Found RAM Disk (DiskNumber: %lu, MediaPresent: %u)\n",
|
BlDebugPrint(L"Found RAM Disk (DiskNumber: %lu, MediaPresent: %u)\n",
|
||||||
DriveNumber, Media->MediaPresent);
|
DriveNumber, Media->MediaPresent);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!BlpFindParentEfiBlockDevice(&BlockDevices, BlockDeviceData, ParentNode))
|
if(!BlpFindParentBlockDevice(&BlockDevices, BlockDeviceData, ParentNode))
|
||||||
{
|
{
|
||||||
BlDbgPrint(L"WARNING: No parent device found, skipping orphaned media device path\n");
|
BlDebugPrint(L"WARNING: No parent device found, skipping orphaned media device path\n");
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Make sure the device found has valid type set */
|
/* Make sure the device found has valid type set */
|
||||||
if(DriveType != XT_BOOT_DEVICE_UNKNOWN)
|
if(DriveType != XTBL_BOOT_DEVICE_UNKNOWN)
|
||||||
{
|
{
|
||||||
/* Allocate memory for block device */
|
/* Allocate memory for block device */
|
||||||
Status = BlEfiMemoryAllocatePool(sizeof(EFI_BLOCK_DEVICE), (PVOID *)&BlockDevice);
|
Status = BlMemoryAllocatePool(sizeof(EFI_BLOCK_DEVICE), (PVOID *)&BlockDevice);
|
||||||
if(Status != STATUS_EFI_SUCCESS)
|
if(Status != STATUS_EFI_SUCCESS)
|
||||||
{
|
{
|
||||||
BlDbgPrint(L"ERROR: Unable to allocate memory pool for block device (status code: %lx)\n", Status);
|
BlDebugPrint(L"ERROR: Failed to allocate memory pool for block device (Status Code: 0x%lx)\n", Status);
|
||||||
return STATUS_EFI_OUT_OF_RESOURCES;
|
return STATUS_EFI_OUT_OF_RESOURCES;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -248,7 +248,7 @@ BlFindVolumeDevicePath(IN PEFI_DEVICE_PATH_PROTOCOL FsHandle,
|
|||||||
FsPathLength = RtlWideStringLength(FileSystemPath, 0) * sizeof(WCHAR);
|
FsPathLength = RtlWideStringLength(FileSystemPath, 0) * sizeof(WCHAR);
|
||||||
|
|
||||||
/* Allocate memory pool for device path */
|
/* Allocate memory pool for device path */
|
||||||
Status = BlEfiMemoryAllocatePool(FsPathLength + DevicePathLength + sizeof(EFI_DEVICE_PATH_PROTOCOL),
|
Status = BlMemoryAllocatePool(FsPathLength + DevicePathLength + sizeof(EFI_DEVICE_PATH_PROTOCOL),
|
||||||
(PVOID *)DevicePath);
|
(PVOID *)DevicePath);
|
||||||
if(Status != STATUS_EFI_SUCCESS)
|
if(Status != STATUS_EFI_SUCCESS)
|
||||||
{
|
{
|
||||||
@ -294,16 +294,16 @@ BlFindVolumeDevicePath(IN PEFI_DEVICE_PATH_PROTOCOL FsHandle,
|
|||||||
*/
|
*/
|
||||||
XTCDECL
|
XTCDECL
|
||||||
EFI_STATUS
|
EFI_STATUS
|
||||||
BlGetVolumeDevicePath(IN PUCHAR SystemPath,
|
BlGetVolumeDevicePath(IN PWCHAR SystemPath,
|
||||||
OUT PEFI_DEVICE_PATH_PROTOCOL *DevicePath,
|
OUT PEFI_DEVICE_PATH_PROTOCOL *DevicePath,
|
||||||
OUT PUCHAR *ArcName,
|
OUT PWCHAR *ArcName,
|
||||||
OUT PUCHAR *Path)
|
OUT PWCHAR *Path)
|
||||||
{
|
{
|
||||||
PEFI_BLOCK_DEVICE Device;
|
PEFI_BLOCK_DEVICE Device;
|
||||||
USHORT DriveType;
|
USHORT DriveType;
|
||||||
ULONG DriveNumber;
|
ULONG DriveNumber;
|
||||||
ULONG PartNumber;
|
ULONG PartNumber;
|
||||||
PUCHAR Volume;
|
PWCHAR Volume;
|
||||||
ULONG PathLength;
|
ULONG PathLength;
|
||||||
PLIST_ENTRY ListEntry;
|
PLIST_ENTRY ListEntry;
|
||||||
EFI_STATUS Status;
|
EFI_STATUS Status;
|
||||||
@ -333,13 +333,13 @@ BlGetVolumeDevicePath(IN PUCHAR SystemPath,
|
|||||||
if(PathLength == GUID_STRING_LENGTH)
|
if(PathLength == GUID_STRING_LENGTH)
|
||||||
{
|
{
|
||||||
/* This is EFI GUID */
|
/* This is EFI GUID */
|
||||||
BlDbgPrint(L"EFI/GPT GUID in system path is not supported yet\n");
|
BlDebugPrint(L"WARNING: EFI/GPT GUID in system path is not supported\n");
|
||||||
return STATUS_EFI_UNSUPPORTED;
|
return STATUS_EFI_UNSUPPORTED;
|
||||||
}
|
}
|
||||||
else if(PathLength == PARTUUID_STRING_LENGTH)
|
else if(PathLength == PARTUUID_STRING_LENGTH)
|
||||||
{
|
{
|
||||||
/* This is MBR UUID */
|
/* This is MBR UUID */
|
||||||
BlDbgPrint(L"MBR partition UUID in system path is not supported yet\n");
|
BlDebugPrint(L"WARNING: MBR partition UUID in system path is not supported\n");
|
||||||
return STATUS_EFI_UNSUPPORTED;
|
return STATUS_EFI_UNSUPPORTED;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -358,7 +358,7 @@ BlGetVolumeDevicePath(IN PUCHAR SystemPath,
|
|||||||
if(Status != STATUS_EFI_SUCCESS)
|
if(Status != STATUS_EFI_SUCCESS)
|
||||||
{
|
{
|
||||||
/* Failed to parse system path */
|
/* Failed to parse system path */
|
||||||
BlDbgPrint(L"Failed to parse system path: '%s' with status code: %lx\n", SystemPath, Status);
|
BlDebugPrint(L"ERROR: Failed to parse system path: '%s' (Status Code: 0x%lx)\n", SystemPath, Status);
|
||||||
return Status;
|
return Status;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -382,7 +382,7 @@ BlGetVolumeDevicePath(IN PUCHAR SystemPath,
|
|||||||
if(*DevicePath == NULL)
|
if(*DevicePath == NULL)
|
||||||
{
|
{
|
||||||
/* Failed to find volume */
|
/* Failed to find volume */
|
||||||
BlDbgPrint(L"Volume (DriveType: %u, DriveNumber: %lu, PartNumber: %lu) not found\n",
|
BlDebugPrint(L"ERROR: Volume (DriveType: %u, DriveNumber: %lu, PartNumber: %lu) not found\n",
|
||||||
DriveType, DriveNumber, PartNumber);
|
DriveType, DriveNumber, PartNumber);
|
||||||
return STATUS_EFI_NOT_FOUND;
|
return STATUS_EFI_NOT_FOUND;
|
||||||
}
|
}
|
||||||
@ -470,6 +470,125 @@ BlOpenVolume(IN PEFI_DEVICE_PATH_PROTOCOL DevicePath,
|
|||||||
return STATUS_EFI_SUCCESS;
|
return STATUS_EFI_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reads data from the file.
|
||||||
|
*
|
||||||
|
* @param DirHandle
|
||||||
|
* Supplies a handle of the opened filesystem directory.
|
||||||
|
*
|
||||||
|
* @param FileName
|
||||||
|
* Supplies the name of the file to read.
|
||||||
|
*
|
||||||
|
* @param FileData
|
||||||
|
* Provides a buffer to store the data read from the file.
|
||||||
|
*
|
||||||
|
* @param FileSize
|
||||||
|
* Provides a pointer to the variable to store a size of the buffer.
|
||||||
|
*
|
||||||
|
* @return This routine returns status code.
|
||||||
|
*
|
||||||
|
* @since XT 1.0
|
||||||
|
*/
|
||||||
|
XTCDECL
|
||||||
|
EFI_STATUS
|
||||||
|
BlReadFile(IN PEFI_FILE_HANDLE DirHandle,
|
||||||
|
IN CONST PWCHAR FileName,
|
||||||
|
OUT PVOID *FileData,
|
||||||
|
OUT PSIZE_T FileSize)
|
||||||
|
{
|
||||||
|
EFI_GUID FileInfoGuid = EFI_FILE_INFO_PROTOCOL_GUID;
|
||||||
|
EFI_PHYSICAL_ADDRESS Address;
|
||||||
|
PEFI_FILE_HANDLE FileHandle;
|
||||||
|
PEFI_FILE_INFO FileInfo;
|
||||||
|
EFI_STATUS Status;
|
||||||
|
UINT_PTR ReadSize;
|
||||||
|
SIZE_T Pages;
|
||||||
|
|
||||||
|
Status = DirHandle->Open(DirHandle, &FileHandle, FileName, EFI_FILE_MODE_READ,
|
||||||
|
EFI_FILE_READ_ONLY | EFI_FILE_HIDDEN | EFI_FILE_SYSTEM);
|
||||||
|
if(Status != STATUS_EFI_SUCCESS)
|
||||||
|
{
|
||||||
|
/* Failed to open file */
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Set required size for getting file information */
|
||||||
|
ReadSize = sizeof(EFI_FILE_INFO) + 32;
|
||||||
|
|
||||||
|
/* Allocate necessary amount of memory */
|
||||||
|
Status = BlMemoryAllocatePool(ReadSize, (PVOID *)&FileInfo);
|
||||||
|
if(Status != STATUS_EFI_SUCCESS)
|
||||||
|
{
|
||||||
|
/* Memory allocation failure */
|
||||||
|
FileHandle->Close(FileHandle);
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* First attempt to get file information */
|
||||||
|
FileHandle->GetInfo(FileHandle, &FileInfoGuid, &ReadSize, FileInfo);
|
||||||
|
if(Status == STATUS_EFI_BUFFER_TOO_SMALL)
|
||||||
|
{
|
||||||
|
/* Buffer is too small, but EFI tells the required size, so reallocate */
|
||||||
|
BlMemoryFreePool(&FileInfo);
|
||||||
|
Status = BlMemoryAllocatePool(ReadSize, (PVOID *)&FileInfo);
|
||||||
|
if(Status != STATUS_EFI_SUCCESS)
|
||||||
|
{
|
||||||
|
/* Memory allocation failure */
|
||||||
|
FileHandle->Close(FileHandle);
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Second attempt to get file information */
|
||||||
|
Status = FileHandle->GetInfo(FileHandle, &FileInfoGuid, &ReadSize, FileInfo);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Check if file information got successfully */
|
||||||
|
if(Status != STATUS_EFI_SUCCESS)
|
||||||
|
{
|
||||||
|
/* Unable to get file information */
|
||||||
|
FileHandle->Close(FileHandle);
|
||||||
|
BlMemoryFreePool(&FileInfo);
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Store file size and calculate number of pages */
|
||||||
|
*FileSize = FileInfo->FileSize;
|
||||||
|
Pages = EFI_SIZE_TO_PAGES(FileInfo->FileSize);
|
||||||
|
|
||||||
|
/* Allocate pages */
|
||||||
|
Status = BlMemoryAllocatePages(Pages, &Address);
|
||||||
|
if(Status != STATUS_EFI_SUCCESS)
|
||||||
|
{
|
||||||
|
/* Pages allocation failure */
|
||||||
|
FileHandle->Close(FileHandle);
|
||||||
|
BlMemoryFreePool(&FileInfo);
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Calculate number of bytes to read and zero memory*/
|
||||||
|
ReadSize = Pages * EFI_PAGE_SIZE;
|
||||||
|
*FileData = (PCHAR)(UINT_PTR)Address;
|
||||||
|
RtlZeroMemory(*FileData, ReadSize);
|
||||||
|
|
||||||
|
/* Read data from the file */
|
||||||
|
Status = FileHandle->Read(FileHandle, &ReadSize, *FileData);
|
||||||
|
if(Status != STATUS_EFI_SUCCESS)
|
||||||
|
{
|
||||||
|
/* Failed to read data */
|
||||||
|
FileHandle->Close(FileHandle);
|
||||||
|
BlMemoryFreePool(&FileInfo);
|
||||||
|
BlMemoryFreePages(Pages, (EFI_PHYSICAL_ADDRESS)(UINT_PTR)*FileData);
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Close handle and free memory */
|
||||||
|
FileHandle->Close(FileHandle);
|
||||||
|
BlMemoryFreePool(&FileInfo);
|
||||||
|
|
||||||
|
/* Return success */
|
||||||
|
return STATUS_EFI_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets a list of block devices from an EFI enabled BIOS.
|
* Gets a list of block devices from an EFI enabled BIOS.
|
||||||
*
|
*
|
||||||
@ -498,7 +617,7 @@ BlpDiscoverEfiBlockDevices(OUT PLIST_ENTRY BlockDevices)
|
|||||||
if(Status != STATUS_EFI_SUCCESS)
|
if(Status != STATUS_EFI_SUCCESS)
|
||||||
{
|
{
|
||||||
/* Failed to locate handles */
|
/* Failed to locate handles */
|
||||||
BlDbgPrint(L"ERROR: Failed to locate block devices handles (status code: %lx)\n", Status);
|
BlDebugPrint(L"ERROR: Failed to locate block devices handles (Status Code: 0x%lx)\n", Status);
|
||||||
return Status;
|
return Status;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -506,7 +625,7 @@ BlpDiscoverEfiBlockDevices(OUT PLIST_ENTRY BlockDevices)
|
|||||||
for(Index = 0; Index < HandlesCount; Index++)
|
for(Index = 0; Index < HandlesCount; Index++)
|
||||||
{
|
{
|
||||||
/* Print debug message */
|
/* Print debug message */
|
||||||
BlDbgPrint(L"Opening %lu block device from %lu discovered\n", Index + 1, HandlesCount);
|
BlDebugPrint(L"Opening %lu block device from %lu discovered\n", Index + 1, HandlesCount);
|
||||||
|
|
||||||
/* Open I/O protocol for given handle */
|
/* Open I/O protocol for given handle */
|
||||||
Io = NULL;
|
Io = NULL;
|
||||||
@ -515,7 +634,7 @@ BlpDiscoverEfiBlockDevices(OUT PLIST_ENTRY BlockDevices)
|
|||||||
if(Status != STATUS_EFI_SUCCESS || Io == NULL)
|
if(Status != STATUS_EFI_SUCCESS || Io == NULL)
|
||||||
{
|
{
|
||||||
/* Failed to open I/O protocol, skip it */
|
/* Failed to open I/O protocol, skip it */
|
||||||
BlDbgPrint(L"WARNING: Failed to open EFI Block I/O protocol (status code: %lx)\n", Status);
|
BlDebugPrint(L"WARNING: Failed to open EFI Block I/O protocol (Status Code: 0x%lx)\n", Status);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -523,7 +642,7 @@ BlpDiscoverEfiBlockDevices(OUT PLIST_ENTRY BlockDevices)
|
|||||||
if(Io->Media && Io->Media->BlockSize == 1 && Io->Media->MediaId == 0x69505845U)
|
if(Io->Media && Io->Media->BlockSize == 1 && Io->Media->MediaId == 0x69505845U)
|
||||||
{
|
{
|
||||||
/* Skip stub as it is non-functional */
|
/* Skip stub as it is non-functional */
|
||||||
BlDbgPrint(L"WARNING: iPXE stub block I/O protocol");
|
BlDebugPrint(L"WARNING: iPXE stub block I/O protocol");
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -533,17 +652,17 @@ BlpDiscoverEfiBlockDevices(OUT PLIST_ENTRY BlockDevices)
|
|||||||
if(Status != STATUS_EFI_SUCCESS || DevicePath == NULL)
|
if(Status != STATUS_EFI_SUCCESS || DevicePath == NULL)
|
||||||
{
|
{
|
||||||
/* Device failed to handle DP protocol */
|
/* Device failed to handle DP protocol */
|
||||||
BlDbgPrint(L"WARNING: Unable to open DevicePath protocol (status code: %lx)\n", Status);
|
BlDebugPrint(L"WARNING: Unable to open DevicePath protocol (Status Code: 0x%lx)\n", Status);
|
||||||
EfiSystemTable->BootServices->CloseProtocol(Handles[Index], &IoGuid, EfiImageHandle, NULL);
|
EfiSystemTable->BootServices->CloseProtocol(Handles[Index], &IoGuid, EfiImageHandle, NULL);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Allocate memory for block device */
|
/* Allocate memory for block device */
|
||||||
Status = BlEfiMemoryAllocatePool(sizeof(*BlockDevice), (PVOID *)&BlockDevice);
|
Status = BlMemoryAllocatePool(sizeof(*BlockDevice), (PVOID *)&BlockDevice);
|
||||||
if(Status != STATUS_EFI_SUCCESS)
|
if(Status != STATUS_EFI_SUCCESS)
|
||||||
{
|
{
|
||||||
/* Memory allocation failure */
|
/* Memory allocation failure */
|
||||||
BlDbgPrint(L"ERROR: Unable to allocate memory pool for block device (status code: %lx)\n", Status);
|
BlDebugPrint(L"ERROR: Failed to allocate memory pool for block device (Status Code: 0x%lx)\n", Status);
|
||||||
EfiSystemTable->BootServices->CloseProtocol(Handles[Index], &DevicePathGuid, EfiImageHandle, NULL);
|
EfiSystemTable->BootServices->CloseProtocol(Handles[Index], &DevicePathGuid, EfiImageHandle, NULL);
|
||||||
EfiSystemTable->BootServices->CloseProtocol(Handles[Index], &IoGuid, EfiImageHandle, NULL);
|
EfiSystemTable->BootServices->CloseProtocol(Handles[Index], &IoGuid, EfiImageHandle, NULL);
|
||||||
return Status;
|
return Status;
|
||||||
@ -556,7 +675,7 @@ BlpDiscoverEfiBlockDevices(OUT PLIST_ENTRY BlockDevices)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Free handles buffer */
|
/* Free handles buffer */
|
||||||
BlEfiMemoryFreePool(Handles);
|
BlMemoryFreePool(Handles);
|
||||||
|
|
||||||
/* Return success */
|
/* Return success */
|
||||||
return STATUS_EFI_SUCCESS;
|
return STATUS_EFI_SUCCESS;
|
||||||
@ -586,36 +705,36 @@ BlpDiscoverEfiBlockDevices(OUT PLIST_ENTRY BlockDevices)
|
|||||||
*/
|
*/
|
||||||
XTCDECL
|
XTCDECL
|
||||||
EFI_STATUS
|
EFI_STATUS
|
||||||
BlpDissectVolumeArcPath(IN PUCHAR SystemPath,
|
BlpDissectVolumeArcPath(IN PWCHAR SystemPath,
|
||||||
OUT PUCHAR *ArcName,
|
OUT PWCHAR *ArcName,
|
||||||
OUT PUCHAR *Path,
|
OUT PWCHAR *Path,
|
||||||
OUT PUSHORT DriveType,
|
OUT PUSHORT DriveType,
|
||||||
OUT PULONG DriveNumber,
|
OUT PULONG DriveNumber,
|
||||||
OUT PULONG PartNumber)
|
OUT PULONG PartNumber)
|
||||||
{
|
{
|
||||||
PUCHAR ArcPath, LocalArcName;
|
PWCHAR ArcPath, LocalArcName;
|
||||||
ULONG ArcLength = 0;
|
ULONG ArcLength = 0;
|
||||||
|
|
||||||
/* Set default values */
|
/* Set default values */
|
||||||
*DriveType = XT_BOOT_DEVICE_UNKNOWN;
|
*DriveType = XTBL_BOOT_DEVICE_UNKNOWN;
|
||||||
*DriveNumber = 0;
|
*DriveNumber = 0;
|
||||||
*PartNumber = 0;
|
*PartNumber = 0;
|
||||||
|
|
||||||
/* Look for the ARC path */
|
/* Look for the ARC path */
|
||||||
if(BlStringCompareInsensitive(SystemPath, (PUCHAR)"ramdisk(0)") == 0)
|
if(RtlCompareWideStringInsensitive(SystemPath, L"ramdisk(0)", 0) == 0)
|
||||||
{
|
{
|
||||||
/* This is RAM disk */
|
/* This is RAM disk */
|
||||||
ArcLength = 10;
|
ArcLength = 10;
|
||||||
*DriveType = XT_BOOT_DEVICE_RAMDISK;
|
*DriveType = XTBL_BOOT_DEVICE_RAMDISK;
|
||||||
}
|
}
|
||||||
else if(BlStringCompareInsensitive(SystemPath, (PUCHAR)"multi(0)disk(0)") == 0)
|
else if(RtlCompareWideStringInsensitive(SystemPath, L"multi(0)disk(0)", 0) == 0)
|
||||||
{
|
{
|
||||||
/* This is a multi-disk port */
|
/* This is a multi-disk port */
|
||||||
ArcLength = 15;
|
ArcLength = 15;
|
||||||
ArcPath = SystemPath + ArcLength;
|
ArcPath = SystemPath + ArcLength;
|
||||||
|
|
||||||
/* Check for disk type */
|
/* Check for disk type */
|
||||||
if(BlStringCompareInsensitive(ArcPath, (PUCHAR)"cdrom(") == 0)
|
if(RtlCompareWideStringInsensitive(ArcPath, L"cdrom(", 0) == 0)
|
||||||
{
|
{
|
||||||
/* This is an optical drive */
|
/* This is an optical drive */
|
||||||
ArcLength += 6;
|
ArcLength += 6;
|
||||||
@ -633,10 +752,10 @@ BlpDissectVolumeArcPath(IN PUCHAR SystemPath,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Set proper drive type */
|
/* Set proper drive type */
|
||||||
*DriveType = XT_BOOT_DEVICE_CDROM;
|
*DriveType = XTBL_BOOT_DEVICE_CDROM;
|
||||||
ArcLength++;
|
ArcLength++;
|
||||||
}
|
}
|
||||||
else if(BlStringCompareInsensitive(ArcPath, (PUCHAR)"fdisk(") == 0)
|
else if(RtlCompareWideStringInsensitive(ArcPath, L"fdisk(", 0) == 0)
|
||||||
{
|
{
|
||||||
/* This is a floppy drive */
|
/* This is a floppy drive */
|
||||||
ArcLength += 6;
|
ArcLength += 6;
|
||||||
@ -654,10 +773,10 @@ BlpDissectVolumeArcPath(IN PUCHAR SystemPath,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Set proper drive type */
|
/* Set proper drive type */
|
||||||
*DriveType = XT_BOOT_DEVICE_FLOPPY;
|
*DriveType = XTBL_BOOT_DEVICE_FLOPPY;
|
||||||
ArcLength++;
|
ArcLength++;
|
||||||
}
|
}
|
||||||
else if(BlStringCompareInsensitive(ArcPath, (PUCHAR)"rdisk(") == 0)
|
else if(RtlCompareWideStringInsensitive(ArcPath, L"rdisk(", 0) == 0)
|
||||||
{
|
{
|
||||||
/* This is a hard disk */
|
/* This is a hard disk */
|
||||||
ArcLength += 6;
|
ArcLength += 6;
|
||||||
@ -675,12 +794,12 @@ BlpDissectVolumeArcPath(IN PUCHAR SystemPath,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Set proper drive type */
|
/* Set proper drive type */
|
||||||
*DriveType = XT_BOOT_DEVICE_HARDDISK;
|
*DriveType = XTBL_BOOT_DEVICE_HARDDISK;
|
||||||
ArcLength++;
|
ArcLength++;
|
||||||
ArcPath = SystemPath + ArcLength;
|
ArcPath = SystemPath + ArcLength;
|
||||||
|
|
||||||
/* Look for a partition */
|
/* Look for a partition */
|
||||||
if(BlStringCompareInsensitive(ArcPath, (PUCHAR)"partition(") == 0)
|
if(RtlCompareWideStringInsensitive(ArcPath, L"partition(", 0) == 0)
|
||||||
{
|
{
|
||||||
/* Partition information found */
|
/* Partition information found */
|
||||||
ArcLength += 10;
|
ArcLength += 10;
|
||||||
@ -720,8 +839,8 @@ BlpDissectVolumeArcPath(IN PUCHAR SystemPath,
|
|||||||
/* Store ARC name if possible */
|
/* Store ARC name if possible */
|
||||||
if(ArcName)
|
if(ArcName)
|
||||||
{
|
{
|
||||||
BlEfiMemoryAllocatePool(ArcLength, (PVOID *)&LocalArcName);
|
BlMemoryAllocatePool(ArcLength * sizeof(WCHAR), (PVOID *)&LocalArcName);
|
||||||
RtlCopyMemory(LocalArcName, SystemPath, ArcLength);
|
RtlCopyMemory(LocalArcName, SystemPath, ArcLength * sizeof(WCHAR));
|
||||||
LocalArcName[ArcLength] = '\0';
|
LocalArcName[ArcLength] = '\0';
|
||||||
*ArcName = LocalArcName;
|
*ArcName = LocalArcName;
|
||||||
}
|
}
|
||||||
@ -770,11 +889,11 @@ BlpDuplicateDevicePath(IN PEFI_DEVICE_PATH_PROTOCOL DevicePath)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Allocate memory for the new device path */
|
/* Allocate memory for the new device path */
|
||||||
Status = BlEfiMemoryAllocatePool(Length, (PVOID *)&DevicePathClone);
|
Status = BlMemoryAllocatePool(Length, (PVOID *)&DevicePathClone);
|
||||||
if(Status != STATUS_EFI_SUCCESS)
|
if(Status != STATUS_EFI_SUCCESS)
|
||||||
{
|
{
|
||||||
/* Failed to allocate memory */
|
/* Failed to allocate memory */
|
||||||
BlDbgPrint(L"ERROR: Unable to allocate memory pool for device path duplicate\n");
|
BlDebugPrint(L"ERROR: Failed to allocate memory pool for device path duplicate (Status Code: 0x%lx)\n", Status);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -800,8 +919,8 @@ BlpDuplicateDevicePath(IN PEFI_DEVICE_PATH_PROTOCOL DevicePath)
|
|||||||
*/
|
*/
|
||||||
XTCDECL
|
XTCDECL
|
||||||
EFI_STATUS
|
EFI_STATUS
|
||||||
BlpFindLastEfiBlockDeviceNode(IN PEFI_DEVICE_PATH_PROTOCOL DevicePath,
|
BlpFindLastBlockDeviceNode(IN PEFI_DEVICE_PATH_PROTOCOL DevicePath,
|
||||||
OUT PEFI_DEVICE_PATH_PROTOCOL *LastNode)
|
OUT PEFI_DEVICE_PATH_PROTOCOL *LastNode)
|
||||||
{
|
{
|
||||||
PEFI_DEVICE_PATH_PROTOCOL EndNode, NextNode;
|
PEFI_DEVICE_PATH_PROTOCOL EndNode, NextNode;
|
||||||
|
|
||||||
@ -846,9 +965,9 @@ BlpFindLastEfiBlockDeviceNode(IN PEFI_DEVICE_PATH_PROTOCOL DevicePath,
|
|||||||
*/
|
*/
|
||||||
XTCDECL
|
XTCDECL
|
||||||
BOOLEAN
|
BOOLEAN
|
||||||
BlpFindParentEfiBlockDevice(IN PLIST_ENTRY BlockDevices,
|
BlpFindParentBlockDevice(IN PLIST_ENTRY BlockDevices,
|
||||||
IN PEFI_BLOCK_DEVICE_DATA ChildNode,
|
IN PEFI_BLOCK_DEVICE_DATA ChildNode,
|
||||||
OUT PEFI_BLOCK_DEVICE_DATA ParentNode)
|
OUT PEFI_BLOCK_DEVICE_DATA ParentNode)
|
||||||
{
|
{
|
||||||
PEFI_DEVICE_PATH_PROTOCOL ChildDevicePath, ParentDevicePath;
|
PEFI_DEVICE_PATH_PROTOCOL ChildDevicePath, ParentDevicePath;
|
||||||
PEFI_BLOCK_DEVICE_DATA BlockDeviceData;
|
PEFI_BLOCK_DEVICE_DATA BlockDeviceData;
|
||||||
|
614
xtldr/xtldr.c
614
xtldr/xtldr.c
@ -2,216 +2,160 @@
|
|||||||
* PROJECT: ExectOS
|
* PROJECT: ExectOS
|
||||||
* COPYRIGHT: See COPYING.md in the top level directory
|
* COPYRIGHT: See COPYING.md in the top level directory
|
||||||
* FILE: xtldr/xtldr.c
|
* FILE: xtldr/xtldr.c
|
||||||
* DESCRIPTION: UEFI XT Bootloader
|
* DESCRIPTION: XTOS UEFI Boot Loader
|
||||||
* DEVELOPERS: Rafal Kupiec <belliash@codingworkshop.eu.org>
|
* DEVELOPERS: Rafal Kupiec <belliash@codingworkshop.eu.org>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <xtbl.h>
|
#include <xtldr.h>
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This routine loads XTLDR EFI modules.
|
* Initializes EFI Boot Loader (XTLDR).
|
||||||
*
|
*
|
||||||
* @return This routine returns status code.
|
* @return This routine does not return any value.
|
||||||
*
|
*
|
||||||
* @since XT 1.0
|
* @since XT 1.0
|
||||||
*/
|
*/
|
||||||
XTCDECL
|
XTCDECL
|
||||||
EFI_STATUS
|
VOID
|
||||||
BlLoadEfiModules()
|
BlInitializeBootLoader()
|
||||||
{
|
{
|
||||||
CONST PWCHAR ModulesDirPath = L"\\EFI\\BOOT\\XTLDR\\";
|
EFI_GUID LipGuid = EFI_LOADED_IMAGE_PROTOCOL_GUID;
|
||||||
EFI_GUID DevicePathGuid = EFI_DEVICE_PATH_PROTOCOL_GUID;
|
|
||||||
EFI_GUID LIPGuid = EFI_LOADED_IMAGE_PROTOCOL_GUID;
|
|
||||||
PEFI_DEVICE_PATH_PROTOCOL VolumeDevicePath, DevicePath;
|
|
||||||
PEFI_LOADED_IMAGE_PROTOCOL LoadedImage;
|
PEFI_LOADED_IMAGE_PROTOCOL LoadedImage;
|
||||||
PEFI_FILE_HANDLE FsHandle, ModulesDir;
|
|
||||||
EFI_HANDLE DiskHandle, ModuleHandle;
|
|
||||||
SIZE_T Length;
|
|
||||||
EFI_STATUS Status;
|
EFI_STATUS Status;
|
||||||
UINT_PTR DirSize;
|
|
||||||
CHAR Buffer[1024];
|
|
||||||
WCHAR ModulePath[1024];
|
|
||||||
PWCHAR ModuleName;
|
|
||||||
|
|
||||||
/* Open EFI volume */
|
/* Set current XTLDR's EFI BootServices status */
|
||||||
Status = BlOpenVolume(NULL, &DiskHandle, &FsHandle);
|
BlpStatus.BootServices = TRUE;
|
||||||
if(Status != STATUS_EFI_SUCCESS)
|
|
||||||
|
/* Initialize console */
|
||||||
|
BlpInitializeConsole();
|
||||||
|
|
||||||
|
/* Print XTLDR version */
|
||||||
|
BlConsolePrint(L"XTLDR boot loader v%s\n", XTOS_VERSION);
|
||||||
|
|
||||||
|
/* Initialize XTLDR configuration linked lists */
|
||||||
|
RtlInitializeListHead(&BlpBootProtocols);
|
||||||
|
RtlInitializeListHead(&BlpConfig);
|
||||||
|
RtlInitializeListHead(&BlpLoadedModules);
|
||||||
|
|
||||||
|
/* Store SecureBoot status */
|
||||||
|
BlpStatus.SecureBoot = BlGetSecureBootStatus();
|
||||||
|
|
||||||
|
/* Check if debug is enabled */
|
||||||
|
if(DEBUG)
|
||||||
{
|
{
|
||||||
/* Failed to open a volume */
|
/* Attempt to open EFI LoadedImage protocol */
|
||||||
return Status;
|
Status = BlOpenProtocol((PVOID *)&LoadedImage, &LipGuid);
|
||||||
|
if(Status == STATUS_EFI_SUCCESS)
|
||||||
|
{
|
||||||
|
/* Protocol opened successfully, print useful debug information */
|
||||||
|
BlConsolePrint(L"\n---------- BOOTLOADER DEBUG ----------\n"
|
||||||
|
L"Pointer Size : %d\n"
|
||||||
|
L"Image Base Address: 0x%lx\n"
|
||||||
|
L"Image Base Size : 0x%lx\n"
|
||||||
|
L"Image Revision : 0x%lx\n"
|
||||||
|
L"--------------------------------------\n",
|
||||||
|
sizeof(PVOID),
|
||||||
|
LoadedImage->ImageBase,
|
||||||
|
LoadedImage->ImageSize,
|
||||||
|
LoadedImage->Revision);
|
||||||
|
BlSleepExecution(3000);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Open EFI/BOOT/XTLDR directory, which contains all the modules and close the FS immediately */
|
|
||||||
Status = FsHandle->Open(FsHandle, &ModulesDir, ModulesDirPath, EFI_FILE_MODE_READ, 0);
|
|
||||||
FsHandle->Close(FsHandle);
|
|
||||||
|
|
||||||
/* Check if modules directory opened successfully */
|
|
||||||
if(Status == STATUS_EFI_NOT_FOUND)
|
|
||||||
{
|
|
||||||
/* Directory not found, nothing to load */
|
|
||||||
BlDbgPrint(L"WARNING: Boot loader directory (EFI/BOOT/XTLDR) not found\n");
|
|
||||||
|
|
||||||
/* Close volume */
|
|
||||||
BlCloseVolume(DiskHandle);
|
|
||||||
return STATUS_EFI_SUCCESS;
|
|
||||||
}
|
|
||||||
else if(Status != STATUS_EFI_SUCCESS)
|
|
||||||
{
|
|
||||||
/* Failed to open directory */
|
|
||||||
BlDbgPrint(L"ERROR: Unable to open XTLDR directory (EFI/BOOT/XTLDR)\n");
|
|
||||||
BlCloseVolume(DiskHandle);
|
|
||||||
return Status;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Open EFI device path protocol */
|
|
||||||
Status = EfiSystemTable->BootServices->HandleProtocol(DiskHandle, &DevicePathGuid, (PVOID *)&DevicePath);
|
|
||||||
if(Status != STATUS_EFI_SUCCESS)
|
|
||||||
{
|
|
||||||
/* Close volume */
|
|
||||||
BlCloseVolume(DiskHandle);
|
|
||||||
return Status;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Iterate through files inside XTLDR directory */
|
|
||||||
while(TRUE)
|
|
||||||
{
|
|
||||||
/* Read directory */
|
|
||||||
DirSize = sizeof(Buffer);
|
|
||||||
Status = ModulesDir->Read(ModulesDir, &DirSize, Buffer);
|
|
||||||
if(Status != STATUS_EFI_SUCCESS)
|
|
||||||
{
|
|
||||||
/* Failed to read directory */
|
|
||||||
BlDbgPrint(L"\n");
|
|
||||||
|
|
||||||
/* Close directory and volume */
|
|
||||||
ModulesDir->Close(ModulesDir);
|
|
||||||
BlCloseVolume(DiskHandle);
|
|
||||||
return Status;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Check if read anything */
|
|
||||||
if(DirSize == 0)
|
|
||||||
{
|
|
||||||
/* Already read all contents, break loop execution */
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Take filename and its length */
|
|
||||||
ModuleName = ((PEFI_FILE_INFO)Buffer)->FileName;
|
|
||||||
Length = RtlWideStringLength(ModuleName, 0);
|
|
||||||
|
|
||||||
/* Make sure we deal with .EFI executable file */
|
|
||||||
if(Length < 4 || ModuleName[Length - 4] != '.' ||
|
|
||||||
(ModuleName[Length - 3] != 'E' && ModuleName[Length - 3] != 'e') ||
|
|
||||||
(ModuleName[Length - 2] != 'F' && ModuleName[Length - 2] != 'f') ||
|
|
||||||
(ModuleName[Length - 1] != 'I' && ModuleName[Length - 1] != 'i'))
|
|
||||||
{
|
|
||||||
/* Skip non .EFI file */
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Print debug message */
|
|
||||||
BlDbgPrint(L"Loading module '%S' ... ", ModuleName);
|
|
||||||
|
|
||||||
/* Set correct path to the module file */
|
|
||||||
RtlCopyMemory(ModulePath, ModulesDirPath, sizeof(ModulePath) / sizeof(WCHAR));
|
|
||||||
RtlConcatenateWideString(ModulePath, ModuleName, 0);
|
|
||||||
|
|
||||||
/* Find valid device path */
|
|
||||||
Status = BlFindVolumeDevicePath(DevicePath, ModulePath, &VolumeDevicePath);
|
|
||||||
if(Status != STATUS_EFI_SUCCESS)
|
|
||||||
{
|
|
||||||
/* Failed to set path */
|
|
||||||
BlDbgPrint(L"FAIL\n");
|
|
||||||
BlDbgPrint(L"ERROR: Unable to set valid device path\n");
|
|
||||||
|
|
||||||
/* Close directory and volume */
|
|
||||||
ModulesDir->Close(ModulesDir);
|
|
||||||
BlCloseVolume(DiskHandle);
|
|
||||||
return Status;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Load the module into memory */
|
|
||||||
Status = EfiSystemTable->BootServices->LoadImage(FALSE, EfiImageHandle, VolumeDevicePath,
|
|
||||||
NULL, 0, &ModuleHandle);
|
|
||||||
if(Status != STATUS_EFI_SUCCESS)
|
|
||||||
{
|
|
||||||
/* Module failed */
|
|
||||||
BlDbgPrint(L"FAIL\n");
|
|
||||||
|
|
||||||
/* Check if caused by secure boot */
|
|
||||||
if(Status == STATUS_EFI_ACCESS_DENIED && EfiSecureBoot >= 1)
|
|
||||||
{
|
|
||||||
BlDbgPrint(L"ERROR: SecureBoot signature validation failed\n");
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
BlDbgPrint(L"ERROR: Unable to load module (Status code: %lx)\n", Status);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Free memory and skip module */
|
|
||||||
BlEfiMemoryFreePool(VolumeDevicePath);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Free memory */
|
|
||||||
BlEfiMemoryFreePool(VolumeDevicePath);
|
|
||||||
|
|
||||||
/* Access module interface for further module type check */
|
|
||||||
Status = EfiSystemTable->BootServices->OpenProtocol(ModuleHandle, &LIPGuid, (PVOID *)&LoadedImage,
|
|
||||||
EfiImageHandle, NULL, EFI_OPEN_PROTOCOL_GET_PROTOCOL);
|
|
||||||
if(Status != STATUS_EFI_SUCCESS)
|
|
||||||
{
|
|
||||||
/* Failed to open protocol */
|
|
||||||
BlDbgPrint(L"FAIL\n");
|
|
||||||
BlDbgPrint(L"ERROR: Unable to access module interface\n");
|
|
||||||
|
|
||||||
/* Skip to the next module */
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Some firmwares do not allow to start drivers which are not of 'boot system driver' type, so check it */
|
|
||||||
if(LoadedImage->ImageCodeType != EfiBootServicesCode)
|
|
||||||
{
|
|
||||||
/* Different type set, probably 'runtime driver', refuse to load it */
|
|
||||||
BlDbgPrint(L"FAIL\n");
|
|
||||||
BlDbgPrint(L"ERROR: Loaded module is not a boot system driver\n");
|
|
||||||
|
|
||||||
/* Close protocol and skip module */
|
|
||||||
EfiSystemTable->BootServices->CloseProtocol(LoadedImage, &LIPGuid, LoadedImage, NULL);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Close loaded image protocol */
|
|
||||||
EfiSystemTable->BootServices->CloseProtocol(LoadedImage, &LIPGuid, LoadedImage, NULL);
|
|
||||||
|
|
||||||
/* Start the module */
|
|
||||||
Status = EfiSystemTable->BootServices->StartImage(ModuleHandle, NULL, NULL);
|
|
||||||
if(Status != STATUS_EFI_SUCCESS)
|
|
||||||
{
|
|
||||||
/* Module failed */
|
|
||||||
BlDbgPrint(L"FAIL\n");
|
|
||||||
BlDbgPrint(L"ERROR: Unable to start module\n");
|
|
||||||
|
|
||||||
/* Skip module */
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Module loaded successfully */
|
|
||||||
BlDbgPrint(L"OK\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Close directory and volume */
|
|
||||||
ModulesDir->Close(ModulesDir);
|
|
||||||
BlCloseVolume(DiskHandle);
|
|
||||||
|
|
||||||
/* Return success */
|
|
||||||
return STATUS_EFI_SUCCESS;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This routine attempts to start XT Operating System.
|
* Initializes a list of operating systems for XTLDR boot menu.
|
||||||
|
*
|
||||||
|
* @param MenuEntries
|
||||||
|
* Supplies a pointer to memory area where operating systems list will be stored.
|
||||||
|
*
|
||||||
|
* @param EntriesCount
|
||||||
|
* Supplies a pointer to memory area where number of menu entries will be stored.
|
||||||
|
*
|
||||||
|
* @param DefaultId
|
||||||
|
* Supplies a pointer to memory area where ID of default menu entry will be stored.
|
||||||
|
*
|
||||||
|
* @return This routine does not return any value.
|
||||||
|
*
|
||||||
|
* @since XT 1.0
|
||||||
|
*/
|
||||||
|
XTCDECL
|
||||||
|
VOID
|
||||||
|
BlInitializeBootMenuList(OUT PXTBL_BOOTMENU_ITEM MenuEntries,
|
||||||
|
OUT PULONG EntriesCount,
|
||||||
|
OUT PULONG DefaultId)
|
||||||
|
{
|
||||||
|
PWCHAR DefaultMenuEntry, MenuEntryName;
|
||||||
|
PLIST_ENTRY MenuEntrySectionList, MenuEntryList;
|
||||||
|
PXTBL_CONFIG_SECTION MenuEntrySection;
|
||||||
|
PXTBL_CONFIG_ENTRY MenuEntryOption;
|
||||||
|
PXTBL_BOOTMENU_ITEM OsList;
|
||||||
|
ULONG DefaultOS, NumberOfEntries;
|
||||||
|
|
||||||
|
/* Set default values */
|
||||||
|
DefaultOS = 0;
|
||||||
|
NumberOfEntries = 0;
|
||||||
|
OsList = NULL;
|
||||||
|
|
||||||
|
/* Get default menu entry from configuration */
|
||||||
|
DefaultMenuEntry = BlGetConfigValue(L"DEFAULT");
|
||||||
|
|
||||||
|
/* Iterate through all menu sections */
|
||||||
|
MenuEntrySectionList = BlpMenuList->Flink;
|
||||||
|
while(MenuEntrySectionList != BlpMenuList)
|
||||||
|
{
|
||||||
|
/* NULLify menu entry name */
|
||||||
|
MenuEntryName = NULL;
|
||||||
|
|
||||||
|
/* Get menu section */
|
||||||
|
MenuEntrySection = CONTAIN_RECORD(MenuEntrySectionList, XTBL_CONFIG_SECTION, Flink);
|
||||||
|
|
||||||
|
/* Check if this is the default menu entry */
|
||||||
|
if(RtlCompareWideStringInsensitive(MenuEntrySection->SectionName, DefaultMenuEntry, 0) == 0)
|
||||||
|
{
|
||||||
|
/* Set default OS ID */
|
||||||
|
DefaultOS = NumberOfEntries;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Iterate through all entry parameters */
|
||||||
|
MenuEntryList = MenuEntrySection->Options.Flink;
|
||||||
|
while(MenuEntryList != &MenuEntrySection->Options)
|
||||||
|
{
|
||||||
|
/* Get menu entry parameter */
|
||||||
|
MenuEntryOption = CONTAIN_RECORD(MenuEntryList, XTBL_CONFIG_ENTRY, Flink);
|
||||||
|
|
||||||
|
/* Check if this is the menu entry display name */
|
||||||
|
if(RtlCompareWideStringInsensitive(MenuEntryOption->Name, L"SYSTEMNAME", 0) == 0)
|
||||||
|
{
|
||||||
|
/* Set menu entry display name */
|
||||||
|
MenuEntryName = MenuEntryOption->Value;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Get next parameter for this menu entry */
|
||||||
|
MenuEntryList = MenuEntryList->Flink;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Add OS to the boot menu list */
|
||||||
|
OsList[NumberOfEntries].EntryName = MenuEntryName;
|
||||||
|
OsList[NumberOfEntries].Options = &MenuEntrySection->Options;
|
||||||
|
|
||||||
|
/* Get next menu entry */
|
||||||
|
MenuEntrySectionList = MenuEntrySectionList->Flink;
|
||||||
|
NumberOfEntries++;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Set return values */
|
||||||
|
*DefaultId = DefaultOS;
|
||||||
|
*EntriesCount = NumberOfEntries;
|
||||||
|
MenuEntries = OsList;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Loads all necessary modules and invokes boot protocol.
|
||||||
|
*
|
||||||
|
* @param OptionsList
|
||||||
|
* Supplies a pointer to list of options associated with chosen boot menu entry.
|
||||||
*
|
*
|
||||||
* @return This routine returns a status code.
|
* @return This routine returns a status code.
|
||||||
*
|
*
|
||||||
@ -219,90 +163,117 @@ BlLoadEfiModules()
|
|||||||
*/
|
*/
|
||||||
XTCDECL
|
XTCDECL
|
||||||
EFI_STATUS
|
EFI_STATUS
|
||||||
BlLoadXtSystem()
|
BlInvokeBootProtocol(IN PLIST_ENTRY OptionsList)
|
||||||
{
|
{
|
||||||
EFI_GUID ProtocolGuid = XT_XTOS_BOOT_PROTOCOL_GUID;
|
XTBL_BOOT_PARAMETERS BootParameters;
|
||||||
XT_BOOT_PROTOCOL_PARAMETERS BootParameters;
|
PXTBL_BOOT_PROTOCOL BootProtocol;
|
||||||
PXT_BOOT_PROTOCOL BootProtocol;
|
PLIST_ENTRY OptionsListEntry;
|
||||||
PUCHAR ArcName, SystemPath;
|
PXTBL_CONFIG_ENTRY Option;
|
||||||
|
EFI_GUID BootProtocolGuid;
|
||||||
|
SIZE_T ModuleListLength;
|
||||||
|
PWCHAR ModulesList;
|
||||||
EFI_STATUS Status;
|
EFI_STATUS Status;
|
||||||
PCHAR ArcPath;
|
|
||||||
SIZE_T Length;
|
|
||||||
|
|
||||||
/* Set ARC path */
|
/* Initialize boot parameters and a list of modules */
|
||||||
ArcPath = "multi(0)disk(0)rdisk(0)partition(1)/ExectOS";
|
RtlZeroMemory(&BootParameters, sizeof(XTBL_BOOT_PARAMETERS));
|
||||||
|
ModulesList = NULL;
|
||||||
|
|
||||||
/* Zero boot parameters structure to NULLify all pointers */
|
/* Iterate through all options provided by boot menu entry and propagate boot parameters */
|
||||||
RtlZeroMemory(&BootParameters, sizeof(XT_BOOT_PROTOCOL_PARAMETERS));
|
OptionsListEntry = OptionsList->Flink;
|
||||||
|
while(OptionsListEntry != OptionsList)
|
||||||
/* Get boot volume path */
|
|
||||||
Status = BlGetVolumeDevicePath((PUCHAR)ArcPath, &BootParameters.DevicePath, &ArcName, &SystemPath);
|
|
||||||
if(Status != STATUS_EFI_SUCCESS)
|
|
||||||
{
|
{
|
||||||
/* Failed to find volume */
|
/* Get option */
|
||||||
BlDbgPrint(L"ERROR: Unable to find volume device path\n");
|
Option = CONTAIN_RECORD(OptionsListEntry, XTBL_CONFIG_ENTRY, Flink);
|
||||||
return Status;
|
|
||||||
|
/* Look for boot protocol and modules list */
|
||||||
|
if(RtlCompareWideStringInsensitive(Option->Name, L"BOOTMODULES", 0) == 0)
|
||||||
|
{
|
||||||
|
/* Check a length of modules list */
|
||||||
|
ModuleListLength = RtlWideStringLength(Option->Value, 0);
|
||||||
|
|
||||||
|
Status = BlMemoryAllocatePool(sizeof(PWCHAR) * ModuleListLength, (PVOID *)&ModulesList);
|
||||||
|
if(Status != STATUS_EFI_SUCCESS)
|
||||||
|
{
|
||||||
|
/* Failed to allocate memory, print error message and return status code */
|
||||||
|
BlDebugPrint(L"ERROR: Memory allocation failure (Status Code: 0x%lx)\n");
|
||||||
|
return STATUS_EFI_OUT_OF_RESOURCES;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Make a copy of modules list */
|
||||||
|
RtlCopyMemory(ModulesList, Option->Value, sizeof(PWCHAR) * ModuleListLength);
|
||||||
|
}
|
||||||
|
else if(RtlCompareWideStringInsensitive(Option->Name, L"SYSTEMTYPE", 0) == 0)
|
||||||
|
{
|
||||||
|
/* Boot protocol found */
|
||||||
|
BootParameters.SystemType = Option->Value;
|
||||||
|
}
|
||||||
|
else if(RtlCompareWideStringInsensitive(Option->Name, L"SYSTEMPATH", 0) == 0)
|
||||||
|
{
|
||||||
|
/* System path found, get volume device path */
|
||||||
|
Status = BlGetVolumeDevicePath((PWCHAR)Option->Value, &BootParameters.DevicePath, &BootParameters.ArcName, &BootParameters.SystemPath);
|
||||||
|
if(Status != STATUS_EFI_SUCCESS)
|
||||||
|
{
|
||||||
|
/* Failed to find volume */
|
||||||
|
BlDebugPrint(L"ERROR: Failed to find volume device path (Status Code: 0x%lx)\n", Status);
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if(RtlCompareWideStringInsensitive(Option->Name, L"KERNELFILE", 0) == 0)
|
||||||
|
{
|
||||||
|
/* Kernel file name found */
|
||||||
|
BootParameters.KernelFile = Option->Value;
|
||||||
|
}
|
||||||
|
else if(RtlCompareWideStringInsensitive(Option->Name, L"INITRDFILE", 0) == 0)
|
||||||
|
{
|
||||||
|
/* Initrd file name found */
|
||||||
|
BootParameters.InitrdFile = Option->Value;
|
||||||
|
}
|
||||||
|
else if(RtlCompareWideStringInsensitive(Option->Name, L"HALFILE", 0) == 0)
|
||||||
|
{
|
||||||
|
/* Hal file name found */
|
||||||
|
BootParameters.HalFile = Option->Value;
|
||||||
|
}
|
||||||
|
else if(RtlCompareWideStringInsensitive(Option->Name, L"PARAMETERS", 0) == 0)
|
||||||
|
{
|
||||||
|
/* Kernel parameters found */
|
||||||
|
BootParameters.Parameters = Option->Value;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Move to the next option entry */
|
||||||
|
OptionsListEntry = OptionsListEntry->Flink;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Store ARC name in boot parameters */
|
/* Load all necessary modules */
|
||||||
Length = RtlStringLength(ArcName, 0);
|
Status = BlLoadModules(ModulesList);
|
||||||
BlEfiMemoryAllocatePool(Length + 1, (PVOID *)&BootParameters.ArcName);
|
if(Status != STATUS_EFI_SUCCESS)
|
||||||
RtlStringToWideString(BootParameters.ArcName, &ArcName, Length * 2);
|
{
|
||||||
|
/* Failed to load modules, print error message and return status code */
|
||||||
|
BlDebugPrint(L"ERROR: Failed to load XTLDR modules\n");
|
||||||
|
return STATUS_EFI_NOT_READY;
|
||||||
|
}
|
||||||
|
|
||||||
/* Store system path in boot parameters */
|
/* Attempt to get boot protocol GUID */
|
||||||
Length = RtlStringLength(SystemPath, 0);
|
Status = BlFindBootProtocol(BootParameters.SystemType, &BootProtocolGuid);
|
||||||
BlEfiMemoryAllocatePool(Length + 1, (PVOID *)&BootParameters.SystemPath);
|
if(Status != STATUS_EFI_SUCCESS)
|
||||||
RtlStringToWideString(BootParameters.SystemPath, &SystemPath, Length + 1);
|
{
|
||||||
|
/* Failed to get boot protocol GUID */
|
||||||
|
BlDebugPrint(L"ERROR: Unable to find appropriate boot protocol (Status Code: 0x%lx)\n", Status);
|
||||||
|
return STATUS_EFI_UNSUPPORTED;
|
||||||
|
}
|
||||||
|
|
||||||
/* Open the XT boot protocol */
|
/* Open boot protocol */
|
||||||
Status = BlLoadXtProtocol((PVOID *)&BootProtocol, &ProtocolGuid);
|
Status = BlOpenProtocol((PVOID *)&BootProtocol, &BootProtocolGuid);
|
||||||
if(Status != STATUS_EFI_SUCCESS)
|
if(Status != STATUS_EFI_SUCCESS)
|
||||||
{
|
{
|
||||||
/* Failed to open boot protocol */
|
/* Failed to open boot protocol */
|
||||||
BlDbgPrint(L"ERROR: Unable to load boot protocol\n");
|
BlDebugPrint(L"ERROR: Failed to open boot protocol (Status Code: 0x%lx)\n", Status);
|
||||||
return STATUS_EFI_PROTOCOL_ERROR;
|
return Status;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Boot operating system */
|
/* Boot Operating System */
|
||||||
return BootProtocol->BootSystem(&BootParameters);
|
return BootProtocol->BootSystem(&BootParameters);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* This routine registers XTLDR protocol for further usage by modules.
|
|
||||||
*
|
|
||||||
* @return This routine returns status code.
|
|
||||||
*
|
|
||||||
* @since XT 1.0
|
|
||||||
*/
|
|
||||||
XTCDECL
|
|
||||||
EFI_STATUS
|
|
||||||
BlRegisterXtLoaderProtocol()
|
|
||||||
{
|
|
||||||
EFI_GUID Guid = XT_BOOT_LOADER_PROTOCOL_GUID;
|
|
||||||
EFI_HANDLE Handle = NULL;
|
|
||||||
|
|
||||||
/* Set all routines available via loader protocol */
|
|
||||||
EfiLdrProtocol.AddVirtualMemoryMapping = BlAddVirtualMemoryMapping;
|
|
||||||
EfiLdrProtocol.AllocatePages = BlEfiMemoryAllocatePages;
|
|
||||||
EfiLdrProtocol.AllocatePool = BlEfiMemoryAllocatePool;
|
|
||||||
EfiLdrProtocol.FreePages = BlEfiMemoryFreePages;
|
|
||||||
EfiLdrProtocol.FreePool = BlEfiMemoryFreePool;
|
|
||||||
EfiLdrProtocol.EnablePaging = BlEnablePaging;
|
|
||||||
EfiLdrProtocol.GetMemoryMap = BlGetMemoryMap;
|
|
||||||
EfiLdrProtocol.GetVirtualAddress = BlGetVirtualAddress;
|
|
||||||
EfiLdrProtocol.InitializeVirtualMemory = BlInitializeVirtualMemory;
|
|
||||||
EfiLdrProtocol.MapVirtualMemory = BlMapVirtualMemory;
|
|
||||||
EfiLdrProtocol.DbgPrint = BlDbgPrint;
|
|
||||||
EfiLdrProtocol.EfiPrint = BlEfiPrint;
|
|
||||||
EfiLdrProtocol.CloseVolume = BlCloseVolume;
|
|
||||||
EfiLdrProtocol.OpenVolume = BlOpenVolume;
|
|
||||||
|
|
||||||
/* Register loader protocol */
|
|
||||||
BlDbgPrint(L"Registering XT loader protocol\n");
|
|
||||||
return EfiSystemTable->BootServices->InstallProtocolInterface(&Handle, &Guid, EFI_NATIVE_INTERFACE,
|
|
||||||
&EfiLdrProtocol);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This routine is the entry point of the XT EFI boot loader.
|
* This routine is the entry point of the XT EFI boot loader.
|
||||||
*
|
*
|
||||||
@ -327,71 +298,136 @@ BlStartXtLoader(IN EFI_HANDLE ImageHandle,
|
|||||||
EfiImageHandle = ImageHandle;
|
EfiImageHandle = ImageHandle;
|
||||||
EfiSystemTable = SystemTable;
|
EfiSystemTable = SystemTable;
|
||||||
|
|
||||||
/* Initialize EFI console */
|
/* Initialize XTLDR and */
|
||||||
BlConsoleInitialize();
|
BlInitializeBootLoader();
|
||||||
BlEfiPrint(L"XTLDR boot loader v%s\n", XTOS_VERSION);
|
|
||||||
|
|
||||||
/* Early initialize COM port for debugging */
|
/* Parse configuration options passed from UEFI shell */
|
||||||
|
Status = BlpParseCommandLine();
|
||||||
|
if(Status != STATUS_EFI_SUCCESS)
|
||||||
|
{
|
||||||
|
/* Failed to parse command line options */
|
||||||
|
BlDisplayErrorDialog(L"XTLDR", L"Failed to parse command line parameters.");
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Attempt to early initialize debug console */
|
||||||
if(DEBUG)
|
if(DEBUG)
|
||||||
{
|
{
|
||||||
Status = BlComPortInitialize();
|
Status = BlpInitializeDebugConsole();
|
||||||
if(Status != STATUS_EFI_SUCCESS)
|
if(Status != STATUS_EFI_SUCCESS)
|
||||||
{
|
{
|
||||||
/* Initialization failed, try printing error to stdout and serial console */
|
/* Initialization failed, notify user on stdout */
|
||||||
BlEfiPrint(L"ERROR: Failed to initialize serial console\n");
|
BlDisplayErrorDialog(L"XTLDR", L"Failed to initialize debug console.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Check SecureBoot status */
|
/* Load XTLDR configuration file */
|
||||||
EfiSecureBoot = BlEfiGetSecureBootStatus();
|
Status = BlpLoadConfiguration();
|
||||||
|
if(Status != STATUS_EFI_SUCCESS)
|
||||||
|
{
|
||||||
|
/* Failed to load/parse config file */
|
||||||
|
BlDisplayErrorDialog(L"XTLDR", L"Failed to load and parse configuration file.");
|
||||||
|
}
|
||||||
|
|
||||||
/* Print firmware information */
|
/* Reinitialize debug console if it was not initialized earlier */
|
||||||
BlDbgPrint(L"UEFI v%d.%d (%S 0x%08x), SecureBoot %S\n", EfiSystemTable->Hdr.Revision >> 16,
|
if(DEBUG)
|
||||||
EfiSystemTable->Hdr.Revision & 0xFFFF, EfiSystemTable->FirmwareVendor, EfiSystemTable->FirmwareRevision,
|
{
|
||||||
EfiSecureBoot == 0 ? L"DISABLED" : EfiSecureBoot > 0 ? L"ENABLED" : L"SETUP");
|
Status = BlpInitializeDebugConsole();
|
||||||
|
if(Status != STATUS_EFI_SUCCESS)
|
||||||
|
{
|
||||||
|
/* Initialization failed, notify user on stdout */
|
||||||
|
BlDisplayErrorDialog(L"XTLDR", L"Failed to initialize debug console.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* Disable watchdog timer */
|
/* Disable watchdog timer */
|
||||||
Status = EfiSystemTable->BootServices->SetWatchdogTimer(0, 0x10000, 0, NULL);
|
Status = EfiSystemTable->BootServices->SetWatchdogTimer(0, 0x10000, 0, NULL);
|
||||||
if(Status != STATUS_EFI_SUCCESS)
|
if(Status != STATUS_EFI_SUCCESS)
|
||||||
{
|
{
|
||||||
/* Failed to disable the timer, print message */
|
/* Failed to disable the timer, print message */
|
||||||
BlDbgPrint(L"WARNING: Failed to disable watchdog timer\n");
|
BlDebugPrint(L"WARNING: Failed to disable watchdog timer\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Register loader protocol */
|
/* Register loader protocol */
|
||||||
Status = BlRegisterXtLoaderProtocol();
|
Status = BlpRegisterXtLoaderProtocol();
|
||||||
if(Status != STATUS_EFI_SUCCESS)
|
if(Status != STATUS_EFI_SUCCESS)
|
||||||
{
|
{
|
||||||
/* Failed to register loader protocol */
|
/* Failed to register loader protocol */
|
||||||
BlDbgPrint(L"ERROR: Failed to register XTLDR loader protocol\n");
|
BlDebugPrint(L"ERROR: Failed to register XTLDR boot protocol\n");
|
||||||
|
return Status;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Load XTLDR modules */
|
/* Load boot loader modules */
|
||||||
Status = BlLoadEfiModules();
|
Status = BlLoadModules(BlGetConfigValue(L"MODULES"));
|
||||||
if(Status != STATUS_EFI_SUCCESS)
|
if(Status != STATUS_EFI_SUCCESS)
|
||||||
{
|
{
|
||||||
BlDbgPrint(L"ERROR: Failed to load XTLDR modules\n");
|
/* Failed to load modules */
|
||||||
|
BlDebugPrint(L"ERROR: Failed to load XTLDR modules (Status Code: 0x%lx)\n", Status);
|
||||||
|
BlDisplayErrorDialog(L"XTLDR", L"Failed to load some XTLDR modules.");
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Discover and enumerate EFI block devices */
|
/* Discover and enumerate EFI block devices */
|
||||||
BlEnumerateEfiBlockDevices();
|
Status = BlEnumerateBlockDevices();
|
||||||
|
|
||||||
/* Boot XTOS */
|
|
||||||
Status = BlLoadXtSystem();
|
|
||||||
if(Status != STATUS_EFI_SUCCESS)
|
if(Status != STATUS_EFI_SUCCESS)
|
||||||
{
|
{
|
||||||
/* Boot process failed */
|
/* Failed to enumerate block devices */
|
||||||
BlEfiPrint(L"Failed to start XT OS (Status code: %lx)!\n", Status);
|
BlDebugPrint(L"ERROR: Failed to discover and enumerate block devices\n");
|
||||||
|
return Status;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Infinite bootloader loop */
|
|
||||||
BlEfiPrint(L"System halted!");
|
// BlConsolePrint(L"\n\n\n\n\n\n\n\nList of loaded modules:");
|
||||||
for(;;)
|
// PLIST_ENTRY ModuleListEntry;
|
||||||
|
// PXTBL_MODULE_INFO ModuleInfo;
|
||||||
|
|
||||||
|
// ModuleListEntry = BlpLoadedModules.Flink;
|
||||||
|
// while(ModuleListEntry != &BlpLoadedModules)
|
||||||
|
// {
|
||||||
|
// /* Get module information */
|
||||||
|
// ModuleInfo = CONTAIN_RECORD(ModuleListEntry, XTBL_MODULE_INFO, Flink);
|
||||||
|
|
||||||
|
// /* Module already loaded */
|
||||||
|
// BlConsolePrint(L"\n%S", ModuleInfo->ModuleName);
|
||||||
|
// if(ModuleInfo->ModuleDescription != 0)
|
||||||
|
// {
|
||||||
|
// BlConsolePrint(L" (%S)", ModuleInfo->ModuleDescription);
|
||||||
|
// }
|
||||||
|
|
||||||
|
// PLIST_ENTRY DepsListEntry;
|
||||||
|
// PXTBL_MODULE_DEPS DepsInfo;
|
||||||
|
// BlConsolePrint(L"\n - Uses: ");
|
||||||
|
// DepsListEntry = ModuleInfo->Dependencies.Flink;
|
||||||
|
// while(DepsListEntry != &ModuleInfo->Dependencies)
|
||||||
|
// {
|
||||||
|
// DepsInfo = CONTAIN_RECORD(DepsListEntry, XTBL_MODULE_DEPS, Flink);
|
||||||
|
// BlConsolePrint(L"%S ", DepsInfo->ModuleName);
|
||||||
|
// DepsListEntry = DepsListEntry->Flink;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// /* Move to the module */
|
||||||
|
// ModuleListEntry = ModuleListEntry->Flink;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// BlConsolePrint(L"\n\n END OF LIST\n");
|
||||||
|
|
||||||
|
/* Main boot loader loop */
|
||||||
|
while(TRUE)
|
||||||
{
|
{
|
||||||
ArClearInterruptFlag();
|
/* Check if custom boot menu registered */
|
||||||
ArHalt();
|
if(BlpStatus.BootMenu != NULL)
|
||||||
|
{
|
||||||
|
/* Display alternative boot menu */
|
||||||
|
BlpStatus.BootMenu();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Display default boot menu */
|
||||||
|
BlDisplayBootMenu();
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Fallback to shell, if boot menu returned */
|
||||||
|
BlStartLoaderShell();
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Return success */
|
/* This point should be never reached, if this happen return error code */
|
||||||
return STATUS_EFI_SUCCESS;
|
return STATUS_EFI_LOAD_ERROR;
|
||||||
}
|
}
|
||||||
|
@ -1,54 +0,0 @@
|
|||||||
# XT Boot Manager
|
|
||||||
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.c)
|
|
||||||
|
|
||||||
# Specify list of source code files
|
|
||||||
list(APPEND XTLDR_SOURCE
|
|
||||||
${XTLDR_SOURCE_DIR}/config.c
|
|
||||||
${XTLDR_SOURCE_DIR}/console.c
|
|
||||||
${XTLDR_SOURCE_DIR}/debug.c
|
|
||||||
${XTLDR_SOURCE_DIR}/efiutils.c
|
|
||||||
${XTLDR_SOURCE_DIR}/globals.c
|
|
||||||
${XTLDR_SOURCE_DIR}/hardware.c
|
|
||||||
${XTLDR_SOURCE_DIR}/memory.c
|
|
||||||
${XTLDR_SOURCE_DIR}/protocol.c
|
|
||||||
${XTLDR_SOURCE_DIR}/shell.c
|
|
||||||
${XTLDR_SOURCE_DIR}/string.c
|
|
||||||
${XTLDR_SOURCE_DIR}/textui.c
|
|
||||||
${XTLDR_SOURCE_DIR}/volume.c
|
|
||||||
${XTLDR_SOURCE_DIR}/xtldr.c)
|
|
||||||
|
|
||||||
# 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_imagebase(xtldr ${BASEADDRESS_XTLDR})
|
|
||||||
set_linker_map(xtldr TRUE)
|
|
||||||
set_subsystem(xtldr efi_application)
|
|
@ -1,14 +0,0 @@
|
|||||||
## XT Boot Manager (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.
|
|
297
xtldr2/console.c
297
xtldr2/console.c
@ -1,297 +0,0 @@
|
|||||||
/**
|
|
||||||
* PROJECT: ExectOS
|
|
||||||
* COPYRIGHT: See COPYING.md in the top level directory
|
|
||||||
* FILE: xtldr/console.c
|
|
||||||
* DESCRIPTION: EFI console support
|
|
||||||
* DEVELOPERS: Rafal Kupiec <belliash@codingworkshop.eu.org>
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <xtldr.h>
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 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
|
|
||||||
BlClearConsoleLine(IN ULONGLONG LineNo)
|
|
||||||
{
|
|
||||||
UINT_PTR Index, ResX, ResY;
|
|
||||||
|
|
||||||
/* Query console mode */
|
|
||||||
BlQueryConsoleMode(&ResX, &ResY);
|
|
||||||
|
|
||||||
/* Set cursor position and clear line */
|
|
||||||
BlSetCursorPosition(0, LineNo);
|
|
||||||
for(Index = 0; Index < ResX; Index++)
|
|
||||||
{
|
|
||||||
/* Clear line */
|
|
||||||
BlConsoleWrite(L" ");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This routine clears the UEFI console screen.
|
|
||||||
*
|
|
||||||
* @return This routine does not return any value.
|
|
||||||
*
|
|
||||||
* @since XT 1.0
|
|
||||||
*/
|
|
||||||
XTCDECL
|
|
||||||
VOID
|
|
||||||
BlClearConsoleScreen()
|
|
||||||
{
|
|
||||||
/* Clear screen */
|
|
||||||
EfiSystemTable->ConOut->ClearScreen(EfiSystemTable->ConOut);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Disables the cursor on the UEFI console.
|
|
||||||
*
|
|
||||||
* @return This routine does not return any value.
|
|
||||||
*
|
|
||||||
* @since XT 1.0
|
|
||||||
*/
|
|
||||||
XTCDECL
|
|
||||||
VOID
|
|
||||||
BlDisableConsoleCursor()
|
|
||||||
{
|
|
||||||
EfiSystemTable->ConOut->EnableCursor(EfiSystemTable->ConOut, FALSE);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Enables the cursor on the UEFI console.
|
|
||||||
*
|
|
||||||
* @return This routine does not return any value.
|
|
||||||
*
|
|
||||||
* @since XT 1.0
|
|
||||||
*/
|
|
||||||
XTCDECL
|
|
||||||
VOID
|
|
||||||
BlEnableConsoleCursor()
|
|
||||||
{
|
|
||||||
EfiSystemTable->ConOut->EnableCursor(EfiSystemTable->ConOut, TRUE);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 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
|
|
||||||
BlConsolePrint(IN PUINT16 Format,
|
|
||||||
IN ...)
|
|
||||||
{
|
|
||||||
VA_LIST Arguments;
|
|
||||||
|
|
||||||
/* Initialise the va_list */
|
|
||||||
VA_START(Arguments, Format);
|
|
||||||
|
|
||||||
/* Format and print the string to the stdout */
|
|
||||||
BlpStringPrint(BlpConsolePrintChar, Format, Arguments);
|
|
||||||
|
|
||||||
/* Print to serial console only if not running under OVMF */
|
|
||||||
if(RtlCompareWideString(EfiSystemTable->FirmwareVendor, L"EDK II", 6) != 0)
|
|
||||||
{
|
|
||||||
/* Check if debugging enabled and if EFI serial port is fully initialized */
|
|
||||||
if(DEBUG && (BlpStatus.SerialPort.Flags & COMPORT_FLAG_INIT))
|
|
||||||
{
|
|
||||||
/* Format and print the string to the serial console */
|
|
||||||
BlpStringPrint(BlpDebugPutChar, Format, Arguments);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Clean up the va_list */
|
|
||||||
VA_END(Arguments);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 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
|
|
||||||
BlConsoleWrite(IN PUSHORT String)
|
|
||||||
{
|
|
||||||
EfiSystemTable->ConOut->OutputString(EfiSystemTable->ConOut, String);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 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
|
|
||||||
BlQueryConsoleMode(OUT PUINT_PTR ResX,
|
|
||||||
OUT PUINT_PTR ResY)
|
|
||||||
{
|
|
||||||
EfiSystemTable->ConOut->QueryMode(EfiSystemTable->ConOut, EfiSystemTable->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
|
|
||||||
BlReadKeyStroke(OUT PEFI_INPUT_KEY Key)
|
|
||||||
{
|
|
||||||
EfiSystemTable->ConIn->ReadKeyStroke(EfiSystemTable->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
|
|
||||||
BlResetConsoleInputBuffer()
|
|
||||||
{
|
|
||||||
EfiSystemTable->ConIn->Reset(EfiSystemTable->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
|
|
||||||
BlSetConsoleAttributes(IN ULONGLONG Attributes)
|
|
||||||
{
|
|
||||||
EfiSystemTable->ConOut->SetAttribute(EfiSystemTable->ConOut, Attributes);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 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
|
|
||||||
BlSetConsoleMode(IN ULONGLONG Mode)
|
|
||||||
{
|
|
||||||
return EfiSystemTable->ConOut->SetMode(EfiSystemTable->ConOut, Mode);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 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
|
|
||||||
BlSetCursorPosition(IN ULONGLONG PosX,
|
|
||||||
IN ULONGLONG PosY)
|
|
||||||
{
|
|
||||||
EfiSystemTable->ConOut->SetCursorPosition(EfiSystemTable->ConOut, PosX, PosY);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Writes a character to the default EFI console.
|
|
||||||
*
|
|
||||||
* @param Character
|
|
||||||
* The integer promotion of the character to be written.
|
|
||||||
*
|
|
||||||
* @return This routine does not return any value.
|
|
||||||
*
|
|
||||||
* @since XT 1.0
|
|
||||||
*/
|
|
||||||
XTCDECL
|
|
||||||
VOID
|
|
||||||
BlpConsolePrintChar(IN USHORT Character)
|
|
||||||
{
|
|
||||||
USHORT Buffer[2];
|
|
||||||
|
|
||||||
/* Write character to the screen console */
|
|
||||||
Buffer[0] = Character;
|
|
||||||
Buffer[1] = 0;
|
|
||||||
EfiSystemTable->ConOut->OutputString(EfiSystemTable->ConOut, Buffer);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This routine initializes the EFI console.
|
|
||||||
*
|
|
||||||
* @return This routine returns status code.
|
|
||||||
*
|
|
||||||
* @since XT 1.0
|
|
||||||
*/
|
|
||||||
XTCDECL
|
|
||||||
VOID
|
|
||||||
BlpInitializeConsole()
|
|
||||||
{
|
|
||||||
/* Clear console buffers */
|
|
||||||
EfiSystemTable->ConIn->Reset(EfiSystemTable->ConIn, TRUE);
|
|
||||||
EfiSystemTable->ConOut->Reset(EfiSystemTable->ConOut, TRUE);
|
|
||||||
EfiSystemTable->StdErr->Reset(EfiSystemTable->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(EfiSystemTable->ConOut->Mode->Mode != 0)
|
|
||||||
{
|
|
||||||
/* Set console mode to 0, which is standard, 80x25 text mode */
|
|
||||||
BlSetConsoleMode(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Clear screen and enable cursor */
|
|
||||||
BlClearConsoleScreen();
|
|
||||||
BlEnableConsoleCursor();
|
|
||||||
}
|
|
@ -1,43 +0,0 @@
|
|||||||
/**
|
|
||||||
* PROJECT: ExectOS
|
|
||||||
* COPYRIGHT: See COPYING.md in the top level directory
|
|
||||||
* FILE: xtldr/globals.c
|
|
||||||
* DESCRIPTION: XT Boot Loader global variables
|
|
||||||
* DEVELOPERS: Rafal Kupiec <belliash@codingworkshop.eu.org>
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <xtldr.h>
|
|
||||||
|
|
||||||
|
|
||||||
/* XT Boot Loader registered boot protocol list */
|
|
||||||
LIST_ENTRY BlpBootProtocols;
|
|
||||||
|
|
||||||
/* XT Boot Loader configuration list */
|
|
||||||
LIST_ENTRY BlpConfig;
|
|
||||||
|
|
||||||
/* XT Boot Loader loaded configuration */
|
|
||||||
LIST_ENTRY BlpConfigSections;
|
|
||||||
|
|
||||||
/* XT Boot Loader hex table */
|
|
||||||
STATIC PUINT16 BlpHexTable = L"0123456789ABCDEF";
|
|
||||||
|
|
||||||
/* XT Boot Loader protocol */
|
|
||||||
XTBL_LOADER_PROTOCOL BlpLdrProtocol;
|
|
||||||
|
|
||||||
/* XT Boot Loader loaded modules list */
|
|
||||||
LIST_ENTRY BlpLoadedModules;
|
|
||||||
|
|
||||||
/* XT Boot Loader menu list */
|
|
||||||
PLIST_ENTRY BlpMenuList = NULL;
|
|
||||||
|
|
||||||
/* XT Boot Loader status data */
|
|
||||||
XTBL_STATUS BlpStatus = {0};
|
|
||||||
|
|
||||||
/* List of available block devices */
|
|
||||||
LIST_ENTRY EfiBlockDevices;
|
|
||||||
|
|
||||||
/* EFI Image Handle */
|
|
||||||
EFI_HANDLE EfiImageHandle;
|
|
||||||
|
|
||||||
/* EFI System Table */
|
|
||||||
PEFI_SYSTEM_TABLE EfiSystemTable;
|
|
155
xtldr2/memory.c
155
xtldr2/memory.c
@ -1,155 +0,0 @@
|
|||||||
/**
|
|
||||||
* PROJECT: ExectOS
|
|
||||||
* COPYRIGHT: See COPYING.md in the top level directory
|
|
||||||
* FILE: xtldr/memory.c
|
|
||||||
* DESCRIPTION: XT Boot Loader memory management
|
|
||||||
* DEVELOPERS: Rafal Kupiec <belliash@codingworkshop.eu.org>
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <xtldr.h>
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 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
|
|
||||||
BlGetMemoryMap(OUT PEFI_MEMORY_MAP MemoryMap)
|
|
||||||
{
|
|
||||||
EFI_STATUS Status;
|
|
||||||
|
|
||||||
if(MemoryMap == NULL)
|
|
||||||
{
|
|
||||||
return STATUS_EFI_INVALID_PARAMETER;
|
|
||||||
}
|
|
||||||
|
|
||||||
MemoryMap->Map = NULL;
|
|
||||||
MemoryMap->MapSize = 0;
|
|
||||||
|
|
||||||
/* Get memory map */
|
|
||||||
do
|
|
||||||
{
|
|
||||||
/* Attempt do get EFI memory map */
|
|
||||||
Status = EfiSystemTable->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 */
|
|
||||||
BlMemoryFreePool(MemoryMap->Map);
|
|
||||||
}
|
|
||||||
return Status;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Allocate the desired amount of memory */
|
|
||||||
MemoryMap->MapSize += 2 * MemoryMap->DescriptorSize;
|
|
||||||
BlMemoryAllocatePool(MemoryMap->MapSize, (PVOID *)&MemoryMap->Map);
|
|
||||||
}
|
|
||||||
while(Status == STATUS_EFI_BUFFER_TOO_SMALL);
|
|
||||||
|
|
||||||
/* Make sure memory map is set */
|
|
||||||
if(MemoryMap->Map == NULL)
|
|
||||||
{
|
|
||||||
/* Something went wrong */
|
|
||||||
return STATUS_EFI_NO_MAPPING;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Return success */
|
|
||||||
return STATUS_EFI_SUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This routine allocates one or more 4KB pages.
|
|
||||||
*
|
|
||||||
* @param Pages
|
|
||||||
* 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
|
|
||||||
BlMemoryAllocatePages(IN UINT64 Pages,
|
|
||||||
OUT PEFI_PHYSICAL_ADDRESS Memory)
|
|
||||||
{
|
|
||||||
return EfiSystemTable->BootServices->AllocatePages(AllocateAnyPages, EfiLoaderData, Pages, 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
|
|
||||||
BlMemoryAllocatePool(IN UINT_PTR Size,
|
|
||||||
OUT PVOID *Memory)
|
|
||||||
{
|
|
||||||
/* Allocate pool */
|
|
||||||
return EfiSystemTable->BootServices->AllocatePool(EfiLoaderData, Size, Memory);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This routine frees memory pages.
|
|
||||||
*
|
|
||||||
* @param Pages
|
|
||||||
* 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
|
|
||||||
BlMemoryFreePages(IN UINT64 Pages,
|
|
||||||
IN EFI_PHYSICAL_ADDRESS Memory)
|
|
||||||
{
|
|
||||||
return EfiSystemTable->BootServices->FreePages(Memory, Pages);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 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
|
|
||||||
BlMemoryFreePool(IN PVOID Memory)
|
|
||||||
{
|
|
||||||
/* Free pool */
|
|
||||||
return EfiSystemTable->BootServices->FreePool(Memory);
|
|
||||||
}
|
|
@ -1,4 +0,0 @@
|
|||||||
add_subdirectory(dummy)
|
|
||||||
add_subdirectory(fb_o)
|
|
||||||
add_subdirectory(pecoff_o)
|
|
||||||
add_subdirectory(xtos_o)
|
|
444
xtldr2/string.c
444
xtldr2/string.c
@ -1,444 +0,0 @@
|
|||||||
/**
|
|
||||||
* PROJECT: ExectOS
|
|
||||||
* COPYRIGHT: See COPYING.md in the top level directory
|
|
||||||
* FILE: xtldr/string.c
|
|
||||||
* DESCRIPTION: EFI string manipulation support
|
|
||||||
* DEVELOPERS: Rafal Kupiec <belliash@codingworkshop.eu.org>
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <xtldr.h>
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This routine formats the input string and prints it using specified routine.
|
|
||||||
*
|
|
||||||
* @param PrintCharRoutine
|
|
||||||
* Pointer to the routine that writes an input data to specific device.
|
|
||||||
*
|
|
||||||
* @param Format
|
|
||||||
* The formatted string that is to be written to the specified device.
|
|
||||||
*
|
|
||||||
* @param Arguments
|
|
||||||
* A value identifying a variable arguments list initialized with VA_START.
|
|
||||||
*
|
|
||||||
* @return This routine does not return any value.
|
|
||||||
*
|
|
||||||
* @since XT 1.0
|
|
||||||
*/
|
|
||||||
XTCDECL
|
|
||||||
VOID
|
|
||||||
BlpStringPrint(IN IN BLPRINTCHAR PrintCharRoutine,
|
|
||||||
IN PUINT16 Format,
|
|
||||||
IN VA_LIST Arguments)
|
|
||||||
{
|
|
||||||
PEFI_GUID Guid;
|
|
||||||
PUCHAR String;
|
|
||||||
PWCHAR WideString;
|
|
||||||
ULONG PaddingCount;
|
|
||||||
|
|
||||||
/* Read the variable arguments */
|
|
||||||
for(; *Format; ++Format)
|
|
||||||
{
|
|
||||||
switch(*Format)
|
|
||||||
{
|
|
||||||
case L'%':
|
|
||||||
switch(*++Format)
|
|
||||||
{
|
|
||||||
case L'b':
|
|
||||||
/* Boolean */
|
|
||||||
BlpStringFormat(PrintCharRoutine, L"%s", VA_ARG(Arguments, INT32) ? "TRUE" : "FALSE");
|
|
||||||
break;
|
|
||||||
case L'c':
|
|
||||||
/* Character */
|
|
||||||
PrintCharRoutine(VA_ARG(Arguments, INT));
|
|
||||||
break;
|
|
||||||
case L'd':
|
|
||||||
/* Signed 32-bit integer */
|
|
||||||
BlpStringPrintSigned32(PrintCharRoutine, VA_ARG(Arguments, INT32), 10);
|
|
||||||
break;
|
|
||||||
case L'g':
|
|
||||||
/* EFI GUID */
|
|
||||||
Guid = VA_ARG(Arguments, PEFI_GUID);
|
|
||||||
BlpStringFormat(PrintCharRoutine, L"%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x", Guid->Data1,
|
|
||||||
Guid->Data2, Guid->Data3, Guid->Data4[0], Guid->Data4[1], Guid->Data4[2],
|
|
||||||
Guid->Data4[3], Guid->Data4[4], Guid->Data4[5], Guid->Data4[6], Guid->Data4[7]);
|
|
||||||
break;
|
|
||||||
case L'l':
|
|
||||||
/* 64-bit numbers */
|
|
||||||
switch(*++Format)
|
|
||||||
{
|
|
||||||
case L'd':
|
|
||||||
/* Signed 64-bit integer */
|
|
||||||
BlpStringPrintSigned64(PrintCharRoutine, VA_ARG(Arguments, INT_PTR), 10);
|
|
||||||
break;
|
|
||||||
case L'u':
|
|
||||||
/* Unsigned 64-bit integer */
|
|
||||||
BlpStringPrintUnsigned64(PrintCharRoutine, VA_ARG(Arguments, UINT_PTR), 10, 0);
|
|
||||||
break;
|
|
||||||
case L'x':
|
|
||||||
/* Unsigned 64-bit hexadecimal integer */
|
|
||||||
BlpStringPrintUnsigned64(PrintCharRoutine, VA_ARG(Arguments, UINT_PTR), 16, 0);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
/* Unknown by default */
|
|
||||||
PrintCharRoutine(L'?');
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case L'p':
|
|
||||||
/* Pointer address */
|
|
||||||
BlpStringPrintUnsigned64(PrintCharRoutine, VA_ARG(Arguments, UINT_PTR), 16, 0);
|
|
||||||
break;
|
|
||||||
case L's':
|
|
||||||
/* String of characters */
|
|
||||||
String = VA_ARG(Arguments, PUCHAR);
|
|
||||||
while(*String)
|
|
||||||
{
|
|
||||||
PrintCharRoutine(*String++);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case L'S':
|
|
||||||
WideString = VA_ARG(Arguments, PWCHAR);
|
|
||||||
while(*WideString)
|
|
||||||
{
|
|
||||||
PrintCharRoutine((UCHAR)*WideString++);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case L'u':
|
|
||||||
/* Unsigned 32-bit integer */
|
|
||||||
BlpStringPrintUnsigned32(PrintCharRoutine, VA_ARG(Arguments, UINT32), 10, 0);
|
|
||||||
break;
|
|
||||||
case L'x':
|
|
||||||
/* Unsigned 32-bit hexadecimal integer */
|
|
||||||
BlpStringPrintUnsigned32(PrintCharRoutine, VA_ARG(Arguments, UINT32), 16, 0);
|
|
||||||
break;
|
|
||||||
case L'0':
|
|
||||||
/* Zero padded numbers */
|
|
||||||
++Format;
|
|
||||||
PaddingCount = BlpStringReadPadding(&Format);
|
|
||||||
switch(*Format)
|
|
||||||
{
|
|
||||||
case L'd':
|
|
||||||
/* Zero-padded, signed 32-bit integer */
|
|
||||||
BlpStringPrintSigned32(PrintCharRoutine, VA_ARG(Arguments, INT32), 10);
|
|
||||||
break;
|
|
||||||
case L'l':
|
|
||||||
/* 64-bit numbers */
|
|
||||||
switch(*++Format)
|
|
||||||
{
|
|
||||||
case L'd':
|
|
||||||
/* Zero-padded, signed 64-bit integer */
|
|
||||||
BlpStringPrintSigned64(PrintCharRoutine, VA_ARG(Arguments, INT_PTR), 10);
|
|
||||||
break;
|
|
||||||
case L'u':
|
|
||||||
/* Zero-padded, unsigned 64-bit integer */
|
|
||||||
BlpStringPrintUnsigned64(PrintCharRoutine, VA_ARG(Arguments, UINT_PTR), 10, PaddingCount);
|
|
||||||
break;
|
|
||||||
case L'x':
|
|
||||||
/* Zero-padded, unsigned 64-bit hexadecimal integer */
|
|
||||||
BlpStringPrintUnsigned64(PrintCharRoutine, VA_ARG(Arguments, UINT_PTR), 16, PaddingCount);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
/* Unknown by default */
|
|
||||||
PrintCharRoutine(L'?');
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case L'u':
|
|
||||||
/* Zero-padded, unsigned 32-bit integer */
|
|
||||||
BlpStringPrintUnsigned32(PrintCharRoutine, VA_ARG(Arguments, UINT32), 10, PaddingCount);
|
|
||||||
break;
|
|
||||||
case L'x':
|
|
||||||
/* Zero-padded, unsigned 32-bit hexadecimal integer */
|
|
||||||
BlpStringPrintUnsigned32(PrintCharRoutine, VA_ARG(Arguments, UINT32), 16, PaddingCount);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
/* Unknown by default */
|
|
||||||
PrintCharRoutine(L'?');
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case L'%':
|
|
||||||
/* Percent character */
|
|
||||||
PrintCharRoutine(L'%');
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
/* Unknown by default */
|
|
||||||
PrintCharRoutine(L'?');
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case L'\r':
|
|
||||||
/* Carriage return is ignored */
|
|
||||||
break;
|
|
||||||
case L'\n':
|
|
||||||
/* New line together with carriage return */
|
|
||||||
PrintCharRoutine(L'\r');
|
|
||||||
PrintCharRoutine(L'\n');
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
/* Put character by default */
|
|
||||||
PrintCharRoutine(*Format);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This routine formats the input string and prints it using specified routine.
|
|
||||||
*
|
|
||||||
* @param PrintCharRoutine
|
|
||||||
* Pointer to the routine that writes an input data to specific device.
|
|
||||||
*
|
|
||||||
* @param Format
|
|
||||||
* The formatted string that is to be written to the specified device.
|
|
||||||
*
|
|
||||||
* @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
|
|
||||||
BlpStringFormat(IN BLPRINTCHAR PrintCharRoutine,
|
|
||||||
IN PUINT16 Format,
|
|
||||||
IN ...)
|
|
||||||
{
|
|
||||||
VA_LIST Arguments;
|
|
||||||
|
|
||||||
/* Initialise the va_list */
|
|
||||||
VA_START(Arguments, Format);
|
|
||||||
|
|
||||||
/* Format and print the string to the desired output */
|
|
||||||
BlpStringPrint(PrintCharRoutine, Format, Arguments);
|
|
||||||
|
|
||||||
/* Clean up the va_list */
|
|
||||||
VA_END(Arguments);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This routine converts 32-bit integer as string and prints it using specified routine.
|
|
||||||
*
|
|
||||||
* @param PrintCharRoutine
|
|
||||||
* Pointer to the routine that writes an input data to specific device.
|
|
||||||
*
|
|
||||||
* @param Number
|
|
||||||
* 32-bit integer value.
|
|
||||||
*
|
|
||||||
* @param Base
|
|
||||||
* Specifies the number base system representation.
|
|
||||||
*
|
|
||||||
* @return This routine does not return any value.
|
|
||||||
*
|
|
||||||
* @since XT 1.0
|
|
||||||
*/
|
|
||||||
XTCDECL
|
|
||||||
VOID
|
|
||||||
BlpStringPrintSigned32(IN BLPRINTCHAR PrintCharRoutine,
|
|
||||||
IN INT Number,
|
|
||||||
IN UINT Base)
|
|
||||||
{
|
|
||||||
/* Print - (minus) if this is negative value */
|
|
||||||
if(Number < 0)
|
|
||||||
{
|
|
||||||
PrintCharRoutine(L'-');
|
|
||||||
Number *= -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Print the integer value */
|
|
||||||
BlpStringPrintUnsigned32(PrintCharRoutine, Number, Base, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This routine converts 64-bit integer as string and prints it using specified routine.
|
|
||||||
*
|
|
||||||
* @param PrintCharRoutine
|
|
||||||
* Pointer to the routine that writes an input data to specific device.
|
|
||||||
*
|
|
||||||
* @param Number
|
|
||||||
* 64-bit integer value.
|
|
||||||
*
|
|
||||||
* @param Base
|
|
||||||
* Specifies the number base system representation.
|
|
||||||
*
|
|
||||||
* @return This routine does not return any value.
|
|
||||||
*
|
|
||||||
* @since XT 1.0
|
|
||||||
*/
|
|
||||||
XTCDECL
|
|
||||||
VOID
|
|
||||||
BlpStringPrintSigned64(IN BLPRINTCHAR PrintCharRoutine,
|
|
||||||
IN INT_PTR Number,
|
|
||||||
IN UINT_PTR Base)
|
|
||||||
{
|
|
||||||
/* Print - (minus) if this is negative value */
|
|
||||||
if(Number < 0)
|
|
||||||
{
|
|
||||||
PrintCharRoutine(L'-');
|
|
||||||
Number *= -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Print the integer value */
|
|
||||||
BlpStringPrintUnsigned64(PrintCharRoutine, Number, Base, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This routine converts 32-bit unsigned integer as string and prints it using specified routine.
|
|
||||||
*
|
|
||||||
* @param PrintCharRoutine
|
|
||||||
* Pointer to the routine that writes an input data to specific device.
|
|
||||||
*
|
|
||||||
* @param Number
|
|
||||||
* 32-bit integer value.
|
|
||||||
*
|
|
||||||
* @param Base
|
|
||||||
* Specifies the number base system representation.
|
|
||||||
*
|
|
||||||
* @param Padding
|
|
||||||
* Specifies the number of leading zeros to complete the field width.
|
|
||||||
*
|
|
||||||
* @return This routine does not return any value.
|
|
||||||
*
|
|
||||||
* @since XT 1.0
|
|
||||||
*/
|
|
||||||
XTCDECL
|
|
||||||
VOID
|
|
||||||
BlpStringPrintUnsigned32(IN BLPRINTCHAR PrintCharRoutine,
|
|
||||||
IN UINT Number,
|
|
||||||
IN UINT Base,
|
|
||||||
IN UINT Padding)
|
|
||||||
{
|
|
||||||
UINT Buffer[20];
|
|
||||||
UINT NumberLength;
|
|
||||||
PUINT Pointer;
|
|
||||||
|
|
||||||
/* Set pointer to the end of buffer */
|
|
||||||
Pointer = Buffer + ARRAY_SIZE(Buffer);
|
|
||||||
|
|
||||||
/* Convert value to specified base system */
|
|
||||||
*--Pointer = 0;
|
|
||||||
do
|
|
||||||
{
|
|
||||||
*--Pointer = BlpHexTable[Number % Base];
|
|
||||||
} while(Pointer >= Buffer && (Number /= Base));
|
|
||||||
|
|
||||||
/* Calculate number length */
|
|
||||||
NumberLength = ARRAY_SIZE(Buffer) - (Pointer - Buffer) - 1;
|
|
||||||
|
|
||||||
/* Check if leading zeros are needed */
|
|
||||||
if(NumberLength < Padding)
|
|
||||||
{
|
|
||||||
Padding -= NumberLength;
|
|
||||||
while(Padding--)
|
|
||||||
{
|
|
||||||
/* Write leading zeroes */
|
|
||||||
PrintCharRoutine(L'0');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Print value to the console */
|
|
||||||
for(; *Pointer; ++Pointer)
|
|
||||||
{
|
|
||||||
PrintCharRoutine(*Pointer);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This routine converts 64-bit unsigned integer as string and prints it using specified routine.
|
|
||||||
*
|
|
||||||
* @param PrintCharRoutine
|
|
||||||
* Pointer to the routine that writes an input data to specific device.
|
|
||||||
*
|
|
||||||
* @param Number
|
|
||||||
* 64-bit integer value.
|
|
||||||
*
|
|
||||||
* @param Base
|
|
||||||
* Specifies the number base system representation.
|
|
||||||
*
|
|
||||||
* @param Padding
|
|
||||||
* Specifies the number of leading zeros to complete the field width.
|
|
||||||
*
|
|
||||||
* @return This routine does not return any value.
|
|
||||||
*
|
|
||||||
* @since XT 1.0
|
|
||||||
*/
|
|
||||||
XTCDECL
|
|
||||||
VOID
|
|
||||||
BlpStringPrintUnsigned64(IN BLPRINTCHAR PrintCharRoutine,
|
|
||||||
IN UINT_PTR Number,
|
|
||||||
IN UINT_PTR Base,
|
|
||||||
IN UINT_PTR Padding)
|
|
||||||
{
|
|
||||||
UINT16 Buffer[20];
|
|
||||||
UINT_PTR NumberLength;
|
|
||||||
PUINT16 Pointer;
|
|
||||||
|
|
||||||
/* Set pointer to the end of buffer */
|
|
||||||
Pointer = Buffer + ARRAY_SIZE(Buffer);
|
|
||||||
|
|
||||||
/* Convert value to specified base system */
|
|
||||||
*--Pointer = 0;
|
|
||||||
do
|
|
||||||
{
|
|
||||||
*--Pointer = BlpHexTable[Number % Base];
|
|
||||||
} while(Pointer >= Buffer && (Number /= Base));
|
|
||||||
|
|
||||||
/* Calculate number length */
|
|
||||||
NumberLength = ARRAY_SIZE(Buffer) - (Pointer - Buffer) - 1;
|
|
||||||
|
|
||||||
/* Check if leading zeros are needed */
|
|
||||||
if(NumberLength < Padding)
|
|
||||||
{
|
|
||||||
Padding -= NumberLength;
|
|
||||||
while(Padding--)
|
|
||||||
{
|
|
||||||
/* Write leading zeroes */
|
|
||||||
PrintCharRoutine(L'0');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Print value to the console */
|
|
||||||
for(; *Pointer; ++Pointer)
|
|
||||||
{
|
|
||||||
PrintCharRoutine(*Pointer);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Reads the number of padding characters from the format string.
|
|
||||||
*
|
|
||||||
* @param Format
|
|
||||||
* The format string.
|
|
||||||
*
|
|
||||||
* @return Number of padding characters.
|
|
||||||
*
|
|
||||||
* @since XT 1.0
|
|
||||||
*/
|
|
||||||
XTCDECL
|
|
||||||
UINT64
|
|
||||||
BlpStringReadPadding(IN PUINT16 *Format)
|
|
||||||
{
|
|
||||||
ULONG Count = 0;
|
|
||||||
PUINT16 Fmt = *Format;
|
|
||||||
|
|
||||||
/* Read the padding */
|
|
||||||
for(;; ++Fmt)
|
|
||||||
{
|
|
||||||
switch(*Fmt)
|
|
||||||
{
|
|
||||||
case L'0' ... L'9':
|
|
||||||
/* Check the number of leading zeroes */
|
|
||||||
Count = Count * 10 + *Fmt - L'0';
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
/* No padding by default */
|
|
||||||
*Format = Fmt;
|
|
||||||
return Count;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* No padding by default */
|
|
||||||
return 0;
|
|
||||||
}
|
|
1019
xtldr2/volume.c
1019
xtldr2/volume.c
File diff suppressed because it is too large
Load Diff
433
xtldr2/xtldr.c
433
xtldr2/xtldr.c
@ -1,433 +0,0 @@
|
|||||||
/**
|
|
||||||
* PROJECT: ExectOS
|
|
||||||
* COPYRIGHT: See COPYING.md in the top level directory
|
|
||||||
* FILE: xtldr/xtldr.c
|
|
||||||
* DESCRIPTION: XTOS UEFI Boot Loader
|
|
||||||
* DEVELOPERS: Rafal Kupiec <belliash@codingworkshop.eu.org>
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <xtldr.h>
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Initializes EFI Boot Loader (XTLDR).
|
|
||||||
*
|
|
||||||
* @return This routine does not return any value.
|
|
||||||
*
|
|
||||||
* @since XT 1.0
|
|
||||||
*/
|
|
||||||
XTCDECL
|
|
||||||
VOID
|
|
||||||
BlInitializeBootLoader()
|
|
||||||
{
|
|
||||||
EFI_GUID LipGuid = EFI_LOADED_IMAGE_PROTOCOL_GUID;
|
|
||||||
PEFI_LOADED_IMAGE_PROTOCOL LoadedImage;
|
|
||||||
EFI_STATUS Status;
|
|
||||||
|
|
||||||
/* Set current XTLDR's EFI BootServices status */
|
|
||||||
BlpStatus.BootServices = TRUE;
|
|
||||||
|
|
||||||
/* Initialize console */
|
|
||||||
BlpInitializeConsole();
|
|
||||||
|
|
||||||
/* Print XTLDR version */
|
|
||||||
BlConsolePrint(L"XTLDR boot loader v%s\n", XTOS_VERSION);
|
|
||||||
|
|
||||||
/* Initialize XTLDR configuration linked lists */
|
|
||||||
RtlInitializeListHead(&BlpBootProtocols);
|
|
||||||
RtlInitializeListHead(&BlpConfig);
|
|
||||||
RtlInitializeListHead(&BlpLoadedModules);
|
|
||||||
|
|
||||||
/* Store SecureBoot status */
|
|
||||||
BlpStatus.SecureBoot = BlGetSecureBootStatus();
|
|
||||||
|
|
||||||
/* Check if debug is enabled */
|
|
||||||
if(DEBUG)
|
|
||||||
{
|
|
||||||
/* Attempt to open EFI LoadedImage protocol */
|
|
||||||
Status = BlOpenProtocol((PVOID *)&LoadedImage, &LipGuid);
|
|
||||||
if(Status == STATUS_EFI_SUCCESS)
|
|
||||||
{
|
|
||||||
/* Protocol opened successfully, print useful debug information */
|
|
||||||
BlConsolePrint(L"\n---------- BOOTLOADER DEBUG ----------\n"
|
|
||||||
L"Pointer Size : %d\n"
|
|
||||||
L"Image Base Address: 0x%lx\n"
|
|
||||||
L"Image Base Size : 0x%lx\n"
|
|
||||||
L"Image Revision : 0x%lx\n"
|
|
||||||
L"--------------------------------------\n",
|
|
||||||
sizeof(PVOID),
|
|
||||||
LoadedImage->ImageBase,
|
|
||||||
LoadedImage->ImageSize,
|
|
||||||
LoadedImage->Revision);
|
|
||||||
BlSleepExecution(3000);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Initializes a list of operating systems for XTLDR boot menu.
|
|
||||||
*
|
|
||||||
* @param MenuEntries
|
|
||||||
* Supplies a pointer to memory area where operating systems list will be stored.
|
|
||||||
*
|
|
||||||
* @param EntriesCount
|
|
||||||
* Supplies a pointer to memory area where number of menu entries will be stored.
|
|
||||||
*
|
|
||||||
* @param DefaultId
|
|
||||||
* Supplies a pointer to memory area where ID of default menu entry will be stored.
|
|
||||||
*
|
|
||||||
* @return This routine does not return any value.
|
|
||||||
*
|
|
||||||
* @since XT 1.0
|
|
||||||
*/
|
|
||||||
XTCDECL
|
|
||||||
VOID
|
|
||||||
BlInitializeBootMenuList(OUT PXTBL_BOOTMENU_ITEM MenuEntries,
|
|
||||||
OUT PULONG EntriesCount,
|
|
||||||
OUT PULONG DefaultId)
|
|
||||||
{
|
|
||||||
PWCHAR DefaultMenuEntry, MenuEntryName;
|
|
||||||
PLIST_ENTRY MenuEntrySectionList, MenuEntryList;
|
|
||||||
PXTBL_CONFIG_SECTION MenuEntrySection;
|
|
||||||
PXTBL_CONFIG_ENTRY MenuEntryOption;
|
|
||||||
PXTBL_BOOTMENU_ITEM OsList;
|
|
||||||
ULONG DefaultOS, NumberOfEntries;
|
|
||||||
|
|
||||||
/* Set default values */
|
|
||||||
DefaultOS = 0;
|
|
||||||
NumberOfEntries = 0;
|
|
||||||
OsList = NULL;
|
|
||||||
|
|
||||||
/* Get default menu entry from configuration */
|
|
||||||
DefaultMenuEntry = BlGetConfigValue(L"DEFAULT");
|
|
||||||
|
|
||||||
/* Iterate through all menu sections */
|
|
||||||
MenuEntrySectionList = BlpMenuList->Flink;
|
|
||||||
while(MenuEntrySectionList != BlpMenuList)
|
|
||||||
{
|
|
||||||
/* NULLify menu entry name */
|
|
||||||
MenuEntryName = NULL;
|
|
||||||
|
|
||||||
/* Get menu section */
|
|
||||||
MenuEntrySection = CONTAIN_RECORD(MenuEntrySectionList, XTBL_CONFIG_SECTION, Flink);
|
|
||||||
|
|
||||||
/* Check if this is the default menu entry */
|
|
||||||
if(RtlCompareWideStringInsensitive(MenuEntrySection->SectionName, DefaultMenuEntry, 0) == 0)
|
|
||||||
{
|
|
||||||
/* Set default OS ID */
|
|
||||||
DefaultOS = NumberOfEntries;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Iterate through all entry parameters */
|
|
||||||
MenuEntryList = MenuEntrySection->Options.Flink;
|
|
||||||
while(MenuEntryList != &MenuEntrySection->Options)
|
|
||||||
{
|
|
||||||
/* Get menu entry parameter */
|
|
||||||
MenuEntryOption = CONTAIN_RECORD(MenuEntryList, XTBL_CONFIG_ENTRY, Flink);
|
|
||||||
|
|
||||||
/* Check if this is the menu entry display name */
|
|
||||||
if(RtlCompareWideStringInsensitive(MenuEntryOption->Name, L"SYSTEMNAME", 0) == 0)
|
|
||||||
{
|
|
||||||
/* Set menu entry display name */
|
|
||||||
MenuEntryName = MenuEntryOption->Value;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Get next parameter for this menu entry */
|
|
||||||
MenuEntryList = MenuEntryList->Flink;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Add OS to the boot menu list */
|
|
||||||
OsList[NumberOfEntries].EntryName = MenuEntryName;
|
|
||||||
OsList[NumberOfEntries].Options = &MenuEntrySection->Options;
|
|
||||||
|
|
||||||
/* Get next menu entry */
|
|
||||||
MenuEntrySectionList = MenuEntrySectionList->Flink;
|
|
||||||
NumberOfEntries++;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Set return values */
|
|
||||||
*DefaultId = DefaultOS;
|
|
||||||
*EntriesCount = NumberOfEntries;
|
|
||||||
MenuEntries = OsList;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Loads all necessary modules and invokes boot protocol.
|
|
||||||
*
|
|
||||||
* @param OptionsList
|
|
||||||
* Supplies a pointer to list of options associated with chosen boot menu entry.
|
|
||||||
*
|
|
||||||
* @return This routine returns a status code.
|
|
||||||
*
|
|
||||||
* @since XT 1.0
|
|
||||||
*/
|
|
||||||
XTCDECL
|
|
||||||
EFI_STATUS
|
|
||||||
BlInvokeBootProtocol(IN PLIST_ENTRY OptionsList)
|
|
||||||
{
|
|
||||||
XTBL_BOOT_PARAMETERS BootParameters;
|
|
||||||
PXTBL_BOOT_PROTOCOL BootProtocol;
|
|
||||||
PLIST_ENTRY OptionsListEntry;
|
|
||||||
PXTBL_CONFIG_ENTRY Option;
|
|
||||||
EFI_GUID BootProtocolGuid;
|
|
||||||
SIZE_T ModuleListLength;
|
|
||||||
PWCHAR ModulesList;
|
|
||||||
EFI_STATUS Status;
|
|
||||||
|
|
||||||
/* Initialize boot parameters and a list of modules */
|
|
||||||
RtlZeroMemory(&BootParameters, sizeof(XTBL_BOOT_PARAMETERS));
|
|
||||||
ModulesList = NULL;
|
|
||||||
|
|
||||||
/* Iterate through all options provided by boot menu entry and propagate boot parameters */
|
|
||||||
OptionsListEntry = OptionsList->Flink;
|
|
||||||
while(OptionsListEntry != OptionsList)
|
|
||||||
{
|
|
||||||
/* Get option */
|
|
||||||
Option = CONTAIN_RECORD(OptionsListEntry, XTBL_CONFIG_ENTRY, Flink);
|
|
||||||
|
|
||||||
/* Look for boot protocol and modules list */
|
|
||||||
if(RtlCompareWideStringInsensitive(Option->Name, L"BOOTMODULES", 0) == 0)
|
|
||||||
{
|
|
||||||
/* Check a length of modules list */
|
|
||||||
ModuleListLength = RtlWideStringLength(Option->Value, 0);
|
|
||||||
|
|
||||||
Status = BlMemoryAllocatePool(sizeof(PWCHAR) * ModuleListLength, (PVOID *)&ModulesList);
|
|
||||||
if(Status != STATUS_EFI_SUCCESS)
|
|
||||||
{
|
|
||||||
/* Failed to allocate memory, print error message and return status code */
|
|
||||||
BlDebugPrint(L"ERROR: Memory allocation failure (Status Code: 0x%lx)\n");
|
|
||||||
return STATUS_EFI_OUT_OF_RESOURCES;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Make a copy of modules list */
|
|
||||||
RtlCopyMemory(ModulesList, Option->Value, sizeof(PWCHAR) * ModuleListLength);
|
|
||||||
}
|
|
||||||
else if(RtlCompareWideStringInsensitive(Option->Name, L"SYSTEMTYPE", 0) == 0)
|
|
||||||
{
|
|
||||||
/* Boot protocol found */
|
|
||||||
BootParameters.SystemType = Option->Value;
|
|
||||||
}
|
|
||||||
else if(RtlCompareWideStringInsensitive(Option->Name, L"SYSTEMPATH", 0) == 0)
|
|
||||||
{
|
|
||||||
/* System path found, get volume device path */
|
|
||||||
Status = BlGetVolumeDevicePath((PWCHAR)Option->Value, &BootParameters.DevicePath, &BootParameters.ArcName, &BootParameters.SystemPath);
|
|
||||||
if(Status != STATUS_EFI_SUCCESS)
|
|
||||||
{
|
|
||||||
/* Failed to find volume */
|
|
||||||
BlDebugPrint(L"ERROR: Failed to find volume device path (Status Code: 0x%lx)\n", Status);
|
|
||||||
return Status;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if(RtlCompareWideStringInsensitive(Option->Name, L"KERNELFILE", 0) == 0)
|
|
||||||
{
|
|
||||||
/* Kernel file name found */
|
|
||||||
BootParameters.KernelFile = Option->Value;
|
|
||||||
}
|
|
||||||
else if(RtlCompareWideStringInsensitive(Option->Name, L"INITRDFILE", 0) == 0)
|
|
||||||
{
|
|
||||||
/* Initrd file name found */
|
|
||||||
BootParameters.InitrdFile = Option->Value;
|
|
||||||
}
|
|
||||||
else if(RtlCompareWideStringInsensitive(Option->Name, L"HALFILE", 0) == 0)
|
|
||||||
{
|
|
||||||
/* Hal file name found */
|
|
||||||
BootParameters.HalFile = Option->Value;
|
|
||||||
}
|
|
||||||
else if(RtlCompareWideStringInsensitive(Option->Name, L"PARAMETERS", 0) == 0)
|
|
||||||
{
|
|
||||||
/* Kernel parameters found */
|
|
||||||
BootParameters.Parameters = Option->Value;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Move to the next option entry */
|
|
||||||
OptionsListEntry = OptionsListEntry->Flink;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Load all necessary modules */
|
|
||||||
Status = BlLoadModules(ModulesList);
|
|
||||||
if(Status != STATUS_EFI_SUCCESS)
|
|
||||||
{
|
|
||||||
/* Failed to load modules, print error message and return status code */
|
|
||||||
BlDebugPrint(L"ERROR: Failed to load XTLDR modules\n");
|
|
||||||
return STATUS_EFI_NOT_READY;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Attempt to get boot protocol GUID */
|
|
||||||
Status = BlFindBootProtocol(BootParameters.SystemType, &BootProtocolGuid);
|
|
||||||
if(Status != STATUS_EFI_SUCCESS)
|
|
||||||
{
|
|
||||||
/* Failed to get boot protocol GUID */
|
|
||||||
BlDebugPrint(L"ERROR: Unable to find appropriate boot protocol (Status Code: 0x%lx)\n", Status);
|
|
||||||
return STATUS_EFI_UNSUPPORTED;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Open boot protocol */
|
|
||||||
Status = BlOpenProtocol((PVOID *)&BootProtocol, &BootProtocolGuid);
|
|
||||||
if(Status != STATUS_EFI_SUCCESS)
|
|
||||||
{
|
|
||||||
/* Failed to open boot protocol */
|
|
||||||
BlDebugPrint(L"ERROR: Failed to open boot protocol (Status Code: 0x%lx)\n", Status);
|
|
||||||
return Status;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Boot Operating System */
|
|
||||||
return BootProtocol->BootSystem(&BootParameters);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 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)
|
|
||||||
{
|
|
||||||
EFI_STATUS Status;
|
|
||||||
|
|
||||||
/* Set the system table and image handle */
|
|
||||||
EfiImageHandle = ImageHandle;
|
|
||||||
EfiSystemTable = SystemTable;
|
|
||||||
|
|
||||||
/* Initialize XTLDR and */
|
|
||||||
BlInitializeBootLoader();
|
|
||||||
|
|
||||||
/* Parse configuration options passed from UEFI shell */
|
|
||||||
Status = BlpParseCommandLine();
|
|
||||||
if(Status != STATUS_EFI_SUCCESS)
|
|
||||||
{
|
|
||||||
/* Failed to parse command line options */
|
|
||||||
BlDisplayErrorDialog(L"XTLDR", L"Failed to parse command line parameters.");
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Attempt to early initialize debug console */
|
|
||||||
if(DEBUG)
|
|
||||||
{
|
|
||||||
Status = BlpInitializeDebugConsole();
|
|
||||||
if(Status != STATUS_EFI_SUCCESS)
|
|
||||||
{
|
|
||||||
/* Initialization failed, notify user on stdout */
|
|
||||||
BlDisplayErrorDialog(L"XTLDR", L"Failed to initialize debug console.");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Load XTLDR configuration file */
|
|
||||||
Status = BlpLoadConfiguration();
|
|
||||||
if(Status != STATUS_EFI_SUCCESS)
|
|
||||||
{
|
|
||||||
/* Failed to load/parse config file */
|
|
||||||
BlDisplayErrorDialog(L"XTLDR", L"Failed to load and parse configuration file.");
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Reinitialize debug console if it was not initialized earlier */
|
|
||||||
if(DEBUG)
|
|
||||||
{
|
|
||||||
Status = BlpInitializeDebugConsole();
|
|
||||||
if(Status != STATUS_EFI_SUCCESS)
|
|
||||||
{
|
|
||||||
/* Initialization failed, notify user on stdout */
|
|
||||||
BlDisplayErrorDialog(L"XTLDR", L"Failed to initialize debug console.");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Disable watchdog timer */
|
|
||||||
Status = EfiSystemTable->BootServices->SetWatchdogTimer(0, 0x10000, 0, NULL);
|
|
||||||
if(Status != STATUS_EFI_SUCCESS)
|
|
||||||
{
|
|
||||||
/* Failed to disable the timer, print message */
|
|
||||||
BlDebugPrint(L"WARNING: Failed to disable watchdog timer\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Register loader protocol */
|
|
||||||
Status = BlpRegisterXtLoaderProtocol();
|
|
||||||
if(Status != STATUS_EFI_SUCCESS)
|
|
||||||
{
|
|
||||||
/* Failed to register loader protocol */
|
|
||||||
BlDebugPrint(L"ERROR: Failed to register XTLDR boot protocol\n");
|
|
||||||
return Status;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Load boot loader modules */
|
|
||||||
Status = BlLoadModules(BlGetConfigValue(L"MODULES"));
|
|
||||||
if(Status != STATUS_EFI_SUCCESS)
|
|
||||||
{
|
|
||||||
/* Failed to load modules */
|
|
||||||
BlDebugPrint(L"ERROR: Failed to load XTLDR modules (Status Code: 0x%lx)\n", Status);
|
|
||||||
BlDisplayErrorDialog(L"XTLDR", L"Failed to load some XTLDR modules.");
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Discover and enumerate EFI block devices */
|
|
||||||
Status = BlEnumerateBlockDevices();
|
|
||||||
if(Status != STATUS_EFI_SUCCESS)
|
|
||||||
{
|
|
||||||
/* Failed to enumerate block devices */
|
|
||||||
BlDebugPrint(L"ERROR: Failed to discover and enumerate block devices\n");
|
|
||||||
return Status;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// BlConsolePrint(L"\n\n\n\n\n\n\n\nList of loaded modules:");
|
|
||||||
// PLIST_ENTRY ModuleListEntry;
|
|
||||||
// PXTBL_MODULE_INFO ModuleInfo;
|
|
||||||
|
|
||||||
// ModuleListEntry = BlpLoadedModules.Flink;
|
|
||||||
// while(ModuleListEntry != &BlpLoadedModules)
|
|
||||||
// {
|
|
||||||
// /* Get module information */
|
|
||||||
// ModuleInfo = CONTAIN_RECORD(ModuleListEntry, XTBL_MODULE_INFO, Flink);
|
|
||||||
|
|
||||||
// /* Module already loaded */
|
|
||||||
// BlConsolePrint(L"\n%S", ModuleInfo->ModuleName);
|
|
||||||
// if(ModuleInfo->ModuleDescription != 0)
|
|
||||||
// {
|
|
||||||
// BlConsolePrint(L" (%S)", ModuleInfo->ModuleDescription);
|
|
||||||
// }
|
|
||||||
|
|
||||||
// PLIST_ENTRY DepsListEntry;
|
|
||||||
// PXTBL_MODULE_DEPS DepsInfo;
|
|
||||||
// BlConsolePrint(L"\n - Uses: ");
|
|
||||||
// DepsListEntry = ModuleInfo->Dependencies.Flink;
|
|
||||||
// while(DepsListEntry != &ModuleInfo->Dependencies)
|
|
||||||
// {
|
|
||||||
// DepsInfo = CONTAIN_RECORD(DepsListEntry, XTBL_MODULE_DEPS, Flink);
|
|
||||||
// BlConsolePrint(L"%S ", DepsInfo->ModuleName);
|
|
||||||
// DepsListEntry = DepsListEntry->Flink;
|
|
||||||
// }
|
|
||||||
|
|
||||||
// /* Move to the module */
|
|
||||||
// ModuleListEntry = ModuleListEntry->Flink;
|
|
||||||
// }
|
|
||||||
|
|
||||||
// BlConsolePrint(L"\n\n END OF LIST\n");
|
|
||||||
|
|
||||||
/* Main boot loader loop */
|
|
||||||
while(TRUE)
|
|
||||||
{
|
|
||||||
/* Check if custom boot menu registered */
|
|
||||||
if(BlpStatus.BootMenu != NULL)
|
|
||||||
{
|
|
||||||
/* Display alternative boot menu */
|
|
||||||
BlpStatus.BootMenu();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
/* Display default boot menu */
|
|
||||||
BlDisplayBootMenu();
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Fallback to shell, if boot menu returned */
|
|
||||||
BlStartLoaderShell();
|
|
||||||
}
|
|
||||||
|
|
||||||
/* This point should be never reached, if this happen return error code */
|
|
||||||
return STATUS_EFI_LOAD_ERROR;
|
|
||||||
}
|
|
Loading…
Reference in New Issue
Block a user