zig/lib/std/os/uefi/pool_allocator.zig
Carmen 5b4e982169
std.os.uefi.tables: ziggify boot and runtime services (#23441)
* std.os.uefi.tables: ziggify boot and runtime services

* avoid T{} syntax

Co-authored-by: linusg <mail@linusgroh.de>

* misc fixes

* work

* self-review quickfixes

* dont make MemoryMapSlice generic

* more review fixes, work

* more work

* more work

* review fixes

* update boot/runtime services references throughout codebase

* self-review fixes

* couple of fixes i forgot to commit earlier

* fixes from integrating in my own project

* fixes from refAllDeclsRecursive

* Apply suggestions from code review

Co-authored-by: truemedian <truemedian@gmail.com>

* more fixes from review

* fixes from project integration

* make natural alignment of Guid align-8

* EventRegistration is a new opaque type

* fix getNextHighMonotonicCount

* fix locateProtocol

* fix exit

* partly revert 7372d65

* oops exit data_len is num of bytes

* fixes from project integration

* MapInfo consistency, MemoryType update per review

* turn EventRegistration back into a pointer

* forgot to finish updating MemoryType methods

* fix IntFittingRange calls

* set uefi.Page nat alignment

* Back out "set uefi.Page nat alignment"

This backs out commit cdd9bd6f7f5fb763f994b8fbe3e1a1c2996a2393.

* get rid of some error.NotFound-s

* fix .exit call in panic

* review comments, add format method

* fix resetSystem data alignment

* oops, didnt do a final refAllDeclsRecursive i guess

* review comments

* writergate update MemoryType.format

* fix rename

---------

Co-authored-by: linusg <mail@linusgroh.de>
Co-authored-by: truemedian <truemedian@gmail.com>
2025-07-12 17:18:53 +00:00

169 lines
3.8 KiB
Zig

const std = @import("std");
const mem = std.mem;
const uefi = std.os.uefi;
const assert = std.debug.assert;
const Allocator = mem.Allocator;
const UefiPoolAllocator = struct {
fn getHeader(ptr: [*]u8) *[*]align(8) u8 {
return @as(*[*]align(8) u8, @ptrFromInt(@intFromPtr(ptr) - @sizeOf(usize)));
}
fn alloc(
_: *anyopaque,
len: usize,
alignment: mem.Alignment,
ret_addr: usize,
) ?[*]u8 {
_ = ret_addr;
assert(len > 0);
const ptr_align = alignment.toByteUnits();
const metadata_len = mem.alignForward(usize, @sizeOf(usize), ptr_align);
const full_len = metadata_len + len;
const unaligned_slice = uefi.system_table.boot_services.?.allocatePool(
uefi.efi_pool_memory_type,
full_len,
) catch return null;
const unaligned_addr = @intFromPtr(unaligned_slice.ptr);
const aligned_addr = mem.alignForward(usize, unaligned_addr + @sizeOf(usize), ptr_align);
const aligned_ptr = unaligned_slice.ptr + (aligned_addr - unaligned_addr);
getHeader(aligned_ptr).* = unaligned_slice.ptr;
return aligned_ptr;
}
fn resize(
_: *anyopaque,
buf: []u8,
alignment: mem.Alignment,
new_len: usize,
ret_addr: usize,
) bool {
_ = ret_addr;
_ = alignment;
if (new_len > buf.len) return false;
return true;
}
fn remap(
_: *anyopaque,
buf: []u8,
alignment: mem.Alignment,
new_len: usize,
ret_addr: usize,
) ?[*]u8 {
_ = alignment;
_ = ret_addr;
if (new_len > buf.len) return null;
return buf.ptr;
}
fn free(
_: *anyopaque,
buf: []u8,
alignment: mem.Alignment,
ret_addr: usize,
) void {
_ = alignment;
_ = ret_addr;
uefi.system_table.boot_services.?.freePool(getHeader(buf.ptr).*) catch unreachable;
}
};
/// Supports the full Allocator interface, including alignment.
/// For a direct call of `allocatePool`, see `raw_pool_allocator`.
pub const pool_allocator = Allocator{
.ptr = undefined,
.vtable = &pool_allocator_vtable,
};
const pool_allocator_vtable = Allocator.VTable{
.alloc = UefiPoolAllocator.alloc,
.resize = UefiPoolAllocator.resize,
.remap = UefiPoolAllocator.remap,
.free = UefiPoolAllocator.free,
};
/// Asserts allocations are 8 byte aligned and calls `boot_services.allocatePool`.
pub const raw_pool_allocator = Allocator{
.ptr = undefined,
.vtable = &raw_pool_allocator_table,
};
const raw_pool_allocator_table = Allocator.VTable{
.alloc = uefi_alloc,
.resize = uefi_resize,
.remap = uefi_remap,
.free = uefi_free,
};
fn uefi_alloc(
_: *anyopaque,
len: usize,
alignment: mem.Alignment,
ret_addr: usize,
) ?[*]u8 {
_ = ret_addr;
std.debug.assert(@intFromEnum(alignment) <= 3);
const slice = uefi.system_table.boot_services.?.allocatePool(
uefi.efi_pool_memory_type,
len,
) catch return null;
return slice.ptr;
}
fn uefi_resize(
_: *anyopaque,
buf: []u8,
alignment: mem.Alignment,
new_len: usize,
ret_addr: usize,
) bool {
_ = ret_addr;
std.debug.assert(@intFromEnum(alignment) <= 3);
if (new_len > buf.len) return false;
return true;
}
fn uefi_remap(
_: *anyopaque,
buf: []u8,
alignment: mem.Alignment,
new_len: usize,
ret_addr: usize,
) ?[*]u8 {
_ = ret_addr;
std.debug.assert(@intFromEnum(alignment) <= 3);
if (new_len > buf.len) return null;
return buf.ptr;
}
fn uefi_free(
_: *anyopaque,
buf: []u8,
alignment: mem.Alignment,
ret_addr: usize,
) void {
_ = alignment;
_ = ret_addr;
uefi.system_table.boot_services.?.freePool(@alignCast(buf.ptr)) catch unreachable;
}