UEFI pool allocator changes

* Changed the interface to align with the new allocator interface.
* Fixed bug where not enough memory was allocated for the header or to
  align the pointer.
This commit is contained in:
antlilja 2023-01-11 22:51:47 +01:00 committed by Andrew Kelley
parent 2a92b04b9d
commit 4971df8572

View File

@ -12,14 +12,27 @@ const UefiPoolAllocator = struct {
return @intToPtr(*[*]align(8) u8, @ptrToInt(ptr) - @sizeOf(usize)); return @intToPtr(*[*]align(8) u8, @ptrToInt(ptr) - @sizeOf(usize));
} }
fn alignedAlloc(len: usize, alignment: usize) ?[*]u8 { fn alloc(
var unaligned_ptr: [*]align(8) u8 = undefined; _: *anyopaque,
len: usize,
log2_ptr_align: u8,
ret_addr: usize,
) ?[*]u8 {
_ = ret_addr;
if (uefi.system_table.boot_services.?.allocatePool(uefi.efi_pool_memory_type, len, &unaligned_ptr) != .Success) assert(len > 0);
return null;
const ptr_align = 1 << log2_ptr_align;
const metadata_len = mem.alignForward(@sizeOf(usize), ptr_align);
const full_len = metadata_len + len;
var unaligned_ptr: [*]align(8) u8 = undefined;
if (uefi.system_table.boot_services.?.allocatePool(uefi.efi_pool_memory_type, full_len, &unaligned_ptr) != .Success) return null;
const unaligned_addr = @ptrToInt(unaligned_ptr); const unaligned_addr = @ptrToInt(unaligned_ptr);
const aligned_addr = mem.alignForward(unaligned_addr + @sizeOf(usize), alignment); const aligned_addr = mem.alignForward(unaligned_addr + @sizeOf(usize), ptr_align);
var aligned_ptr = unaligned_ptr + (aligned_addr - unaligned_addr); var aligned_ptr = unaligned_ptr + (aligned_addr - unaligned_addr);
getHeader(aligned_ptr).* = unaligned_ptr; getHeader(aligned_ptr).* = unaligned_ptr;
@ -27,53 +40,31 @@ const UefiPoolAllocator = struct {
return aligned_ptr; return aligned_ptr;
} }
fn alignedFree(ptr: [*]u8) void {
_ = uefi.system_table.boot_services.?.freePool(getHeader(ptr).*);
}
fn alloc(
_: *anyopaque,
len: usize,
ptr_align: u29,
len_align: u29,
ret_addr: usize,
) Allocator.Error![]u8 {
_ = ret_addr;
assert(len > 0);
assert(std.math.isPowerOfTwo(ptr_align));
var ptr = alignedAlloc(len, ptr_align) orelse return error.OutOfMemory;
if (len_align == 0)
return ptr[0..len];
return ptr[0..mem.alignBackwardAnyAlign(len, len_align)];
}
fn resize( fn resize(
_: *anyopaque, _: *anyopaque,
buf: []u8, buf: []u8,
buf_align: u29, log2_old_ptr_align: u8,
new_len: usize, new_len: usize,
len_align: u29,
ret_addr: usize, ret_addr: usize,
) ?usize { ) bool {
_ = buf_align;
_ = ret_addr; _ = ret_addr;
return if (new_len <= buf.len) mem.alignAllocLen(buf.len, new_len, len_align) else null; if (new_len > buf.len) return false;
_ = mem.alignAllocLen(buf.len, new_len, log2_old_ptr_align);
return true;
} }
fn free( fn free(
_: *anyopaque, _: *anyopaque,
buf: []u8, buf: []u8,
buf_align: u29, log2_old_ptr_align: u8,
ret_addr: usize, ret_addr: usize,
) void { ) void {
_ = buf_align; _ = log2_old_ptr_align;
_ = ret_addr; _ = ret_addr;
alignedFree(buf.ptr); _ = uefi.system_table.boot_services.?.freePool(getHeader(buf.ptr).*);
} }
}; };
@ -105,49 +96,44 @@ const raw_pool_allocator_table = Allocator.VTable{
fn uefi_alloc( fn uefi_alloc(
_: *anyopaque, _: *anyopaque,
len: usize, len: usize,
ptr_align: u29, log2_ptr_align: u8,
len_align: u29,
ret_addr: usize, ret_addr: usize,
) Allocator.Error![]u8 { ) ?[*]u8 {
_ = len_align;
_ = ret_addr; _ = ret_addr;
std.debug.assert(ptr_align <= 8); std.debug.assert(log2_ptr_align <= 3);
var ptr: [*]align(8) u8 = undefined; var ptr: [*]align(8) u8 = undefined;
if (uefi.system_table.boot_services.?.allocatePool(uefi.efi_pool_memory_type, len, &ptr) != .Success) return null;
if (uefi.system_table.boot_services.?.allocatePool(uefi.efi_pool_memory_type, len, &ptr) != .Success) { return ptr;
return error.OutOfMemory;
}
return ptr[0..len];
} }
fn uefi_resize( fn uefi_resize(
_: *anyopaque, _: *anyopaque,
buf: []u8, buf: []u8,
old_align: u29, log2_old_ptr_align: u8,
new_len: usize, new_len: usize,
len_align: u29,
ret_addr: usize, ret_addr: usize,
) ?usize { ) bool {
_ = old_align;
_ = ret_addr; _ = ret_addr;
if (new_len <= buf.len) { std.debug.assert(log2_old_ptr_align <= 3);
return mem.alignAllocLen(buf.len, new_len, len_align);
}
return null; if (new_len > buf.len) return false;
_ = mem.alignAllocLen(buf.len, new_len, 8);
return true;
} }
fn uefi_free( fn uefi_free(
_: *anyopaque, _: *anyopaque,
buf: []u8, buf: []u8,
buf_align: u29, log2_old_ptr_align: u8,
ret_addr: usize, ret_addr: usize,
) void { ) void {
_ = buf_align; _ = log2_old_ptr_align;
_ = ret_addr; _ = ret_addr;
_ = uefi.system_table.boot_services.?.freePool(@alignCast(8, buf.ptr)); _ = uefi.system_table.boot_services.?.freePool(@alignCast(8, buf.ptr));
} }