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 withEFI_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
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.
Comments
Explore related questions
See similar questions with these tags.