EFI GetMemoryMap returning strange results

Question about which tools to use, bugs, the best way to implement a function, etc should go here. Don't forget to see if your question is answered in the wiki first! When in doubt post here.
Post Reply
Beachhouse13
Posts: 1
Joined: Sat Jan 11, 2025 10:10 pm
Libera.chat IRC: Beachhouse13

EFI GetMemoryMap returning strange results

Post by Beachhouse13 »

Hello OS devs. I am having an issue getting the memory map from EFI. Some of the background info, my OS uses multiboot2, which uses the MULTIBOOT_HEADER_TAG_EFI_BS and MULTIBOOT_HEADER_TAG_ENTRY_ADDRESS_EFI64 tags to use EFI and is already in 64-bit mode when my code starts. I have been able to get the EFI_BOOT_SERVICES table from multiboot2 through the MULTIBOOT_TAG_TYPE_EFI64 tag. I wrote a function to output the header of the boot services table and the results are as expected:
Boot Services Signature: 0x56524553544F4F42
Boot Services Revision: 0x0000000000020046
Boot Services Header Size: 0x0000000000000178

The revision is a little suspect with the 6, as I do not believe this is per the EFI specs, but could be an emulator specific variation.

Here is the code that use to get the memory:

Code: Select all

        EFI_SYSTEM_TABLE *efi_system_table = (EFI_SYSTEM_TABLE *)efi64_tag->pointer;
        EFI_BOOT_SERVICES *boot_services = (EFI_BOOT_SERVICES *)efi_system_table->BootServices;
        inspect_boot_services(efi_system_table);

        uint8_t memory_map[4096];
        EFI_MEMORY_MAP_INFO mmap_info = {
          .MemoryMapSize = 0,
          .MapKey = 0,
          .DescriptorSize = 0,
          .DescriptorVersion = 0
        };

        size_t mmap_num = 0;

        // call GetMeoryMap once. EFI will populate errorous values with correct ones.
        EFI_STATUS status = boot_services->GetMemoryMap(
            &mmap_info.MemoryMapSize,
            (EFI_MEMORY_DESCRIPTOR *)memory_map,
            &mmap_info.MapKey,
            &mmap_info.DescriptorSize,
            &mmap_info.DescriptorVersion);
As expected, the GetMemoryMap returns EFI_BUFFER_TOO_SMALL and populates the .MemoryMapSize value. But this comes out to be 0x107FDC, which is way to large. In addition the descriptor size is changed to 0x1470, and the descriptor version is changed to 0x55D. These are way off as well. And it doesn’t matter if I put in the expected descriptor size of 0x24, and version of 0x1, it will still change the values.

To make maters worse, if I try to rung GetMemoryMap again, even with a fresh set of data, the CPU will crash (but that’s an issue for another day).

After much debugging, I feel it comes down to some little thing that I am doing wrong in my code, or a problem with emulation. I am using QEMU version 8.1.0 and windows 10.0.19045.5247.

Here is my code for my EFI tables which may have the issue:

Code: Select all

typedef uint64_t EFI_STATUS;
typedef struct
{
    uint64_t Signature;
    uint32_t Revision;
    uint32_t HeaderSize;
    uint32_t CRC32;
    uint32_t Reserved;
} EFI_TABLE_HEADER;
typedef struct
{
    // Table Header
    EFI_TABLE_HEADER Hdr;

    // Task Priority Services
    void *RaiseTPL;
    void *RestoreTPL;

    // Memory Services
    EFI_STATUS (*AllocatePages)
    (uint32_t Type, uint32_t MemoryType, uint64_t Pages, uint64_t *Memory);
    EFI_STATUS (*FreePages)
    (uint64_t Memory, uint64_t Pages);
    EFI_STATUS (*GetMemoryMap)
    (
        uint64_t *MemoryMapSize,
        void *MemoryMap,
        uint64_t *MapKey,
        uint64_t *DescriptorSize,
        uint32_t *DescriptorVersion);
    EFI_STATUS (*AllocatePool)
    (uint32_t PoolType, uint64_t Size, void **Buffer);
    EFI_STATUS (*FreePool)
    (void *Buffer);
    …
} EFI_BOOT_SERVICES;
Any help finding where my error is would be greatly appreciated.
User avatar
zaval
Member
Member
Posts: 660
Joined: Fri Feb 17, 2017 4:01 pm
Location: Ukraine, Bachmut
Contact:

Re: EFI GetMemoryMap returning strange results

Post by zaval »

in your definitions, you use uint64_t where the UEFI specification uses UINTN. they are of the same size only in 64 bits, this is already what you should change in your definitions. next, instead of using that EFI_MEMORY_MAP_INFO thing, what is this, just use local stack variables of the required type. finally, use AllocatePages() for the memory map buffer after you got the map size, not this lame byte buffer of page size. btw, memory map will be often bigger, than that. The cause of this issue is most probably type mismatch in that map info structure.
ANT - NT-like OS for x64 and arm64.
efify - UEFI for a couple of boards (mips and arm). suspended due to lost of all the target park boards (russians destroyed our town).
Octocontrabass
Member
Member
Posts: 5623
Joined: Mon Mar 25, 2013 7:01 pm

Re: EFI GetMemoryMap returning strange results

Post by Octocontrabass »

Beachhouse13 wrote: Sun Jan 12, 2025 3:27 pmHere is my code for my EFI tables which may have the issue:
You forgot EFIAPI. Or are you passing options to make your compiler follow the Microsoft x64 ABI everywhere?
Post Reply