authorgravatar for carmen@dotcarmen.devCarmen <carmen@dotcarmen.dev> 2025-07-12 10:18:53-07:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2025-07-12 17:18:53+00:00
log5b4e982169ab660a427da8b2c28c5eb7930362e2
tree4da8edd2834ee6eb67517121cb87e6726afa5bfd
parentbd97b66186dabb3533df1ea9eb650d7574496a59
signaturebadge-check Signed by PGP key B5690EEEBB952194

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>

10 files changed, 1898 insertions(+), 145 deletions(-)

lib/std/Thread.zig+1-1
...@@ -58,7 +58,7 @@ pub fn sleep(nanoseconds: u64) void {...@@ -58,7 +58,7 @@ pub fn sleep(nanoseconds: u64) void {
58 const boot_services = std.os.uefi.system_table.boot_services.?;58 const boot_services = std.os.uefi.system_table.boot_services.?;
59 const us_from_ns = nanoseconds / std.time.ns_per_us;59 const us_from_ns = nanoseconds / std.time.ns_per_us;
60 const us = math.cast(usize, us_from_ns) orelse math.maxInt(usize);60 const us = math.cast(usize, us_from_ns) orelse math.maxInt(usize);
61 _ = boot_services.stall(us);61 boot_services.stall(us) catch unreachable;
62 return;62 return;
63 }63 }
6464
lib/std/debug.zig+2-3
...@@ -654,9 +654,8 @@ pub fn defaultPanic(...@@ -654,9 +654,8 @@ pub fn defaultPanic(
654654
655 if (uefi.system_table.boot_services) |bs| {655 if (uefi.system_table.boot_services) |bs| {
656 // ExitData buffer must be allocated using boot_services.allocatePool (spec: page 220)656 // ExitData buffer must be allocated using boot_services.allocatePool (spec: page 220)
657 const exit_data: []u16 = uefi.raw_pool_allocator.alloc(u16, exit_msg.len + 1) catch @trap();657 const exit_data = uefi.raw_pool_allocator.dupeZ(u16, exit_msg) catch @trap();
658 @memcpy(exit_data, exit_msg[0..exit_data.len]); // Includes null terminator.658 bs.exit(uefi.handle, .aborted, exit_data) catch {};
659 _ = bs.exit(uefi.handle, .aborted, exit_data.len, exit_data.ptr);
660 }659 }
661 @trap();660 @trap();
662 },661 },
lib/std/os/uefi.zig+49-3
...@@ -24,9 +24,51 @@ pub var handle: Handle = undefined;...@@ -24,9 +24,51 @@ pub var handle: Handle = undefined;
24/// A pointer to the EFI System Table that is passed to the EFI image's entry point.24/// A pointer to the EFI System Table that is passed to the EFI image's entry point.
25pub var system_table: *tables.SystemTable = undefined;25pub var system_table: *tables.SystemTable = undefined;
2626
27/// UEFI's memory interfaces exclusively act on 4096-byte pages.
28pub const Page = [4096]u8;
29
27/// A handle to an event structure.30/// A handle to an event structure.
28pub const Event = *opaque {};31pub const Event = *opaque {};
2932
33pub const EventRegistration = *const opaque {};
34
35pub const EventType = packed struct(u32) {
36 lo_context: u8 = 0,
37 /// If an event of this type is not already in the signaled state, then
38 /// the event’s NotificationFunction will be queued at the event’s NotifyTpl
39 /// whenever the event is being waited on via EFI_BOOT_SERVICES.WaitForEvent()
40 /// or EFI_BOOT_SERVICES.CheckEvent() .
41 wait: bool = false,
42 /// The event’s NotifyFunction is queued whenever the event is signaled.
43 signal: bool = false,
44 hi_context: u20 = 0,
45 /// The event is allocated from runtime memory. If an event is to be signaled
46 /// after the call to EFI_BOOT_SERVICES.ExitBootServices() the event’s data
47 /// structure and notification function need to be allocated from runtime
48 /// memory.
49 runtime: bool = false,
50 timer: bool = false,
51
52 /// This event should not be combined with any other event types. This event
53 /// type is functionally equivalent to the EFI_EVENT_GROUP_EXIT_BOOT_SERVICES
54 /// event group.
55 pub const signal_exit_boot_services: EventType = .{
56 .signal = true,
57 .lo_context = 1,
58 };
59
60 /// The event is to be notified by the system when SetVirtualAddressMap()
61 /// is performed. This event type is a composite of EVT_NOTIFY_SIGNAL,
62 /// EVT_RUNTIME, and EVT_RUNTIME_CONTEXT and should not be combined with
63 /// any other event types.
64 pub const signal_virtual_address_change: EventType = .{
65 .runtime = true,
66 .hi_context = 0x20000,
67 .signal = true,
68 .lo_context = 2,
69 };
70};
71
30/// The calling convention used for all external functions part of the UEFI API.72/// The calling convention used for all external functions part of the UEFI API.
31pub const cc: std.builtin.CallingConvention = switch (@import("builtin").target.cpu.arch) {73pub const cc: std.builtin.CallingConvention = switch (@import("builtin").target.cpu.arch) {
32 .x86_64 => .{ .x86_64_win = .{} },74 .x86_64 => .{ .x86_64_win = .{} },
...@@ -52,7 +94,11 @@ pub const IpAddress = extern union {...@@ -52,7 +94,11 @@ pub const IpAddress = extern union {
5294
53/// GUIDs are align(8) unless otherwise specified.95/// GUIDs are align(8) unless otherwise specified.
54pub const Guid = extern struct {96pub const Guid = extern struct {
55 time_low: u32,97 comptime {
98 std.debug.assert(std.mem.Alignment.of(Guid) == .@"8");
99 }
100
101 time_low: u32 align(8),
56 time_mid: u16,102 time_mid: u16,
57 time_high_and_version: u16,103 time_high_and_version: u16,
58 clock_seq_high_and_reserved: u8,104 clock_seq_high_and_reserved: u8,
...@@ -60,7 +106,7 @@ pub const Guid = extern struct {...@@ -60,7 +106,7 @@ pub const Guid = extern struct {
60 node: [6]u8,106 node: [6]u8,
61107
62 /// Format GUID into hexadecimal lowercase xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx format108 /// Format GUID into hexadecimal lowercase xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx format
63 pub fn format(self: @This(), writer: *std.io.Writer) std.io.Writer.Error!void {109 pub fn format(self: Guid, writer: *std.io.Writer) std.io.Writer.Error!void {
64 const time_low = @byteSwap(self.time_low);110 const time_low = @byteSwap(self.time_low);
65 const time_mid = @byteSwap(self.time_mid);111 const time_mid = @byteSwap(self.time_mid);
66 const time_high_and_version = @byteSwap(self.time_high_and_version);112 const time_high_and_version = @byteSwap(self.time_high_and_version);
...@@ -75,7 +121,7 @@ pub const Guid = extern struct {...@@ -75,7 +121,7 @@ pub const Guid = extern struct {
75 });121 });
76 }122 }
77123
78 pub fn eql(a: std.os.uefi.Guid, b: std.os.uefi.Guid) bool {124 pub fn eql(a: Guid, b: Guid) bool {
79 return a.time_low == b.time_low and125 return a.time_low == b.time_low and
80 a.time_mid == b.time_mid and126 a.time_mid == b.time_mid and
81 a.time_high_and_version == b.time_high_and_version and127 a.time_high_and_version == b.time_high_and_version and
lib/std/os/uefi/pool_allocator.zig+14-10
...@@ -28,14 +28,16 @@ const UefiPoolAllocator = struct {...@@ -28,14 +28,16 @@ const UefiPoolAllocator = struct {
2828
29 const full_len = metadata_len + len;29 const full_len = metadata_len + len;
3030
31 var unaligned_ptr: [*]align(8) u8 = undefined;31 const unaligned_slice = uefi.system_table.boot_services.?.allocatePool(
32 if (uefi.system_table.boot_services.?.allocatePool(uefi.efi_pool_memory_type, full_len, &unaligned_ptr) != .success) return null;32 uefi.efi_pool_memory_type,
33 full_len,
34 ) catch return null;
3335
34 const unaligned_addr = @intFromPtr(unaligned_ptr);36 const unaligned_addr = @intFromPtr(unaligned_slice.ptr);
35 const aligned_addr = mem.alignForward(usize, unaligned_addr + @sizeOf(usize), ptr_align);37 const aligned_addr = mem.alignForward(usize, unaligned_addr + @sizeOf(usize), ptr_align);
3638
37 const aligned_ptr = unaligned_ptr + (aligned_addr - unaligned_addr);39 const aligned_ptr = unaligned_slice.ptr + (aligned_addr - unaligned_addr);
38 getHeader(aligned_ptr).* = unaligned_ptr;40 getHeader(aligned_ptr).* = unaligned_slice.ptr;
3941
40 return aligned_ptr;42 return aligned_ptr;
41 }43 }
...@@ -76,7 +78,7 @@ const UefiPoolAllocator = struct {...@@ -76,7 +78,7 @@ const UefiPoolAllocator = struct {
76 ) void {78 ) void {
77 _ = alignment;79 _ = alignment;
78 _ = ret_addr;80 _ = ret_addr;
79 _ = uefi.system_table.boot_services.?.freePool(getHeader(buf.ptr).*);81 uefi.system_table.boot_services.?.freePool(getHeader(buf.ptr).*) catch unreachable;
80 }82 }
81};83};
8284
...@@ -117,10 +119,12 @@ fn uefi_alloc(...@@ -117,10 +119,12 @@ fn uefi_alloc(
117119
118 std.debug.assert(@intFromEnum(alignment) <= 3);120 std.debug.assert(@intFromEnum(alignment) <= 3);
119121
120 var ptr: [*]align(8) u8 = undefined;122 const slice = uefi.system_table.boot_services.?.allocatePool(
121 if (uefi.system_table.boot_services.?.allocatePool(uefi.efi_pool_memory_type, len, &ptr) != .success) return null;123 uefi.efi_pool_memory_type,
124 len,
125 ) catch return null;
122126
123 return ptr;127 return slice.ptr;
124}128}
125129
126fn uefi_resize(130fn uefi_resize(
...@@ -161,5 +165,5 @@ fn uefi_free(...@@ -161,5 +165,5 @@ fn uefi_free(
161) void {165) void {
162 _ = alignment;166 _ = alignment;
163 _ = ret_addr;167 _ = ret_addr;
164 _ = uefi.system_table.boot_services.?.freePool(@alignCast(buf.ptr));168 uefi.system_table.boot_services.?.freePool(@alignCast(buf.ptr)) catch unreachable;
165}169}
lib/std/os/uefi/tables.zig+200-28
...@@ -1,3 +1,12 @@...@@ -1,3 +1,12 @@
1const std = @import("std");
2const uefi = std.os.uefi;
3const Handle = uefi.Handle;
4const Event = uefi.Event;
5const Guid = uefi.Guid;
6const cc = uefi.cc;
7const math = std.math;
8const assert = std.debug.assert;
9
1pub const BootServices = @import("tables/boot_services.zig").BootServices;10pub const BootServices = @import("tables/boot_services.zig").BootServices;
2pub const RuntimeServices = @import("tables/runtime_services.zig").RuntimeServices;11pub const RuntimeServices = @import("tables/runtime_services.zig").RuntimeServices;
3pub const ConfigurationTable = @import("tables/configuration_table.zig").ConfigurationTable;12pub const ConfigurationTable = @import("tables/configuration_table.zig").ConfigurationTable;
...@@ -7,29 +16,90 @@ pub const TableHeader = @import("tables/table_header.zig").TableHeader;...@@ -7,29 +16,90 @@ pub const TableHeader = @import("tables/table_header.zig").TableHeader;
7pub const EventNotify = *const fn (event: Event, ctx: *anyopaque) callconv(cc) void;16pub const EventNotify = *const fn (event: Event, ctx: *anyopaque) callconv(cc) void;
817
9pub const TimerDelay = enum(u32) {18pub const TimerDelay = enum(u32) {
10 timer_cancel,19 cancel,
11 timer_periodic,20 periodic,
12 timer_relative,21 relative,
13};22};
1423
15pub const MemoryType = enum(u32) {24pub const MemoryType = enum(u32) {
25 pub const Oem = math.IntFittingRange(
26 0,
27 @intFromEnum(MemoryType.oem_end) - @intFromEnum(MemoryType.oem_start),
28 );
29 pub const Vendor = math.IntFittingRange(
30 0,
31 @intFromEnum(MemoryType.vendor_end) - @intFromEnum(MemoryType.vendor_start),
32 );
33
34 /// can only be allocated using .allocate_any_pages mode unless you are explicitly targeting an interface that states otherwise
16 reserved_memory_type,35 reserved_memory_type,
17 loader_code,36 loader_code,
18 loader_data,37 loader_data,
19 boot_services_code,38 boot_services_code,
20 boot_services_data,39 boot_services_data,
40 /// can only be allocated using .allocate_any_pages mode unless you are explicitly targeting an interface that states otherwise
21 runtime_services_code,41 runtime_services_code,
42 /// can only be allocated using .allocate_any_pages mode unless you are explicitly targeting an interface that states otherwise
22 runtime_services_data,43 runtime_services_data,
23 conventional_memory,44 conventional_memory,
24 unusable_memory,45 unusable_memory,
46 /// can only be allocated using .allocate_any_pages mode unless you are explicitly targeting an interface that states otherwise
25 acpi_reclaim_memory,47 acpi_reclaim_memory,
48 /// can only be allocated using .allocate_any_pages mode unless you are explicitly targeting an interface that states otherwise
26 acpi_memory_nvs,49 acpi_memory_nvs,
27 memory_mapped_io,50 memory_mapped_io,
28 memory_mapped_io_port_space,51 memory_mapped_io_port_space,
29 pal_code,52 pal_code,
30 persistent_memory,53 persistent_memory,
54 unaccepted_memory,
31 max_memory_type,55 max_memory_type,
56 invalid_start,
57 invalid_end = 0x6FFFFFFF,
58 /// MemoryType values in the range 0x70000000..0x7FFFFFFF are reserved for OEM use.
59 oem_start = 0x70000000,
60 oem_end = 0x7FFFFFFF,
61 /// MemoryType values in the range 0x80000000..0xFFFFFFFF are reserved for use by UEFI
62 /// OS loaders that are provided by operating system vendors.
63 vendor_start = 0x80000000,
64 vendor_end = 0xFFFFFFFF,
32 _,65 _,
66
67 pub fn fromOem(value: Oem) MemoryType {
68 const oem_start = @intFromEnum(MemoryType.oem_start);
69 return @enumFromInt(oem_start + value);
70 }
71
72 pub fn toOem(memtype: MemoryType) ?Oem {
73 const as_int = @intFromEnum(memtype);
74 const oem_start = @intFromEnum(MemoryType.oem_start);
75 if (as_int < oem_start) return null;
76 if (as_int > @intFromEnum(MemoryType.oem_end)) return null;
77 return @truncate(as_int - oem_start);
78 }
79
80 pub fn fromVendor(value: Vendor) MemoryType {
81 const vendor_start = @intFromEnum(MemoryType.vendor_start);
82 return @enumFromInt(vendor_start + value);
83 }
84
85 pub fn toVendor(memtype: MemoryType) ?Vendor {
86 const as_int = @intFromEnum(memtype);
87 const vendor_start = @intFromEnum(MemoryType.vendor_start);
88 if (as_int < @intFromEnum(MemoryType.vendor_end)) return null;
89 if (as_int > @intFromEnum(MemoryType.vendor_end)) return null;
90 return @truncate(as_int - vendor_start);
91 }
92
93 pub fn format(self: MemoryType, w: *std.io.Writer) std.io.WriteError!void {
94 if (self.toOem()) |oemval|
95 try w.print("OEM({X})", .{oemval})
96 else if (self.toVendor()) |vendorval|
97 try w.print("Vendor({X})", .{vendorval})
98 else if (std.enums.tagName(MemoryType, self)) |name|
99 try w.print("{s}", .{name})
100 else
101 try w.print("INVALID({X})", .{@intFromEnum(self)});
102 }
33};103};
34104
35pub const MemoryDescriptorAttribute = packed struct(u64) {105pub const MemoryDescriptorAttribute = packed struct(u64) {
...@@ -51,6 +121,8 @@ pub const MemoryDescriptorAttribute = packed struct(u64) {...@@ -51,6 +121,8 @@ pub const MemoryDescriptorAttribute = packed struct(u64) {
51 memory_runtime: bool,121 memory_runtime: bool,
52};122};
53123
124pub const MemoryMapKey = enum(usize) { _ };
125
54pub const MemoryDescriptor = extern struct {126pub const MemoryDescriptor = extern struct {
55 type: MemoryType,127 type: MemoryType,
56 physical_start: u64,128 physical_start: u64,
...@@ -59,20 +131,121 @@ pub const MemoryDescriptor = extern struct {...@@ -59,20 +131,121 @@ pub const MemoryDescriptor = extern struct {
59 attribute: MemoryDescriptorAttribute,131 attribute: MemoryDescriptorAttribute,
60};132};
61133
134pub const MemoryMapInfo = struct {
135 key: MemoryMapKey,
136 descriptor_size: usize,
137 descriptor_version: u32,
138 /// The number of descriptors in the map.
139 len: usize,
140};
141
142pub const MemoryMapSlice = struct {
143 info: MemoryMapInfo,
144 ptr: [*]align(@alignOf(MemoryDescriptor)) u8,
145
146 pub fn iterator(self: MemoryMapSlice) MemoryDescriptorIterator {
147 return .{ .ctx = self };
148 }
149
150 pub fn get(self: MemoryMapSlice, index: usize) ?*MemoryDescriptor {
151 if (index >= self.info.len) return null;
152 return self.getUnchecked(index);
153 }
154
155 pub fn getUnchecked(self: MemoryMapSlice, index: usize) *MemoryDescriptor {
156 const offset: usize = index * self.info.descriptor_size;
157 return @alignCast(@ptrCast(self.ptr[offset..]));
158 }
159};
160
161pub const MemoryDescriptorIterator = struct {
162 ctx: MemoryMapSlice,
163 index: usize = 0,
164
165 pub fn next(self: *MemoryDescriptorIterator) ?*MemoryDescriptor {
166 const md = self.ctx.get(self.index) orelse return null;
167 self.index += 1;
168 return md;
169 }
170};
171
62pub const LocateSearchType = enum(u32) {172pub const LocateSearchType = enum(u32) {
63 all_handles,173 all_handles,
64 by_register_notify,174 by_register_notify,
65 by_protocol,175 by_protocol,
66};176};
67177
68pub const OpenProtocolAttributes = packed struct(u32) {178pub const LocateSearch = union(LocateSearchType) {
69 by_handle_protocol: bool = false,179 all_handles,
70 get_protocol: bool = false,180 by_register_notify: uefi.EventRegistration,
71 test_protocol: bool = false,181 by_protocol: *const Guid,
72 by_child_controller: bool = false,182};
73 by_driver: bool = false,183
74 exclusive: bool = false,184pub const OpenProtocolAttributes = enum(u32) {
75 reserved: u26 = 0,185 pub const Bits = packed struct(u32) {
186 by_handle_protocol: bool = false,
187 get_protocol: bool = false,
188 test_protocol: bool = false,
189 by_child_controller: bool = false,
190 by_driver: bool = false,
191 exclusive: bool = false,
192 reserved: u26 = 0,
193 };
194
195 by_handle_protocol = @bitCast(Bits{ .by_handle_protocol = true }),
196 get_protocol = @bitCast(Bits{ .get_protocol = true }),
197 test_protocol = @bitCast(Bits{ .test_protocol = true }),
198 by_child_controller = @bitCast(Bits{ .by_child_controller = true }),
199 by_driver = @bitCast(Bits{ .by_driver = true }),
200 by_driver_exclusive = @bitCast(Bits{ .by_driver = true, .exclusive = true }),
201 exclusive = @bitCast(Bits{ .exclusive = true }),
202 _,
203
204 pub fn fromBits(bits: Bits) OpenProtocolAttributes {
205 return @bitCast(bits);
206 }
207
208 pub fn toBits(self: OpenProtocolAttributes) Bits {
209 return @bitCast(self);
210 }
211};
212
213pub const OpenProtocolArgs = union(OpenProtocolAttributes) {
214 /// Used in the implementation of `handleProtocol`.
215 by_handle_protocol: struct { agent: ?Handle = null, controller: ?Handle = null },
216 /// Used by a driver to get a protocol interface from a handle. Care must be
217 /// taken when using this open mode because the driver that opens a protocol
218 /// interface in this manner will not be informed if the protocol interface
219 /// is uninstalled or reinstalled. The caller is also not required to close
220 /// the protocol interface with `closeProtocol`.
221 get_protocol: struct { agent: ?Handle = null, controller: ?Handle = null },
222 /// Used by a driver to test for the existence of a protocol interface on a
223 /// handle. The caller only use the return status code. The caller is also
224 /// not required to close the protocol interface with `closeProtocol`.
225 test_protocol: struct { agent: ?Handle = null, controller: ?Handle = null },
226 /// Used by bus drivers to show that a protocol interface is being used by one
227 /// of the child controllers of a bus. This information is used by
228 /// `BootServices.connectController` to recursively connect all child controllers
229 /// and by `BootServices.disconnectController` to get the list of child
230 /// controllers that a bus driver created.
231 by_child_controller: struct { agent: Handle, controller: Handle },
232 /// Used by a driver to gain access to a protocol interface. When this mode
233 /// is used, the driver’s Stop() function will be called by
234 /// `BootServices.disconnectController` if the protocol interface is reinstalled
235 /// or uninstalled. Once a protocol interface is opened by a driver with this
236 /// attribute, no other drivers will be allowed to open the same protocol interface
237 /// with the `.by_driver` attribute.
238 by_driver: struct { agent: Handle, controller: Handle },
239 /// Used by a driver to gain exclusive access to a protocol interface. If any
240 /// other drivers have the protocol interface opened with an attribute of
241 /// `.by_driver`, then an attempt will be made to remove them with
242 /// `BootServices.disconnectController`.
243 by_driver_exclusive: struct { agent: Handle, controller: Handle },
244 /// Used by applications to gain exclusive access to a protocol interface. If
245 /// any drivers have the protocol interface opened with an attribute of
246 /// `.by_driver`, then an attempt will be made to remove them by calling the
247 /// driver’s Stop() function.
248 exclusive: struct { agent: Handle, controller: ?Handle = null },
76};249};
77250
78pub const ProtocolInformationEntry = extern struct {251pub const ProtocolInformationEntry = extern struct {
...@@ -83,19 +256,25 @@ pub const ProtocolInformationEntry = extern struct {...@@ -83,19 +256,25 @@ pub const ProtocolInformationEntry = extern struct {
83};256};
84257
85pub const InterfaceType = enum(u32) {258pub const InterfaceType = enum(u32) {
86 efi_native_interface,259 native,
260};
261
262pub const AllocateLocation = union(AllocateType) {
263 any,
264 max_address: [*]align(4096) uefi.Page,
265 address: [*]align(4096) uefi.Page,
87};266};
88267
89pub const AllocateType = enum(u32) {268pub const AllocateType = enum(u32) {
90 allocate_any_pages,269 any,
91 allocate_max_address,270 max_address,
92 allocate_address,271 address,
93};272};
94273
95pub const PhysicalAddress = u64;274pub const PhysicalAddress = u64;
96275
97pub const CapsuleHeader = extern struct {276pub const CapsuleHeader = extern struct {
98 capsule_guid: Guid align(8),277 capsule_guid: Guid,
99 header_size: u32,278 header_size: u32,
100 flags: u32,279 flags: u32,
101 capsule_image_size: u32,280 capsule_image_size: u32,
...@@ -110,13 +289,13 @@ pub const UefiCapsuleBlockDescriptor = extern struct {...@@ -110,13 +289,13 @@ pub const UefiCapsuleBlockDescriptor = extern struct {
110};289};
111290
112pub const ResetType = enum(u32) {291pub const ResetType = enum(u32) {
113 reset_cold,292 cold,
114 reset_warm,293 warm,
115 reset_shutdown,294 shutdown,
116 reset_platform_specific,295 platform_specific,
117};296};
118297
119pub const global_variable align(8) = Guid{298pub const global_variable = Guid{
120 .time_low = 0x8be4df61,299 .time_low = 0x8be4df61,
121 .time_mid = 0x93ca,300 .time_mid = 0x93ca,
122 .time_high_and_version = 0x11d2,301 .time_high_and_version = 0x11d2,
...@@ -128,10 +307,3 @@ pub const global_variable align(8) = Guid{...@@ -128,10 +307,3 @@ pub const global_variable align(8) = Guid{
128test {307test {
129 std.testing.refAllDeclsRecursive(@This());308 std.testing.refAllDeclsRecursive(@This());
130}309}
131
132const std = @import("std");
133const uefi = std.os.uefi;
134const Handle = uefi.Handle;
135const Event = uefi.Event;
136const Guid = uefi.Guid;
137const cc = uefi.cc;
lib/std/os/uefi/tables/boot_services.zig+1141-68
...@@ -1,21 +1,31 @@...@@ -1,21 +1,31 @@
1const std = @import("std");1const std = @import("std");
2const uefi = std.os.uefi;2const uefi = std.os.uefi;
3const Event = uefi.Event;3const Event = uefi.Event;
4const EventRegistration = uefi.EventRegistration;
4const Guid = uefi.Guid;5const Guid = uefi.Guid;
5const Handle = uefi.Handle;6const Handle = uefi.Handle;
7const Page = uefi.Page;
8const Pages = uefi.Pages;
6const Status = uefi.Status;9const Status = uefi.Status;
7const TableHeader = uefi.tables.TableHeader;10const TableHeader = uefi.tables.TableHeader;
8const DevicePathProtocol = uefi.protocol.DevicePath;11const DevicePathProtocol = uefi.protocol.DevicePath;
12const AllocateLocation = uefi.tables.AllocateLocation;
9const AllocateType = uefi.tables.AllocateType;13const AllocateType = uefi.tables.AllocateType;
10const MemoryType = uefi.tables.MemoryType;14const MemoryType = uefi.tables.MemoryType;
11const MemoryDescriptor = uefi.tables.MemoryDescriptor;15const MemoryDescriptor = uefi.tables.MemoryDescriptor;
16const MemoryMapKey = uefi.tables.MemoryMapKey;
17const MemoryMapInfo = uefi.tables.MemoryMapInfo;
18const MemoryMapSlice = uefi.tables.MemoryMapSlice;
12const TimerDelay = uefi.tables.TimerDelay;19const TimerDelay = uefi.tables.TimerDelay;
13const InterfaceType = uefi.tables.InterfaceType;20const InterfaceType = uefi.tables.InterfaceType;
21const LocateSearch = uefi.tables.LocateSearch;
14const LocateSearchType = uefi.tables.LocateSearchType;22const LocateSearchType = uefi.tables.LocateSearchType;
23const OpenProtocolArgs = uefi.tables.OpenProtocolArgs;
15const OpenProtocolAttributes = uefi.tables.OpenProtocolAttributes;24const OpenProtocolAttributes = uefi.tables.OpenProtocolAttributes;
16const ProtocolInformationEntry = uefi.tables.ProtocolInformationEntry;25const ProtocolInformationEntry = uefi.tables.ProtocolInformationEntry;
17const EventNotify = uefi.tables.EventNotify;26const EventNotify = uefi.tables.EventNotify;
18const cc = uefi.cc;27const cc = uefi.cc;
28const Error = Status.Error;
1929
20/// Boot services are services provided by the system's firmware until the operating system takes30/// Boot services are services provided by the system's firmware until the operating system takes
21/// over control over the hardware by calling exitBootServices.31/// over control over the hardware by calling exitBootServices.
...@@ -32,173 +42,1236 @@ pub const BootServices = extern struct {...@@ -32,173 +42,1236 @@ pub const BootServices = extern struct {
32 hdr: TableHeader,42 hdr: TableHeader,
3343
34 /// Raises a task's priority level and returns its previous level.44 /// Raises a task's priority level and returns its previous level.
35 raiseTpl: *const fn (new_tpl: usize) callconv(cc) usize,45 raiseTpl: *const fn (new_tpl: TaskPriorityLevel) callconv(cc) TaskPriorityLevel,
3646
37 /// Restores a task's priority level to its previous value.47 /// Restores a task's priority level to its previous value.
38 restoreTpl: *const fn (old_tpl: usize) callconv(cc) void,48 restoreTpl: *const fn (old_tpl: TaskPriorityLevel) callconv(cc) void,
3949
40 /// Allocates memory pages from the system.50 /// Allocates memory pages from the system.
41 allocatePages: *const fn (alloc_type: AllocateType, mem_type: MemoryType, pages: usize, memory: *[*]align(4096) u8) callconv(cc) Status,51 _allocatePages: *const fn (alloc_type: AllocateType, mem_type: MemoryType, pages: usize, memory: *[*]align(4096) Page) callconv(cc) Status,
4252
43 /// Frees memory pages.53 /// Frees memory pages.
44 freePages: *const fn (memory: [*]align(4096) u8, pages: usize) callconv(cc) Status,54 _freePages: *const fn (memory: [*]align(4096) Page, pages: usize) callconv(cc) Status,
4555
46 /// Returns the current memory map.56 /// Returns the current memory map.
47 getMemoryMap: *const fn (mmap_size: *usize, mmap: ?[*]MemoryDescriptor, map_key: *usize, descriptor_size: *usize, descriptor_version: *u32) callconv(cc) Status,57 _getMemoryMap: *const fn (mmap_size: *usize, mmap: ?[*]align(@alignOf(MemoryDescriptor)) u8, map_key: *MemoryMapKey, descriptor_size: *usize, descriptor_version: *u32) callconv(cc) Status,
4858
49 /// Allocates pool memory.59 /// Allocates pool memory.
50 allocatePool: *const fn (pool_type: MemoryType, size: usize, buffer: *[*]align(8) u8) callconv(cc) Status,60 _allocatePool: *const fn (pool_type: MemoryType, size: usize, buffer: *[*]align(8) u8) callconv(cc) Status,
5161
52 /// Returns pool memory to the system.62 /// Returns pool memory to the system.
53 freePool: *const fn (buffer: [*]align(8) u8) callconv(cc) Status,63 _freePool: *const fn (buffer: [*]align(8) u8) callconv(cc) Status,
5464
55 /// Creates an event.65 /// Creates an event.
56 createEvent: *const fn (type: u32, notify_tpl: usize, notify_func: ?*const fn (Event, ?*anyopaque) callconv(cc) void, notify_ctx: ?*const anyopaque, event: *Event) callconv(cc) Status,66 _createEvent: *const fn (type: u32, notify_tpl: TaskPriorityLevel, notify_func: ?*const fn (Event, ?*anyopaque) callconv(cc) void, notify_ctx: ?*anyopaque, event: *Event) callconv(cc) Status,
5767
58 /// Sets the type of timer and the trigger time for a timer event.68 /// Sets the type of timer and the trigger time for a timer event.
59 setTimer: *const fn (event: Event, type: TimerDelay, trigger_time: u64) callconv(cc) Status,69 _setTimer: *const fn (event: Event, type: TimerDelay, trigger_time: u64) callconv(cc) Status,
6070
61 /// Stops execution until an event is signaled.71 /// Stops execution until an event is signaled.
62 waitForEvent: *const fn (event_len: usize, events: [*]const Event, index: *usize) callconv(cc) Status,72 _waitForEvent: *const fn (event_len: usize, events: [*]const Event, index: *usize) callconv(cc) Status,
6373
64 /// Signals an event.74 /// Signals an event.
65 signalEvent: *const fn (event: Event) callconv(cc) Status,75 _signalEvent: *const fn (event: Event) callconv(cc) Status,
6676
67 /// Closes an event.77 /// Closes an event.
68 closeEvent: *const fn (event: Event) callconv(cc) Status,78 _closeEvent: *const fn (event: Event) callconv(cc) Status,
6979
70 /// Checks whether an event is in the signaled state.80 /// Checks whether an event is in the signaled state.
71 checkEvent: *const fn (event: Event) callconv(cc) Status,81 _checkEvent: *const fn (event: Event) callconv(cc) Status,
7282
73 /// Installs a protocol interface on a device handle. If the handle does not exist, it is created83 /// Installs a protocol interface on a device handle. If the handle does not exist, it is created
74 /// and added to the list of handles in the system. installMultipleProtocolInterfaces()84 /// and added to the list of handles in the system. installMultipleProtocolInterfaces()
75 /// performs more error checking than installProtocolInterface(), so its use is recommended over this.85 /// performs more error checking than installProtocolInterface(), so its use is recommended over this.
76 installProtocolInterface: *const fn (handle: Handle, protocol: *align(8) const Guid, interface_type: InterfaceType, interface: *anyopaque) callconv(cc) Status,86 _installProtocolInterface: *const fn (handle: Handle, protocol: *const Guid, interface_type: InterfaceType, interface: *anyopaque) callconv(cc) Status,
7787
78 /// Reinstalls a protocol interface on a device handle88 /// Reinstalls a protocol interface on a device handle
79 reinstallProtocolInterface: *const fn (handle: Handle, protocol: *align(8) const Guid, old_interface: *anyopaque, new_interface: *anyopaque) callconv(cc) Status,89 _reinstallProtocolInterface: *const fn (handle: Handle, protocol: *const Guid, old_interface: *anyopaque, new_interface: *anyopaque) callconv(cc) Status,
8090
81 /// Removes a protocol interface from a device handle. Usage of91 /// Removes a protocol interface from a device handle. Usage of
82 /// uninstallMultipleProtocolInterfaces is recommended over this.92 /// uninstallMultipleProtocolInterfaces is recommended over this.
83 uninstallProtocolInterface: *const fn (handle: Handle, protocol: *align(8) const Guid, interface: *anyopaque) callconv(cc) Status,93 _uninstallProtocolInterface: *const fn (handle: Handle, protocol: *const Guid, interface: *anyopaque) callconv(cc) Status,
8494
85 /// Queries a handle to determine if it supports a specified protocol.95 /// Queries a handle to determine if it supports a specified protocol.
86 handleProtocol: *const fn (handle: Handle, protocol: *align(8) const Guid, interface: *?*anyopaque) callconv(cc) Status,96 _handleProtocol: *const fn (handle: Handle, protocol: *const Guid, interface: *?*anyopaque) callconv(cc) Status,
8797
88 reserved: *anyopaque,98 _reserved: *anyopaque,
8999
90 /// Creates an event that is to be signaled whenever an interface is installed for a specified protocol.100 /// Creates an event that is to be signaled whenever an interface is installed for a specified protocol.
91 registerProtocolNotify: *const fn (protocol: *align(8) const Guid, event: Event, registration: **anyopaque) callconv(cc) Status,101 _registerProtocolNotify: *const fn (protocol: *const Guid, event: Event, registration: *EventRegistration) callconv(cc) Status,
92102
93 /// Returns an array of handles that support a specified protocol.103 /// Returns an array of handles that support a specified protocol.
94 locateHandle: *const fn (search_type: LocateSearchType, protocol: ?*align(8) const Guid, search_key: ?*const anyopaque, buffer_size: *usize, buffer: [*]Handle) callconv(cc) Status,104 _locateHandle: *const fn (search_type: LocateSearchType, protocol: ?*const Guid, search_key: ?*const anyopaque, buffer_size: *usize, buffer: ?[*]Handle) callconv(cc) Status,
95105
96 /// Locates the handle to a device on the device path that supports the specified protocol106 /// Locates the handle to a device on the device path that supports the specified protocol
97 locateDevicePath: *const fn (protocols: *align(8) const Guid, device_path: **const DevicePathProtocol, device: *?Handle) callconv(cc) Status,107 _locateDevicePath: *const fn (protocols: *const Guid, device_path: **const DevicePathProtocol, device: *?Handle) callconv(cc) Status,
98108
99 /// Adds, updates, or removes a configuration table entry from the EFI System Table.109 /// Adds, updates, or removes a configuration table entry from the EFI System Table.
100 installConfigurationTable: *const fn (guid: *align(8) const Guid, table: ?*anyopaque) callconv(cc) Status,110 _installConfigurationTable: *const fn (guid: *const Guid, table: ?*anyopaque) callconv(cc) Status,
101111
102 /// Loads an EFI image into memory.112 /// Loads an EFI image into memory.
103 loadImage: *const fn (boot_policy: bool, parent_image_handle: Handle, device_path: ?*const DevicePathProtocol, source_buffer: ?[*]const u8, source_size: usize, image_handle: *?Handle) callconv(cc) Status,113 _loadImage: *const fn (boot_policy: bool, parent_image_handle: Handle, device_path: ?*const DevicePathProtocol, source_buffer: ?[*]const u8, source_size: usize, image_handle: *Handle) callconv(cc) Status,
104114
105 /// Transfers control to a loaded image's entry point.115 /// Transfers control to a loaded image's entry point.
106 startImage: *const fn (image_handle: Handle, exit_data_size: ?*usize, exit_data: ?*[*]u16) callconv(cc) Status,116 _startImage: *const fn (image_handle: Handle, exit_data_size: ?*usize, exit_data: ?*[*]u16) callconv(cc) Status,
107117
108 /// Terminates a loaded EFI image and returns control to boot services.118 /// Terminates a loaded EFI image and returns control to boot services.
109 exit: *const fn (image_handle: Handle, exit_status: Status, exit_data_size: usize, exit_data: ?*const anyopaque) callconv(cc) Status,119 _exit: *const fn (image_handle: Handle, exit_status: Status, exit_data_size: usize, exit_data: ?[*]align(2) const u8) callconv(cc) Status,
110120
111 /// Unloads an image.121 /// Unloads an image.
112 unloadImage: *const fn (image_handle: Handle) callconv(cc) Status,122 _unloadImage: *const fn (image_handle: Handle) callconv(cc) Status,
113123
114 /// Terminates all boot services.124 /// Terminates all boot services.
115 exitBootServices: *const fn (image_handle: Handle, map_key: usize) callconv(cc) Status,125 _exitBootServices: *const fn (image_handle: Handle, map_key: MemoryMapKey) callconv(cc) Status,
116126
117 /// Returns a monotonically increasing count for the platform.127 /// Returns a monotonically increasing count for the platform.
118 getNextMonotonicCount: *const fn (count: *u64) callconv(cc) Status,128 _getNextMonotonicCount: *const fn (count: *u64) callconv(cc) Status,
119129
120 /// Induces a fine-grained stall.130 /// Induces a fine-grained stall.
121 stall: *const fn (microseconds: usize) callconv(cc) Status,131 _stall: *const fn (microseconds: usize) callconv(cc) Status,
122132
123 /// Sets the system's watchdog timer.133 /// Sets the system's watchdog timer.
124 setWatchdogTimer: *const fn (timeout: usize, watchdog_code: u64, data_size: usize, watchdog_data: ?[*]const u16) callconv(cc) Status,134 _setWatchdogTimer: *const fn (timeout: usize, watchdog_code: u64, data_size: usize, watchdog_data: ?[*]const u16) callconv(cc) Status,
125135
126 /// Connects one or more drives to a controller.136 /// Connects one or more drives to a controller.
127 connectController: *const fn (controller_handle: Handle, driver_image_handle: ?Handle, remaining_device_path: ?*DevicePathProtocol, recursive: bool) callconv(cc) Status,137 _connectController: *const fn (controller_handle: Handle, driver_image_handle: ?[*:null]?Handle, remaining_device_path: ?*const DevicePathProtocol, recursive: bool) callconv(cc) Status,
128138
129 // Disconnects one or more drivers from a controller139 // Disconnects one or more drivers from a controller
130 disconnectController: *const fn (controller_handle: Handle, driver_image_handle: ?Handle, child_handle: ?Handle) callconv(cc) Status,140 _disconnectController: *const fn (controller_handle: Handle, driver_image_handle: ?Handle, child_handle: ?Handle) callconv(cc) Status,
131141
132 /// Queries a handle to determine if it supports a specified protocol.142 /// Queries a handle to determine if it supports a specified protocol.
133 openProtocol: *const fn (handle: Handle, protocol: *align(8) const Guid, interface: *?*anyopaque, agent_handle: ?Handle, controller_handle: ?Handle, attributes: OpenProtocolAttributes) callconv(cc) Status,143 _openProtocol: *const fn (handle: Handle, protocol: *const Guid, interface: ?*?*anyopaque, agent_handle: ?Handle, controller_handle: ?Handle, attributes: OpenProtocolAttributes) callconv(cc) Status,
134144
135 /// Closes a protocol on a handle that was opened using openProtocol().145 /// Closes a protocol on a handle that was opened using openProtocol().
136 closeProtocol: *const fn (handle: Handle, protocol: *align(8) const Guid, agent_handle: Handle, controller_handle: ?Handle) callconv(cc) Status,146 _closeProtocol: *const fn (handle: Handle, protocol: *const Guid, agent_handle: Handle, controller_handle: ?Handle) callconv(cc) Status,
137147
138 /// Retrieves the list of agents that currently have a protocol interface opened.148 /// Retrieves the list of agents that currently have a protocol interface opened.
139 openProtocolInformation: *const fn (handle: Handle, protocol: *align(8) const Guid, entry_buffer: *[*]ProtocolInformationEntry, entry_count: *usize) callconv(cc) Status,149 _openProtocolInformation: *const fn (handle: Handle, protocol: *const Guid, entry_buffer: *[*]ProtocolInformationEntry, entry_count: *usize) callconv(cc) Status,
140150
141 /// Retrieves the list of protocol interface GUIDs that are installed on a handle in a buffer allocated from pool.151 /// Retrieves the list of protocol interface GUIDs that are installed on a handle in a buffer allocated from pool.
142 protocolsPerHandle: *const fn (handle: Handle, protocol_buffer: *[*]*align(8) const Guid, protocol_buffer_count: *usize) callconv(cc) Status,152 _protocolsPerHandle: *const fn (handle: Handle, protocol_buffer: *[*]*const Guid, protocol_buffer_count: *usize) callconv(cc) Status,
143153
144 /// Returns an array of handles that support the requested protocol in a buffer allocated from pool.154 /// Returns an array of handles that support the requested protocol in a buffer allocated from pool.
145 locateHandleBuffer: *const fn (search_type: LocateSearchType, protocol: ?*align(8) const Guid, search_key: ?*const anyopaque, num_handles: *usize, buffer: *[*]Handle) callconv(cc) Status,155 _locateHandleBuffer: *const fn (search_type: LocateSearchType, protocol: ?*const Guid, search_key: ?*const anyopaque, num_handles: *usize, buffer: *[*]Handle) callconv(cc) Status,
146156
147 /// Returns the first protocol instance that matches the given protocol.157 /// Returns the first protocol instance that matches the given protocol.
148 locateProtocol: *const fn (protocol: *align(8) const Guid, registration: ?*const anyopaque, interface: *?*anyopaque) callconv(cc) Status,158 _locateProtocol: *const fn (protocol: *const Guid, registration: ?EventRegistration, interface: *?*const anyopaque) callconv(cc) Status,
149159
150 /// Installs one or more protocol interfaces into the boot services environment160 /// Installs one or more protocol interfaces into the boot services environment
151 // TODO: use callconv(cc) instead once that works161 // TODO: use callconv(cc) instead once that works
152 installMultipleProtocolInterfaces: *const fn (handle: *Handle, ...) callconv(.c) Status,162 _installMultipleProtocolInterfaces: *const fn (handle: *Handle, ...) callconv(.c) Status,
153163
154 /// Removes one or more protocol interfaces into the boot services environment164 /// Removes one or more protocol interfaces into the boot services environment
155 // TODO: use callconv(cc) instead once that works165 // TODO: use callconv(cc) instead once that works
156 uninstallMultipleProtocolInterfaces: *const fn (handle: *Handle, ...) callconv(.c) Status,166 _uninstallMultipleProtocolInterfaces: *const fn (handle: *Handle, ...) callconv(.c) Status,
157167
158 /// Computes and returns a 32-bit CRC for a data buffer.168 /// Computes and returns a 32-bit CRC for a data buffer.
159 calculateCrc32: *const fn (data: [*]const u8, data_size: usize, *u32) callconv(cc) Status,169 _calculateCrc32: *const fn (data: [*]const u8, data_size: usize, *u32) callconv(cc) Status,
160170
161 /// Copies the contents of one buffer to another buffer171 /// Copies the contents of one buffer to another buffer
162 copyMem: *const fn (dest: [*]u8, src: [*]const u8, len: usize) callconv(cc) void,172 _copyMem: *const fn (dest: [*]u8, src: [*]const u8, len: usize) callconv(cc) void,
163173
164 /// Fills a buffer with a specified value174 /// Fills a buffer with a specified value
165 setMem: *const fn (buffer: [*]u8, size: usize, value: u8) callconv(cc) void,175 _setMem: *const fn (buffer: [*]u8, size: usize, value: u8) callconv(cc) void,
166176
167 /// Creates an event in a group.177 /// Creates an event in a group.
168 createEventEx: *const fn (type: u32, notify_tpl: usize, notify_func: EventNotify, notify_ctx: *const anyopaque, event_group: *align(8) const Guid, event: *Event) callconv(cc) Status,178 _createEventEx: *const fn (type: u32, notify_tpl: usize, notify_func: EventNotify, notify_ctx: *const anyopaque, event_group: *const Guid, event: *Event) callconv(cc) Status,
179
180 pub const AllocatePagesError = uefi.UnexpectedError || error{
181 OutOfResources,
182 InvalidParameter,
183 NotFound,
184 };
185
186 pub const FreePagesError = uefi.UnexpectedError || error{
187 NotFound,
188 InvalidParameter,
189 };
190
191 pub const GetMemoryMapError = uefi.UnexpectedError || error{
192 InvalidParameter,
193 BufferTooSmall,
194 };
195
196 pub const AllocatePoolError = uefi.UnexpectedError || error{
197 OutOfResources,
198 InvalidParameter,
199 };
200
201 pub const FreePoolError = uefi.UnexpectedError || error{
202 InvalidParameter,
203 };
204
205 pub const CreateEventError = uefi.UnexpectedError || error{
206 InvalidParameter,
207 OutOfResources,
208 };
209
210 pub const SetTimerError = uefi.UnexpectedError || error{
211 InvalidParameter,
212 };
213
214 pub const WaitForEventError = uefi.UnexpectedError || error{
215 InvalidParameter,
216 Unsupported,
217 };
218
219 pub const CheckEventError = uefi.UnexpectedError || error{
220 InvalidParameter,
221 };
222
223 pub const ReinstallProtocolInterfaceError = uefi.UnexpectedError || error{
224 NotFound,
225 AccessDenied,
226 InvalidParameter,
227 };
228
229 pub const HandleProtocolError = uefi.UnexpectedError || error{
230 Unsupported,
231 };
232
233 pub const RegisterProtocolNotifyError = uefi.UnexpectedError || error{
234 OutOfResources,
235 InvalidParameter,
236 };
237
238 pub const NumHandlesError = uefi.UnexpectedError || error{
239 OutOfResources,
240 };
241
242 pub const LocateHandleError = uefi.UnexpectedError || error{
243 BufferTooSmall,
244 InvalidParameter,
245 };
246
247 pub const LocateDevicePathError = uefi.UnexpectedError || error{
248 NotFound,
249 InvalidParameter,
250 };
251
252 pub const InstallConfigurationTableError = uefi.UnexpectedError || error{
253 InvalidParameter,
254 OutOfResources,
255 };
256
257 pub const UninstallConfigurationTableError = InstallConfigurationTableError || error{
258 NotFound,
259 };
260
261 pub const LoadImageError = uefi.UnexpectedError || error{
262 NotFound,
263 InvalidParameter,
264 Unsupported,
265 OutOfResources,
266 LoadError,
267 DeviceError,
268 AccessDenied,
269 SecurityViolation,
270 };
271
272 pub const StartImageError = uefi.UnexpectedError || error{
273 InvalidParameter,
274 SecurityViolation,
275 };
276
277 pub const ExitError = uefi.UnexpectedError || error{
278 InvalidParameter,
279 };
280
281 pub const ExitBootServicesError = uefi.UnexpectedError || error{
282 InvalidParameter,
283 };
284
285 pub const GetNextMonotonicCountError = uefi.UnexpectedError || error{
286 DeviceError,
287 InvalidParameter,
288 };
289
290 pub const SetWatchdogTimerError = uefi.UnexpectedError || error{
291 InvalidParameter,
292 Unsupported,
293 DeviceError,
294 };
295
296 pub const ConnectControllerError = uefi.UnexpectedError || error{
297 InvalidParameter,
298 NotFound,
299 SecurityViolation,
300 };
301
302 pub const DisconnectControllerError = uefi.UnexpectedError || error{
303 InvalidParameter,
304 OutOfResources,
305 DeviceError,
306 };
307
308 pub const OpenProtocolError = uefi.UnexpectedError || error{
309 InvalidParameter,
310 Unsupported,
311 AccessDenied,
312 AlreadyStarted,
313 };
314
315 pub const CloseProtocolError = uefi.UnexpectedError || error{
316 InvalidParameter,
317 NotFound,
318 };
319
320 pub const OpenProtocolInformationError = uefi.UnexpectedError || error{
321 OutOfResources,
322 };
323
324 pub const ProtocolsPerHandleError = uefi.UnexpectedError || error{
325 InvalidParameter,
326 OutOfResources,
327 };
328
329 pub const LocateHandleBufferError = uefi.UnexpectedError || error{
330 InvalidParameter,
331 OutOfResources,
332 };
333
334 pub const LocateProtocolError = uefi.UnexpectedError || error{
335 InvalidParameter,
336 };
337
338 pub const InstallProtocolInterfacesError = uefi.UnexpectedError || error{
339 AlreadyStarted,
340 OutOfResources,
341 InvalidParameter,
342 };
343
344 pub const UninstallProtocolInterfacesError = uefi.UnexpectedError || error{
345 InvalidParameter,
346 };
347
348 pub const CalculateCrc32Error = uefi.UnexpectedError || error{
349 InvalidParameter,
350 };
351
352 /// Allocates pages of memory.
353 ///
354 /// This function scans the memory map to locate free pages. When it finds a
355 /// physically contiguous block of pages that is large enough and also satisfies
356 /// the allocation requirements of `alloc_type`, it changes the memory map to
357 /// indicate that the pages are now of type `mem_type`.
358 ///
359 /// In general, UEFI OS loaders and UEFI applications should allocate memory
360 /// (and pool) of type `.loader_data`. UEFI boot service drivers must allocate
361 /// memory (and pool) of type `.boot_services_data`. UREFI runtime drivers
362 /// should allocate memory (and pool) of type `.runtime_services_data`
363 /// (although such allocation can only be made during boot services time).
364 ///
365 /// Allocation requests of `.allocate_any_pages` allocate any available range
366 /// of pages that satisfies the request.
367 ///
368 /// Allocation requests of `.allocate_max_address` allocate any available range
369 /// of pages whose uppermost address is less than or equal to the address
370 /// pointed to by the input.
371 ///
372 /// Allocation requests of `.allocate_address` allocate pages at the address
373 /// pointed to by the input.
374 pub fn allocatePages(
375 self: *BootServices,
376 location: AllocateLocation,
377 mem_type: MemoryType,
378 pages: usize,
379 ) AllocatePagesError![]align(4096) Page {
380 var ptr: [*]align(4096) Page = switch (location) {
381 .any => undefined,
382 .address, .max_address => |ptr| ptr,
383 };
384
385 switch (self._allocatePages(
386 std.meta.activeTag(location),
387 mem_type,
388 pages,
389 &ptr,
390 )) {
391 .success => return ptr[0..pages],
392 .out_of_resources => return error.OutOfResources,
393 .invalid_parameter => return error.InvalidParameter,
394 .not_found => return error.NotFound,
395 else => |status| return uefi.unexpectedStatus(status),
396 }
397 }
398
399 pub fn freePages(self: *BootServices, pages: []align(4096) Page) FreePagesError!void {
400 switch (self._freePages(pages.ptr, pages.len)) {
401 .success => {},
402 .not_found => return error.NotFound,
403 .invalid_parameter => return error.InvalidParameter,
404 else => |status| return uefi.unexpectedStatus(status),
405 }
406 }
407
408 pub fn getMemoryMapInfo(self: *const BootServices) uefi.UnexpectedError!MemoryMapInfo {
409 var info: MemoryMapInfo = undefined;
410 info.len = 0;
411
412 switch (self._getMemoryMap(
413 &info.len,
414 null,
415 &info.key,
416 &info.descriptor_size,
417 &info.descriptor_version,
418 )) {
419 .success, .buffer_too_small => {
420 info.len = @divExact(info.len, info.descriptor_size);
421 return info;
422 },
423 else => |status| return uefi.unexpectedStatus(status),
424 }
425 }
426
427 pub fn getMemoryMap(
428 self: *const BootServices,
429 buffer: []align(@alignOf(MemoryDescriptor)) u8,
430 ) GetMemoryMapError!MemoryMapSlice {
431 var info: MemoryMapInfo = undefined;
432 info.len = buffer.len;
433
434 switch (self._getMemoryMap(
435 &info.len,
436 buffer.ptr,
437 &info.key,
438 &info.descriptor_size,
439 &info.descriptor_version,
440 )) {
441 .success => {
442 info.len = @divExact(info.len, info.descriptor_size);
443 return .{ .info = info, .ptr = buffer.ptr };
444 },
445 .buffer_too_small => return error.BufferTooSmall,
446 .invalid_parameter => return error.InvalidParameter,
447 else => |status| return uefi.unexpectedStatus(status),
448 }
449 }
450
451 /// Allocates a memory region of `size` bytes from memory of type `pool_type`
452 /// and returns the allocated memory. Allocates pages from `.conventional_memory`
453 /// as needed to grow the requested pool type.
454 pub fn allocatePool(
455 self: *BootServices,
456 pool_type: MemoryType,
457 size: usize,
458 ) AllocatePoolError![]align(8) u8 {
459 var ptr: [*]align(8) u8 = undefined;
460
461 switch (self._allocatePool(pool_type, size, &ptr)) {
462 .success => return ptr[0..size],
463 .out_of_resources => return error.OutOfResources,
464 .invalid_parameter => return error.InvalidParameter,
465 else => |status| return uefi.unexpectedStatus(status),
466 }
467 }
468
469 pub fn freePool(self: *BootServices, ptr: [*]align(8) u8) FreePoolError!void {
470 switch (self._freePool(ptr)) {
471 .success => {},
472 .invalid_parameter => return error.InvalidParameter,
473 else => |status| return uefi.unexpectedStatus(status),
474 }
475 }
476
477 pub fn createEvent(
478 self: *BootServices,
479 event_type: uefi.EventType,
480 notify_opts: NotifyOpts,
481 ) CreateEventError!Event {
482 var evt: Event = undefined;
483
484 switch (self._createEvent(
485 @bitCast(event_type),
486 notify_opts.tpl,
487 notify_opts.function,
488 notify_opts.context,
489 &evt,
490 )) {
491 .success => return evt,
492 .invalid_parameter => return error.InvalidParameter,
493 .out_of_resources => return error.OutOfResources,
494 else => |status| return uefi.unexpectedStatus(status),
495 }
496 }
497
498 /// Cancels any previous time trigger setting for the event, and sets a new
499 /// trigger timer for the event.
500 ///
501 /// Returns `error.InvalidParameter` if the event is not a timer event.
502 pub fn setTimer(
503 self: *BootServices,
504 event: Event,
505 @"type": TimerDelay,
506 trigger_time: u64,
507 ) SetTimerError!void {
508 switch (self._setTimer(event, @"type", trigger_time)) {
509 .success => {},
510 .invalid_parameter => return error.InvalidParameter,
511 else => |status| return uefi.unexpectedStatus(status),
512 }
513 }
514
515 /// Returns the event that was signaled, along with its index in the slice.
516 pub fn waitForEvent(
517 self: *BootServices,
518 events: []const Event,
519 ) WaitForEventError!struct { *const Event, usize } {
520 var idx: usize = undefined;
521 switch (self._waitForEvent(events.len, events.ptr, &idx)) {
522 .success => return .{ &events[idx], idx },
523 .invalid_parameter => return error.InvalidParameter,
524 .unsupported => return error.Unsupported,
525 else => |status| return uefi.unexpectedStatus(status),
526 }
527 }
528
529 /// If `event` is `EventType.signal`, then the event’s notification function
530 /// is scheduled to be invoked at the event’s notification task priority level.
531 /// This function may be invoked from any task priority level.
532 ///
533 /// If the supplied Event is a part of an event group, then all of the events
534 /// in the event group are also signaled and their notification functions are
535 /// scheduled.
536 ///
537 /// When signaling an event group, it is possible to create an event in the
538 /// group, signal it and then close the event to remove it from the group.
539 pub fn signalEvent(self: *BootServices, event: Event) uefi.UnexpectedError!void {
540 switch (self._signalEvent(event)) {
541 .success => {},
542 else => |status| return uefi.unexpectedStatus(status),
543 }
544 }
545
546 pub fn closeEvent(self: *BootServices, event: Event) uefi.UnexpectedError!void {
547 switch (self._closeEvent(event)) {
548 .success => {},
549 else => |status| return uefi.unexpectedStatus(status),
550 }
551 }
552
553 /// Checks to see whether an event is signaled.
554 ///
555 /// The underlying function is equivalent to this pseudo-code:
556 /// ```
557 /// if (event.type.signal)
558 /// return error.InvalidParameter;
559 ///
560 /// if (event.signaled) {
561 /// event.signaled = false;
562 /// return true;
563 /// }
564 ///
565 /// const notify = event.notification_function orelse return false;
566 /// notify();
567 ///
568 /// if (event.signaled) {
569 /// event.signaled = false;
570 /// return true;
571 /// }
572 ///
573 /// return false;
574 /// ```
575 pub fn checkEvent(self: *BootServices, event: Event) CheckEventError!bool {
576 switch (self._checkEvent(event)) {
577 .success => return true,
578 .not_ready => return false,
579 .invalid_parameter => return error.InvalidParameter,
580 else => |status| return uefi.unexpectedStatus(status),
581 }
582 }
583
584 /// See `installProtocolInterfaces`.
585 ///
586 /// Does not call `self._installProtocolInterface`, because
587 /// `self._installMultipleProtocolInterfaces` performs more error checks.
588 pub fn installProtocolInterface(
589 self: *BootServices,
590 handle: ?Handle,
591 interface: anytype,
592 ) InstallProtocolInterfacesError!Handle {
593 return self.installProtocolInterfaces(handle, .{
594 interface,
595 });
596 }
597
598 /// Reinstalls a protocol interface on a device handle.
599 ///
600 /// `new` may be the same as `old`. If it is, the registered protocol notifications
601 /// occur for the handle without replacing the interface on the handle.
602 ///
603 /// Any process that has registered to wait for the installation of the interface
604 /// is notified.
605 ///
606 /// The caller is responsible for ensuring that there are no references to `old`
607 /// if it is being removed.
608 pub fn reinstallProtocolInterface(
609 self: *BootServices,
610 handle: Handle,
611 Protocol: type,
612 old: ?*const Protocol,
613 new: ?*const Protocol,
614 ) ReinstallProtocolInterfaceError!void {
615 if (!@hasDecl(Protocol, "guid"))
616 @compileError("protocol is missing guid");
617
618 switch (self._reinstallProtocolInterface(
619 handle,
620 &Protocol.guid,
621 old,
622 new,
623 )) {
624 .success => {},
625 .not_found => return error.NotFound,
626 .access_denied => return error.AccessDenied,
627 .invalid_parameter => return error.InvalidParameter,
628 else => |status| return uefi.unexpectedStatus(status),
629 }
630 }
631
632 /// See `uninstallProtocolInterfaces`.
633 ///
634 /// Does not call `self._uninstallProtocolInterface`, because
635 /// `self._uninstallMultipleProtocolInterfaces` performs more error checks.
636 pub fn uninstallProtocolInterface(
637 self: *BootServices,
638 handle: Handle,
639 interface: anytype,
640 ) UninstallProtocolInterfacesError!void {
641 return self.uninstallProtocolInterfaces(handle, .{
642 interface,
643 });
644 }
645
646 /// Returns a pointer to the `Protocol` interface if it's supported by the
647 /// handle.
648 ///
649 /// Note that UEFI implementations are no longer required to implement this
650 /// function, so it's implemented using `openProtocol` instead.
651 pub fn handleProtocol(
652 self: *BootServices,
653 Protocol: type,
654 handle: Handle,
655 ) HandleProtocolError!?*Protocol {
656 // per https://uefi.org/specs/UEFI/2.10/07_Services_Boot_Services.html#efi-boot-services-handleprotocol
657 // handleProtocol is basically `openProtocol` where:
658 // 1. agent_handle is `uefi.handle` (aka handle passed to `EfiMain`)
659 // 2. controller_handle is `null`
660 // 3. attributes is `EFI_OPEN_PROTOCOL_BY_HANDLE_PROTOCOL`
661
662 return self.openProtocol(
663 Protocol,
664 handle,
665 .{ .by_handle_protocol = .{ .agent = uefi.handle } },
666 ) catch |err| switch (err) {
667 error.AlreadyStarted => return uefi.unexpectedStatus(.already_started),
668 error.AccessDenied => return uefi.unexpectedStatus(.access_denied),
669 error.InvalidParameter => return uefi.unexpectedStatus(.invalid_parameter),
670 else => return @errorCast(err),
671 };
672 }
673
674 pub fn registerProtocolNotify(
675 self: *BootServices,
676 Protocol: type,
677 event: Event,
678 ) RegisterProtocolNotifyError!EventRegistration {
679 if (!@hasDecl(Protocol, "guid"))
680 @compileError("Protocol is missing guid");
681
682 var registration: EventRegistration = undefined;
683 switch (self._registerProtocolNotify(
684 &Protocol.guid,
685 event,
686 &registration,
687 )) {
688 .success => return registration,
689 .out_of_resources => return error.OutOfResources,
690 .invalid_parameter => return error.InvalidParameter,
691 else => |status| return uefi.unexpectedStatus(status),
692 }
693 }
694
695 /// Returns the number of handles that match the given search criteria.
696 pub fn locateHandleLen(self: *const BootServices, search: LocateSearch) NumHandlesError!usize {
697 var len: usize = 0;
698 switch (self._locateHandle(
699 std.meta.activeTag(search),
700 if (search == .by_protocol) search.by_protocol else null,
701 if (search == .by_register_notify) search.by_register_notify else null,
702 &len,
703 null,
704 )) {
705 .success => return @divExact(len, @sizeOf(Handle)),
706 .out_of_resources => return error.OutOfResources,
707 else => |status| return uefi.unexpectedStatus(status),
708 }
709 }
710
711 /// To determine the necessary size of `buffer`, call `locateHandleLen` first.
712 pub fn locateHandle(
713 self: *BootServices,
714 search: LocateSearch,
715 buffer: []Handle,
716 ) LocateHandleError![]Handle {
717 var len: usize = @sizeOf(Handle) * buffer.len;
718 switch (self._locateHandle(
719 std.meta.activeTag(search),
720 if (search == .by_protocol) search.by_protocol else null,
721 if (search == .by_register_notify) search.by_register_notify else null,
722 &len,
723 buffer.ptr,
724 )) {
725 .success => return buffer[0..@divExact(len, @sizeOf(Handle))],
726 .not_found => return buffer[0..0],
727 .buffer_too_small => return error.BufferTooSmall,
728 .invalid_parameter => return error.InvalidParameter,
729 else => |status| return uefi.unexpectedStatus(status),
730 }
731 }
732
733 /// Locates all devices on `device_path` that support `Protocol`. Once the closest
734 /// match to `device_path` is found, it returns the unmatched device path and handle.
735 pub fn locateDevicePath(
736 self: *const BootServices,
737 device_path: *const DevicePathProtocol,
738 Protocol: type,
739 ) LocateHandleError!?struct { *const DevicePathProtocol, Handle } {
740 if (!@hasDecl(Protocol, "guid"))
741 @compileError("Protocol is missing guid");
742
743 var dev_path = device_path;
744 var device: ?Handle = undefined;
745 switch (self._locateDevicePath(
746 &Protocol.guid,
747 &dev_path,
748 &device,
749 )) {
750 .success => return .{ dev_path, device.? },
751 .not_found => return null,
752 .invalid_parameter => return error.InvalidParameter,
753 else => |status| return uefi.unexpectedStatus(status),
754 }
755 }
756
757 pub fn installConfigurationTable(
758 self: *BootServices,
759 guid: *const Guid,
760 table: *anyopaque,
761 ) InstallConfigurationTableError!void {
762 switch (self._installConfigurationTable(
763 guid,
764 table,
765 )) {
766 .success => {},
767 .invalid_parameter => return error.InvalidParameter,
768 .out_of_resources => return error.OutOfResources,
769 else => |status| return uefi.unexpectedStatus(status),
770 }
771 }
772
773 pub fn uninstallConfigurationTable(
774 self: *BootServices,
775 guid: *const Guid,
776 ) UninstallConfigurationTableError!void {
777 switch (self._installConfigurationTable(
778 guid,
779 null,
780 )) {
781 .success => {},
782 .not_found => return error.NotFound,
783 .invalid_parameter => return error.InvalidParameter,
784 .out_of_resources => return error.OutOfResources,
785 else => |status| return uefi.unexpectedStatus(status),
786 }
787 }
788
789 pub const LoadImageSource = union(enum) {
790 buffer: []const u8,
791 device_path: *const DevicePathProtocol,
792 };
793
794 pub fn loadImage(
795 self: *BootServices,
796 boot_policy: bool,
797 parent_image: Handle,
798 source: LoadImageSource,
799 ) LoadImageError!Handle {
800 var handle: Handle = undefined;
801
802 switch (self._loadImage(
803 boot_policy,
804 parent_image,
805 if (source == .device_path) source.device_path else null,
806 if (source == .buffer) source.buffer.ptr else null,
807 if (source == .buffer) source.buffer.len else 0,
808 &handle,
809 )) {
810 .success => return handle,
811 .not_found => return error.NotFound,
812 .invalid_parameter => return error.InvalidParameter,
813 .unsupported => return error.Unsupported,
814 .out_of_resources => return error.OutOfResources,
815 .load_error => return error.LoadError,
816 .device_error => return error.DeviceError,
817 .access_denied => return error.AccessDenied,
818 .security_violation => return error.SecurityViolation,
819 else => |status| return uefi.unexpectedStatus(status),
820 }
821 }
822
823 pub fn startImage(self: *BootServices, image: Handle) StartImageError!ImageExitData {
824 var exit_data_size: usize = undefined;
825 var exit_data: [*]u16 = undefined;
826
827 const exit_code = switch (self._startImage(
828 image,
829 &exit_data_size,
830 &exit_data,
831 )) {
832 .invalid_parameter => return error.InvalidParameter,
833 .security_violation => return error.SecurityViolation,
834 else => |exit_code| exit_code,
835 };
836
837 if (exit_data_size == 0) return .{
838 .code = exit_code,
839 .description = null,
840 .data = null,
841 };
842
843 const description_ptr: [*:0]const u16 = @ptrCast(exit_data);
844 const description = std.mem.sliceTo(description_ptr, 0);
845
846 return ImageExitData{
847 .code = exit_code,
848 .description = description,
849 .data = exit_data[description.len + 1 .. exit_data_size],
850 };
851 }
852
853 /// `message` must be allocated using `allocatePool`.
854 pub fn exit(
855 self: *BootServices,
856 handle: Handle,
857 status: Status,
858 message: ?[:0]const u16,
859 ) ExitError!void {
860 switch (self._exit(
861 handle,
862 status,
863 if (message) |msg| (2 * msg.len) + 1 else 0,
864 if (message) |msg| @ptrCast(msg.ptr) else null,
865 )) {
866 .success => {},
867 .invalid_parameter => return error.InvalidParameter,
868 else => |exit_status| return uefi.unexpectedStatus(exit_status),
869 }
870 }
871
872 /// `message` should be a null-terminated u16 string followed by binary data
873 /// allocated using `allocatePool`.
874 pub fn exitWithData(
875 self: *BootServices,
876 handle: Handle,
877 status: Status,
878 data: []align(2) const u8,
879 ) ExitError!void {
880 switch (self._exit(handle, status, data.len, data.ptr)) {
881 .success => {},
882 .invalid_parameter => return error.InvalidParameter,
883 else => |exit_status| return uefi.unexpectedStatus(exit_status),
884 }
885 }
886
887 /// The result is the exit code of the unload handler. Any error codes are
888 /// `try/catch`-able, leaving only success and warning codes as the result.
889 pub fn unloadImage(
890 self: *BootServices,
891 image: Handle,
892 ) Status.Error!Status {
893 const status = self._unloadImage(image);
894 try status.err();
895 return status;
896 }
897
898 pub fn exitBootServices(
899 self: *BootServices,
900 image: Handle,
901 map_key: MemoryMapKey,
902 ) ExitBootServicesError!void {
903 switch (self._exitBootServices(image, map_key)) {
904 .success => {},
905 .invalid_parameter => return error.InvalidParameter,
906 else => |status| return uefi.unexpectedStatus(status),
907 }
908 }
909
910 pub fn getNextMonotonicCount(
911 self: *const BootServices,
912 count: *u64,
913 ) GetNextMonotonicCountError!void {
914 switch (self._getNextMonotonicCount(count)) {
915 .success => {},
916 .device_error => return error.DeviceError,
917 .invalid_parameter => return error.InvalidParameter,
918 else => |status| return uefi.unexpectedStatus(status),
919 }
920 }
921
922 pub fn stall(self: *const BootServices, microseconds: usize) uefi.UnexpectedError!void {
923 switch (self._stall(microseconds)) {
924 .success => {},
925 else => |status| return uefi.unexpectedStatus(status),
926 }
927 }
928
929 pub fn setWatchdogTimer(
930 self: *BootServices,
931 timeout: usize,
932 watchdog_code: u64,
933 data: ?[]const u16,
934 ) SetWatchdogTimerError!void {
935 switch (self._setWatchdogTimer(
936 timeout,
937 watchdog_code,
938 if (data) |d| d.len else 0,
939 if (data) |d| d.ptr else null,
940 )) {
941 .success => {},
942 .invalid_parameter => return error.InvalidParameter,
943 .unsupported => return error.Unsupported,
944 .device_error => return error.DeviceError,
945 else => |status| return uefi.unexpectedStatus(status),
946 }
947 }
948
949 /// `driver_image` should be a null-terminated ordered list of handles.
950 pub fn connectController(
951 self: *BootServices,
952 controller: Handle,
953 driver_image: ?[*:null]?Handle,
954 remaining_device_path: ?*const DevicePathProtocol,
955 recursive: bool,
956 ) ConnectControllerError!void {
957 switch (self._connectController(
958 controller,
959 driver_image,
960 remaining_device_path,
961 recursive,
962 )) {
963 .success => {},
964 .invalid_parameter => return error.InvalidParameter,
965 .not_found => return error.NotFound,
966 .security_violation => return error.SecurityViolation,
967 else => |status| return uefi.unexpectedStatus(status),
968 }
969 }
970
971 pub fn disconnectController(
972 self: *BootServices,
973 controller: Handle,
974 driver_image: ?Handle,
975 child: ?Handle,
976 ) DisconnectControllerError!void {
977 switch (self._disconnectController(
978 controller,
979 driver_image,
980 child,
981 )) {
982 .success => {},
983 .invalid_parameter => return error.InvalidParameter,
984 .out_of_resources => return error.OutOfResources,
985 .device_error => return error.DeviceError,
986 else => |status| return uefi.unexpectedStatus(status),
987 }
988 }
169989
170 /// Opens a protocol with a structure as the loaded image for a UEFI application990 /// Opens a protocol with a structure as the loaded image for a UEFI application
171 pub fn openProtocolSt(self: *BootServices, comptime protocol: type, handle: Handle) !*protocol {991 ///
172 if (!@hasDecl(protocol, "guid"))992 /// If `flag` is `.test_protocol`, then the only valid return value is `null`,
173 @compileError("Protocol is missing guid!");993 /// and `Status.unsupported` is returned. Otherwise, if `_openProtocol` returns
994 /// `Status.unsupported`, then `null` is returned.
995 pub fn openProtocol(
996 self: *BootServices,
997 Protocol: type,
998 handle: Handle,
999 attributes: OpenProtocolArgs,
1000 ) OpenProtocolError!?*Protocol {
1001 if (!@hasDecl(Protocol, "guid"))
1002 @compileError("Protocol is missing guid: " ++ @typeName(Protocol));
1741003
175 var ptr: ?*protocol = undefined;1004 const agent_handle: ?Handle, const controller_handle: ?Handle = switch (attributes) {
1005 inline else => |arg| .{ arg.agent, arg.controller },
1006 };
1761007
177 try self.openProtocol(1008 var ptr: ?*Protocol = undefined;
1009
1010 switch (self._openProtocol(
178 handle,1011 handle,
179 &protocol.guid,1012 &Protocol.guid,
180 @as(*?*anyopaque, @ptrCast(&ptr)),1013 @as(*?*anyopaque, @ptrCast(&ptr)),
181 // Invoking handle (loaded image)1014 agent_handle,
182 uefi.handle,1015 controller_handle,
183 // Control handle (null as not a driver)1016 std.meta.activeTag(attributes),
184 null,1017 )) {
185 uefi.tables.OpenProtocolAttributes{ .by_handle_protocol = true },1018 .success => return if (attributes == .test_protocol) null else ptr,
186 ).err();1019 .unsupported => return if (attributes == .test_protocol) error.Unsupported else null,
1020 .access_denied => return error.AccessDenied,
1021 .already_started => return error.AlreadyStarted,
1022 else => |status| return uefi.unexpectedStatus(status),
1023 }
1024 }
1025
1026 pub fn closeProtocol(
1027 self: *BootServices,
1028 handle: Handle,
1029 Protocol: type,
1030 agent: Handle,
1031 controller: ?Handle,
1032 ) CloseProtocolError!void {
1033 if (!@hasDecl(Protocol, "guid"))
1034 @compileError("protocol is missing guid: " ++ @typeName(Protocol));
1035
1036 switch (self._closeProtocol(
1037 handle,
1038 &Protocol.guid,
1039 agent,
1040 controller,
1041 )) {
1042 .success => {},
1043 .invalid_parameter => return error.InvalidParameter,
1044 .not_found => return error.NotFound,
1045 else => |status| return uefi.unexpectedStatus(status),
1046 }
1047 }
1048
1049 pub fn openProtocolInformation(
1050 self: *const BootServices,
1051 handle: Handle,
1052 Protocol: type,
1053 ) OpenProtocolInformationError!?[]ProtocolInformationEntry {
1054 var entries: [*]ProtocolInformationEntry = undefined;
1055 var len: usize = undefined;
1056
1057 switch (self._openProtocolInformation(
1058 handle,
1059 &Protocol.guid,
1060 &entries,
1061 &len,
1062 )) {
1063 .success => return entries[0..len],
1064 .not_found => return null,
1065 .out_of_resources => return error.OutOfResources,
1066 else => |status| return uefi.unexpectedStatus(status),
1067 }
1068 }
1069
1070 pub fn protocolsPerHandle(
1071 self: *const BootServices,
1072 handle: Handle,
1073 ) ProtocolsPerHandleError![]*const Guid {
1074 var guids: [*]*const Guid = undefined;
1075 var len: usize = undefined;
1076
1077 switch (self._protocolsPerHandle(
1078 handle,
1079 &guids,
1080 &len,
1081 )) {
1082 .success => return guids[0..len],
1083 .invalid_parameter => return error.InvalidParameter,
1084 .out_of_resources => return error.OutOfResources,
1085 else => |status| return uefi.unexpectedStatus(status),
1086 }
1087 }
1088
1089 pub fn locateHandleBuffer(
1090 self: *const BootServices,
1091 search: LocateSearch,
1092 ) LocateHandleBufferError!?[]Handle {
1093 var handles: [*]Handle = undefined;
1094 var len: usize = undefined;
1095
1096 switch (self._locateHandleBuffer(
1097 std.meta.activeTag(search),
1098 if (search == .by_protocol) search.by_protocol else null,
1099 if (search == .by_register_notify) search.by_register_notify else null,
1100 &len,
1101 &handles,
1102 )) {
1103 .success => return handles[0..len],
1104 .invalid_parameter => return error.InvalidParameter,
1105 .not_found => return null,
1106 .out_of_resources => return error.OutOfResources,
1107 else => |status| return uefi.unexpectedStatus(status),
1108 }
1109 }
1110
1111 pub fn locateProtocol(
1112 self: *const BootServices,
1113 Protocol: type,
1114 registration: ?EventRegistration,
1115 ) LocateProtocolError!?*Protocol {
1116 var interface: *Protocol = undefined;
1117
1118 switch (self._locateProtocol(
1119 &Protocol.guid,
1120 registration,
1121 @ptrCast(&interface),
1122 )) {
1123 .success => return interface,
1124 .not_found => return null,
1125 .invalid_parameter => return error.InvalidParameter,
1126 else => |status| return uefi.unexpectedStatus(status),
1127 }
1128 }
1129
1130 /// Installs a set of protocol interfaces into the boot services environment.
1131 ///
1132 /// This function's final argument should be a tuple of pointers to protocol
1133 /// interfaces. For example:
1134 ///
1135 /// ```
1136 /// const handle = try boot_services.installProtocolInterfaces(null, .{
1137 /// &my_interface_1,
1138 /// &my_interface_2,
1139 /// });
1140 /// ```
1141 ///
1142 /// The underlying function accepts a vararg list of pairs of Guid pointers
1143 /// and opaque pointers to the interface. To provide a guid, the interface
1144 /// types should declare a `guid` constant like so:
1145 ///
1146 /// ```
1147 /// pub const guid: uefi.Guid = .{ ... };
1148 /// ```
1149 ///
1150 /// See `std.os.uefi.protocol` for examples of protocol type definitions.
1151 pub fn installProtocolInterfaces(
1152 self: *BootServices,
1153 handle: ?Handle,
1154 interfaces: anytype,
1155 ) InstallProtocolInterfacesError!Handle {
1156 var hdl: ?Handle = handle;
1157 const args_tuple = protocolInterfaces(&hdl, interfaces);
1158
1159 switch (@call(
1160 .auto,
1161 self._installMultipleProtocolInterfaces,
1162 args_tuple,
1163 )) {
1164 .success => return hdl.?,
1165 .already_started => return error.AlreadyStarted,
1166 .out_of_resources => return error.OutOfResources,
1167 .invalid_parameter => return error.InvalidParameter,
1168 else => |status| return uefi.unexpectedStatus(status),
1169 }
1170 }
1171
1172 pub fn uninstallProtocolInterfaces(
1173 self: *BootServices,
1174 handle: Handle,
1175 interfaces: anytype,
1176 ) UninstallProtocolInterfacesError!void {
1177 const args_tuple = protocolInterfaces(handle, interfaces);
1871178
188 return ptr.?;1179 switch (@call(
1180 .auto,
1181 self._uninstallMultipleProtocolInterfaces,
1182 args_tuple,
1183 )) {
1184 .success => {},
1185 .invalid_parameter => return error.InvalidParameter,
1186 else => |status| return uefi.unexpectedStatus(status),
1187 }
1188 }
1189
1190 pub fn calculateCrc32(
1191 self: *const BootServices,
1192 data: []const u8,
1193 ) CalculateCrc32Error!u32 {
1194 var value: u32 = undefined;
1195 switch (self._calculateCrc32(data.ptr, data.len, &value)) {
1196 .success => return value,
1197 .invalid_parameter => return error.InvalidParameter,
1198 else => |status| return uefi.unexpectedStatus(status),
1199 }
189 }1200 }
1901201
191 pub const signature: u64 = 0x56524553544f4f42;1202 pub const signature: u64 = 0x56524553544f4f42;
1921203
193 pub const event_timer: u32 = 0x80000000;1204 pub const NotifyOpts = struct {
194 pub const event_runtime: u32 = 0x40000000;1205 tpl: TaskPriorityLevel = .application,
195 pub const event_notify_wait: u32 = 0x00000100;1206 function: ?*const fn (Event, ?*anyopaque) callconv(cc) void = null,
196 pub const event_notify_signal: u32 = 0x00000200;1207 context: ?*anyopaque = null,
197 pub const event_signal_exit_boot_services: u32 = 0x00000201;1208 };
198 pub const event_signal_virtual_address_change: u32 = 0x00000202;1209
1991210 pub const TaskPriorityLevel = enum(usize) {
200 pub const tpl_application: usize = 4;1211 application = 4,
201 pub const tpl_callback: usize = 8;1212 callback = 8,
202 pub const tpl_notify: usize = 16;1213 notify = 16,
203 pub const tpl_high_level: usize = 31;1214 high_level = 31,
1215 _,
1216 };
1217
1218 pub const ImageExitData = struct {
1219 code: Status,
1220 description: ?[:0]const u16,
1221 data: ?[]const u16,
1222 };
204};1223};
1224
1225fn protocolInterfaces(
1226 handle_arg: anytype,
1227 interfaces: anytype,
1228) ProtocolInterfaces(@TypeOf(handle_arg), @TypeOf(interfaces)) {
1229 var result: ProtocolInterfaces(
1230 @TypeOf(handle_arg),
1231 @TypeOf(interfaces),
1232 ) = undefined;
1233 result[0] = handle_arg;
1234
1235 var idx: usize = 1;
1236 inline for (interfaces) |interface| {
1237 const InterfacePtr = @TypeOf(interface);
1238 const Interface = switch (@typeInfo(InterfacePtr)) {
1239 .pointer => |pointer| pointer.child,
1240 else => @compileError("expected tuple of '*const Protocol', got " ++ @typeName(InterfacePtr)),
1241 };
1242
1243 if (!@hasDecl(Interface, "guid"))
1244 @compileError("protocol interface '" ++ @typeName(Interface) ++
1245 "' does not declare a 'const guid: uefi.Guid'.");
1246
1247 switch (@typeInfo(Interface)) {
1248 .@"struct" => |struct_info| if (struct_info.layout != .@"extern")
1249 @compileLog("protocol interface '" ++ @typeName(Interface) ++
1250 "' is not extern - this is likely a mistake"),
1251 else => @compileError("protocol interface must be a struct, got " ++ @typeName(Interface)),
1252 }
1253
1254 result[idx] = &Interface.guid;
1255 result[idx + 1] = @ptrCast(interface);
1256 idx += 2;
1257 }
1258
1259 return result;
1260}
1261
1262fn ProtocolInterfaces(HandleType: type, Interfaces: type) type {
1263 const interfaces_type_info = @typeInfo(Interfaces);
1264 if (interfaces_type_info != .@"struct" or !interfaces_type_info.@"struct".is_tuple)
1265 @compileError("expected tuple of protocol interfaces, got " ++ @typeName(Interfaces));
1266 const interfaces_info = interfaces_type_info.@"struct";
1267
1268 var tuple_types: [interfaces_info.fields.len * 2 + 1]type = undefined;
1269 tuple_types[0] = HandleType;
1270 var idx = 1;
1271 while (idx < tuple_types.len) : (idx += 2) {
1272 tuple_types[idx] = *const Guid;
1273 tuple_types[idx + 1] = *const anyopaque;
1274 }
1275
1276 return std.meta.Tuple(tuple_types[0..]);
1277}
lib/std/os/uefi/tables/configuration_table.zig+9-9
...@@ -5,7 +5,7 @@ pub const ConfigurationTable = extern struct {...@@ -5,7 +5,7 @@ pub const ConfigurationTable = extern struct {
5 vendor_guid: Guid,5 vendor_guid: Guid,
6 vendor_table: *anyopaque,6 vendor_table: *anyopaque,
77
8 pub const acpi_20_table_guid align(8) = Guid{8 pub const acpi_20_table_guid: Guid = .{
9 .time_low = 0x8868e871,9 .time_low = 0x8868e871,
10 .time_mid = 0xe4f1,10 .time_mid = 0xe4f1,
11 .time_high_and_version = 0x11d3,11 .time_high_and_version = 0x11d3,
...@@ -13,7 +13,7 @@ pub const ConfigurationTable = extern struct {...@@ -13,7 +13,7 @@ pub const ConfigurationTable = extern struct {
13 .clock_seq_low = 0x22,13 .clock_seq_low = 0x22,
14 .node = [_]u8{ 0x00, 0x80, 0xc7, 0x3c, 0x88, 0x81 },14 .node = [_]u8{ 0x00, 0x80, 0xc7, 0x3c, 0x88, 0x81 },
15 };15 };
16 pub const acpi_10_table_guid align(8) = Guid{16 pub const acpi_10_table_guid: Guid = .{
17 .time_low = 0xeb9d2d30,17 .time_low = 0xeb9d2d30,
18 .time_mid = 0x2d88,18 .time_mid = 0x2d88,
19 .time_high_and_version = 0x11d3,19 .time_high_and_version = 0x11d3,
...@@ -21,7 +21,7 @@ pub const ConfigurationTable = extern struct {...@@ -21,7 +21,7 @@ pub const ConfigurationTable = extern struct {
21 .clock_seq_low = 0x16,21 .clock_seq_low = 0x16,
22 .node = [_]u8{ 0x00, 0x90, 0x27, 0x3f, 0xc1, 0x4d },22 .node = [_]u8{ 0x00, 0x90, 0x27, 0x3f, 0xc1, 0x4d },
23 };23 };
24 pub const sal_system_table_guid align(8) = Guid{24 pub const sal_system_table_guid: Guid = .{
25 .time_low = 0xeb9d2d32,25 .time_low = 0xeb9d2d32,
26 .time_mid = 0x2d88,26 .time_mid = 0x2d88,
27 .time_high_and_version = 0x113d,27 .time_high_and_version = 0x113d,
...@@ -29,7 +29,7 @@ pub const ConfigurationTable = extern struct {...@@ -29,7 +29,7 @@ pub const ConfigurationTable = extern struct {
29 .clock_seq_low = 0x16,29 .clock_seq_low = 0x16,
30 .node = [_]u8{ 0x00, 0x90, 0x27, 0x3f, 0xc1, 0x4d },30 .node = [_]u8{ 0x00, 0x90, 0x27, 0x3f, 0xc1, 0x4d },
31 };31 };
32 pub const smbios_table_guid align(8) = Guid{32 pub const smbios_table_guid: Guid = .{
33 .time_low = 0xeb9d2d31,33 .time_low = 0xeb9d2d31,
34 .time_mid = 0x2d88,34 .time_mid = 0x2d88,
35 .time_high_and_version = 0x11d3,35 .time_high_and_version = 0x11d3,
...@@ -37,7 +37,7 @@ pub const ConfigurationTable = extern struct {...@@ -37,7 +37,7 @@ pub const ConfigurationTable = extern struct {
37 .clock_seq_low = 0x16,37 .clock_seq_low = 0x16,
38 .node = [_]u8{ 0x00, 0x90, 0x27, 0x3f, 0xc1, 0x4d },38 .node = [_]u8{ 0x00, 0x90, 0x27, 0x3f, 0xc1, 0x4d },
39 };39 };
40 pub const smbios3_table_guid align(8) = Guid{40 pub const smbios3_table_guid: Guid = .{
41 .time_low = 0xf2fd1544,41 .time_low = 0xf2fd1544,
42 .time_mid = 0x9794,42 .time_mid = 0x9794,
43 .time_high_and_version = 0x4a2c,43 .time_high_and_version = 0x4a2c,
...@@ -45,7 +45,7 @@ pub const ConfigurationTable = extern struct {...@@ -45,7 +45,7 @@ pub const ConfigurationTable = extern struct {
45 .clock_seq_low = 0x2e,45 .clock_seq_low = 0x2e,
46 .node = [_]u8{ 0xe5, 0xbb, 0xcf, 0x20, 0xe3, 0x94 },46 .node = [_]u8{ 0xe5, 0xbb, 0xcf, 0x20, 0xe3, 0x94 },
47 };47 };
48 pub const mps_table_guid align(8) = Guid{48 pub const mps_table_guid: Guid = .{
49 .time_low = 0xeb9d2d2f,49 .time_low = 0xeb9d2d2f,
50 .time_mid = 0x2d88,50 .time_mid = 0x2d88,
51 .time_high_and_version = 0x11d3,51 .time_high_and_version = 0x11d3,
...@@ -53,7 +53,7 @@ pub const ConfigurationTable = extern struct {...@@ -53,7 +53,7 @@ pub const ConfigurationTable = extern struct {
53 .clock_seq_low = 0x16,53 .clock_seq_low = 0x16,
54 .node = [_]u8{ 0x00, 0x90, 0x27, 0x3f, 0xc1, 0x4d },54 .node = [_]u8{ 0x00, 0x90, 0x27, 0x3f, 0xc1, 0x4d },
55 };55 };
56 pub const json_config_data_table_guid align(8) = Guid{56 pub const json_config_data_table_guid: Guid = .{
57 .time_low = 0x87367f87,57 .time_low = 0x87367f87,
58 .time_mid = 0x1119,58 .time_mid = 0x1119,
59 .time_high_and_version = 0x41ce,59 .time_high_and_version = 0x41ce,
...@@ -61,7 +61,7 @@ pub const ConfigurationTable = extern struct {...@@ -61,7 +61,7 @@ pub const ConfigurationTable = extern struct {
61 .clock_seq_low = 0xec,61 .clock_seq_low = 0xec,
62 .node = [_]u8{ 0x8b, 0xe0, 0x11, 0x1f, 0x55, 0x8a },62 .node = [_]u8{ 0x8b, 0xe0, 0x11, 0x1f, 0x55, 0x8a },
63 };63 };
64 pub const json_capsule_data_table_guid align(8) = Guid{64 pub const json_capsule_data_table_guid: Guid = .{
65 .time_low = 0x35e7a725,65 .time_low = 0x35e7a725,
66 .time_mid = 0x8dd2,66 .time_mid = 0x8dd2,
67 .time_high_and_version = 0x4cac,67 .time_high_and_version = 0x4cac,
...@@ -69,7 +69,7 @@ pub const ConfigurationTable = extern struct {...@@ -69,7 +69,7 @@ pub const ConfigurationTable = extern struct {
69 .clock_seq_low = 0x11,69 .clock_seq_low = 0x11,
70 .node = [_]u8{ 0x33, 0xcd, 0xa8, 0x10, 0x90, 0x56 },70 .node = [_]u8{ 0x33, 0xcd, 0xa8, 0x10, 0x90, 0x56 },
71 };71 };
72 pub const json_capsule_result_table_guid align(8) = Guid{72 pub const json_capsule_result_table_guid: Guid = .{
73 .time_low = 0xdbc461c3,73 .time_low = 0xdbc461c3,
74 .time_mid = 0xb3de,74 .time_mid = 0xb3de,
75 .time_high_and_version = 0x422a,75 .time_high_and_version = 0x422a,
lib/std/os/uefi/tables/runtime_services.zig+477-14
...@@ -6,10 +6,12 @@ const Time = uefi.Time;...@@ -6,10 +6,12 @@ const Time = uefi.Time;
6const TimeCapabilities = uefi.TimeCapabilities;6const TimeCapabilities = uefi.TimeCapabilities;
7const Status = uefi.Status;7const Status = uefi.Status;
8const MemoryDescriptor = uefi.tables.MemoryDescriptor;8const MemoryDescriptor = uefi.tables.MemoryDescriptor;
9const MemoryMapSlice = uefi.tables.MemoryMapSlice;
9const ResetType = uefi.tables.ResetType;10const ResetType = uefi.tables.ResetType;
10const CapsuleHeader = uefi.tables.CapsuleHeader;11const CapsuleHeader = uefi.tables.CapsuleHeader;
11const PhysicalAddress = uefi.tables.PhysicalAddress;12const PhysicalAddress = uefi.tables.PhysicalAddress;
12const cc = uefi.cc;13const cc = uefi.cc;
14const Error = Status.Error;
1315
14/// Runtime services are provided by the firmware before and after exitBootServices has been called.16/// Runtime services are provided by the firmware before and after exitBootServices has been called.
15///17///
...@@ -23,50 +25,511 @@ pub const RuntimeServices = extern struct {...@@ -23,50 +25,511 @@ pub const RuntimeServices = extern struct {
23 hdr: TableHeader,25 hdr: TableHeader,
2426
25 /// Returns the current time and date information, and the time-keeping capabilities of the hardware platform.27 /// Returns the current time and date information, and the time-keeping capabilities of the hardware platform.
26 getTime: *const fn (time: *uefi.Time, capabilities: ?*TimeCapabilities) callconv(cc) Status,28 _getTime: *const fn (time: *Time, capabilities: ?*TimeCapabilities) callconv(cc) Status,
2729
28 /// Sets the current local time and date information30 /// Sets the current local time and date information
29 setTime: *const fn (time: *uefi.Time) callconv(cc) Status,31 _setTime: *const fn (time: *const Time) callconv(cc) Status,
3032
31 /// Returns the current wakeup alarm clock setting33 /// Returns the current wakeup alarm clock setting
32 getWakeupTime: *const fn (enabled: *bool, pending: *bool, time: *uefi.Time) callconv(cc) Status,34 _getWakeupTime: *const fn (enabled: *bool, pending: *bool, time: *Time) callconv(cc) Status,
3335
34 /// Sets the system wakeup alarm clock time36 /// Sets the system wakeup alarm clock time
35 setWakeupTime: *const fn (enable: *bool, time: ?*uefi.Time) callconv(cc) Status,37 _setWakeupTime: *const fn (enable: bool, time: ?*const Time) callconv(cc) Status,
3638
37 /// Changes the runtime addressing mode of EFI firmware from physical to virtual.39 /// Changes the runtime addressing mode of EFI firmware from physical to virtual.
38 setVirtualAddressMap: *const fn (mmap_size: usize, descriptor_size: usize, descriptor_version: u32, virtual_map: [*]MemoryDescriptor) callconv(cc) Status,40 _setVirtualAddressMap: *const fn (mmap_size: usize, descriptor_size: usize, descriptor_version: u32, virtual_map: [*]align(@alignOf(MemoryDescriptor)) u8) callconv(cc) Status,
3941
40 /// Determines the new virtual address that is to be used on subsequent memory accesses.42 /// Determines the new virtual address that is to be used on subsequent memory accesses.
41 convertPointer: *const fn (debug_disposition: usize, address: **anyopaque) callconv(cc) Status,43 _convertPointer: *const fn (debug_disposition: DebugDisposition, address: *?*anyopaque) callconv(cc) Status,
4244
43 /// Returns the value of a variable.45 /// Returns the value of a variable.
44 getVariable: *const fn (var_name: [*:0]const u16, vendor_guid: *align(8) const Guid, attributes: ?*u32, data_size: *usize, data: ?*anyopaque) callconv(cc) Status,46 _getVariable: *const fn (var_name: [*:0]const u16, vendor_guid: *const Guid, attributes: ?*VariableAttributes, data_size: *usize, data: ?*anyopaque) callconv(cc) Status,
4547
46 /// Enumerates the current variable names.48 /// Enumerates the current variable names.
47 getNextVariableName: *const fn (var_name_size: *usize, var_name: [*:0]u16, vendor_guid: *align(8) Guid) callconv(cc) Status,49 _getNextVariableName: *const fn (var_name_size: *usize, var_name: ?[*:0]const u16, vendor_guid: *Guid) callconv(cc) Status,
4850
49 /// Sets the value of a variable.51 /// Sets the value of a variable.
50 setVariable: *const fn (var_name: [*:0]const u16, vendor_guid: *align(8) const Guid, attributes: u32, data_size: usize, data: *anyopaque) callconv(cc) Status,52 _setVariable: *const fn (var_name: [*:0]const u16, vendor_guid: *const Guid, attributes: VariableAttributes, data_size: usize, data: [*]const u8) callconv(cc) Status,
5153
52 /// Return the next high 32 bits of the platform's monotonic counter54 /// Return the next high 32 bits of the platform's monotonic counter
53 getNextHighMonotonicCount: *const fn (high_count: *u32) callconv(cc) Status,55 _getNextHighMonotonicCount: *const fn (high_count: *u32) callconv(cc) Status,
5456
55 /// Resets the entire platform.57 /// Resets the entire platform.
56 resetSystem: *const fn (reset_type: ResetType, reset_status: Status, data_size: usize, reset_data: ?*const anyopaque) callconv(cc) noreturn,58 _resetSystem: *const fn (reset_type: ResetType, reset_status: Status, data_size: usize, reset_data: ?[*]const u16) callconv(cc) noreturn,
5759
58 /// Passes capsules to the firmware with both virtual and physical mapping.60 /// Passes capsules to the firmware with both virtual and physical mapping.
59 /// Depending on the intended consumption, the firmware may process the capsule immediately.61 /// Depending on the intended consumption, the firmware may process the capsule immediately.
60 /// If the payload should persist across a system reset, the reset value returned from62 /// If the payload should persist across a system reset, the reset value returned from
61 /// `queryCapsuleCapabilities` must be passed into resetSystem and will cause the capsule63 /// `queryCapsuleCapabilities` must be passed into resetSystem and will cause the capsule
62 /// to be processed by the firmware as part of the reset process.64 /// to be processed by the firmware as part of the reset process.
63 updateCapsule: *const fn (capsule_header_array: **CapsuleHeader, capsule_count: usize, scatter_gather_list: PhysicalAddress) callconv(cc) Status,65 _updateCapsule: *const fn (capsule_header_array: [*]*const CapsuleHeader, capsule_count: usize, scatter_gather_list: PhysicalAddress) callconv(cc) Status,
6466
65 /// Returns if the capsule can be supported via `updateCapsule`67 /// Returns if the capsule can be supported via `updateCapsule`
66 queryCapsuleCapabilities: *const fn (capsule_header_array: **CapsuleHeader, capsule_count: usize, maximum_capsule_size: *usize, reset_type: ResetType) callconv(cc) Status,68 _queryCapsuleCapabilities: *const fn (capsule_header_array: [*]*const CapsuleHeader, capsule_count: usize, maximum_capsule_size: *usize, reset_type: *ResetType) callconv(cc) Status,
6769
68 /// Returns information about the EFI variables70 /// Returns information about the EFI variables
69 queryVariableInfo: *const fn (attributes: *u32, maximum_variable_storage_size: *u64, remaining_variable_storage_size: *u64, maximum_variable_size: *u64) callconv(cc) Status,71 _queryVariableInfo: *const fn (attributes: VariableAttributes, maximum_variable_storage_size: *u64, remaining_variable_storage_size: *u64, maximum_variable_size: *u64) callconv(cc) Status,
72
73 pub const GetTimeError = uefi.UnexpectedError || error{
74 DeviceError,
75 Unsupported,
76 };
77
78 pub const SetTimeError = uefi.UnexpectedError || error{
79 DeviceError,
80 Unsupported,
81 };
82
83 pub const GetWakeupTimeError = uefi.UnexpectedError || error{
84 DeviceError,
85 Unsupported,
86 };
87
88 pub const SetWakeupTimeError = uefi.UnexpectedError || error{
89 InvalidParameter,
90 DeviceError,
91 Unsupported,
92 };
93
94 pub const SetVirtualAddressMapError = uefi.UnexpectedError || error{
95 Unsupported,
96 NoMapping,
97 NotFound,
98 };
99
100 pub const ConvertPointerError = uefi.UnexpectedError || error{
101 InvalidParameter,
102 Unsupported,
103 };
104
105 pub const GetVariableSizeError = uefi.UnexpectedError || error{
106 DeviceError,
107 Unsupported,
108 };
109
110 pub const GetVariableError = GetVariableSizeError || error{
111 BufferTooSmall,
112 };
113
114 pub const SetVariableError = uefi.UnexpectedError || error{
115 InvalidParameter,
116 OutOfResources,
117 DeviceError,
118 WriteProtected,
119 SecurityViolation,
120 NotFound,
121 Unsupported,
122 };
123
124 pub const GetNextHighMonotonicCountError = uefi.UnexpectedError || error{
125 DeviceError,
126 Unsupported,
127 };
128
129 pub const UpdateCapsuleError = uefi.UnexpectedError || error{
130 InvalidParameter,
131 DeviceError,
132 Unsupported,
133 OutOfResources,
134 };
135
136 pub const QueryCapsuleCapabilitiesError = uefi.UnexpectedError || error{
137 Unsupported,
138 OutOfResources,
139 };
140
141 pub const QueryVariableInfoError = uefi.UnexpectedError || error{
142 InvalidParameter,
143 Unsupported,
144 };
145
146 /// Returns the current time and the time capabilities of the platform.
147 pub fn getTime(
148 self: *const RuntimeServices,
149 ) GetTimeError!struct { Time, TimeCapabilities } {
150 var time: Time = undefined;
151 var capabilities: TimeCapabilities = undefined;
152
153 switch (self._getTime(&time, &capabilities)) {
154 .success => return .{ time, capabilities },
155 .device_error => return error.DeviceError,
156 .unsupported => return error.Unsupported,
157 else => |status| return uefi.unexpectedStatus(status),
158 }
159 }
160
161 pub fn setTime(self: *RuntimeServices, time: *const Time) SetTimeError!void {
162 switch (self._setTime(time)) {
163 .success => {},
164 .device_error => return error.DeviceError,
165 .unsupported => return error.Unsupported,
166 else => |status| return uefi.unexpectedStatus(status),
167 }
168 }
169
170 pub const GetWakeupTime = struct {
171 enabled: bool,
172 pending: bool,
173 time: Time,
174 };
175
176 pub fn getWakeupTime(
177 self: *const RuntimeServices,
178 ) GetWakeupTimeError!GetWakeupTime {
179 var result: GetWakeupTime = undefined;
180 switch (self._getWakeupTime(
181 &result.enabled,
182 &result.pending,
183 &result.time,
184 )) {
185 .success => return result,
186 .device_error => return error.DeviceError,
187 .unsupported => return error.Unsupported,
188 else => |status| return uefi.unexpectedStatus(status),
189 }
190 }
191
192 pub const SetWakeupTime = union(enum) {
193 enabled: *const Time,
194 disabled,
195 };
196
197 pub fn setWakeupTime(
198 self: *RuntimeServices,
199 set: SetWakeupTime,
200 ) SetWakeupTimeError!void {
201 switch (self._setWakeupTime(
202 set != .disabled,
203 if (set == .enabled) set.enabled else null,
204 )) {
205 .success => {},
206 .invalid_parameter => return error.InvalidParameter,
207 .device_error => return error.DeviceError,
208 .unsupported => return error.Unsupported,
209 else => |status| return uefi.unexpectedStatus(status),
210 }
211 }
212
213 pub fn setVirtualAddressMap(
214 self: *RuntimeServices,
215 map: MemoryMapSlice,
216 ) SetVirtualAddressMapError!void {
217 switch (self._setVirtualAddressMap(
218 map.info.len * map.info.descriptor_size,
219 map.info.descriptor_size,
220 map.info.descriptor_version,
221 @ptrCast(map.ptr),
222 )) {
223 .success => {},
224 .unsupported => return error.Unsupported,
225 .no_mapping => return error.NoMapping,
226 .not_found => return error.NotFound,
227 else => |status| return uefi.unexpectedStatus(status),
228 }
229 }
230
231 pub fn convertPointer(
232 self: *const RuntimeServices,
233 comptime disposition: DebugDisposition,
234 cvt: @FieldType(PointerConversion, @tagName(disposition)),
235 ) ConvertPointerError!?@FieldType(PointerConversion, @tagName(disposition)) {
236 var pointer = cvt;
237
238 switch (self._convertPointer(disposition, @ptrCast(&pointer))) {
239 .success => return pointer,
240 .not_found => return null,
241 .invalid_parameter => return error.InvalidParameter,
242 .unsupported => return error.Unsupported,
243 else => |status| return uefi.unexpectedStatus(status),
244 }
245 }
246
247 /// Returns the length of the variable's data and its attributes.
248 pub fn getVariableSize(
249 self: *const RuntimeServices,
250 name: [*:0]const u16,
251 guid: *const Guid,
252 ) GetVariableSizeError!?struct { usize, VariableAttributes } {
253 var size: usize = 0;
254 var attrs: VariableAttributes = undefined;
255
256 switch (self._getVariable(
257 name,
258 guid,
259 &attrs,
260 &size,
261 null,
262 )) {
263 .buffer_too_small => return .{ size, attrs },
264 .not_found => return null,
265 .device_error => return error.DeviceError,
266 .unsupported => return error.Unsupported,
267 else => |status| return uefi.unexpectedStatus(status),
268 }
269 }
270
271 /// To determine the minimum necessary buffer size for the variable, call
272 /// `getVariableSize` first.
273 pub fn getVariable(
274 self: *const RuntimeServices,
275 name: [*:0]const u16,
276 guid: *const Guid,
277 buffer: []u8,
278 ) GetVariableError!?struct { []u8, VariableAttributes } {
279 var attrs: VariableAttributes = undefined;
280 var len = buffer.len;
281
282 switch (self._getVariable(
283 name,
284 guid,
285 &attrs,
286 &len,
287 buffer.ptr,
288 )) {
289 .success => return .{ buffer[0..len], attrs },
290 .not_found => return null,
291 .buffer_too_small => return error.BufferTooSmall,
292 .device_error => return error.DeviceError,
293 .unsupported => return error.Unsupported,
294 else => |status| return uefi.unexpectedStatus(status),
295 }
296 }
297
298 pub fn variableNameIterator(
299 self: *const RuntimeServices,
300 buffer: []u16,
301 ) VariableNameIterator {
302 buffer[0] = 0;
303 return .{
304 .services = self,
305 .buffer = buffer,
306 .guid = undefined,
307 };
308 }
309
310 pub fn setVariable(
311 self: *RuntimeServices,
312 name: [*:0]const u16,
313 guid: *const Guid,
314 attributes: VariableAttributes,
315 data: []const u8,
316 ) SetVariableError!void {
317 switch (self._setVariable(
318 name,
319 guid,
320 attributes,
321 data.len,
322 data.ptr,
323 )) {
324 .success => {},
325 .invalid_parameter => return error.InvalidParameter,
326 .out_of_resources => return error.OutOfResources,
327 .device_error => return error.DeviceError,
328 .write_protected => return error.WriteProtected,
329 .security_violation => return error.SecurityViolation,
330 .not_found => return error.NotFound,
331 .unsupported => return error.Unsupported,
332 else => |status| return uefi.unexpectedStatus(status),
333 }
334 }
335
336 pub fn getNextHighMonotonicCount(self: *const RuntimeServices) GetNextHighMonotonicCountError!u32 {
337 var cnt: u32 = undefined;
338 switch (self._getNextHighMonotonicCount(&cnt)) {
339 .success => return cnt,
340 .device_error => return error.DeviceError,
341 .unsupported => return error.Unsupported,
342 else => |status| return uefi.unexpectedStatus(status),
343 }
344 }
345
346 pub fn resetSystem(
347 self: *RuntimeServices,
348 reset_type: ResetType,
349 reset_status: Status,
350 data: ?[]align(2) const u8,
351 ) noreturn {
352 self._resetSystem(
353 reset_type,
354 reset_status,
355 if (data) |d| d.len else 0,
356 if (data) |d| @alignCast(@ptrCast(d.ptr)) else null,
357 );
358 }
359
360 pub fn updateCapsule(
361 self: *RuntimeServices,
362 capsules: []*const CapsuleHeader,
363 scatter_gather_list: PhysicalAddress,
364 ) UpdateCapsuleError!void {
365 switch (self._updateCapsule(
366 capsules.ptr,
367 capsules.len,
368 scatter_gather_list,
369 )) {
370 .success => {},
371 .invalid_parameter => return error.InvalidParameter,
372 .device_error => return error.DeviceError,
373 .unsupported => return error.Unsupported,
374 .out_of_resources => return error.OutOfResources,
375 else => |status| return uefi.unexpectedStatus(status),
376 }
377 }
378
379 pub fn queryCapsuleCapabilities(
380 self: *const RuntimeServices,
381 capsules: []*const CapsuleHeader,
382 ) QueryCapsuleCapabilitiesError!struct { u64, ResetType } {
383 var max_capsule_size: u64 = undefined;
384 var reset_type: ResetType = undefined;
385
386 switch (self._queryCapsuleCapabilities(
387 capsules.ptr,
388 capsules.len,
389 &max_capsule_size,
390 &reset_type,
391 )) {
392 .success => return .{ max_capsule_size, reset_type },
393 .unsupported => return error.Unsupported,
394 .out_of_resources => return error.OutOfResources,
395 else => |status| return uefi.unexpectedStatus(status),
396 }
397 }
398
399 pub fn queryVariableInfo(
400 self: *const RuntimeServices,
401 // Note: .append_write is ignored
402 attributes: VariableAttributes,
403 ) QueryVariableInfoError!VariableInfo {
404 var res: VariableInfo = undefined;
405
406 switch (self._queryVariableInfo(
407 attributes,
408 &res.max_variable_storage_size,
409 &res.remaining_variable_storage_size,
410 &res.max_variable_size,
411 )) {
412 .success => return res,
413 .invalid_parameter => return error.InvalidParameter,
414 .unsupported => return error.Unsupported,
415 else => |status| return uefi.unexpectedStatus(status),
416 }
417 }
418
419 pub const DebugDisposition = enum(usize) {
420 const Bits = packed struct(usize) {
421 optional_ptr: bool = false,
422 _pad: std.meta.Int(.unsigned, @bitSizeOf(usize) - 1) = 0,
423 };
424
425 pointer = @bitCast(Bits{}),
426 optional = @bitCast(Bits{ .optional_ptr = true }),
427 _,
428 };
429
430 pub const PointerConversion = union(DebugDisposition) {
431 pointer: *anyopaque,
432 optional: ?*anyopaque,
433 };
434
435 pub const VariableAttributes = packed struct(u32) {
436 non_volatile: bool = false,
437 bootservice_access: bool = false,
438 runtime_access: bool = false,
439 hardware_error_record: bool = false,
440 /// Note: deprecated and should be considered reserved.
441 authenticated_write_access: bool = false,
442 time_based_authenticated_write_access: bool = false,
443 append_write: bool = false,
444 /// Indicates that the variable payload begins with a EFI_VARIABLE_AUTHENTICATION_3
445 /// structure, and potentially more structures as indicated by fields of
446 /// this structure.
447 enhanced_authenticated_access: bool = false,
448 _pad: u24 = 0,
449 };
450
451 pub const VariableAuthentication3 = extern struct {
452 version: u8 = 1,
453 type: Type,
454 metadata_size: u32,
455 flags: Flags,
456
457 pub fn payloadConst(self: *const VariableAuthentication3) []const u8 {
458 return @constCast(self).payload();
459 }
460
461 pub fn payload(self: *VariableAuthentication3) []u8 {
462 var ptr: [*]u8 = @ptrCast(self);
463 return ptr[@sizeOf(VariableAuthentication3)..self.metadata_size];
464 }
465
466 pub const Flags = packed struct(u32) {
467 update_cert: bool = false,
468 _pad: u31 = 0,
469 };
470
471 pub const Type = enum(u8) {
472 timestamp = 1,
473 nonce = 2,
474 _,
475 };
476 };
477
478 pub const VariableInfo = struct {
479 max_variable_storage_size: u64,
480 remaining_variable_storage_size: u64,
481 max_variable_size: u64,
482 };
483
484 pub const VariableNameIterator = struct {
485 pub const NextSizeError = uefi.UnexpectedError || error{
486 DeviceError,
487 Unsupported,
488 };
489
490 pub const IterateVariableNameError = NextSizeError || error{
491 BufferTooSmall,
492 };
493
494 services: *const RuntimeServices,
495 buffer: []u16,
496 guid: Guid,
497
498 pub fn nextSize(self: *VariableNameIterator) NextSizeError!?usize {
499 var len: usize = 0;
500 switch (self.services._getNextVariableName(
501 &len,
502 null,
503 &self.guid,
504 )) {
505 .buffer_too_small => return len,
506 .not_found => return null,
507 .device_error => return error.DeviceError,
508 .unsupported => return error.Unsupported,
509 else => |status| return uefi.unexpectedStatus(status),
510 }
511 }
512
513 /// Call `nextSize` to get the length of the next variable name and check
514 /// if `buffer` is large enough to hold the name.
515 pub fn next(
516 self: *VariableNameIterator,
517 ) IterateVariableNameError!?[:0]const u16 {
518 var len = self.buffer.len;
519 switch (self.services._getNextVariableName(
520 &len,
521 @ptrCast(self.buffer.ptr),
522 &self.guid,
523 )) {
524 .success => return self.buffer[0 .. len - 1 :0],
525 .not_found => return null,
526 .buffer_too_small => return error.BufferTooSmall,
527 .device_error => return error.DeviceError,
528 .unsupported => return error.Unsupported,
529 else => |status| return uefi.unexpectedStatus(status),
530 }
531 }
532 };
70533
71 pub const signature: u64 = 0x56524553544e5552;534 pub const signature: u64 = 0x56524553544e5552;
72};535};
lib/std/posix.zig+3-3
...@@ -772,12 +772,12 @@ pub fn exit(status: u8) noreturn {...@@ -772,12 +772,12 @@ pub fn exit(status: u8) noreturn {
772 if (native_os == .uefi) {772 if (native_os == .uefi) {
773 const uefi = std.os.uefi;773 const uefi = std.os.uefi;
774 // exit() is only available if exitBootServices() has not been called yet.774 // exit() is only available if exitBootServices() has not been called yet.
775 // This call to exit should not fail, so we don't care about its return value.775 // This call to exit should not fail, so we catch-ignore errors.
776 if (uefi.system_table.boot_services) |bs| {776 if (uefi.system_table.boot_services) |bs| {
777 _ = bs.exit(uefi.handle, @enumFromInt(status), 0, null);777 bs.exit(uefi.handle, @enumFromInt(status), null) catch {};
778 }778 }
779 // If we can't exit, reboot the system instead.779 // If we can't exit, reboot the system instead.
780 uefi.system_table.runtime_services.resetSystem(.reset_cold, @enumFromInt(status), 0, null);780 uefi.system_table.runtime_services.resetSystem(.cold, @enumFromInt(status), null);
781 }781 }
782 system.exit(status);782 system.exit(status);
783}783}
lib/std/time.zig+2-6
...@@ -56,9 +56,7 @@ pub fn nanoTimestamp() i128 {...@@ -56,9 +56,7 @@ pub fn nanoTimestamp() i128 {
56 return ns;56 return ns;
57 },57 },
58 .uefi => {58 .uefi => {
59 var value: std.os.uefi.Time = undefined;59 const value, _ = std.os.uefi.system_table.runtime_services.getTime() catch return 0;
60 const status = std.os.uefi.system_table.runtime_services.getTime(&value, null);
61 assert(status == .success);
62 return value.toEpoch();60 return value.toEpoch();
63 },61 },
64 else => {62 else => {
...@@ -141,9 +139,7 @@ pub const Instant = struct {...@@ -141,9 +139,7 @@ pub const Instant = struct {
141 return .{ .timestamp = ns };139 return .{ .timestamp = ns };
142 },140 },
143 .uefi => {141 .uefi => {
144 var value: std.os.uefi.Time = undefined;142 const value, _ = std.os.uefi.system_table.runtime_services.getTime() catch return error.Unsupported;
145 const status = std.os.uefi.system_table.runtime_services.getTime(&value, null);
146 if (status != .success) return error.Unsupported;
147 return .{ .timestamp = value.toEpoch() };143 return .{ .timestamp = value.toEpoch() };
148 },144 },
149 // On darwin, use UPTIME_RAW instead of MONOTONIC as it ticks while145 // On darwin, use UPTIME_RAW instead of MONOTONIC as it ticks while