I'm writing a small UEFI x86_64 os. After getting a memory map and exiting boot services, I print the memory map and notice that all entries map a certain physical address to the virtual address 0. Here is a screenshot of the first entries in the memory map: This is the structure I use for the memory descriptor:
#[repr(C)]
#[derive(Clone, Copy)]
pub struct MemoryDescriptor {
pub t: MemoryType,
pub physical_start: *const c_void,
pub virtual_start: *const c_void,
pub number_of_pages: u64,
pub attribute: u64,
}
#[repr(u32)]
#[derive(Clone, Copy, Debug)]
pub enum MemoryType {
ReservedMemoryType = 0,
LoaderCode,
LoaderData,
BootServicesCode,
BootServicesData,
RuntimeServicesCode,
RuntimeServicesData,
ConventionalMemory,
UnusableMemory,
ACPIReclaimMemory,
ACPIMemoryNVS,
MemoryMappedIO,
MemoryMappedIOPortSpace,
PalCode,
PersistentMemory,
UnacceptedMemoryType,
MaxMemoryType,
}
I checked that I iterate correctly through the memory map (incrementing the memory map pointer by the descriptor size provided by the GetMemoryMap function and not the size of the descriptor struct) but still can't make sense of it. The UEFI spec says that it identity maps all memory, but doesn't that mean that I should see all physical addresses be equal to the virtual addresses in the memory map? Or am I missing something? This seems to be happening both in QEMU and on real hardware (Surface pro 8). I also tried taking a look at the page tables (through the address in CR3), though I think I have done something wrong (or the pages aren't mapped correctly), because only the first entry of the level 4 table seems to be present and it points a level 3 page with no present entries.
Apparently the virtual addresses in the memory map you get before exiting boot services are just place holders. You have to manually set them to be identity mapped and then call the SetMemoryMap function for them to be updated (after exiting boot services). This solved the issue for me