2

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:

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:

[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.

1 Answer 1

3

This error case is described in the UEFI specification at the description of GetMemoryMap:

The actual size of the buffer allocated for the consequent call to GetMemoryMap() should be bigger then the value returned in MemoryMapSize, since allocation of the new buffer may potentially increase memory map size.

Likely your call to AllocatePool has created a new entry in the memory map.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.