authorgravatar for ybham6@gmail.comfifty-six <ybham6@gmail.com> 2022-01-11 03:59:48-05:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2022-01-11 10:49:40-07:00
logb65a88416974e697f1cf2402ca7550f6225f8d39
treefccf0e67d437c588a99ad1caf11b04ae0d7791ae
parentc78a108d10838d67064e63bf7cb8b9128239a36c

std/os/uefi: Add pool_allocator and raw_pool_allocator


2 files changed, 160 insertions(+), 0 deletions(-)

lib/std/os/uefi.zig+7
......@@ -7,6 +7,13 @@ pub const protocols = @import("uefi/protocols.zig");
77pub const Status = @import("uefi/status.zig").Status;
88pub const tables = @import("uefi/tables.zig");
99
10/// The memory type to allocate when using the pool
11/// Defaults to .LoaderData, the default data allocation type
12/// used by UEFI applications to allocate pool memory.
13pub var efi_pool_memory_type: tables.MemoryType = .LoaderData;
14pub const pool_allocator = @import("uefi/pool_allocator.zig").pool_allocator;
15pub const raw_pool_allocator = @import("uefi/pool_allocator.zig").raw_pool_allocator;
16
1017/// The EFI image's handle that is passed to its entry point.
1118pub var handle: Handle = undefined;
1219
lib/std/os/uefi/pool_allocator.zig created+153
......@@ -0,0 +1,153 @@
1const std = @import("std");
2
3const mem = std.mem;
4const uefi = std.os.uefi;
5
6const assert = std.debug.assert;
7
8const Allocator = mem.Allocator;
9
10const UefiPoolAllocator = struct {
11 fn getHeader(ptr: [*]u8) *[*]align(8) u8 {
12 return @intToPtr(*[*]align(8) u8, @ptrToInt(ptr) - @sizeOf(usize));
13 }
14
15 fn alignedAlloc(len: usize, alignment: usize) ?[*]u8 {
16 var unaligned_ptr: [*]align(8) u8 = undefined;
17
18 if (uefi.system_table.boot_services.?.allocatePool(uefi.efi_pool_memory_type, len, &unaligned_ptr) != .Success)
19 return null;
20
21 const unaligned_addr = @ptrToInt(unaligned_ptr);
22 const aligned_addr = mem.alignForward(unaligned_addr + @sizeOf(usize), alignment);
23
24 var aligned_ptr = unaligned_ptr + (aligned_addr - unaligned_addr);
25 getHeader(aligned_ptr).* = unaligned_ptr;
26
27 return aligned_ptr;
28 }
29
30 fn alignedFree(ptr: [*]u8) void {
31 _ = uefi.system_table.boot_services.?.freePool(getHeader(ptr).*);
32 }
33
34 fn alloc(
35 _: *anyopaque,
36 len: usize,
37 ptr_align: u29,
38 len_align: u29,
39 ret_addr: usize,
40 ) Allocator.Error![]u8 {
41 _ = ret_addr;
42
43 assert(len > 0);
44 assert(std.math.isPowerOfTwo(ptr_align));
45
46 var ptr = alignedAlloc(len, ptr_align) orelse return error.OutOfMemory;
47
48 if (len_align == 0)
49 return ptr[0..len];
50
51 return ptr[0..mem.alignBackwardAnyAlign(len, len_align)];
52 }
53
54 fn resize(
55 _: *anyopaque,
56 buf: []u8,
57 buf_align: u29,
58 new_len: usize,
59 len_align: u29,
60 ret_addr: usize,
61 ) ?usize {
62 _ = buf_align;
63 _ = ret_addr;
64
65 return if (new_len <= buf.len) mem.alignAllocLen(buf.len, new_len, len_align) else null;
66 }
67
68 fn free(
69 _: *anyopaque,
70 buf: []u8,
71 buf_align: u29,
72 ret_addr: usize,
73 ) void {
74 _ = buf_align;
75 _ = ret_addr;
76 alignedFree(buf.ptr);
77 }
78};
79
80/// Supports the full Allocator interface, including alignment.
81/// For a direct call of `allocatePool`, see `raw_pool_allocator`.
82pub const pool_allocator = Allocator{
83 .ptr = undefined,
84 .vtable = &pool_allocator_vtable,
85};
86
87const pool_allocator_vtable = Allocator.VTable{
88 .alloc = UefiPoolAllocator.alloc,
89 .resize = UefiPoolAllocator.resize,
90 .free = UefiPoolAllocator.free,
91};
92
93/// Asserts allocations are 8 byte aligned and calls `boot_services.allocatePool`.
94pub const raw_pool_allocator = Allocator{
95 .ptr = undefined,
96 .vtable = &raw_pool_allocator_table,
97};
98
99const raw_pool_allocator_table = Allocator.VTable{
100 .alloc = uefi_alloc,
101 .resize = uefi_resize,
102 .free = uefi_free,
103};
104
105fn uefi_alloc(
106 _: *anyopaque,
107 len: usize,
108 ptr_align: u29,
109 len_align: u29,
110 ret_addr: usize,
111) Allocator.Error![]u8 {
112 _ = len_align;
113 _ = ret_addr;
114
115 std.debug.assert(ptr_align <= 8);
116
117 var ptr: [*]align(8) u8 = undefined;
118
119 if (uefi.system_table.boot_services.?.allocatePool(uefi.efi_pool_memory_type, len, &ptr) != .Success) {
120 return error.OutOfMemory;
121 }
122
123 return ptr[0..len];
124}
125
126fn uefi_resize(
127 _: *anyopaque,
128 buf: []u8,
129 old_align: u29,
130 new_len: usize,
131 len_align: u29,
132 ret_addr: usize,
133) ?usize {
134 _ = old_align;
135 _ = ret_addr;
136
137 if (new_len <= buf.len) {
138 return mem.alignAllocLen(buf.len, new_len, len_align);
139 }
140
141 return null;
142}
143
144fn uefi_free(
145 _: *anyopaque,
146 buf: []u8,
147 buf_align: u29,
148 ret_addr: usize,
149) void {
150 _ = buf_align;
151 _ = ret_addr;
152 _ = uefi.system_table.boot_services.?.freePool(@alignCast(8, buf.ptr));
153}