Page 1 of 1

Why does UEFI GetMemoryMap return EFI_BUFFER_TOO_SMALL after allocating a buffer of the reported size?

Posted: Sat Jul 12, 2025 2:20 pm
by OrdChaosXQ
I've asked this question on stackoverflow.

url: https://stackoverflow.com/questions/796 ... g-a-buffer

I'm writing a UEFI application in Zig.

I'm calling GetMemoryMap() twice: once to get the required buffer size, then again after allocating the buffer using AllocatePool().

Here's my code:

Code: Select all

fn getMemoryMap() uefi.Status {
    const log = std.log.scoped(.memory_map);
    const system_table = uefi.system_table;
    const boot_services = system_table.boot_services.?;
    var status: uefi.Status = undefined;

    var mmap_size: usize = 0;
    var mmap: ?[*]uefi.tables.MemoryDescriptor = null;
    var map_key: usize = undefined;
    var descriptor_size: usize = undefined;
    var descriptor_version: u32 = undefined;

    status = boot_services.getMemoryMap(&mmap_size, mmap, &map_key, &descriptor_size, &descriptor_version);
    switch (status) {
        .buffer_too_small => log.debug("Buffer too small, need {d} bytes for buffer", .{mmap_size}),
        else => {
            log.err("Excepted buffer_too_small but got {s} instead", .{@tagName(status)});
            return status;
        },
    }
    //mmap_size += descriptor_size * 2;

    status = boot_services.allocatePool(.loader_data, mmap_size, @ptrCast(&mmap));
    switch (status) {
        .success => log.debug("Allocated {d} bytes for memory map at {*}", .{ mmap_size, mmap }),
        else => {
            log.err("Excepted success but got {s} instead", .{@tagName(status)});
            return status;
        },
    }

    status = boot_services.getMemoryMap(&mmap_size, mmap, &map_key, &descriptor_size, &descriptor_version);
    switch (status) {
        .success => log.debug("Got memory map", .{}),
        else => {
            log.err("Excepted success but got {s} instead", .{@tagName(status)});
            return status;
        },
    }

    return uefi.Status.success;
}
The problem:
The second call to getMemoryMap() fails with EFI_BUFFER_TOO_SMALL, even though I allocated the exact size reported in the first call.
log:

Code: Select all

[debug(memory_map)]Buffer too small, need 5856 bytes for buffer
[debug(memory_map)]Allocated 5856 bytes for memory map at [*]os.uefi.tables.MemoryDescriptor@2808018
[error(memory_map)]Excepted success but got buffer_too_small instead
And if I add mmap_size += descriptor_size * 2; before the 2nd call, it can run.

Is this normal? I can't find any examples of this, sorry.

Re: Why does UEFI GetMemoryMap return EFI_BUFFER_TOO_SMALL after allocating a buffer of the reported size?

Posted: Sat Jul 12, 2025 3:47 pm
by iansjack
If you read the documentation for the function it says that the buffer allocated should be larger than the required size indicated by the first call. This is because the memory allocation will have altered the map.

Re: Why does UEFI GetMemoryMap return EFI_BUFFER_TOO_SMALL after allocating a buffer of the reported size?

Posted: Sat Jul 12, 2025 5:17 pm
by OrdChaosXQ
iansjack wrote: Sat Jul 12, 2025 3:47 pm If you read the documentation for the function it says that the buffer allocated should be larger than the required size indicated by the first call. This is because the memory allocation will have altered the map.
OH WELL, THANKS.

I found that in the doc.

I had questioned about that because I can't find some examples which really request for more memory.