Import old and deprecated 'xtos_o' module from old XTLDR
This commit is contained in:
parent
a90cf727c5
commit
e0b31ad945
@ -32,15 +32,17 @@
|
||||
#include <rtltypes.h>
|
||||
|
||||
/* Architecture dependent XT kernel data types */
|
||||
// #include ARCH_HEADER(artypes.h)
|
||||
// #include ARCH_HEADER(hltypes.h)
|
||||
#include ARCH_HEADER(artypes.h)
|
||||
#include ARCH_HEADER(hltypes.h)
|
||||
#include ARCH_HEADER(ketypes.h)
|
||||
#include ARCH_HEADER(mmtypes.h)
|
||||
|
||||
/* XT Kernel runtime routines */
|
||||
#include <hlfuncs.h>
|
||||
#include <rtlfuncs.h>
|
||||
|
||||
/* Architecture specific XT kernel routines */
|
||||
// #include ARCH_HEADER(arfuncs.h)
|
||||
#include ARCH_HEADER(arfuncs.h)
|
||||
// #include ARCH_HEADER(hlfuncs.h)
|
||||
|
||||
/* Boot Manager specific structures */
|
||||
|
@ -1,3 +1,4 @@
|
||||
add_subdirectory(dummy)
|
||||
add_subdirectory(fb_o)
|
||||
add_subdirectory(pecoff_o)
|
||||
add_subdirectory(xtos_o)
|
||||
|
28
xtldr2/modules/xtos_o/CMakeLists.txt
Normal file
28
xtldr2/modules/xtos_o/CMakeLists.txt
Normal file
@ -0,0 +1,28 @@
|
||||
# XT Boot Loader
|
||||
PROJECT(XTLDR_XTOS_O)
|
||||
|
||||
# Specify include directories
|
||||
include_directories(
|
||||
${EXECTOS_SOURCE_DIR}/sdk/xtdk
|
||||
${XTLDR_XTOS_O_SOURCE_DIR}/includes)
|
||||
|
||||
# Specify list of source code files
|
||||
list(APPEND XTLDR_XTOS_O_SOURCE
|
||||
${XTLDR_XTOS_O_SOURCE_DIR}/${ARCH}/memory.c
|
||||
${XTLDR_XTOS_O_SOURCE_DIR}/memory.c
|
||||
${XTLDR_XTOS_O_SOURCE_DIR}/xtos.c)
|
||||
|
||||
# Link bootloader executable
|
||||
add_executable(xtos_o ${XTLDR_XTOS_O_SOURCE})
|
||||
|
||||
# Add linker libraries
|
||||
target_link_libraries(xtos_o libxtos libxtldr)
|
||||
|
||||
# Set proper binary name and install target
|
||||
set_target_properties(xtos_o PROPERTIES SUFFIX .efi)
|
||||
set_install_target(xtos_o efi/boot/xtldr/modules)
|
||||
|
||||
# Set module entrypoint and subsystem
|
||||
set_entrypoint(xtos_o "XtLdrModuleMain")
|
||||
set_linker_map(xtos_o TRUE)
|
||||
set_subsystem(xtos_o efi_boot_service_driver)
|
305
xtldr2/modules/xtos_o/amd64/memory.c
Normal file
305
xtldr2/modules/xtos_o/amd64/memory.c
Normal file
@ -0,0 +1,305 @@
|
||||
/**
|
||||
* 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 <xtos.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
|
||||
XtEnablePaging(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 = XtLdrProtocol->Memory.AllocatePages(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 = XtAddVirtualMemoryMapping(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 = XtAddVirtualMemoryMapping(MemoryMappings, NULL, *PtePointer, 1, LoaderMemoryData);
|
||||
if(Status != STATUS_EFI_SUCCESS)
|
||||
{
|
||||
/* Mapping PML4 failed */
|
||||
return Status;
|
||||
}
|
||||
|
||||
/* Iterate through and map all the mappings*/
|
||||
XtLdrProtocol->Debug.Print(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 */
|
||||
XtLdrProtocol->Debug.Print(L" Type=%02lu, PhysicalBase=0x%016lx, VirtualBase=0x%016lx, Pages=%lu\n", Mapping->MemoryType,
|
||||
Mapping->PhysicalAddress, Mapping->VirtualAddress, Mapping->NumberOfPages);
|
||||
|
||||
/* Map memory */
|
||||
Status = XtMapVirtualMemory(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 */
|
||||
XtMapVirtualMemory(MemoryMappings, 0, 0, 1, PtePointer);
|
||||
|
||||
/* Allocate and zero-fill buffer for EFI memory map */
|
||||
XtLdrProtocol->Memory.AllocatePool(sizeof(EFI_MEMORY_MAP), (PVOID*)&MemoryMap);
|
||||
RtlZeroMemory(MemoryMap, sizeof(EFI_MEMORY_MAP));
|
||||
|
||||
/* Get EFI memory map and prepare for exiting boot services */
|
||||
XtLdrProtocol->Debug.Print(L"Exiting EFI boot services\n");
|
||||
Status = XtLdrProtocol->Memory.GetMemoryMap(MemoryMap);
|
||||
if(Status != STATUS_EFI_SUCCESS)
|
||||
{
|
||||
/* Unable to get memory map */
|
||||
return Status;
|
||||
}
|
||||
|
||||
/* Exit EFI Boot Services */
|
||||
Status = XtLdrProtocol->Util.ExitBootServices(MemoryMap->MapKey);
|
||||
|
||||
/* Check if exitted boot services successfully */
|
||||
if(Status != STATUS_EFI_SUCCESS)
|
||||
{
|
||||
/* Failed to exit boot services */
|
||||
XtLdrProtocol->Debug.Print(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
|
||||
XtMapVirtualMemory(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 = XtLdrProtocol->Memory.AllocatePages(1, &Address);
|
||||
if (Status != STATUS_EFI_SUCCESS) {
|
||||
/* Memory allocation failure */
|
||||
return Status;
|
||||
}
|
||||
|
||||
/* Add new memory mapping */
|
||||
Status = XtAddVirtualMemoryMapping(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 = XtLdrProtocol->Memory.AllocatePages(1, &Address);
|
||||
if (Status != STATUS_EFI_SUCCESS) {
|
||||
/* Memory allocation failure */
|
||||
return Status;
|
||||
}
|
||||
|
||||
/* Add new memory mapping */
|
||||
Status = XtAddVirtualMemoryMapping(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 = XtLdrProtocol->Memory.AllocatePages(1, &Address);
|
||||
if (Status != STATUS_EFI_SUCCESS) {
|
||||
/* Memory allocation failure */
|
||||
return Status;
|
||||
}
|
||||
|
||||
/* Add new memory mapping */
|
||||
Status = XtAddVirtualMemoryMapping(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;
|
||||
}
|
329
xtldr2/modules/xtos_o/i686/memory.c
Normal file
329
xtldr2/modules/xtos_o/i686/memory.c
Normal file
@ -0,0 +1,329 @@
|
||||
/**
|
||||
* 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 <xtos.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
|
||||
XtEnablePaging(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 */
|
||||
XtLdrProtocol->Debug.Print(L"ERROR: PAE extension not supported by the CPU\n");
|
||||
return STATUS_EFI_UNSUPPORTED;
|
||||
}
|
||||
|
||||
/* Allocate and zero-fill buffer for EFI memory map */
|
||||
XtLdrProtocol->Memory.AllocatePool(sizeof(EFI_MEMORY_MAP), (PVOID*)&MemoryMap);
|
||||
RtlZeroMemory(MemoryMap, sizeof(EFI_MEMORY_MAP));
|
||||
|
||||
/* Get EFI memory map */
|
||||
Status = XtLdrProtocol->Memory.GetMemoryMap(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 = XtLdrProtocol->Memory.AllocatePages(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 = XtLdrProtocol->Memory.AllocatePages(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 = XtAddVirtualMemoryMapping(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 = XtAddVirtualMemoryMapping(MemoryMappings, NULL, *PtePointer, 1, LoaderMemoryData);
|
||||
if(Status != STATUS_EFI_SUCCESS)
|
||||
{
|
||||
/* Mapping PD failed */
|
||||
return Status;
|
||||
}
|
||||
|
||||
/* Iterate through and map all the mappings */
|
||||
XtLdrProtocol->Debug.Print(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 */
|
||||
XtLdrProtocol->Debug.Print(L" Type=%02lu, PhysicalBase=0x%08lx, VirtualBase=0x%08lx, Pages=%lu\n", Mapping->MemoryType,
|
||||
Mapping->PhysicalAddress, Mapping->VirtualAddress, Mapping->NumberOfPages);
|
||||
|
||||
/* Map memory */
|
||||
Status = XtMapVirtualMemory(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 */
|
||||
XtMapVirtualMemory(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 */
|
||||
XtLdrProtocol->Debug.Print(L"Exiting EFI boot services\n");
|
||||
Status = XtLdrProtocol->Memory.GetMemoryMap(MemoryMap);
|
||||
if(Status != STATUS_EFI_SUCCESS)
|
||||
{
|
||||
/* Unable to get memory map */
|
||||
return Status;
|
||||
}
|
||||
|
||||
/* Exit EFI Boot Services */
|
||||
Status = XtLdrProtocol->Util.ExitBootServices(MemoryMap->MapKey);
|
||||
|
||||
/* Check if exitted boot services successfully */
|
||||
if(Status != STATUS_EFI_SUCCESS)
|
||||
{
|
||||
/* Failed to exit boot services */
|
||||
XtLdrProtocol->Debug.Print(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
|
||||
XtMapVirtualMemory(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 = XtLdrProtocol->Memory.AllocatePages(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;
|
||||
}
|
107
xtldr2/modules/xtos_o/includes/xtos.h
Normal file
107
xtldr2/modules/xtos_o/includes/xtos.h
Normal file
@ -0,0 +1,107 @@
|
||||
/**
|
||||
* 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 <xtblapi.h>
|
||||
|
||||
|
||||
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)();
|
||||
|
||||
/* 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;
|
||||
|
||||
/* EFI XT Loader Protocol */
|
||||
EXTERN PXTBL_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
|
||||
XtAddVirtualMemoryMapping(IN PLIST_ENTRY MemoryMappings,
|
||||
IN PVOID VirtualAddress,
|
||||
IN PVOID PhysicalAddress,
|
||||
IN UINT NumberOfPages,
|
||||
IN LOADER_MEMORY_TYPE MemoryType);
|
||||
|
||||
XTCDECL
|
||||
EFI_STATUS
|
||||
XtBootSystem(IN PXTBL_BOOT_PARAMETERS Parameters);
|
||||
|
||||
XTCDECL
|
||||
LOADER_MEMORY_TYPE
|
||||
XtConvertEfiMemoryType(IN EFI_MEMORY_TYPE EfiMemoryType);
|
||||
|
||||
XTCDECL
|
||||
EFI_STATUS
|
||||
XtEnablePaging(IN PLIST_ENTRY MemoryMappings,
|
||||
IN PVOID VirtualAddress,
|
||||
IN PEFI_LOADED_IMAGE_PROTOCOL ImageProtocol,
|
||||
IN PVOID *PtePointer);
|
||||
|
||||
XTCDECL
|
||||
EFI_STATUS
|
||||
XtGetVirtualAddress(IN PLIST_ENTRY MemoryMappings,
|
||||
IN PVOID PhysicalAddress,
|
||||
OUT PVOID *VirtualAddress);
|
||||
|
||||
XTCDECL
|
||||
EFI_STATUS
|
||||
XtInitializeVirtualMemory(IN OUT PLIST_ENTRY MemoryMappings,
|
||||
IN OUT PVOID *MemoryMapAddress);
|
||||
|
||||
XTCDECL
|
||||
EFI_STATUS
|
||||
XtMapVirtualMemory(IN PLIST_ENTRY MemoryMappings,
|
||||
IN UINT_PTR VirtualAddress,
|
||||
IN UINT_PTR PhysicalAddress,
|
||||
IN UINT NumberOfPages,
|
||||
IN OUT PVOID *PtePointer);
|
||||
|
||||
XTCDECL
|
||||
EFI_STATUS
|
||||
XtpBootSequence(IN PEFI_FILE_HANDLE BootDir,
|
||||
IN PXTBL_BOOT_PARAMETERS Parameters);
|
||||
|
||||
|
||||
XTCDECL
|
||||
EFI_STATUS
|
||||
XtpInitializeApicBase(IN PLIST_ENTRY MemoryMappings);
|
||||
|
||||
XTCDECL
|
||||
EFI_STATUS
|
||||
XtpInitializeLoaderBlock(IN PLIST_ENTRY MemoryMappings,
|
||||
IN PVOID *VirtualAddress,
|
||||
IN PXTBL_BOOT_PARAMETERS Parameters);
|
||||
|
||||
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 */
|
385
xtldr2/modules/xtos_o/memory.c
Normal file
385
xtldr2/modules/xtos_o/memory.c
Normal file
@ -0,0 +1,385 @@
|
||||
/**
|
||||
* PROJECT: ExectOS
|
||||
* COPYRIGHT: See COPYING.md in the top level directory
|
||||
* FILE: xtldr/memory.c
|
||||
* DESCRIPTION: EFI memory management
|
||||
* DEVELOPERS: Rafal Kupiec <belliash@codingworkshop.eu.org>
|
||||
*/
|
||||
|
||||
#include <xtos.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
|
||||
XtAddVirtualMemoryMapping(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 = XtLdrProtocol->Memory.AllocatePool(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 = XtLdrProtocol->Memory.AllocatePool(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 = XtLdrProtocol->Memory.AllocatePool(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);
|
||||
Status = XtLdrProtocol->Memory.FreePool(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
|
||||
XtConvertEfiMemoryType(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;
|
||||
}
|
||||
|
||||
/**
|
||||
* Attempts to find a virtual address of the specified physical address in memory mappings.
|
||||
*
|
||||
* @param MemoryMappings
|
||||
* Supplies a pointer to linked list containing all memory mappings.
|
||||
*
|
||||
* @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.
|
||||
*
|
||||
* @return This routine returns a status code.
|
||||
*
|
||||
* @since XT 1.0
|
||||
*/
|
||||
XTCDECL
|
||||
EFI_STATUS
|
||||
XtGetVirtualAddress(IN PLIST_ENTRY MemoryMappings,
|
||||
IN PVOID PhysicalAddress,
|
||||
OUT PVOID *VirtualAddress)
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
/**
|
||||
* Initializes virtual memory by adding known and general mappings.
|
||||
*
|
||||
* @param MemoryMappings
|
||||
* Supplies a pointer to linked list containing all memory mappings.
|
||||
*
|
||||
* @param MemoryMapAddress
|
||||
* Supplies an address of the mapped virtual memory area.
|
||||
*
|
||||
* @return This routine returns a status code.
|
||||
*
|
||||
* @since XT 1.0
|
||||
*/
|
||||
XTCDECL
|
||||
EFI_STATUS
|
||||
XtInitializeVirtualMemory(IN OUT PLIST_ENTRY MemoryMappings,
|
||||
IN OUT PVOID *MemoryMapAddress)
|
||||
{
|
||||
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 */
|
||||
XtLdrProtocol->Memory.AllocatePool(sizeof(EFI_MEMORY_MAP), (PVOID*)&MemoryMap);
|
||||
RtlZeroMemory(MemoryMap, sizeof(EFI_MEMORY_MAP));
|
||||
|
||||
/* Get EFI memory map */
|
||||
Status = XtLdrProtocol->Memory.GetMemoryMap(MemoryMap);
|
||||
if(Status != STATUS_EFI_SUCCESS)
|
||||
{
|
||||
return Status;
|
||||
}
|
||||
|
||||
/* Calculate descriptors count and get first one */
|
||||
Descriptor = MemoryMap->Map;
|
||||
DescriptorCount = MemoryMap->MapSize / MemoryMap->DescriptorSize;
|
||||
|
||||
/* Iterate through all descriptors from the memory map */
|
||||
for(Index = 0; Index < DescriptorCount; Index++)
|
||||
{
|
||||
/* Make sure descriptor does not 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 = XtConvertEfiMemoryType(Descriptor->Type);
|
||||
|
||||
/* Do memory mappings depending on memory type */
|
||||
if(MemoryType == LoaderFirmwareTemporary)
|
||||
{
|
||||
/* Map EFI firmware code */
|
||||
Status = XtAddVirtualMemoryMapping(MemoryMappings, (PVOID)Descriptor->PhysicalStart,
|
||||
(PVOID)Descriptor->PhysicalStart, Descriptor->NumberOfPages, MemoryType);
|
||||
}
|
||||
else if(MemoryType != LoaderFree)
|
||||
{
|
||||
/* Add any non-free memory mapping */
|
||||
Status = XtAddVirtualMemoryMapping(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 = XtAddVirtualMemoryMapping(MemoryMappings, NULL, (PVOID)Descriptor->PhysicalStart,
|
||||
Descriptor->NumberOfPages, LoaderFree);
|
||||
}
|
||||
|
||||
/* Make sure memory mapping succeeded */
|
||||
if(Status != STATUS_EFI_SUCCESS)
|
||||
{
|
||||
/* Mapping failed */
|
||||
return Status;
|
||||
}
|
||||
|
||||
/* Grab next descriptor */
|
||||
Descriptor = (PEFI_MEMORY_DESCRIPTOR)((PUCHAR)Descriptor + MemoryMap->DescriptorSize);
|
||||
}
|
||||
}
|
||||
|
||||
/* Store next valid virtual address and return success */
|
||||
*MemoryMapAddress = VirtualAddress;
|
||||
return STATUS_EFI_SUCCESS;
|
||||
}
|
548
xtldr2/modules/xtos_o/xtos.c
Normal file
548
xtldr2/modules/xtos_o/xtos.c
Normal file
@ -0,0 +1,548 @@
|
||||
/**
|
||||
* 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>
|
||||
|
||||
|
||||
/* XTOS module information */
|
||||
XTBL_MODINFO = L"XTOS boot protocol support";
|
||||
XTBL_MODDEPS = {L"fb_o", L"pecoff_o"};
|
||||
|
||||
/* EFI XT Loader Protocol */
|
||||
PXTBL_LOADER_PROTOCOL XtLdrProtocol;
|
||||
|
||||
/* XTOS PE/COFF Image Protocol */
|
||||
PXTBL_EXECUTABLE_IMAGE_PROTOCOL XtPeCoffProtocol;
|
||||
|
||||
/* XTOS Boot Protocol */
|
||||
XTBL_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 PXTBL_BOOT_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->Debug.Print(L"XTOS boot protocol activated\n");
|
||||
|
||||
/* Open the XT PE/COFF protocol */
|
||||
Status = XtLdrProtocol->Protocol.Open((PVOID *)&XtPeCoffProtocol, &PeCoffProtocolGuid);
|
||||
if(Status != STATUS_EFI_SUCCESS)
|
||||
{
|
||||
/* Failed to open loader protocol */
|
||||
XtLdrProtocol->Debug.Print(L"ERROR: Unable to load PE/COFF image protocol\n");
|
||||
return STATUS_EFI_PROTOCOL_ERROR;
|
||||
}
|
||||
|
||||
/* Check device path */
|
||||
if(Parameters->DevicePath == NULL)
|
||||
{
|
||||
/* No device path set */
|
||||
XtLdrProtocol->Debug.Print(L"ERROR: No device path provided, unable to boot system\n");
|
||||
return STATUS_EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
/* Check if system path is set */
|
||||
if(Parameters->SystemPath != 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->Debug.Print(L"ERROR: System path does not point to the valid XTOS installation\n");
|
||||
return STATUS_EFI_INVALID_PARAMETER;
|
||||
}
|
||||
/* Check next character in the path */
|
||||
SystemPath++;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Fallback to '/ExectOS' by default */
|
||||
XtLdrProtocol->Debug.Print(L"WARNING: No system path set, falling back to defaults\n");
|
||||
Parameters->SystemPath = L"\\ExectOS";
|
||||
}
|
||||
|
||||
/* Check if kernel file is set */
|
||||
if(Parameters->KernelFile == NULL)
|
||||
{
|
||||
/* No kernel filename set, fallback to default */
|
||||
XtLdrProtocol->Debug.Print(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->Parameters == NULL)
|
||||
{
|
||||
/* No argument supplied */
|
||||
Parameters->Parameters = L"";
|
||||
}
|
||||
|
||||
/* Print a debug message */
|
||||
XtLdrProtocol->Debug.Print(L"[XTOS] ARC Path: %S\n"
|
||||
L"[XTOS] System Path: %S\n"
|
||||
L"[XTOS] Kernel File: %S\n"
|
||||
L"[XTOS] Boot Arguments: %S\n",
|
||||
Parameters->ArcName, Parameters->SystemPath,
|
||||
Parameters->KernelFile, Parameters->Parameters);
|
||||
|
||||
/* Open EFI volume */
|
||||
Status = XtLdrProtocol->Disk.OpenVolume(NULL, &DiskHandle, &FsHandle);
|
||||
if(Status != STATUS_EFI_SUCCESS)
|
||||
{
|
||||
/* Failed to open a volume */
|
||||
XtLdrProtocol->Debug.Print(L"ERROR: Unable to open boot volume\n");
|
||||
return Status;
|
||||
}
|
||||
|
||||
/* System path has to point to the boot directory */
|
||||
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->Debug.Print(L"ERROR: System boot directory not found\n");
|
||||
|
||||
/* Close volume */
|
||||
XtLdrProtocol->Disk.CloseVolume(DiskHandle);
|
||||
return Status;
|
||||
}
|
||||
else if(Status != STATUS_EFI_SUCCESS)
|
||||
{
|
||||
/* Failed to open directory */
|
||||
XtLdrProtocol->Debug.Print(L"ERROR: Unable to open system boot directory\n");
|
||||
XtLdrProtocol->Disk.CloseVolume(DiskHandle);
|
||||
return Status;
|
||||
}
|
||||
|
||||
/* Start boot sequence */
|
||||
return 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 PXTBL_BOOT_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->Debug.Print(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 = XtInitializeVirtualMemory(&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 = XtAddVirtualMemoryMapping(&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, Parameters);
|
||||
if(Status != STATUS_EFI_SUCCESS)
|
||||
{
|
||||
/* Failed to setup kernel initialization block */
|
||||
XtLdrProtocol->Debug.Print(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->Debug.Print(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 */
|
||||
XtLdrProtocol->Protocol.Open((PVOID*)&ImageProtocol, &LoadedImageGuid);
|
||||
Status = XtEnablePaging(&MemoryMappings, VirtualAddress, ImageProtocol, &XtPageMap);
|
||||
if(Status != STATUS_EFI_SUCCESS)
|
||||
{
|
||||
/* Failed to enable paging */
|
||||
XtLdrProtocol->Debug.Print(L"Failed to enable paging (Status Code: %lx)\n", Status);
|
||||
return Status;
|
||||
}
|
||||
|
||||
/* Call XTOS kernel */
|
||||
XtLdrProtocol->Debug.Print(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 */
|
||||
XtAddVirtualMemoryMapping(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,
|
||||
IN PXTBL_BOOT_PARAMETERS Parameters)
|
||||
{
|
||||
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->Memory.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->Debug.Print;
|
||||
|
||||
/* Load FrameBuffer protocol */
|
||||
Status = XtLdrProtocol->Protocol.Open((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 = 0; //EfiSystemTable->Hdr.Revision;
|
||||
LoaderBlock->FirmwareInformation.EfiFirmware.EfiRuntimeServices = NULL;
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// /* Set invalid firmware type to indicate that kernel cannot rely on FirmwareInformation block */
|
||||
// LoaderBlock->FirmwareInformation.FirmwareType = SystemFirmwareInvalid;
|
||||
// }
|
||||
|
||||
/* Copy parameters to kernel initialization block */
|
||||
RtlCopyMemory(&LoaderBlock->KernelParameters, Parameters->Parameters, RtlWideStringLength(Parameters->Parameters, 0));
|
||||
|
||||
/* Map kernel initialization block */
|
||||
XtAddVirtualMemoryMapping(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 */
|
||||
XtAddVirtualMemoryMapping(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->Debug.Print(L"Loading %S ... \n", FileName);
|
||||
|
||||
/* Open module file */
|
||||
Status = SystemDir->Open(SystemDir, &ModuleHandle, FileName, EFI_FILE_MODE_READ, 0);
|
||||
if(Status != STATUS_EFI_SUCCESS)
|
||||
{
|
||||
/* Unable to open the file */
|
||||
XtLdrProtocol->Debug.Print(L"ERROR: Failed to open '%S'\n", FileName);
|
||||
return Status;
|
||||
}
|
||||
|
||||
/* Load the PE/COFF image file */
|
||||
Status = XtPeCoffProtocol->LoadImage(ModuleHandle, MemoryType, VirtualAddress, (PVOID)ImageContext);
|
||||
if(Status != STATUS_EFI_SUCCESS)
|
||||
{
|
||||
/* Unable to load the file */
|
||||
XtLdrProtocol->Debug.Print(L"ERROR: Failed to load '%S'\n", FileName);
|
||||
return Status;
|
||||
}
|
||||
|
||||
/* Close image file */
|
||||
ModuleHandle->Close(ModuleHandle);
|
||||
|
||||
/* Check PE/COFF image machine type compatibility */
|
||||
XtPeCoffProtocol->GetMachineType(*ImageContext, &MachineType);
|
||||
if(MachineType != _ARCH_IMAGE_MACHINE_TYPE)
|
||||
{
|
||||
/* Machine type mismatch */
|
||||
XtLdrProtocol->Debug.Print(L"ERROR: Loaded incompatible PE/COFF image (machine type mismatch)\n");
|
||||
return STATUS_EFI_INCOMPATIBLE_VERSION;
|
||||
}
|
||||
|
||||
/* Check PE/COFF image subsystem */
|
||||
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->Debug.Print(L"WARNING: Loaded PE/COFF image with non-XT subsystem set\n");
|
||||
}
|
||||
|
||||
/* Print debug message */
|
||||
XtLdrProtocol->Debug.Print(L"Loaded %S at PA: 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
|
||||
XtLdrModuleMain(IN EFI_HANDLE ImageHandle,
|
||||
IN PEFI_SYSTEM_TABLE SystemTable)
|
||||
{
|
||||
EFI_GUID Guid = XT_XTOS_BOOT_PROTOCOL_GUID;
|
||||
EFI_STATUS Status;
|
||||
|
||||
// /* Set the system table and image handle */
|
||||
// EfiImageHandle = ImageHandle;
|
||||
// EfiSystemTable = SystemTable;
|
||||
|
||||
/* Open the XTLDR protocol */
|
||||
Status = BlGetXtLdrProtocol(SystemTable, ImageHandle, &XtLdrProtocol);
|
||||
if(Status != STATUS_EFI_SUCCESS)
|
||||
{
|
||||
/* Failed to open loader protocol */
|
||||
return STATUS_EFI_PROTOCOL_ERROR;
|
||||
}
|
||||
|
||||
/* Set routines available via XTOS boot protocol */
|
||||
XtBootProtocol.BootSystem = XtBootSystem;
|
||||
|
||||
/* Register XTOS boot protocol */
|
||||
return XtLdrProtocol->Protocol.Register(&Guid, &XtBootProtocol);
|
||||
}
|
Loading…
Reference in New Issue
Block a user