I'm writing a little boot loader in UEFI environment for my custom os using POSIX-UEFI.
When trying to get the memory map using GetMemoryMap boot service to calculate the amount of memory, it returns not only a different number of memory descriptors each time the program is executed, but the descriptor table itself seems to be corrupted or something...
Here's the code to get the memory map:
efi_memory_descriptor_t *map = NULL;
uintn_t mapsize, mapkey, descriptorsize;
uint32_t descriptorversion;
uint64_t memory_size = 0;
ST->BootServices->GetMemoryMap(&mapsize, map, &mapkey, &descriptorsize, &descriptorversion);
ST->BootServices->AllocatePool(EfiLoaderData, mapsize, (void **) &map);
ST->BootServices->GetMemoryMap(&mapsize, map, &mapkey, &descriptorsize, &descriptorversion);
printf("Memory map size: %d descriptors\n", mapsize / descriptorsize);
for (int i = 0; i < mapsize / descriptorsize; i++) {
efi_memory_descriptor_t *desc = (efi_memory_descriptor_t *)(map + i * descriptorsize);
memory_size += desc->NumberOfPages * EFI_PAGE_SIZE;
}
printf("Memory size: %d bytes\n", memory_size);
I tried using sizeof(efi_memory_descriptor_t)
too instead of descriptorsize to calculate the number of entries but nothing changes.
Here's a screenshot of the program's output: VirtualBox with an efi shell running 3 times the code above
I use a VirtualBox (v7.0.4) virtual machine with 64MB ram size, no storage device, and a usb drive attached to load the program from.
map
is a pointer to efi_memory_descriptor_t, so map + i * descriptorsize
is scaling by both descriptorsize and sizeof (efi_memory_descriptor_t).
I suggest using (uint8_t *)map + i * descriptorsize
.
Note, descriptorsize may not be equal to sizeof (efi_memory_descriptor_t), so it is correct to use descriptorsize.