UEFI GetMemoryMap success with odd results
Posted: Mon May 21, 2018 11:56 pm
Hi. I've been working on a UEFI bootloader and have been having some issues with the memory map. I'm sure its just a stupid error on my part but I'd gone over this several times and would appreciate if someone might be able to point out what I'm doing wrong.
Here's the relevant code:
It succeeds with no errors but the memory map 'seems' to contain random data. At least, that's what I assume for a few reasons.
For one, the UEFI spec states that the EFI_MEMORY_DESCRIPTOR.PhysicalStart will be 4KiB aligned - I get values of 0, 7, 0, 1857182, - you get the idea.
Same situation for the VirtualStart field. I assumed since the paging is identity-mapped, the VirtualStart would either be equal to the PhysicalStart or 0. But it appears to be random.
Finally, the thing that struck me as most odd was that the EFI_MEMORY_DESCRIPTOR.Type values are large. The Type value is from an the EFI_MEMORY_TYPE enum with only a handful of values, yet I'm getting extremely high values for this field.
Again, I'm probably missing something simple, in which case I'm sorry for wasting anyone's time, but I've pored over this as well as the spec and I can't seem to find the problem.
Maybe my assumptions as the specified values are wrong? Either way, thanks.
Here's the relevant code:
It succeeds with no errors but the memory map 'seems' to contain random data. At least, that's what I assume for a few reasons.
For one, the UEFI spec states that the EFI_MEMORY_DESCRIPTOR.PhysicalStart will be 4KiB aligned - I get values of 0, 7, 0, 1857182, - you get the idea.
Same situation for the VirtualStart field. I assumed since the paging is identity-mapped, the VirtualStart would either be equal to the PhysicalStart or 0. But it appears to be random.
Finally, the thing that struck me as most odd was that the EFI_MEMORY_DESCRIPTOR.Type values are large. The Type value is from an the EFI_MEMORY_TYPE enum with only a handful of values, yet I'm getting extremely high values for this field.
Again, I'm probably missing something simple, in which case I'm sorry for wasting anyone's time, but I've pored over this as well as the spec and I can't seem to find the problem.
Maybe my assumptions as the specified values are wrong? Either way, thanks.
Code: Select all
EFI_STATUS
EFIAPI
efi_main (EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE *SystemTable) {
InitializeLib(ImageHandle, SystemTable);
EFI_STATUS status = EFI_SUCCESS;
EFI_MEMORY_DESCRIPTOR *memory_map = NULL;
UINT32 version = 0;
UINTN map_key = 0;
UINTN descriptor_size = 0;
UINTN memory_map_size = 0;
uefi_call_wrapper(ST->ConOut->ClearScreen, 1, ST->ConOut);
status = uefi_call_wrapper(BS->GetMemoryMap, 5, &memory_map_size, memory_map, &map_key, &descriptor_size, &version);
// descriptor size and version should be correct values. memory_map_size should be needed size.
if (status == EFI_BUFFER_TOO_SMALL) {
UINTN encompassing_size = memory_map_size + (2 * descriptor_size);
void *buffer = NULL;
status = uefi_call_wrapper(BS->AllocatePool, 3, EfiLoaderData, encompassing_size, &buffer);
if (status == EFI_SUCCESS) {
memory_map = (EFI_MEMORY_DESCRIPTOR*) buffer;
memory_map_size = encompassing_size;
status = uefi_call_wrapper(BS->GetMemoryMap, 5, &memory_map_size, memory_map, &map_key, &descriptor_size, &version);
if (status != EFI_SUCCESS) {
Print(L"Second call to GetMemoryMap failed for some reason.");
} else {
Print(L"Second call to GetMemoryMap succeeded.\n");
for (int i = 0; i < (memory_map_size / descriptor_size); ++i) {
Print(L"Physical Address of i-th memory descriptor:\t%x\n", memory_map[i].PhysicalStart);
Print(L"Virtual Address of i-th memory descriptor:\t%x\n", memory_map[i].VirtualStart);
Print(L"Memory Type of i-th memory descriptor:\t%d\n", memory_map[i].Type);
uefi_call_wrapper(BS->Stall, 1, 4000000);
}
}
} else {
Print(L"AllocatePool failure.");
}
} else if (status == EFI_SUCCESS) { // shouldn't happen.
Print(L"First call to GetMemoryMap should never succeed... ???");
} else {
Print(L"(First) GetMemoryMap usage failure.");
}
return EFI_SUCCESS;
}