Rework BlGetMemoryMap() routine to use EFI_MEMORY_MAP structure; map EfiBootServicesData instead of EfiReservedMemoryType
All checks were successful
ci/woodpecker/push/build Pipeline was successful

This commit is contained in:
Rafal Kupiec 2022-12-20 18:59:36 +01:00
parent acda7aa37c
commit edee9a8ec6
Signed by: belliash
GPG Key ID: 4E829243E0CFE6B4
5 changed files with 83 additions and 77 deletions

View File

@ -61,16 +61,19 @@ BlEnablePaging(IN PLIST_ENTRY MemoryMappings,
IN PEFI_LOADED_IMAGE_PROTOCOL ImageProtocol, IN PEFI_LOADED_IMAGE_PROTOCOL ImageProtocol,
IN PVOID *PtePointer) IN PVOID *PtePointer)
{ {
UINT_PTR MapKey, DescriptorSize, DescriptorCount;
PEFI_MEMORY_DESCRIPTOR MemoryMap = NULL;
PLOADER_MEMORY_MAPPING Mapping; PLOADER_MEMORY_MAPPING Mapping;
EFI_PHYSICAL_ADDRESS Address; EFI_PHYSICAL_ADDRESS Address;
PEFI_MEMORY_MAP MemoryMap;
PLIST_ENTRY ListEntry; PLIST_ENTRY ListEntry;
EFI_STATUS Status; EFI_STATUS Status;
PVOID Stack; PVOID Stack;
/* Allocate and zero-fill buffer for EFI memory map */
BlEfiMemoryAllocatePool(sizeof(EFI_MEMORY_MAP), (PVOID*)&MemoryMap);
RtlZeroMemory(MemoryMap, sizeof(EFI_MEMORY_MAP));
/* Get EFI memory map */ /* Get EFI memory map */
Status = BlGetMemoryMap(&MemoryMap, &MapKey, &DescriptorSize, &DescriptorCount); Status = BlGetMemoryMap(MemoryMap);
if(Status != STATUS_EFI_SUCCESS) if(Status != STATUS_EFI_SUCCESS)
{ {
/* Unable to get memory map */ /* Unable to get memory map */
@ -144,7 +147,7 @@ BlEnablePaging(IN PLIST_ENTRY MemoryMappings,
/* Exit EFI Boot Services */ /* Exit EFI Boot Services */
BlDbgPrint(L"Exiting EFI boot services\n"); BlDbgPrint(L"Exiting EFI boot services\n");
EfiSystemTable->BootServices->ExitBootServices(EfiImageHandle, MapKey); EfiSystemTable->BootServices->ExitBootServices(EfiImageHandle, MemoryMap->MapKey);
/* Write PML4 to CR3 */ /* Write PML4 to CR3 */
HlWriteCR3((UINT_PTR)*PtePointer); HlWriteCR3((UINT_PTR)*PtePointer);

View File

@ -61,11 +61,12 @@ BlEnablePaging(IN PLIST_ENTRY MemoryMappings,
IN PEFI_LOADED_IMAGE_PROTOCOL ImageProtocol, IN PEFI_LOADED_IMAGE_PROTOCOL ImageProtocol,
IN PVOID *PtePointer) IN PVOID *PtePointer)
{ {
UINT_PTR PhysicalAddress, MapKey, DescriptorSize, DescriptorCount; UINT_PTR PhysicalAddress, DescriptorCount;
EFI_PHYSICAL_ADDRESS Address, PDPTAddress = 0; EFI_PHYSICAL_ADDRESS Address, PDPTAddress = 0;
PEFI_MEMORY_DESCRIPTOR MemoryMap = NULL; PEFI_MEMORY_DESCRIPTOR Descriptor;
PLOADER_MEMORY_MAPPING Mapping; PLOADER_MEMORY_MAPPING Mapping;
PCPUID_REGISTERS CpuRegisters; PCPUID_REGISTERS CpuRegisters;
PEFI_MEMORY_MAP MemoryMap;
PLIST_ENTRY ListEntry; PLIST_ENTRY ListEntry;
BOOLEAN PaeExtension; BOOLEAN PaeExtension;
EFI_STATUS Status; EFI_STATUS Status;
@ -86,14 +87,22 @@ BlEnablePaging(IN PLIST_ENTRY MemoryMappings,
/* Store PAE status from the CPUID results */ /* Store PAE status from the CPUID results */
PaeExtension = CpuRegisters->Edx & CPUID_FEATURES_EDX_PAE; PaeExtension = CpuRegisters->Edx & CPUID_FEATURES_EDX_PAE;
/* Allocate and zero-fill buffer for EFI memory map */
BlEfiMemoryAllocatePool(sizeof(EFI_MEMORY_MAP), (PVOID*)&MemoryMap);
RtlZeroMemory(MemoryMap, sizeof(EFI_MEMORY_MAP));
/* Get EFI memory map */ /* Get EFI memory map */
Status = BlGetMemoryMap(&MemoryMap, &MapKey, &DescriptorSize, &DescriptorCount); Status = BlGetMemoryMap(MemoryMap);
if(Status != STATUS_EFI_SUCCESS) if(Status != STATUS_EFI_SUCCESS)
{ {
/* Unable to get memory map */ /* Unable to get memory map */
return Status; return Status;
} }
/* Calculate descriptors count and get first one */
Descriptor = MemoryMap->Map;
DescriptorCount = MemoryMap->MapSize / MemoryMap->DescriptorSize;
/* Check if PAE supported by the underlying hardware */ /* Check if PAE supported by the underlying hardware */
if(PaeExtension) if(PaeExtension)
{ {
@ -107,11 +116,11 @@ BlEnablePaging(IN PLIST_ENTRY MemoryMappings,
for(Index = 0; Index < DescriptorCount; Index++) for(Index = 0; Index < DescriptorCount; Index++)
{ {
/* Check descriptor if it can be used to store PDPT */ /* Check descriptor if it can be used to store PDPT */
if((MemoryMap->PhysicalStart + ((MemoryMap->NumberOfPages - 1) * EFI_PAGE_SIZE) >= PhysicalAddress) && if((Descriptor->PhysicalStart + ((Descriptor->NumberOfPages - 1) * EFI_PAGE_SIZE) >= PhysicalAddress) &&
(MemoryMap->Type == EfiConventionalMemory)) (Descriptor->Type == EfiConventionalMemory))
{ {
/* Use highest address possible */ /* Use highest address possible */
if(PhysicalAddress >= MemoryMap->PhysicalStart) if(PhysicalAddress >= Descriptor->PhysicalStart)
{ {
/* Use physical address */ /* Use physical address */
PDPTAddress = PhysicalAddress; PDPTAddress = PhysicalAddress;
@ -119,7 +128,7 @@ BlEnablePaging(IN PLIST_ENTRY MemoryMappings,
else else
{ {
/* Use descriptor physical start as PDPT address */ /* Use descriptor physical start as PDPT address */
PDPTAddress = MemoryMap->PhysicalStart; PDPTAddress = Descriptor->PhysicalStart;
} }
/* Allocate pages for the PDPT address */ /* Allocate pages for the PDPT address */
@ -131,7 +140,7 @@ BlEnablePaging(IN PLIST_ENTRY MemoryMappings,
} }
/* Get next descriptor */ /* Get next descriptor */
MemoryMap = (EFI_MEMORY_DESCRIPTOR*)((UINT8*)MemoryMap + DescriptorSize); Descriptor = (EFI_MEMORY_DESCRIPTOR*)((UINT8*)Descriptor + MemoryMap->DescriptorSize);
} }
/* Make sure PDPT address found */ /* Make sure PDPT address found */
@ -244,7 +253,7 @@ BlEnablePaging(IN PLIST_ENTRY MemoryMappings,
/* Exit EFI Boot Services */ /* Exit EFI Boot Services */
BlDbgPrint(L"Exiting EFI boot services\n"); BlDbgPrint(L"Exiting EFI boot services\n");
EfiSystemTable->BootServices->ExitBootServices(EfiImageHandle, MapKey); EfiSystemTable->BootServices->ExitBootServices(EfiImageHandle, MemoryMap->MapKey);
/* Enable PAE if supported by CPU */ /* Enable PAE if supported by CPU */
if(PaeExtension) if(PaeExtension)

View File

@ -20,7 +20,7 @@ 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_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_MAP MemoryMap);
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 BOOLEAN PaeExtension, 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);

View File

@ -110,10 +110,7 @@ BlFindVolumeDevicePath(IN PEFI_DEVICE_PATH_PROTOCOL FsHandle,
OUT PEFI_DEVICE_PATH_PROTOCOL* DevicePath); OUT PEFI_DEVICE_PATH_PROTOCOL* DevicePath);
EFI_STATUS EFI_STATUS
BlGetMemoryMap(OUT PEFI_MEMORY_DESCRIPTOR *MemoryMap, BlGetMemoryMap(OUT PEFI_MEMORY_MAP MemoryMap);
OUT PUINT_PTR MapKey,
OUT PUINT_PTR DescriptorSize,
OUT PUINT_PTR DescriptorCount);
VOID BlGetStackPointer(OUT PVOID *Stack); VOID BlGetStackPointer(OUT PVOID *Stack);

View File

@ -145,20 +145,23 @@ BlAddVirtualMemoryMapping(IN PLIST_ENTRY MemoryMappings,
if((Mapping2->PhysicalAddress >= Mapping1->PhysicalAddress && PhysicalAddress2End <= PhysicalAddressEnd) || if((Mapping2->PhysicalAddress >= Mapping1->PhysicalAddress && PhysicalAddress2End <= PhysicalAddressEnd) ||
(Mapping2->NumberOfPages == 0)) (Mapping2->NumberOfPages == 0))
{ {
/* If it is of LoaderFree type, then we can skip it */ /* Make sure it's memory type is LoaderFree */
if(Mapping2->MemoryType == LoaderFree) if(Mapping2->MemoryType != LoaderFree)
{ {
/* Store address of the next mapping */ /* LoaderFree memory type is strictly expected */
MappingListEntry = ListEntry->Flink; return STATUS_EFI_INVALID_PARAMETER;
/* Remove mapping from the list and free up it's memory */
RtlRemoveEntryList(&Mapping2->ListEntry);
BlEfiMemoryFreePool(Mapping2);
ListEntry = MappingListEntry;
/* Go to the next mapping */
continue;
} }
/* Store address of the next mapping */
MappingListEntry = ListEntry->Flink;
/* Remove mapping from the list and free up it's memory */
RtlRemoveEntryList(&Mapping2->ListEntry);
BlEfiMemoryFreePool(Mapping2);
ListEntry = MappingListEntry;
/* Go to the next mapping */
continue;
} }
/* Determine phsical address order */ /* Determine phsical address order */
@ -199,7 +202,6 @@ BlConvertEfiMemoryType(IN EFI_MEMORY_TYPE EfiMemoryType)
case EfiACPIMemoryNVS: case EfiACPIMemoryNVS:
case EfiACPIReclaimMemory: case EfiACPIReclaimMemory:
case EfiPalCode: case EfiPalCode:
case EfiReservedMemoryType:
MemoryType = LoaderSpecialMemory; MemoryType = LoaderSpecialMemory;
break; break;
case EfiRuntimeServicesCode: case EfiRuntimeServicesCode:
@ -208,6 +210,7 @@ BlConvertEfiMemoryType(IN EFI_MEMORY_TYPE EfiMemoryType)
case EfiMemoryMappedIOPortSpace: case EfiMemoryMappedIOPortSpace:
MemoryType = LoaderFirmwarePermanent; MemoryType = LoaderFirmwarePermanent;
break; break;
case EfiBootServicesData:
case EfiLoaderCode: case EfiLoaderCode:
MemoryType = LoaderFirmwareTemporary; MemoryType = LoaderFirmwareTemporary;
break; break;
@ -307,36 +310,29 @@ BlEfiMemoryFreePool(IN PVOID Memory)
* @param MemoryMap * @param MemoryMap
* Supplies a pointer to the buffer where memory map will be written. * Supplies a pointer to the buffer where memory map will be written.
* *
* @param MapKey
* Supplies a pointer where the firmware stores the map key.
*
* @param DescriptorSize
* Supplies a pointer where the size of EFI_MEMORY_DESCRIPTOR will be stored.
*
* @param DescriptorCount
* Supplies a pointer where number of written descriptors will be stored.
*
* @return This routine returns a status code. * @return This routine returns a status code.
* *
* @since XT 1.0 * @since XT 1.0
*/ */
EFI_STATUS EFI_STATUS
BlGetMemoryMap(OUT PEFI_MEMORY_DESCRIPTOR *MemoryMap, BlGetMemoryMap(OUT PEFI_MEMORY_MAP MemoryMap)
OUT PUINT_PTR MapKey,
OUT PUINT_PTR DescriptorSize,
OUT PUINT_PTR DescriptorCount)
{ {
PEFI_MEMORY_DESCRIPTOR LocalMemoryMap = NULL;
UINT_PTR MemoryMapSize = 0, LocalMapKey, LocalDescriptorSize;
UINT32 DescriptorVersion;
EFI_STATUS Status; EFI_STATUS Status;
if(MemoryMap == NULL)
{
return STATUS_EFI_INVALID_PARAMETER;
}
MemoryMap->Map = NULL;
MemoryMap->MapSize = 0;
/* Get memory map */ /* Get memory map */
do do
{ {
/* Attempt do get EFI memory map */ /* Attempt do get EFI memory map */
Status = EfiSystemTable->BootServices->GetMemoryMap(&MemoryMapSize, LocalMemoryMap, &LocalMapKey, Status = EfiSystemTable->BootServices->GetMemoryMap(&MemoryMap->MapSize, MemoryMap->Map, &MemoryMap->MapKey,
&LocalDescriptorSize, &DescriptorVersion); &MemoryMap->DescriptorSize, &MemoryMap->DescriptorVersion);
if(Status == STATUS_EFI_SUCCESS) if(Status == STATUS_EFI_SUCCESS)
{ {
/* Go further if succeeded */ /* Go further if succeeded */
@ -345,33 +341,27 @@ BlGetMemoryMap(OUT PEFI_MEMORY_DESCRIPTOR *MemoryMap,
else if(Status != STATUS_EFI_BUFFER_TOO_SMALL) else if(Status != STATUS_EFI_BUFFER_TOO_SMALL)
{ {
/* Some error occurred */ /* Some error occurred */
if(MemoryMap) if(MemoryMap->Map)
{ {
/* Free allocated memory */ /* Free allocated memory */
BlEfiMemoryFreePool(MemoryMap); BlEfiMemoryFreePool(MemoryMap->Map);
} }
return Status; return Status;
} }
/* Allocate the desired amount of memory */ /* Allocate the desired amount of memory */
MemoryMapSize += 2 * LocalDescriptorSize; MemoryMap->MapSize += 2 * MemoryMap->DescriptorSize;
BlEfiMemoryAllocatePool(MemoryMapSize, (PVOID *)&LocalMemoryMap); BlEfiMemoryAllocatePool(MemoryMap->MapSize, (PVOID *)&MemoryMap->Map);
} }
while(Status == STATUS_EFI_BUFFER_TOO_SMALL); while(Status == STATUS_EFI_BUFFER_TOO_SMALL);
/* Make sure memory map is set */ /* Make sure memory map is set */
if(LocalMemoryMap == NULL) if(MemoryMap->Map == NULL)
{ {
/* Something went wrong */ /* Something went wrong */
return STATUS_EFI_INVALID_PARAMETER; return STATUS_EFI_NO_MAPPING;
} }
/* Store memory map details */
*MemoryMap = LocalMemoryMap;
*MapKey = LocalMapKey;
*DescriptorSize = LocalDescriptorSize;
*DescriptorCount = MemoryMapSize / LocalDescriptorSize;
/* Return success */ /* Return success */
return STATUS_EFI_SUCCESS; return STATUS_EFI_SUCCESS;
} }
@ -393,9 +383,10 @@ EFI_STATUS
BlInitializeVirtualMemory(IN OUT PLIST_ENTRY MemoryMappings, BlInitializeVirtualMemory(IN OUT PLIST_ENTRY MemoryMappings,
IN OUT PVOID *MemoryMapAddress) IN OUT PVOID *MemoryMapAddress)
{ {
UINT_PTR MapKey, DescriptorSize, DescriptorCount; PEFI_MEMORY_DESCRIPTOR Descriptor;
PEFI_MEMORY_DESCRIPTOR MemoryMap = NULL;
LOADER_MEMORY_TYPE MemoryType; LOADER_MEMORY_TYPE MemoryType;
PEFI_MEMORY_MAP MemoryMap;
SIZE_T DescriptorCount;
PUCHAR VirtualAddress; PUCHAR VirtualAddress;
EFI_STATUS Status; EFI_STATUS Status;
SIZE_T Index; SIZE_T Index;
@ -403,45 +394,51 @@ BlInitializeVirtualMemory(IN OUT PLIST_ENTRY MemoryMappings,
/* Set initial virtual address */ /* Set initial virtual address */
VirtualAddress = *MemoryMapAddress; VirtualAddress = *MemoryMapAddress;
/* Get memory map */ /* Allocate and zero-fill buffer for EFI memory map */
Status = BlGetMemoryMap(&MemoryMap, &MapKey, &DescriptorSize, &DescriptorCount); BlEfiMemoryAllocatePool(sizeof(EFI_MEMORY_MAP), (PVOID*)&MemoryMap);
RtlZeroMemory(MemoryMap, sizeof(EFI_MEMORY_MAP));
/* Get EFI memory map */
Status = BlGetMemoryMap(MemoryMap);
if(Status != STATUS_EFI_SUCCESS) if(Status != STATUS_EFI_SUCCESS)
{ {
return Status; return Status;
} }
/* Iterate through all descriptors from memory map */ /* 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++) for(Index = 0; Index < DescriptorCount; Index++)
{ {
/* Make sure descriptor does not go beyond lowest physical page */ /* Make sure descriptor does not go beyond lowest physical page */
if((MemoryMap->PhysicalStart + (MemoryMap->NumberOfPages * EFI_PAGE_SIZE)) <= (UINT_PTR)-1) if((Descriptor->PhysicalStart + (Descriptor->NumberOfPages * EFI_PAGE_SIZE)) <= (UINT_PTR)-1)
{ {
/* Convert EFI memory type into XTOS memory type */ /* Convert EFI memory type into XTOS memory type */
MemoryType = BlConvertEfiMemoryType(MemoryMap->Type); MemoryType = BlConvertEfiMemoryType(Descriptor->Type);
/* Do memory mappings depending on memory type */ /* Do memory mappings depending on memory type */
if(MemoryType == LoaderFirmwareTemporary) if(MemoryType == LoaderFirmwareTemporary)
{ {
/* Map EFI firmware code */ /* Map EFI firmware code */
Status = BlAddVirtualMemoryMapping(MemoryMappings, (PVOID)MemoryMap->PhysicalStart, Status = BlAddVirtualMemoryMapping(MemoryMappings, (PVOID)Descriptor->PhysicalStart,
(PVOID)MemoryMap->PhysicalStart, MemoryMap->NumberOfPages, MemoryType); (PVOID)Descriptor->PhysicalStart, Descriptor->NumberOfPages, MemoryType);
} }
else if(MemoryType != LoaderFree) else if(MemoryType != LoaderFree)
{ {
/* Add any non-free memory mapping */ /* Add any non-free memory mapping */
Status = BlAddVirtualMemoryMapping(MemoryMappings, VirtualAddress, Status = BlAddVirtualMemoryMapping(MemoryMappings, VirtualAddress,
(PVOID)MemoryMap->PhysicalStart, MemoryMap->NumberOfPages, MemoryType); (PVOID)Descriptor->PhysicalStart, Descriptor->NumberOfPages, MemoryType);
/* Calculate next valid virtual address */ /* Calculate next valid virtual address */
VirtualAddress += MemoryMap->NumberOfPages * EFI_PAGE_SIZE; VirtualAddress += Descriptor->NumberOfPages * EFI_PAGE_SIZE;
} }
else else
{ {
/* Map all other memory as loader free */ /* Map all other memory as loader free */
Status = BlAddVirtualMemoryMapping(MemoryMappings, NULL, (PVOID)MemoryMap->PhysicalStart, Status = BlAddVirtualMemoryMapping(MemoryMappings, NULL, (PVOID)Descriptor->PhysicalStart,
MemoryMap->NumberOfPages, LoaderFree); Descriptor->NumberOfPages, LoaderFree);
} }
/* Make sure memory mapping succeeded */ /* Make sure memory mapping succeeded */
@ -452,7 +449,7 @@ BlInitializeVirtualMemory(IN OUT PLIST_ENTRY MemoryMappings,
} }
/* Grab next descriptor */ /* Grab next descriptor */
MemoryMap = (PEFI_MEMORY_DESCRIPTOR)((PUCHAR)MemoryMap + DescriptorSize); Descriptor = (PEFI_MEMORY_DESCRIPTOR)((PUCHAR)Descriptor + MemoryMap->DescriptorSize);
} }
} }