Add full paging support for AMD64 and i686 architectures, including PAE support
All checks were successful
ci/woodpecker/push/build Pipeline was successful
All checks were successful
ci/woodpecker/push/build Pipeline was successful
This commit is contained in:
parent
324a88cc01
commit
0572b208f1
@ -12,8 +12,26 @@
|
|||||||
#include "xtcommon.h"
|
#include "xtcommon.h"
|
||||||
|
|
||||||
|
|
||||||
/* Page Table entry with PAE support structure definition */
|
/* Page Table entry structure definition */
|
||||||
typedef struct _HARDWARE_PTE
|
typedef struct _HARDWARE_PTE
|
||||||
|
{
|
||||||
|
UINT32 Valid:1;
|
||||||
|
UINT32 Write:1;
|
||||||
|
UINT32 Owner:1;
|
||||||
|
UINT32 WriteThrough:1;
|
||||||
|
UINT32 CacheDisable:1;
|
||||||
|
UINT32 Accessed:1;
|
||||||
|
UINT32 Dirty:1;
|
||||||
|
UINT32 LargePage:1;
|
||||||
|
UINT32 Global:1;
|
||||||
|
UINT32 CopyOnWrite:1;
|
||||||
|
UINT32 Prototype:1;
|
||||||
|
UINT32 Reserved:1;
|
||||||
|
UINT32 PageFrameNumber:20;
|
||||||
|
} HARDWARE_PTE, *PHARDWARE_PTE;
|
||||||
|
|
||||||
|
/* Page Table entry with PAE support structure definition */
|
||||||
|
typedef struct _HARDWARE_PTE_PAE
|
||||||
{
|
{
|
||||||
ULONGLONG Valid:1;
|
ULONGLONG Valid:1;
|
||||||
ULONGLONG Write:1;
|
ULONGLONG Write:1;
|
||||||
@ -31,6 +49,6 @@ typedef struct _HARDWARE_PTE
|
|||||||
ULONGLONG Reserved1:12;
|
ULONGLONG Reserved1:12;
|
||||||
ULONGLONG SoftwareWsIndex:11;
|
ULONGLONG SoftwareWsIndex:11;
|
||||||
ULONGLONG NoExecute:1;
|
ULONGLONG NoExecute:1;
|
||||||
} HARDWARE_PTE, *PHARDWARE_PTE;
|
} HARDWARE_PTE_PAE, *PHARDWARE_PTE_PAE;
|
||||||
|
|
||||||
#endif /* __XTDK_I686_MMTYPES_H */
|
#endif /* __XTDK_I686_MMTYPES_H */
|
||||||
|
@ -36,6 +36,123 @@ BlCreateStack(IN PVOID *StackPtr,
|
|||||||
: "rax", "rbx");
|
: "rax", "rbx");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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
|
||||||
|
*/
|
||||||
|
EFI_STATUS
|
||||||
|
BlEnablePaging(IN PLIST_ENTRY MemoryMappings,
|
||||||
|
IN PVOID VirtualAddress,
|
||||||
|
IN PEFI_LOADED_IMAGE_PROTOCOL ImageProtocol,
|
||||||
|
IN PVOID *PtePointer)
|
||||||
|
{
|
||||||
|
UINT_PTR MapKey, DescriptorSize, DescriptorCount;
|
||||||
|
PEFI_MEMORY_DESCRIPTOR MemoryMap = NULL;
|
||||||
|
PLOADER_MEMORY_MAPPING Mapping;
|
||||||
|
EFI_PHYSICAL_ADDRESS Address;
|
||||||
|
PLIST_ENTRY ListEntry;
|
||||||
|
EFI_STATUS Status;
|
||||||
|
PVOID Stack;
|
||||||
|
|
||||||
|
/* Get EFI memory map */
|
||||||
|
Status = BlGetMemoryMap(&MemoryMap, &MapKey, &DescriptorSize, &DescriptorCount);
|
||||||
|
if(Status != STATUS_EFI_SUCCESS)
|
||||||
|
{
|
||||||
|
/* Unable to get memory map */
|
||||||
|
return 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 the stack */
|
||||||
|
BlGetStackPointer(&Stack);
|
||||||
|
Status = BlAddVirtualMemoryMapping(MemoryMappings, Stack, Stack, XTOS_KERNEL_STACK_SIZE,
|
||||||
|
LoaderOsloaderStack);
|
||||||
|
if(Status != STATUS_EFI_SUCCESS)
|
||||||
|
{
|
||||||
|
/* Mapping the stack failed */
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 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 all mappings */
|
||||||
|
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)
|
||||||
|
{
|
||||||
|
/* Map memory */
|
||||||
|
Status = BlMapVirtualMemory(MemoryMappings, (UINT_PTR)Mapping->VirtualAddress,
|
||||||
|
(UINT_PTR)Mapping->PhysicalAddress, Mapping->NumberOfPages,
|
||||||
|
FALSE, PtePointer);
|
||||||
|
if(Status != STATUS_EFI_SUCCESS)
|
||||||
|
{
|
||||||
|
/* Memory mapping failed */
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Take next element */
|
||||||
|
ListEntry = ListEntry->Flink;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Exit EFI Boot Services */
|
||||||
|
BlDbgPrint(L"Exiting EFI boot services\n");
|
||||||
|
EfiSystemTable->BootServices->ExitBootServices(EfiImageHandle, MapKey);
|
||||||
|
|
||||||
|
/* Write PML4 to CR3 */
|
||||||
|
HlWriteCR3((UINT_PTR)*PtePointer);
|
||||||
|
|
||||||
|
/* Return success */
|
||||||
|
return STATUS_EFI_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This routine does the actual virtual memory mapping.
|
* This routine does the actual virtual memory mapping.
|
||||||
*
|
*
|
||||||
@ -51,6 +168,9 @@ BlCreateStack(IN PVOID *StackPtr,
|
|||||||
* @param NumberOfPages
|
* @param NumberOfPages
|
||||||
* Supplies a number of the pages of the mapping.
|
* 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
|
* @param PtePointer
|
||||||
* Supplies a pointer to an array of pointers to page table entries.
|
* Supplies a pointer to an array of pointers to page table entries.
|
||||||
*
|
*
|
||||||
@ -63,6 +183,7 @@ BlMapVirtualMemory(IN PLIST_ENTRY MemoryMappings,
|
|||||||
IN UINT_PTR VirtualAddress,
|
IN UINT_PTR VirtualAddress,
|
||||||
IN UINT_PTR PhysicalAddress,
|
IN UINT_PTR PhysicalAddress,
|
||||||
IN UINT NumberOfPages,
|
IN UINT NumberOfPages,
|
||||||
|
IN BOOLEAN PaeExtension,
|
||||||
IN OUT PVOID *PtePointer)
|
IN OUT PVOID *PtePointer)
|
||||||
{
|
{
|
||||||
PHARDWARE_PTE PageDirectoryPointTable, PageDirectory, PageTable;
|
PHARDWARE_PTE PageDirectoryPointTable, PageDirectory, PageTable;
|
||||||
@ -101,10 +222,10 @@ BlMapVirtualMemory(IN PLIST_ENTRY MemoryMappings,
|
|||||||
return Status;
|
return Status;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Zero memory */
|
/* Fill allocated memory with zeros */
|
||||||
RtlZeroMemory((PVOID)(UINT_PTR)Address, EFI_PAGE_SIZE);
|
RtlZeroMemory((PVOID)(UINT_PTR)Address, EFI_PAGE_SIZE);
|
||||||
|
|
||||||
/* Set paging entry setting */
|
/* Set paging entry settings */
|
||||||
((PHARDWARE_PTE)(*PtePointer))[Pml4Index].PageFrameNumber = Address / EFI_PAGE_SIZE;
|
((PHARDWARE_PTE)(*PtePointer))[Pml4Index].PageFrameNumber = Address / EFI_PAGE_SIZE;
|
||||||
((PHARDWARE_PTE)(*PtePointer))[Pml4Index].Valid = 1;
|
((PHARDWARE_PTE)(*PtePointer))[Pml4Index].Valid = 1;
|
||||||
((PHARDWARE_PTE)(*PtePointer))[Pml4Index].Write = 1;
|
((PHARDWARE_PTE)(*PtePointer))[Pml4Index].Write = 1;
|
||||||
@ -135,10 +256,10 @@ BlMapVirtualMemory(IN PLIST_ENTRY MemoryMappings,
|
|||||||
return Status;
|
return Status;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Zero memory */
|
/* Fill allocated memory with zeros */
|
||||||
RtlZeroMemory((PVOID)(UINT_PTR)Address, EFI_PAGE_SIZE);
|
RtlZeroMemory((PVOID)(UINT_PTR)Address, EFI_PAGE_SIZE);
|
||||||
|
|
||||||
/* Set paging entry setting */
|
/* Set paging entry settings */
|
||||||
PageDirectoryPointTable[PdpIndex].PageFrameNumber = Address / EFI_PAGE_SIZE;
|
PageDirectoryPointTable[PdpIndex].PageFrameNumber = Address / EFI_PAGE_SIZE;
|
||||||
PageDirectoryPointTable[PdpIndex].Valid = 1;
|
PageDirectoryPointTable[PdpIndex].Valid = 1;
|
||||||
PageDirectoryPointTable[PdpIndex].Write = 1;
|
PageDirectoryPointTable[PdpIndex].Write = 1;
|
||||||
@ -169,10 +290,10 @@ BlMapVirtualMemory(IN PLIST_ENTRY MemoryMappings,
|
|||||||
return Status;
|
return Status;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Zero memory */
|
/* Fill allocated memory with zeros */
|
||||||
RtlZeroMemory((PVOID)(UINT_PTR)Address, EFI_PAGE_SIZE);
|
RtlZeroMemory((PVOID)(UINT_PTR)Address, EFI_PAGE_SIZE);
|
||||||
|
|
||||||
/* Set paging entry setting */
|
/* Set paging entry settings */
|
||||||
PageDirectory[PdIndex].PageFrameNumber = Address / EFI_PAGE_SIZE;
|
PageDirectory[PdIndex].PageFrameNumber = Address / EFI_PAGE_SIZE;
|
||||||
PageDirectory[PdIndex].Valid = 1;
|
PageDirectory[PdIndex].Valid = 1;
|
||||||
PageDirectory[PdIndex].Write = 1;
|
PageDirectory[PdIndex].Write = 1;
|
||||||
@ -186,7 +307,7 @@ BlMapVirtualMemory(IN PLIST_ENTRY MemoryMappings,
|
|||||||
PageTable = (PHARDWARE_PTE)(UINT_PTR)Pointer;
|
PageTable = (PHARDWARE_PTE)(UINT_PTR)Pointer;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Set paging entry setting */
|
/* Set paging entry settings */
|
||||||
PageTable[PtIndex].PageFrameNumber = PageFrameNumber;
|
PageTable[PtIndex].PageFrameNumber = PageFrameNumber;
|
||||||
PageTable[PtIndex].Valid = 1;
|
PageTable[PtIndex].Valid = 1;
|
||||||
PageTable[PtIndex].Write = 1;
|
PageTable[PtIndex].Write = 1;
|
||||||
|
@ -36,6 +36,233 @@ BlCreateStack(IN PVOID *StackPtr,
|
|||||||
: "eax", "ebx");
|
: "eax", "ebx");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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
|
||||||
|
*/
|
||||||
|
EFI_STATUS
|
||||||
|
BlEnablePaging(IN PLIST_ENTRY MemoryMappings,
|
||||||
|
IN PVOID VirtualAddress,
|
||||||
|
IN PEFI_LOADED_IMAGE_PROTOCOL ImageProtocol,
|
||||||
|
IN PVOID *PtePointer)
|
||||||
|
{
|
||||||
|
UINT_PTR PhysicalAddress, MapKey, DescriptorSize, DescriptorCount;
|
||||||
|
EFI_PHYSICAL_ADDRESS Address, PDPTAddress = 0;
|
||||||
|
PEFI_MEMORY_DESCRIPTOR MemoryMap = NULL;
|
||||||
|
PLOADER_MEMORY_MAPPING Mapping;
|
||||||
|
PCPUID_REGISTERS CpuRegisters;
|
||||||
|
PLIST_ENTRY ListEntry;
|
||||||
|
BOOLEAN PaeExtension;
|
||||||
|
EFI_STATUS Status;
|
||||||
|
PVOID Stack;
|
||||||
|
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 */
|
||||||
|
HlCpuId(CpuRegisters);
|
||||||
|
|
||||||
|
/* Store PAE status from the CPUID results */
|
||||||
|
PaeExtension = CpuRegisters->Edx & CPUID_FEATURES_EDX_PAE;
|
||||||
|
|
||||||
|
/* Get EFI memory map */
|
||||||
|
Status = BlGetMemoryMap(&MemoryMap, &MapKey, &DescriptorSize, &DescriptorCount);
|
||||||
|
if(Status != STATUS_EFI_SUCCESS)
|
||||||
|
{
|
||||||
|
/* Unable to get memory map */
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Check if PAE supported by the underlying hardware */
|
||||||
|
if(PaeExtension)
|
||||||
|
{
|
||||||
|
/* Print debug message */
|
||||||
|
BlDbgPrint(L"Physical Address Extension (PAE) available\n");
|
||||||
|
|
||||||
|
/* Calculate physical address based on KSEG0 base */
|
||||||
|
PhysicalAddress = (UINT_PTR)VirtualAddress - XTOS_VIRTUAL_MEMORY_AREA;
|
||||||
|
|
||||||
|
/* 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((MemoryMap->PhysicalStart + ((MemoryMap->NumberOfPages - 1) * EFI_PAGE_SIZE) >= PhysicalAddress) &&
|
||||||
|
(MemoryMap->Type == EfiConventionalMemory))
|
||||||
|
{
|
||||||
|
/* Use highest address possible */
|
||||||
|
if(PhysicalAddress >= MemoryMap->PhysicalStart)
|
||||||
|
{
|
||||||
|
/* Use physical address */
|
||||||
|
PDPTAddress = PhysicalAddress;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Use descriptor physical start as PDPT address */
|
||||||
|
PDPTAddress = MemoryMap->PhysicalStart;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Allocate pages for the PDPT address */
|
||||||
|
Status = BlEfiMemoryAllocatePages(1, &PDPTAddress);
|
||||||
|
if(Status != STATUS_EFI_SUCCESS) {
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Get next descriptor */
|
||||||
|
MemoryMap = (EFI_MEMORY_DESCRIPTOR*)((UINT8*)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 = (void*)(UINT_PTR)(PDPTAddress + EFI_PAGE_SIZE + XTOS_VIRTUAL_MEMORY_AREA);
|
||||||
|
|
||||||
|
/* Set base page frame number */
|
||||||
|
Address = 0x100000; // MEM_TOP_DOWN ?
|
||||||
|
|
||||||
|
/* 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_PAE)*PtePointer)[Index].PageFrameNumber = Address / EFI_PAGE_SIZE;
|
||||||
|
((PHARDWARE_PTE_PAE)*PtePointer)[Index].Valid = 1;
|
||||||
|
|
||||||
|
/* Next valid PFN address */
|
||||||
|
Address += EFI_PAGE_SIZE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Print debug message */
|
||||||
|
BlDbgPrint(L"Physical Address Extension (PAE) NOT available\n");
|
||||||
|
|
||||||
|
/* Allocate pages for Page Directory */
|
||||||
|
Status = BlEfiMemoryAllocatePages(1, &Address);
|
||||||
|
if(Status != STATUS_EFI_SUCCESS)
|
||||||
|
{
|
||||||
|
/* Memory allocation failure */
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Set and zero memory used by Page Directory */
|
||||||
|
*PtePointer = (PVOID)(UINT_PTR)Address;
|
||||||
|
RtlZeroMemory(*PtePointer, EFI_PAGE_SIZE);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Map the stack */
|
||||||
|
BlGetStackPointer(&Stack);
|
||||||
|
Status = BlAddVirtualMemoryMapping(MemoryMappings, Stack, Stack, XTOS_KERNEL_STACK_SIZE,
|
||||||
|
LoaderOsloaderStack);
|
||||||
|
if(Status != STATUS_EFI_SUCCESS)
|
||||||
|
{
|
||||||
|
/* Mapping the stack failed */
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 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 all mappings */
|
||||||
|
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)
|
||||||
|
{
|
||||||
|
/* Map memory */
|
||||||
|
Status = BlMapVirtualMemory(MemoryMappings, (UINT_PTR)Mapping->VirtualAddress,
|
||||||
|
(UINT_PTR)Mapping->PhysicalAddress, Mapping->NumberOfPages,
|
||||||
|
PaeExtension, PtePointer);
|
||||||
|
if(Status != STATUS_EFI_SUCCESS)
|
||||||
|
{
|
||||||
|
/* Memory mapping failed */
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Take next element */
|
||||||
|
ListEntry = ListEntry->Flink;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Exit EFI Boot Services */
|
||||||
|
BlDbgPrint(L"Exiting EFI boot services\n");
|
||||||
|
EfiSystemTable->BootServices->ExitBootServices(EfiImageHandle, MapKey);
|
||||||
|
|
||||||
|
/* Enable PAE if supported by CPU */
|
||||||
|
if(PaeExtension)
|
||||||
|
{
|
||||||
|
/* Enable Physical Address Extension (PAE) */
|
||||||
|
HlWriteCR4(HlReadCR4() | 0x00000020);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Write page mappings to CR3 */
|
||||||
|
HlWriteCR3((UINT_PTR)*PtePointer);
|
||||||
|
|
||||||
|
/* Enable paging */
|
||||||
|
HlWriteCR0(HlReadCR0() | 0x80000000);
|
||||||
|
|
||||||
|
/* Return success */
|
||||||
|
return STATUS_EFI_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This routine does the actual virtual memory mapping.
|
* This routine does the actual virtual memory mapping.
|
||||||
*
|
*
|
||||||
@ -51,6 +278,9 @@ BlCreateStack(IN PVOID *StackPtr,
|
|||||||
* @param NumberOfPages
|
* @param NumberOfPages
|
||||||
* Supplies a number of the pages of the mapping.
|
* Supplies a number of the pages of the mapping.
|
||||||
*
|
*
|
||||||
|
* @param PaeExtension
|
||||||
|
* Specifies whether Physical Address Extension (PAE) is supported by the hardware.
|
||||||
|
*
|
||||||
* @param PtePointer
|
* @param PtePointer
|
||||||
* Supplies a pointer to an array of pointers to page table entries.
|
* Supplies a pointer to an array of pointers to page table entries.
|
||||||
*
|
*
|
||||||
@ -63,7 +293,119 @@ BlMapVirtualMemory(IN PLIST_ENTRY MemoryMappings,
|
|||||||
IN UINT_PTR VirtualAddress,
|
IN UINT_PTR VirtualAddress,
|
||||||
IN UINT_PTR PhysicalAddress,
|
IN UINT_PTR PhysicalAddress,
|
||||||
IN UINT NumberOfPages,
|
IN UINT NumberOfPages,
|
||||||
|
IN BOOLEAN PaeExtension,
|
||||||
IN OUT PVOID *PtePointer)
|
IN OUT PVOID *PtePointer)
|
||||||
{
|
{
|
||||||
|
EFI_PHYSICAL_ADDRESS Address;
|
||||||
|
UINT_PTR PageFrameNumber;
|
||||||
|
PHARDWARE_PTE_PAE PaePageTable, PageDirectory;
|
||||||
|
PHARDWARE_PTE PageTable;
|
||||||
|
EFI_STATUS Status;
|
||||||
|
unsigned int PdIndex, PtIndex;
|
||||||
|
|
||||||
|
/* Set the PFN */
|
||||||
|
PageFrameNumber = PhysicalAddress >> EFI_PAGE_SHIFT;
|
||||||
|
|
||||||
|
/* Check if PAE supported by the hardware */
|
||||||
|
if(PaeExtension)
|
||||||
|
{
|
||||||
|
/* PAE supported, do the recursive mapping */
|
||||||
|
while(NumberOfPages > 0)
|
||||||
|
{
|
||||||
|
/* Find Page Directory and calculate indices from a virtual address */
|
||||||
|
PageDirectory = (HARDWARE_PTE_PAE*)(((PHARDWARE_PTE_PAE)(*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 */
|
||||||
|
PaePageTable = (HARDWARE_PTE_PAE*)(UINT_PTR)Address;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Set page table */
|
||||||
|
PaePageTable = (HARDWARE_PTE_PAE*)(PageDirectory[PdIndex].PageFrameNumber * EFI_PAGE_SIZE);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Set page table settings */
|
||||||
|
PaePageTable[PtIndex].PageFrameNumber = PageFrameNumber;
|
||||||
|
PaePageTable[PtIndex].Valid = 1;
|
||||||
|
PaePageTable[PtIndex].Write = 1;
|
||||||
|
|
||||||
|
/* Take next virtual address and PFN */
|
||||||
|
VirtualAddress += EFI_PAGE_SIZE;
|
||||||
|
PageFrameNumber++;
|
||||||
|
|
||||||
|
/* Decrease number of pages left */
|
||||||
|
NumberOfPages--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* PAE not supported, do the recursive mapping */
|
||||||
|
while (NumberOfPages > 0)
|
||||||
|
{
|
||||||
|
/* Calculate indices from a virtual address */
|
||||||
|
PdIndex = VirtualAddress >> 22;
|
||||||
|
PtIndex = (VirtualAddress & 0x3ff000) >> 12;
|
||||||
|
|
||||||
|
/* Validate Page Table */
|
||||||
|
if(!((PHARDWARE_PTE)(*PtePointer))[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((void*)(UINT_PTR)Address, EFI_PAGE_SIZE);
|
||||||
|
|
||||||
|
/* Set paging entry settings */
|
||||||
|
((PHARDWARE_PTE)(*PtePointer))[PdIndex].PageFrameNumber = Address / EFI_PAGE_SIZE;
|
||||||
|
((PHARDWARE_PTE)(*PtePointer))[PdIndex].Valid = 1;
|
||||||
|
((PHARDWARE_PTE)(*PtePointer))[PdIndex].Write = 1;
|
||||||
|
|
||||||
|
/* Set page table */
|
||||||
|
PageTable = (HARDWARE_PTE*)(UINT_PTR)Address;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Set page table */
|
||||||
|
PageTable = (HARDWARE_PTE*)(((PHARDWARE_PTE)(*PtePointer))[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;
|
return STATUS_EFI_SUCCESS;
|
||||||
}
|
}
|
||||||
|
@ -17,11 +17,12 @@
|
|||||||
typedef EFI_STATUS (*PBL_ADD_VIRTUAL_MEMORY_MAPPING)(IN PLIST_ENTRY MemoryMappings, IN PVOID VirtualAddress, IN PVOID PhysicalAddress, IN UINT NumberOfPages, LOADER_MEMORY_TYPE MemoryType);
|
typedef EFI_STATUS (*PBL_ADD_VIRTUAL_MEMORY_MAPPING)(IN PLIST_ENTRY MemoryMappings, IN PVOID VirtualAddress, IN PVOID PhysicalAddress, IN UINT NumberOfPages, LOADER_MEMORY_TYPE MemoryType);
|
||||||
typedef EFI_STATUS (*PBL_ALLOCATE_PAGES)(IN UINT64 Size, OUT PEFI_PHYSICAL_ADDRESS Memory);
|
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_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_PAGES)(IN UINT64 Size, IN EFI_PHYSICAL_ADDRESS Memory);
|
||||||
typedef EFI_STATUS (*PBL_FREE_POOL)(IN PVOID Memory);
|
typedef EFI_STATUS (*PBL_FREE_POOL)(IN PVOID Memory);
|
||||||
typedef EFI_STATUS (*PBL_GET_MEMORY_MAP)(OUT PEFI_MEMORY_DESCRIPTOR *MemoryMap, OUT PUINT_PTR MapKey, OUT PUINT_PTR DescriptorSize, OUT PUINT_PTR DescriptorCount);
|
typedef EFI_STATUS (*PBL_GET_MEMORY_MAP)(OUT PEFI_MEMORY_DESCRIPTOR *MemoryMap, OUT PUINT_PTR MapKey, OUT PUINT_PTR DescriptorSize, OUT PUINT_PTR DescriptorCount);
|
||||||
typedef EFI_STATUS (*PBL_INIT_VIRTUAL_MEMORY)(IN OUT PLIST_ENTRY MemoryMappings, IN OUT PVOID *MemoryMapAddress);
|
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 EFI_STATUS (*PBL_MAP_VIRTUAL_MEMORY)(IN PLIST_ENTRY MemoryMappings, IN UINT_PTR VirtualAddress, IN UINT_PTR PhysicalAddress, IN UINT NumberOfPages, IN BOOLEAN PaeExtension, IN OUT PVOID *PtePointer);
|
||||||
typedef VOID (*PBL_GET_STACK)(OUT PVOID *Stack);
|
typedef VOID (*PBL_GET_STACK)(OUT PVOID *Stack);
|
||||||
typedef VOID (*PBL_DBG_PRINT)(IN PUINT16 Format, IN ...);
|
typedef VOID (*PBL_DBG_PRINT)(IN PUINT16 Format, IN ...);
|
||||||
typedef VOID (*PBL_EFI_PRINT)(IN PUINT16 Format, IN ...);
|
typedef VOID (*PBL_EFI_PRINT)(IN PUINT16 Format, IN ...);
|
||||||
@ -36,6 +37,7 @@ typedef struct _XT_BOOT_LOADER_PROTOCOL
|
|||||||
PBL_ALLOCATE_POOL AllocatePool;
|
PBL_ALLOCATE_POOL AllocatePool;
|
||||||
PBL_FREE_PAGES FreePages;
|
PBL_FREE_PAGES FreePages;
|
||||||
PBL_FREE_POOL FreePool;
|
PBL_FREE_POOL FreePool;
|
||||||
|
PBL_ENABLE_PAGING EnablePaging;
|
||||||
PBL_GET_MEMORY_MAP GetMemoryMap;
|
PBL_GET_MEMORY_MAP GetMemoryMap;
|
||||||
PBL_INIT_VIRTUAL_MEMORY InitializeVirtualMemory;
|
PBL_INIT_VIRTUAL_MEMORY InitializeVirtualMemory;
|
||||||
PBL_MAP_VIRTUAL_MEMORY MapVirtualMemory;
|
PBL_MAP_VIRTUAL_MEMORY MapVirtualMemory;
|
||||||
|
@ -92,6 +92,12 @@ VOID
|
|||||||
BlEfiPrint(IN PUINT16 Format,
|
BlEfiPrint(IN PUINT16 Format,
|
||||||
IN ...);
|
IN ...);
|
||||||
|
|
||||||
|
EFI_STATUS
|
||||||
|
BlEnablePaging(IN PLIST_ENTRY MemoryMappings,
|
||||||
|
IN PVOID VirtualAddress,
|
||||||
|
IN PEFI_LOADED_IMAGE_PROTOCOL ImageProtocol,
|
||||||
|
IN PVOID *PtePointer);
|
||||||
|
|
||||||
EFI_STATUS
|
EFI_STATUS
|
||||||
BlEnumerateEfiBlockDevices();
|
BlEnumerateEfiBlockDevices();
|
||||||
|
|
||||||
@ -126,6 +132,7 @@ BlMapVirtualMemory(IN PLIST_ENTRY MemoryMappings,
|
|||||||
IN UINT_PTR VirtualAddress,
|
IN UINT_PTR VirtualAddress,
|
||||||
IN UINT_PTR PhysicalAddress,
|
IN UINT_PTR PhysicalAddress,
|
||||||
IN UINT NumberOfPages,
|
IN UINT NumberOfPages,
|
||||||
|
IN BOOLEAN PaeExtension,
|
||||||
IN OUT PVOID *PtePointer);
|
IN OUT PVOID *PtePointer);
|
||||||
|
|
||||||
EFI_STATUS
|
EFI_STATUS
|
||||||
|
@ -330,6 +330,7 @@ BlRegisterXtLoaderProtocol()
|
|||||||
EfiLdrProtocol.AllocatePool = BlEfiMemoryAllocatePool;
|
EfiLdrProtocol.AllocatePool = BlEfiMemoryAllocatePool;
|
||||||
EfiLdrProtocol.FreePages = BlEfiMemoryFreePages;
|
EfiLdrProtocol.FreePages = BlEfiMemoryFreePages;
|
||||||
EfiLdrProtocol.FreePool = BlEfiMemoryFreePool;
|
EfiLdrProtocol.FreePool = BlEfiMemoryFreePool;
|
||||||
|
EfiLdrProtocol.EnablePaging = BlEnablePaging;
|
||||||
EfiLdrProtocol.GetMemoryMap = BlGetMemoryMap;
|
EfiLdrProtocol.GetMemoryMap = BlGetMemoryMap;
|
||||||
EfiLdrProtocol.InitializeVirtualMemory = BlInitializeVirtualMemory;
|
EfiLdrProtocol.InitializeVirtualMemory = BlInitializeVirtualMemory;
|
||||||
EfiLdrProtocol.MapVirtualMemory = BlMapVirtualMemory;
|
EfiLdrProtocol.MapVirtualMemory = BlMapVirtualMemory;
|
||||||
@ -439,7 +440,7 @@ BlStartXtLoader(IN EFI_HANDLE ImageHandle,
|
|||||||
BlCreateStack(&EfiLoaderStack, XTOS_KERNEL_STACK_SIZE, &BlStartNewStack);
|
BlCreateStack(&EfiLoaderStack, XTOS_KERNEL_STACK_SIZE, &BlStartNewStack);
|
||||||
|
|
||||||
/* Infinite bootloader loop */
|
/* Infinite bootloader loop */
|
||||||
BlDbgPrint(L"ERROR: Unexpected exception occurred, probably did not create a new stack");
|
BlDbgPrint(L"ERROR: Unexpected exception occurred, probably did not create a new stack\n");
|
||||||
BlEfiPrint(L"System halted!");
|
BlEfiPrint(L"System halted!");
|
||||||
for(;;);
|
for(;;);
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user