Replace obsolete bootloader code, since new one can already start XTOS kernel
All checks were successful
Builds / ExectOS (amd64) (push) Successful in 27s
Builds / ExectOS (i686) (push) Successful in 28s

This commit is contained in:
Rafal Kupiec 2024-01-04 22:47:40 +01:00
parent 297ac1acf6
commit 2f8820a021
Signed by: belliash
GPG Key ID: 4E829243E0CFE6B4
65 changed files with 927 additions and 6751 deletions

View File

@ -70,5 +70,5 @@ set_disk_image_size(128)
# Build all subprojects
add_subdirectory(bootdata)
add_subdirectory(xtldr2)
add_subdirectory(xtldr)
add_subdirectory(xtoskrnl)

View File

@ -1,4 +1,4 @@
# XT Boot Loader
# XT Boot Manager
PROJECT(XTLDR)
# Build XTLDR modules
@ -9,19 +9,29 @@ 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}/${ARCH}/memory.c
${XTLDR_SOURCE_DIR}/blproto.c
${XTLDR_SOURCE_DIR}/config.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}/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}/system.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})
@ -38,6 +48,7 @@ set_target_properties(xtldr PROPERTIES OUTPUT_NAME ${BINARY_NAME} SUFFIX .efi)
set_install_target(xtldr efi/boot)
# Set loader entrypoint and subsystem
set_imagebase(xtldr ${BASEADDRESS_XTLDR})
set_entrypoint(xtldr "BlStartXtLoader")
set_imagebase(xtldr ${BASEADDRESS_XTLDR})
set_linker_map(xtldr TRUE)
set_subsystem(xtldr efi_application)

View File

@ -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.
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.

View File

@ -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;
}

View File

@ -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;
}

View File

@ -6,9 +6,37 @@
* 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.
*
@ -18,34 +46,205 @@
*/
XTCDECL
VOID
BlConsoleClearScreen()
BlClearConsoleScreen()
{
/* Clear screen */
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
*/
XTCDECL
VOID
BlConsoleInitialize()
BlDisableConsoleCursor()
{
/* Clear console buffers */
EfiSystemTable->ConIn->Reset(EfiSystemTable->ConIn, TRUE);
EfiSystemTable->ConOut->Reset(EfiSystemTable->ConOut, TRUE);
EfiSystemTable->StdErr->Reset(EfiSystemTable->StdErr, TRUE);
EfiSystemTable->ConOut->EnableCursor(EfiSystemTable->ConOut, FALSE);
}
/* Clear screen */
BlConsoleClearScreen();
/* Enable cursor */
/**
* 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 devices 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.
*
@ -58,7 +257,7 @@ BlConsoleInitialize()
*/
XTCDECL
VOID
BlConsolePutChar(IN USHORT Character)
BlpConsolePrintChar(IN USHORT Character)
{
USHORT Buffer[2];
@ -67,3 +266,32 @@ BlConsolePutChar(IN USHORT 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();
}

View File

@ -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);
}

View File

@ -6,26 +6,38 @@
* 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_ENTRY EfiBlockDevices;
/* XT Boot Loader hex table */
STATIC PUINT16 EfiHexTable = L"0123456789ABCDEF";
/* EFI Image Handle */
EFI_HANDLE EfiImageHandle;
/* XT Boot Loader protocol */
XT_BOOT_LOADER_PROTOCOL EfiLdrProtocol;
/* EFI System Table */
PEFI_SYSTEM_TABLE EfiSystemTable;
/* EFI Secure Boot status */
INT_PTR EfiSecureBoot;
/* Serial port configuration */
CPPORT EfiSerialPort;

View File

@ -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;
}

View File

@ -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 */

View File

@ -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 */

View File

@ -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 */

View File

@ -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 */

View File

@ -2,315 +2,13 @@
* PROJECT: ExectOS
* COPYRIGHT: See COPYING.md in the top level directory
* FILE: xtldr/memory.c
* DESCRIPTION: EFI memory management
* DESCRIPTION: XT Boot Loader memory management
* 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.
*
@ -352,14 +50,14 @@ BlGetMemoryMap(OUT PEFI_MEMORY_MAP MemoryMap)
if(MemoryMap->Map)
{
/* Free allocated memory */
BlEfiMemoryFreePool(MemoryMap->Map);
BlMemoryFreePool(MemoryMap->Map);
}
return Status;
}
/* Allocate the desired amount of memory */
MemoryMap->MapSize += 2 * MemoryMap->DescriptorSize;
BlEfiMemoryAllocatePool(MemoryMap->MapSize, (PVOID *)&MemoryMap->Map);
BlMemoryAllocatePool(MemoryMap->MapSize, (PVOID *)&MemoryMap->Map);
}
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
* Supplies a pointer to linked list containing all memory mappings.
* @param Pages
* The number of contiguous 4KB pages to allocate.
*
* @param PhysicalAddress
* Supplies a physical address to search for in the mappings.
*
* @param VirtualAddress
* Supplies a buffer, where mapped virtual address of the found mapping will be stored.
* @param Memory
* The pointer to a physical address.
*
* @return This routine returns a status code.
*
@ -392,58 +87,20 @@ BlGetMemoryMap(OUT PEFI_MEMORY_MAP MemoryMap)
*/
XTCDECL
EFI_STATUS
BlGetVirtualAddress(IN PLIST_ENTRY MemoryMappings,
IN PVOID PhysicalAddress,
OUT PVOID *VirtualAddress)
BlMemoryAllocatePages(IN UINT64 Pages,
OUT PEFI_PHYSICAL_ADDRESS Memory)
{
PLOADER_MEMORY_MAPPING Mapping;
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;
return EfiSystemTable->BootServices->AllocatePages(AllocateAnyPages, EfiLoaderData, Pages, Memory);
}
/**
* Initializes virtual memory by adding known and general mappings.
* This routine allocates a pool memory.
*
* @param MemoryMappings
* Supplies a pointer to linked list containing all memory mappings.
* @param Size
* The number of bytes to allocate from the pool.
*
* @param MemoryMapAddress
* Supplies an address of the mapped virtual memory area.
* @param Memory
* The pointer to a physical address.
*
* @return This routine returns a status code.
*
@ -451,80 +108,48 @@ BlGetVirtualAddress(IN PLIST_ENTRY MemoryMappings,
*/
XTCDECL
EFI_STATUS
BlInitializeVirtualMemory(IN OUT PLIST_ENTRY MemoryMappings,
IN OUT PVOID *MemoryMapAddress)
BlMemoryAllocatePool(IN UINT_PTR Size,
OUT PVOID *Memory)
{
PEFI_MEMORY_DESCRIPTOR Descriptor;
LOADER_MEMORY_TYPE MemoryType;
PEFI_MEMORY_MAP MemoryMap;
SIZE_T DescriptorCount;
PUCHAR VirtualAddress;
EFI_STATUS Status;
SIZE_T Index;
/* Set initial virtual address */
VirtualAddress = *MemoryMapAddress;
/* 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)
{
return Status;
/* Allocate pool */
return EfiSystemTable->BootServices->AllocatePool(EfiLoaderData, Size, Memory);
}
/* Calculate descriptors count and get first one */
Descriptor = MemoryMap->Map;
DescriptorCount = MemoryMap->MapSize / MemoryMap->DescriptorSize;
/* Iterate through all descriptors from the memory map */
for(Index = 0; Index < DescriptorCount; Index++)
/**
* 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)
{
/* Make sure descriptor does not go beyond lowest physical page */
if((Descriptor->PhysicalStart + (Descriptor->NumberOfPages * EFI_PAGE_SIZE)) <= (UINT_PTR)-1)
{
/* Convert EFI memory type into XTOS memory type */
MemoryType = BlConvertEfiMemoryType(Descriptor->Type);
/* Do memory mappings depending on memory type */
if(MemoryType == LoaderFirmwareTemporary)
{
/* Map EFI firmware code */
Status = BlAddVirtualMemoryMapping(MemoryMappings, (PVOID)Descriptor->PhysicalStart,
(PVOID)Descriptor->PhysicalStart, Descriptor->NumberOfPages, MemoryType);
}
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);
return EfiSystemTable->BootServices->FreePages(Memory, Pages);
}
/* Make sure memory mapping succeeded */
if(Status != STATUS_EFI_SUCCESS)
/**
* 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)
{
/* 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;
/* Free pool */
return EfiSystemTable->BootServices->FreePool(Memory);
}

View File

@ -1,3 +1,4 @@
add_subdirectory(framebuf)
add_subdirectory(pecoff)
add_subdirectory(xtos)
add_subdirectory(dummy)
add_subdirectory(fb_o)
add_subdirectory(pecoff_o)
add_subdirectory(xtos_o)

View File

@ -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)

View File

@ -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);
}

View File

@ -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;
}

View File

@ -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 */

View File

@ -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)

View File

@ -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 */

View File

@ -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);
}

View File

@ -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)

View File

@ -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 */

View File

@ -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);
}

View File

@ -2,73 +2,17 @@
* PROJECT: ExectOS
* COPYRIGHT: See COPYING.md in the top level directory
* FILE: xtldr/string.c
* DESCRIPTION: EFI string operations support
* DESCRIPTION: EFI string manipulation support
* 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.
*
* @param PutChar
* @param PrintCharRoutine
* Pointer to the routine that writes an input data to specific device.
*
* @param Format
@ -83,7 +27,7 @@ BlStringCompareInsensitive(IN PUCHAR String1,
*/
XTCDECL
VOID
BlStringPrint(IN VOID PutChar(IN USHORT Character),
BlpStringPrint(IN IN BLPRINTCHAR PrintCharRoutine,
IN PUINT16 Format,
IN VA_LIST Arguments)
{
@ -102,20 +46,20 @@ BlStringPrint(IN VOID PutChar(IN USHORT Character),
{
case L'b':
/* Boolean */
BlpStringFormat(PutChar, L"%s", VA_ARG(Arguments, INT32) ? "TRUE" : "FALSE");
BlpStringFormat(PrintCharRoutine, L"%s", VA_ARG(Arguments, INT32) ? "TRUE" : "FALSE");
break;
case L'c':
/* Character */
PutChar(VA_ARG(Arguments, INT));
PrintCharRoutine(VA_ARG(Arguments, INT));
break;
case L'd':
/* Signed 32-bit integer */
BlpStringPrintSigned32(PutChar, VA_ARG(Arguments, INT32), 10);
BlpStringPrintSigned32(PrintCharRoutine, VA_ARG(Arguments, INT32), 10);
break;
case L'g':
/* EFI 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->Data4[3], Guid->Data4[4], Guid->Data4[5], Guid->Data4[6], Guid->Data4[7]);
break;
@ -125,48 +69,48 @@ BlStringPrint(IN VOID PutChar(IN USHORT Character),
{
case L'd':
/* Signed 64-bit integer */
BlpStringPrintSigned64(PutChar, VA_ARG(Arguments, INT_PTR), 10);
BlpStringPrintSigned64(PrintCharRoutine, VA_ARG(Arguments, INT_PTR), 10);
break;
case L'u':
/* Unsigned 64-bit integer */
BlpStringPrintUnsigned64(PutChar, VA_ARG(Arguments, UINT_PTR), 10, 0);
BlpStringPrintUnsigned64(PrintCharRoutine, VA_ARG(Arguments, UINT_PTR), 10, 0);
break;
case L'x':
/* Unsigned 64-bit hexadecimal integer */
BlpStringPrintUnsigned64(PutChar, VA_ARG(Arguments, UINT_PTR), 16, 0);
BlpStringPrintUnsigned64(PrintCharRoutine, VA_ARG(Arguments, UINT_PTR), 16, 0);
break;
default:
/* Unknown by default */
PutChar(L'?');
PrintCharRoutine(L'?');
break;
}
break;
case L'p':
/* Pointer address */
BlpStringPrintUnsigned64(PutChar, VA_ARG(Arguments, UINT_PTR), 16, 0);
BlpStringPrintUnsigned64(PrintCharRoutine, VA_ARG(Arguments, UINT_PTR), 16, 0);
break;
case L's':
/* String of characters */
String = VA_ARG(Arguments, PUCHAR);
while(*String)
{
PutChar(*String++);
PrintCharRoutine(*String++);
}
break;
case L'S':
WideString = VA_ARG(Arguments, PWCHAR);
while(*WideString)
{
PutChar((UCHAR)*WideString++);
PrintCharRoutine((UCHAR)*WideString++);
}
break;
case L'u':
/* Unsigned 32-bit integer */
BlpStringPrintUnsigned32(PutChar, VA_ARG(Arguments, UINT32), 10, 0);
BlpStringPrintUnsigned32(PrintCharRoutine, VA_ARG(Arguments, UINT32), 10, 0);
break;
case L'x':
/* Unsigned 32-bit hexadecimal integer */
BlpStringPrintUnsigned32(PutChar, VA_ARG(Arguments, UINT32), 16, 0);
BlpStringPrintUnsigned32(PrintCharRoutine, VA_ARG(Arguments, UINT32), 16, 0);
break;
case L'0':
/* Zero padded numbers */
@ -176,7 +120,7 @@ BlStringPrint(IN VOID PutChar(IN USHORT Character),
{
case L'd':
/* Zero-padded, signed 32-bit integer */
BlpStringPrintSigned32(PutChar, VA_ARG(Arguments, INT32), 10);
BlpStringPrintSigned32(PrintCharRoutine, VA_ARG(Arguments, INT32), 10);
break;
case L'l':
/* 64-bit numbers */
@ -184,43 +128,43 @@ BlStringPrint(IN VOID PutChar(IN USHORT Character),
{
case L'd':
/* Zero-padded, signed 64-bit integer */
BlpStringPrintSigned64(PutChar, VA_ARG(Arguments, INT_PTR), 10);
BlpStringPrintSigned64(PrintCharRoutine, VA_ARG(Arguments, INT_PTR), 10);
break;
case L'u':
/* 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;
case L'x':
/* 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;
default:
/* Unknown by default */
PutChar(L'?');
PrintCharRoutine(L'?');
break;
}
break;
case L'u':
/* Zero-padded, unsigned 32-bit integer */
BlpStringPrintUnsigned32(PutChar, VA_ARG(Arguments, UINT32), 10, PaddingCount);
BlpStringPrintUnsigned32(PrintCharRoutine, VA_ARG(Arguments, UINT32), 10, PaddingCount);
break;
case L'x':
/* Zero-padded, unsigned 32-bit hexadecimal integer */
BlpStringPrintUnsigned32(PutChar, VA_ARG(Arguments, UINT32), 16, PaddingCount);
BlpStringPrintUnsigned32(PrintCharRoutine, VA_ARG(Arguments, UINT32), 16, PaddingCount);
break;
default:
/* Unknown by default */
PutChar(L'?');
PrintCharRoutine(L'?');
break;
}
break;
case L'%':
/* Percent character */
PutChar(L'%');
PrintCharRoutine(L'%');
break;
default:
/* Unknown by default */
PutChar(L'?');
PrintCharRoutine(L'?');
break;
}
break;
@ -229,12 +173,12 @@ BlStringPrint(IN VOID PutChar(IN USHORT Character),
break;
case L'\n':
/* New line together with carriage return */
PutChar(L'\r');
PutChar(L'\n');
PrintCharRoutine(L'\r');
PrintCharRoutine(L'\n');
break;
default:
/* Put character by default */
PutChar(*Format);
PrintCharRoutine(*Format);
break;
}
}
@ -243,7 +187,7 @@ BlStringPrint(IN VOID PutChar(IN USHORT Character),
/**
* 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.
*
* @param Format
@ -258,7 +202,7 @@ BlStringPrint(IN VOID PutChar(IN USHORT Character),
*/
XTCDECL
VOID
BlpStringFormat(IN VOID PutChar(IN USHORT Character),
BlpStringFormat(IN BLPRINTCHAR PrintCharRoutine,
IN PUINT16 Format,
IN ...)
{
@ -268,7 +212,7 @@ BlpStringFormat(IN VOID PutChar(IN USHORT Character),
VA_START(Arguments, Format);
/* Format and print the string to the desired output */
BlStringPrint(PutChar, Format, Arguments);
BlpStringPrint(PrintCharRoutine, Format, Arguments);
/* Clean up the va_list */
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.
*
* @param PutChar
* @param PrintCharRoutine
* Pointer to the routine that writes an input data to specific device.
*
* @param Number
@ -292,25 +236,25 @@ BlpStringFormat(IN VOID PutChar(IN USHORT Character),
*/
XTCDECL
VOID
BlpStringPrintSigned32(IN VOID PutChar(IN USHORT Character),
IN INT32 Number,
IN UINT32 Base)
BlpStringPrintSigned32(IN BLPRINTCHAR PrintCharRoutine,
IN INT Number,
IN UINT Base)
{
/* Print - (minus) if this is negative value */
if(Number < 0)
{
PutChar(L'-');
PrintCharRoutine(L'-');
Number *= -1;
}
/* 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.
*
* @param PutChar
* @param PrintCharRoutine
* Pointer to the routine that writes an input data to specific device.
*
* @param Number
@ -325,25 +269,25 @@ BlpStringPrintSigned32(IN VOID PutChar(IN USHORT Character),
*/
XTCDECL
VOID
BlpStringPrintSigned64(IN VOID PutChar(IN USHORT Character),
BlpStringPrintSigned64(IN BLPRINTCHAR PrintCharRoutine,
IN INT_PTR Number,
IN UINT_PTR Base)
{
/* Print - (minus) if this is negative value */
if(Number < 0)
{
PutChar(L'-');
PrintCharRoutine(L'-');
Number *= -1;
}
/* 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.
*
* @param PutChar
* @param PrintCharRoutine
* Pointer to the routine that writes an input data to specific device.
*
* @param Number
@ -361,23 +305,27 @@ BlpStringPrintSigned64(IN VOID PutChar(IN USHORT Character),
*/
XTCDECL
VOID
BlpStringPrintUnsigned32(IN VOID PutChar(IN USHORT Character),
IN UINT32 Number,
IN UINT32 Base,
IN UINT32 Padding)
BlpStringPrintUnsigned32(IN BLPRINTCHAR PrintCharRoutine,
IN UINT Number,
IN UINT Base,
IN UINT Padding)
{
UINT32 Buffer[20];
PUINT32 Pointer = Buffer + ARRAY_SIZE(Buffer);
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 = EfiHexTable[Number % Base];
*--Pointer = BlpHexTable[Number % Base];
} while(Pointer >= Buffer && (Number /= Base));
/* Calculate number length */
UINT32 NumberLength = ARRAY_SIZE(Buffer) - (Pointer - Buffer) - 1;
NumberLength = ARRAY_SIZE(Buffer) - (Pointer - Buffer) - 1;
/* Check if leading zeros are needed */
if(NumberLength < Padding)
@ -386,21 +334,21 @@ BlpStringPrintUnsigned32(IN VOID PutChar(IN USHORT Character),
while(Padding--)
{
/* Write leading zeroes */
PutChar(L'0');
PrintCharRoutine(L'0');
}
}
/* Print value to the console */
for(; *Pointer; ++Pointer)
{
PutChar(*Pointer);
PrintCharRoutine(*Pointer);
}
}
/**
* 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.
*
* @param Number
@ -418,23 +366,27 @@ BlpStringPrintUnsigned32(IN VOID PutChar(IN USHORT Character),
*/
XTCDECL
VOID
BlpStringPrintUnsigned64(IN VOID PutChar(IN USHORT Character),
BlpStringPrintUnsigned64(IN BLPRINTCHAR PrintCharRoutine,
IN UINT_PTR Number,
IN UINT_PTR Base,
IN UINT_PTR Padding)
{
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 */
*--Pointer = 0;
do
{
*--Pointer = EfiHexTable[Number % Base];
*--Pointer = BlpHexTable[Number % Base];
} while(Pointer >= Buffer && (Number /= Base));
/* 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 */
if(NumberLength < Padding)
@ -443,14 +395,14 @@ BlpStringPrintUnsigned64(IN VOID PutChar(IN USHORT Character),
while(Padding--)
{
/* Write leading zeroes */
PutChar(L'0');
PrintCharRoutine(L'0');
}
}
/* Print value to the console */
for(; *Pointer; ++Pointer)
{
PutChar(*Pointer);
PrintCharRoutine(*Pointer);
}
}

View File

@ -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;
}

View File

@ -6,7 +6,7 @@
* DEVELOPERS: Rafal Kupiec <belliash@codingworkshop.eu.org>
*/
#include <xtbl.h>
#include <xtldr.h>
/**
@ -45,7 +45,7 @@ BlCloseVolume(IN PEFI_HANDLE VolumeHandle)
*/
XTCDECL
EFI_STATUS
BlEnumerateEfiBlockDevices()
BlEnumerateBlockDevices()
{
PEFI_DEVICE_PATH_PROTOCOL LastNode = NULL;
PEFI_BLOCK_DEVICE_DATA ParentNode = NULL;
@ -70,7 +70,7 @@ BlEnumerateEfiBlockDevices()
Status = BlpDiscoverEfiBlockDevices(&BlockDevices);
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;
}
@ -82,16 +82,16 @@ BlEnumerateEfiBlockDevices()
BlockDeviceData = CONTAIN_RECORD(ListEntry, EFI_BLOCK_DEVICE_DATA, ListEntry);
/* Find last node */
Status = BlpFindLastEfiBlockDeviceNode(BlockDeviceData->DevicePath, &LastNode);
Status = BlpFindLastBlockDeviceNode(BlockDeviceData->DevicePath, &LastNode);
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;
continue;
}
/* Set drive type to 'unknown' by default */
DriveType = XT_BOOT_DEVICE_UNKNOWN;
DriveType = XTBL_BOOT_DEVICE_UNKNOWN;
/* Check last node type */
if(LastNode->Type == EFI_ACPI_DEVICE_PATH && LastNode->SubType == EFI_ACPI_DP)
@ -102,12 +102,12 @@ BlEnumerateEfiBlockDevices()
{
/* Floppy drive found */
Media = BlockDeviceData->BlockIo->Media;
DriveType = XT_BOOT_DEVICE_FLOPPY;
DriveType = XTBL_BOOT_DEVICE_FLOPPY;
DriveNumber = FDCount++;
PartitionNumber = 0;
/* 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);
}
}
@ -118,12 +118,12 @@ BlEnumerateEfiBlockDevices()
{
/* Optical drive found */
Media = BlockDeviceData->BlockIo->Media;
DriveType = XT_BOOT_DEVICE_CDROM;
DriveType = XTBL_BOOT_DEVICE_CDROM;
DriveNumber = CDCount++;
PartitionNumber = 0;
/* 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);
}
else if(LastNode->SubType == EFI_MEDIA_HARDDRIVE_DP)
@ -131,13 +131,13 @@ BlEnumerateEfiBlockDevices()
/* Hard disk partition found */
Media = BlockDeviceData->BlockIo->Media;
HDPath = (PEFI_HARDDRIVE_DEVICE_PATH)LastNode;
DriveType = XT_BOOT_DEVICE_HARDDISK;
DriveType = XTBL_BOOT_DEVICE_HARDDISK;
DriveNumber = (HDPath->PartitionNumber == 1) ? HDCount++ : HDCount - 1;
PartitionNumber = HDPath->PartitionNumber;
PartitionGuid = (PEFI_GUID)HDPath->Signature;
/* 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",
DriveNumber, PartitionNumber, HDPath->MBRType,
PartitionGuid, HDPath->PartitionSize * Media->BlockSize);
@ -146,30 +146,30 @@ BlEnumerateEfiBlockDevices()
{
/* RAM disk found */
Media = BlockDeviceData->BlockIo->Media;
DriveType = XT_BOOT_DEVICE_RAMDISK;
DriveType = XTBL_BOOT_DEVICE_RAMDISK;
DriveNumber = RDCount++;
PartitionNumber = 0;
/* 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);
}
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;
}
}
/* 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 */
Status = BlEfiMemoryAllocatePool(sizeof(EFI_BLOCK_DEVICE), (PVOID *)&BlockDevice);
Status = BlMemoryAllocatePool(sizeof(EFI_BLOCK_DEVICE), (PVOID *)&BlockDevice);
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;
}
@ -248,7 +248,7 @@ BlFindVolumeDevicePath(IN PEFI_DEVICE_PATH_PROTOCOL FsHandle,
FsPathLength = RtlWideStringLength(FileSystemPath, 0) * sizeof(WCHAR);
/* 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);
if(Status != STATUS_EFI_SUCCESS)
{
@ -294,16 +294,16 @@ BlFindVolumeDevicePath(IN PEFI_DEVICE_PATH_PROTOCOL FsHandle,
*/
XTCDECL
EFI_STATUS
BlGetVolumeDevicePath(IN PUCHAR SystemPath,
BlGetVolumeDevicePath(IN PWCHAR SystemPath,
OUT PEFI_DEVICE_PATH_PROTOCOL *DevicePath,
OUT PUCHAR *ArcName,
OUT PUCHAR *Path)
OUT PWCHAR *ArcName,
OUT PWCHAR *Path)
{
PEFI_BLOCK_DEVICE Device;
USHORT DriveType;
ULONG DriveNumber;
ULONG PartNumber;
PUCHAR Volume;
PWCHAR Volume;
ULONG PathLength;
PLIST_ENTRY ListEntry;
EFI_STATUS Status;
@ -333,13 +333,13 @@ BlGetVolumeDevicePath(IN PUCHAR SystemPath,
if(PathLength == GUID_STRING_LENGTH)
{
/* 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;
}
else if(PathLength == PARTUUID_STRING_LENGTH)
{
/* 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;
}
else
@ -358,7 +358,7 @@ BlGetVolumeDevicePath(IN PUCHAR SystemPath,
if(Status != STATUS_EFI_SUCCESS)
{
/* 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;
}
@ -382,7 +382,7 @@ BlGetVolumeDevicePath(IN PUCHAR SystemPath,
if(*DevicePath == NULL)
{
/* 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);
return STATUS_EFI_NOT_FOUND;
}
@ -470,6 +470,125 @@ BlOpenVolume(IN PEFI_DEVICE_PATH_PROTOCOL DevicePath,
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.
*
@ -498,7 +617,7 @@ BlpDiscoverEfiBlockDevices(OUT PLIST_ENTRY BlockDevices)
if(Status != STATUS_EFI_SUCCESS)
{
/* 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;
}
@ -506,7 +625,7 @@ BlpDiscoverEfiBlockDevices(OUT PLIST_ENTRY BlockDevices)
for(Index = 0; Index < HandlesCount; Index++)
{
/* 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 */
Io = NULL;
@ -515,7 +634,7 @@ BlpDiscoverEfiBlockDevices(OUT PLIST_ENTRY BlockDevices)
if(Status != STATUS_EFI_SUCCESS || Io == NULL)
{
/* 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;
}
@ -523,7 +642,7 @@ BlpDiscoverEfiBlockDevices(OUT PLIST_ENTRY BlockDevices)
if(Io->Media && Io->Media->BlockSize == 1 && Io->Media->MediaId == 0x69505845U)
{
/* 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;
}
@ -533,17 +652,17 @@ BlpDiscoverEfiBlockDevices(OUT PLIST_ENTRY BlockDevices)
if(Status != STATUS_EFI_SUCCESS || DevicePath == NULL)
{
/* 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);
continue;
}
/* Allocate memory for block device */
Status = BlEfiMemoryAllocatePool(sizeof(*BlockDevice), (PVOID *)&BlockDevice);
Status = BlMemoryAllocatePool(sizeof(*BlockDevice), (PVOID *)&BlockDevice);
if(Status != STATUS_EFI_SUCCESS)
{
/* 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], &IoGuid, EfiImageHandle, NULL);
return Status;
@ -556,7 +675,7 @@ BlpDiscoverEfiBlockDevices(OUT PLIST_ENTRY BlockDevices)
}
/* Free handles buffer */
BlEfiMemoryFreePool(Handles);
BlMemoryFreePool(Handles);
/* Return success */
return STATUS_EFI_SUCCESS;
@ -586,36 +705,36 @@ BlpDiscoverEfiBlockDevices(OUT PLIST_ENTRY BlockDevices)
*/
XTCDECL
EFI_STATUS
BlpDissectVolumeArcPath(IN PUCHAR SystemPath,
OUT PUCHAR *ArcName,
OUT PUCHAR *Path,
BlpDissectVolumeArcPath(IN PWCHAR SystemPath,
OUT PWCHAR *ArcName,
OUT PWCHAR *Path,
OUT PUSHORT DriveType,
OUT PULONG DriveNumber,
OUT PULONG PartNumber)
{
PUCHAR ArcPath, LocalArcName;
PWCHAR ArcPath, LocalArcName;
ULONG ArcLength = 0;
/* Set default values */
*DriveType = XT_BOOT_DEVICE_UNKNOWN;
*DriveType = XTBL_BOOT_DEVICE_UNKNOWN;
*DriveNumber = 0;
*PartNumber = 0;
/* Look for the ARC path */
if(BlStringCompareInsensitive(SystemPath, (PUCHAR)"ramdisk(0)") == 0)
if(RtlCompareWideStringInsensitive(SystemPath, L"ramdisk(0)", 0) == 0)
{
/* This is RAM disk */
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 */
ArcLength = 15;
ArcPath = SystemPath + ArcLength;
/* Check for disk type */
if(BlStringCompareInsensitive(ArcPath, (PUCHAR)"cdrom(") == 0)
if(RtlCompareWideStringInsensitive(ArcPath, L"cdrom(", 0) == 0)
{
/* This is an optical drive */
ArcLength += 6;
@ -633,10 +752,10 @@ BlpDissectVolumeArcPath(IN PUCHAR SystemPath,
}
/* Set proper drive type */
*DriveType = XT_BOOT_DEVICE_CDROM;
*DriveType = XTBL_BOOT_DEVICE_CDROM;
ArcLength++;
}
else if(BlStringCompareInsensitive(ArcPath, (PUCHAR)"fdisk(") == 0)
else if(RtlCompareWideStringInsensitive(ArcPath, L"fdisk(", 0) == 0)
{
/* This is a floppy drive */
ArcLength += 6;
@ -654,10 +773,10 @@ BlpDissectVolumeArcPath(IN PUCHAR SystemPath,
}
/* Set proper drive type */
*DriveType = XT_BOOT_DEVICE_FLOPPY;
*DriveType = XTBL_BOOT_DEVICE_FLOPPY;
ArcLength++;
}
else if(BlStringCompareInsensitive(ArcPath, (PUCHAR)"rdisk(") == 0)
else if(RtlCompareWideStringInsensitive(ArcPath, L"rdisk(", 0) == 0)
{
/* This is a hard disk */
ArcLength += 6;
@ -675,12 +794,12 @@ BlpDissectVolumeArcPath(IN PUCHAR SystemPath,
}
/* Set proper drive type */
*DriveType = XT_BOOT_DEVICE_HARDDISK;
*DriveType = XTBL_BOOT_DEVICE_HARDDISK;
ArcLength++;
ArcPath = SystemPath + ArcLength;
/* Look for a partition */
if(BlStringCompareInsensitive(ArcPath, (PUCHAR)"partition(") == 0)
if(RtlCompareWideStringInsensitive(ArcPath, L"partition(", 0) == 0)
{
/* Partition information found */
ArcLength += 10;
@ -720,8 +839,8 @@ BlpDissectVolumeArcPath(IN PUCHAR SystemPath,
/* Store ARC name if possible */
if(ArcName)
{
BlEfiMemoryAllocatePool(ArcLength, (PVOID *)&LocalArcName);
RtlCopyMemory(LocalArcName, SystemPath, ArcLength);
BlMemoryAllocatePool(ArcLength * sizeof(WCHAR), (PVOID *)&LocalArcName);
RtlCopyMemory(LocalArcName, SystemPath, ArcLength * sizeof(WCHAR));
LocalArcName[ArcLength] = '\0';
*ArcName = LocalArcName;
}
@ -770,11 +889,11 @@ BlpDuplicateDevicePath(IN PEFI_DEVICE_PATH_PROTOCOL DevicePath)
}
/* Allocate memory for the new device path */
Status = BlEfiMemoryAllocatePool(Length, (PVOID *)&DevicePathClone);
Status = BlMemoryAllocatePool(Length, (PVOID *)&DevicePathClone);
if(Status != STATUS_EFI_SUCCESS)
{
/* 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;
}
@ -800,7 +919,7 @@ BlpDuplicateDevicePath(IN PEFI_DEVICE_PATH_PROTOCOL DevicePath)
*/
XTCDECL
EFI_STATUS
BlpFindLastEfiBlockDeviceNode(IN PEFI_DEVICE_PATH_PROTOCOL DevicePath,
BlpFindLastBlockDeviceNode(IN PEFI_DEVICE_PATH_PROTOCOL DevicePath,
OUT PEFI_DEVICE_PATH_PROTOCOL *LastNode)
{
PEFI_DEVICE_PATH_PROTOCOL EndNode, NextNode;
@ -846,7 +965,7 @@ BlpFindLastEfiBlockDeviceNode(IN PEFI_DEVICE_PATH_PROTOCOL DevicePath,
*/
XTCDECL
BOOLEAN
BlpFindParentEfiBlockDevice(IN PLIST_ENTRY BlockDevices,
BlpFindParentBlockDevice(IN PLIST_ENTRY BlockDevices,
IN PEFI_BLOCK_DEVICE_DATA ChildNode,
OUT PEFI_BLOCK_DEVICE_DATA ParentNode)
{

View File

@ -2,216 +2,160 @@
* PROJECT: ExectOS
* COPYRIGHT: See COPYING.md in the top level directory
* FILE: xtldr/xtldr.c
* DESCRIPTION: UEFI XT Bootloader
* DESCRIPTION: XTOS UEFI Boot Loader
* 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
*/
XTCDECL
EFI_STATUS
BlLoadEfiModules()
VOID
BlInitializeBootLoader()
{
CONST PWCHAR ModulesDirPath = L"\\EFI\\BOOT\\XTLDR\\";
EFI_GUID DevicePathGuid = EFI_DEVICE_PATH_PROTOCOL_GUID;
EFI_GUID LIPGuid = EFI_LOADED_IMAGE_PROTOCOL_GUID;
PEFI_DEVICE_PATH_PROTOCOL VolumeDevicePath, DevicePath;
EFI_GUID LipGuid = EFI_LOADED_IMAGE_PROTOCOL_GUID;
PEFI_LOADED_IMAGE_PROTOCOL LoadedImage;
PEFI_FILE_HANDLE FsHandle, ModulesDir;
EFI_HANDLE DiskHandle, ModuleHandle;
SIZE_T Length;
EFI_STATUS Status;
UINT_PTR DirSize;
CHAR Buffer[1024];
WCHAR ModulePath[1024];
PWCHAR ModuleName;
/* Open EFI volume */
Status = BlOpenVolume(NULL, &DiskHandle, &FsHandle);
if(Status != STATUS_EFI_SUCCESS)
/* 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)
{
/* Failed to open a volume */
return Status;
}
/* 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)
/* Attempt to open EFI LoadedImage protocol */
Status = BlOpenProtocol((PVOID *)&LoadedImage, &LipGuid);
if(Status == STATUS_EFI_SUCCESS)
{
/* 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;
/* 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);
}
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.
*
@ -219,90 +163,117 @@ BlLoadEfiModules()
*/
XTCDECL
EFI_STATUS
BlLoadXtSystem()
BlInvokeBootProtocol(IN PLIST_ENTRY OptionsList)
{
EFI_GUID ProtocolGuid = XT_XTOS_BOOT_PROTOCOL_GUID;
XT_BOOT_PROTOCOL_PARAMETERS BootParameters;
PXT_BOOT_PROTOCOL BootProtocol;
PUCHAR ArcName, SystemPath;
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;
PCHAR ArcPath;
SIZE_T Length;
/* Set ARC path */
ArcPath = "multi(0)disk(0)rdisk(0)partition(1)/ExectOS";
/* Initialize boot parameters and a list of modules */
RtlZeroMemory(&BootParameters, sizeof(XTBL_BOOT_PARAMETERS));
ModulesList = NULL;
/* Zero boot parameters structure to NULLify all pointers */
RtlZeroMemory(&BootParameters, sizeof(XT_BOOT_PROTOCOL_PARAMETERS));
/* 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);
/* Get boot volume path */
Status = BlGetVolumeDevicePath((PUCHAR)ArcPath, &BootParameters.DevicePath, &ArcName, &SystemPath);
/* 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 */
BlDbgPrint(L"ERROR: Unable to find volume device path\n");
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;
}
/* Store ARC name in boot parameters */
Length = RtlStringLength(ArcName, 0);
BlEfiMemoryAllocatePool(Length + 1, (PVOID *)&BootParameters.ArcName);
RtlStringToWideString(BootParameters.ArcName, &ArcName, Length * 2);
/* Move to the next option entry */
OptionsListEntry = OptionsListEntry->Flink;
}
/* Store system path in boot parameters */
Length = RtlStringLength(SystemPath, 0);
BlEfiMemoryAllocatePool(Length + 1, (PVOID *)&BootParameters.SystemPath);
RtlStringToWideString(BootParameters.SystemPath, &SystemPath, Length + 1);
/* 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;
}
/* Open the XT boot protocol */
Status = BlLoadXtProtocol((PVOID *)&BootProtocol, &ProtocolGuid);
/* 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 */
BlDbgPrint(L"ERROR: Unable to load boot protocol\n");
return STATUS_EFI_PROTOCOL_ERROR;
BlDebugPrint(L"ERROR: Failed to open boot protocol (Status Code: 0x%lx)\n", Status);
return Status;
}
/* Boot operating system */
/* Boot Operating System */
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.
*
@ -327,71 +298,136 @@ BlStartXtLoader(IN EFI_HANDLE ImageHandle,
EfiImageHandle = ImageHandle;
EfiSystemTable = SystemTable;
/* Initialize EFI console */
BlConsoleInitialize();
BlEfiPrint(L"XTLDR boot loader v%s\n", XTOS_VERSION);
/* Initialize XTLDR and */
BlInitializeBootLoader();
/* Early initialize COM port for debugging */
if(DEBUG)
{
Status = BlComPortInitialize();
/* Parse configuration options passed from UEFI shell */
Status = BlpParseCommandLine();
if(Status != STATUS_EFI_SUCCESS)
{
/* Initialization failed, try printing error to stdout and serial console */
BlEfiPrint(L"ERROR: Failed to initialize serial console\n");
/* 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.");
}
}
/* Check SecureBoot status */
EfiSecureBoot = BlEfiGetSecureBootStatus();
/* 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.");
}
/* Print firmware information */
BlDbgPrint(L"UEFI v%d.%d (%S 0x%08x), SecureBoot %S\n", EfiSystemTable->Hdr.Revision >> 16,
EfiSystemTable->Hdr.Revision & 0xFFFF, EfiSystemTable->FirmwareVendor, EfiSystemTable->FirmwareRevision,
EfiSecureBoot == 0 ? L"DISABLED" : EfiSecureBoot > 0 ? L"ENABLED" : L"SETUP");
/* 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 */
BlDbgPrint(L"WARNING: Failed to disable watchdog timer\n");
BlDebugPrint(L"WARNING: Failed to disable watchdog timer\n");
}
/* Register loader protocol */
Status = BlRegisterXtLoaderProtocol();
Status = BlpRegisterXtLoaderProtocol();
if(Status != STATUS_EFI_SUCCESS)
{
/* 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 */
Status = BlLoadEfiModules();
/* Load boot loader modules */
Status = BlLoadModules(BlGetConfigValue(L"MODULES"));
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 */
BlEnumerateEfiBlockDevices();
/* Boot XTOS */
Status = BlLoadXtSystem();
Status = BlEnumerateBlockDevices();
if(Status != STATUS_EFI_SUCCESS)
{
/* Boot process failed */
BlEfiPrint(L"Failed to start XT OS (Status code: %lx)!\n", Status);
/* Failed to enumerate block devices */
BlDebugPrint(L"ERROR: Failed to discover and enumerate block devices\n");
return Status;
}
/* Infinite bootloader loop */
BlEfiPrint(L"System halted!");
for(;;)
// 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)
{
ArClearInterruptFlag();
ArHalt();
/* Check if custom boot menu registered */
if(BlpStatus.BootMenu != NULL)
{
/* Display alternative boot menu */
BlpStatus.BootMenu();
}
else
{
/* Display default boot menu */
BlDisplayBootMenu();
}
/* Return success */
return STATUS_EFI_SUCCESS;
/* 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;
}

View File

@ -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)

View File

@ -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.

View File

@ -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 devices 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();
}

View File

@ -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;

View File

@ -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);
}

View File

@ -1,4 +0,0 @@
add_subdirectory(dummy)
add_subdirectory(fb_o)
add_subdirectory(pecoff_o)
add_subdirectory(xtos_o)

View File

@ -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;
}

File diff suppressed because it is too large Load Diff

View File

@ -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;
}