Commit 5b4e982169

Carmen <carmen@dotcarmen.dev>
2025-07-12 19:18:53
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>
1 parent bd97b66
lib/std/os/uefi/tables/boot_services.zig
@@ -1,21 +1,31 @@
 const std = @import("std");
 const uefi = std.os.uefi;
 const Event = uefi.Event;
+const EventRegistration = uefi.EventRegistration;
 const Guid = uefi.Guid;
 const Handle = uefi.Handle;
+const Page = uefi.Page;
+const Pages = uefi.Pages;
 const Status = uefi.Status;
 const TableHeader = uefi.tables.TableHeader;
 const DevicePathProtocol = uefi.protocol.DevicePath;
+const AllocateLocation = uefi.tables.AllocateLocation;
 const AllocateType = uefi.tables.AllocateType;
 const MemoryType = uefi.tables.MemoryType;
 const MemoryDescriptor = uefi.tables.MemoryDescriptor;
+const MemoryMapKey = uefi.tables.MemoryMapKey;
+const MemoryMapInfo = uefi.tables.MemoryMapInfo;
+const MemoryMapSlice = uefi.tables.MemoryMapSlice;
 const TimerDelay = uefi.tables.TimerDelay;
 const InterfaceType = uefi.tables.InterfaceType;
+const LocateSearch = uefi.tables.LocateSearch;
 const LocateSearchType = uefi.tables.LocateSearchType;
+const OpenProtocolArgs = uefi.tables.OpenProtocolArgs;
 const OpenProtocolAttributes = uefi.tables.OpenProtocolAttributes;
 const ProtocolInformationEntry = uefi.tables.ProtocolInformationEntry;
 const EventNotify = uefi.tables.EventNotify;
 const cc = uefi.cc;
+const Error = Status.Error;
 
 /// Boot services are services provided by the system's firmware until the operating system takes
 /// over control over the hardware by calling exitBootServices.
@@ -32,173 +42,1236 @@ pub const BootServices = extern struct {
     hdr: TableHeader,
 
     /// Raises a task's priority level and returns its previous level.
-    raiseTpl: *const fn (new_tpl: usize) callconv(cc) usize,
+    raiseTpl: *const fn (new_tpl: TaskPriorityLevel) callconv(cc) TaskPriorityLevel,
 
     /// Restores a task's priority level to its previous value.
-    restoreTpl: *const fn (old_tpl: usize) callconv(cc) void,
+    restoreTpl: *const fn (old_tpl: TaskPriorityLevel) callconv(cc) void,
 
     /// Allocates memory pages from the system.
-    allocatePages: *const fn (alloc_type: AllocateType, mem_type: MemoryType, pages: usize, memory: *[*]align(4096) u8) callconv(cc) Status,
+    _allocatePages: *const fn (alloc_type: AllocateType, mem_type: MemoryType, pages: usize, memory: *[*]align(4096) Page) callconv(cc) Status,
 
     /// Frees memory pages.
-    freePages: *const fn (memory: [*]align(4096) u8, pages: usize) callconv(cc) Status,
+    _freePages: *const fn (memory: [*]align(4096) Page, pages: usize) callconv(cc) Status,
 
     /// Returns the current memory map.
-    getMemoryMap: *const fn (mmap_size: *usize, mmap: ?[*]MemoryDescriptor, map_key: *usize, descriptor_size: *usize, descriptor_version: *u32) callconv(cc) Status,
+    _getMemoryMap: *const fn (mmap_size: *usize, mmap: ?[*]align(@alignOf(MemoryDescriptor)) u8, map_key: *MemoryMapKey, descriptor_size: *usize, descriptor_version: *u32) callconv(cc) Status,
 
     /// Allocates pool memory.
-    allocatePool: *const fn (pool_type: MemoryType, size: usize, buffer: *[*]align(8) u8) callconv(cc) Status,
+    _allocatePool: *const fn (pool_type: MemoryType, size: usize, buffer: *[*]align(8) u8) callconv(cc) Status,
 
     /// Returns pool memory to the system.
-    freePool: *const fn (buffer: [*]align(8) u8) callconv(cc) Status,
+    _freePool: *const fn (buffer: [*]align(8) u8) callconv(cc) Status,
 
     /// Creates an event.
-    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,
+    _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,
 
     /// Sets the type of timer and the trigger time for a timer event.
-    setTimer: *const fn (event: Event, type: TimerDelay, trigger_time: u64) callconv(cc) Status,
+    _setTimer: *const fn (event: Event, type: TimerDelay, trigger_time: u64) callconv(cc) Status,
 
     /// Stops execution until an event is signaled.
-    waitForEvent: *const fn (event_len: usize, events: [*]const Event, index: *usize) callconv(cc) Status,
+    _waitForEvent: *const fn (event_len: usize, events: [*]const Event, index: *usize) callconv(cc) Status,
 
     /// Signals an event.
-    signalEvent: *const fn (event: Event) callconv(cc) Status,
+    _signalEvent: *const fn (event: Event) callconv(cc) Status,
 
     /// Closes an event.
-    closeEvent: *const fn (event: Event) callconv(cc) Status,
+    _closeEvent: *const fn (event: Event) callconv(cc) Status,
 
     /// Checks whether an event is in the signaled state.
-    checkEvent: *const fn (event: Event) callconv(cc) Status,
+    _checkEvent: *const fn (event: Event) callconv(cc) Status,
 
     /// Installs a protocol interface on a device handle. If the handle does not exist, it is created
     /// and added to the list of handles in the system. installMultipleProtocolInterfaces()
     /// performs more error checking than installProtocolInterface(), so its use is recommended over this.
-    installProtocolInterface: *const fn (handle: Handle, protocol: *align(8) const Guid, interface_type: InterfaceType, interface: *anyopaque) callconv(cc) Status,
+    _installProtocolInterface: *const fn (handle: Handle, protocol: *const Guid, interface_type: InterfaceType, interface: *anyopaque) callconv(cc) Status,
 
     /// Reinstalls a protocol interface on a device handle
-    reinstallProtocolInterface: *const fn (handle: Handle, protocol: *align(8) const Guid, old_interface: *anyopaque, new_interface: *anyopaque) callconv(cc) Status,
+    _reinstallProtocolInterface: *const fn (handle: Handle, protocol: *const Guid, old_interface: *anyopaque, new_interface: *anyopaque) callconv(cc) Status,
 
     /// Removes a protocol interface from a device handle. Usage of
     /// uninstallMultipleProtocolInterfaces is recommended over this.
-    uninstallProtocolInterface: *const fn (handle: Handle, protocol: *align(8) const Guid, interface: *anyopaque) callconv(cc) Status,
+    _uninstallProtocolInterface: *const fn (handle: Handle, protocol: *const Guid, interface: *anyopaque) callconv(cc) Status,
 
     /// Queries a handle to determine if it supports a specified protocol.
-    handleProtocol: *const fn (handle: Handle, protocol: *align(8) const Guid, interface: *?*anyopaque) callconv(cc) Status,
+    _handleProtocol: *const fn (handle: Handle, protocol: *const Guid, interface: *?*anyopaque) callconv(cc) Status,
 
-    reserved: *anyopaque,
+    _reserved: *anyopaque,
 
     /// Creates an event that is to be signaled whenever an interface is installed for a specified protocol.
-    registerProtocolNotify: *const fn (protocol: *align(8) const Guid, event: Event, registration: **anyopaque) callconv(cc) Status,
+    _registerProtocolNotify: *const fn (protocol: *const Guid, event: Event, registration: *EventRegistration) callconv(cc) Status,
 
     /// Returns an array of handles that support a specified protocol.
-    locateHandle: *const fn (search_type: LocateSearchType, protocol: ?*align(8) const Guid, search_key: ?*const anyopaque, buffer_size: *usize, buffer: [*]Handle) callconv(cc) Status,
+    _locateHandle: *const fn (search_type: LocateSearchType, protocol: ?*const Guid, search_key: ?*const anyopaque, buffer_size: *usize, buffer: ?[*]Handle) callconv(cc) Status,
 
     /// Locates the handle to a device on the device path that supports the specified protocol
-    locateDevicePath: *const fn (protocols: *align(8) const Guid, device_path: **const DevicePathProtocol, device: *?Handle) callconv(cc) Status,
+    _locateDevicePath: *const fn (protocols: *const Guid, device_path: **const DevicePathProtocol, device: *?Handle) callconv(cc) Status,
 
     /// Adds, updates, or removes a configuration table entry from the EFI System Table.
-    installConfigurationTable: *const fn (guid: *align(8) const Guid, table: ?*anyopaque) callconv(cc) Status,
+    _installConfigurationTable: *const fn (guid: *const Guid, table: ?*anyopaque) callconv(cc) Status,
 
     /// Loads an EFI image into memory.
-    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,
+    _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,
 
     /// Transfers control to a loaded image's entry point.
-    startImage: *const fn (image_handle: Handle, exit_data_size: ?*usize, exit_data: ?*[*]u16) callconv(cc) Status,
+    _startImage: *const fn (image_handle: Handle, exit_data_size: ?*usize, exit_data: ?*[*]u16) callconv(cc) Status,
 
     /// Terminates a loaded EFI image and returns control to boot services.
-    exit: *const fn (image_handle: Handle, exit_status: Status, exit_data_size: usize, exit_data: ?*const anyopaque) callconv(cc) Status,
+    _exit: *const fn (image_handle: Handle, exit_status: Status, exit_data_size: usize, exit_data: ?[*]align(2) const u8) callconv(cc) Status,
 
     /// Unloads an image.
-    unloadImage: *const fn (image_handle: Handle) callconv(cc) Status,
+    _unloadImage: *const fn (image_handle: Handle) callconv(cc) Status,
 
     /// Terminates all boot services.
-    exitBootServices: *const fn (image_handle: Handle, map_key: usize) callconv(cc) Status,
+    _exitBootServices: *const fn (image_handle: Handle, map_key: MemoryMapKey) callconv(cc) Status,
 
     /// Returns a monotonically increasing count for the platform.
-    getNextMonotonicCount: *const fn (count: *u64) callconv(cc) Status,
+    _getNextMonotonicCount: *const fn (count: *u64) callconv(cc) Status,
 
     /// Induces a fine-grained stall.
-    stall: *const fn (microseconds: usize) callconv(cc) Status,
+    _stall: *const fn (microseconds: usize) callconv(cc) Status,
 
     /// Sets the system's watchdog timer.
-    setWatchdogTimer: *const fn (timeout: usize, watchdog_code: u64, data_size: usize, watchdog_data: ?[*]const u16) callconv(cc) Status,
+    _setWatchdogTimer: *const fn (timeout: usize, watchdog_code: u64, data_size: usize, watchdog_data: ?[*]const u16) callconv(cc) Status,
 
     /// Connects one or more drives to a controller.
-    connectController: *const fn (controller_handle: Handle, driver_image_handle: ?Handle, remaining_device_path: ?*DevicePathProtocol, recursive: bool) callconv(cc) Status,
+    _connectController: *const fn (controller_handle: Handle, driver_image_handle: ?[*:null]?Handle, remaining_device_path: ?*const DevicePathProtocol, recursive: bool) callconv(cc) Status,
 
     // Disconnects one or more drivers from a controller
-    disconnectController: *const fn (controller_handle: Handle, driver_image_handle: ?Handle, child_handle: ?Handle) callconv(cc) Status,
+    _disconnectController: *const fn (controller_handle: Handle, driver_image_handle: ?Handle, child_handle: ?Handle) callconv(cc) Status,
 
     /// Queries a handle to determine if it supports a specified protocol.
-    openProtocol: *const fn (handle: Handle, protocol: *align(8) const Guid, interface: *?*anyopaque, agent_handle: ?Handle, controller_handle: ?Handle, attributes: OpenProtocolAttributes) callconv(cc) Status,
+    _openProtocol: *const fn (handle: Handle, protocol: *const Guid, interface: ?*?*anyopaque, agent_handle: ?Handle, controller_handle: ?Handle, attributes: OpenProtocolAttributes) callconv(cc) Status,
 
     /// Closes a protocol on a handle that was opened using openProtocol().
-    closeProtocol: *const fn (handle: Handle, protocol: *align(8) const Guid, agent_handle: Handle, controller_handle: ?Handle) callconv(cc) Status,
+    _closeProtocol: *const fn (handle: Handle, protocol: *const Guid, agent_handle: Handle, controller_handle: ?Handle) callconv(cc) Status,
 
     /// Retrieves the list of agents that currently have a protocol interface opened.
-    openProtocolInformation: *const fn (handle: Handle, protocol: *align(8) const Guid, entry_buffer: *[*]ProtocolInformationEntry, entry_count: *usize) callconv(cc) Status,
+    _openProtocolInformation: *const fn (handle: Handle, protocol: *const Guid, entry_buffer: *[*]ProtocolInformationEntry, entry_count: *usize) callconv(cc) Status,
 
     /// Retrieves the list of protocol interface GUIDs that are installed on a handle in a buffer allocated from pool.
-    protocolsPerHandle: *const fn (handle: Handle, protocol_buffer: *[*]*align(8) const Guid, protocol_buffer_count: *usize) callconv(cc) Status,
+    _protocolsPerHandle: *const fn (handle: Handle, protocol_buffer: *[*]*const Guid, protocol_buffer_count: *usize) callconv(cc) Status,
 
     /// Returns an array of handles that support the requested protocol in a buffer allocated from pool.
-    locateHandleBuffer: *const fn (search_type: LocateSearchType, protocol: ?*align(8) const Guid, search_key: ?*const anyopaque, num_handles: *usize, buffer: *[*]Handle) callconv(cc) Status,
+    _locateHandleBuffer: *const fn (search_type: LocateSearchType, protocol: ?*const Guid, search_key: ?*const anyopaque, num_handles: *usize, buffer: *[*]Handle) callconv(cc) Status,
 
     /// Returns the first protocol instance that matches the given protocol.
-    locateProtocol: *const fn (protocol: *align(8) const Guid, registration: ?*const anyopaque, interface: *?*anyopaque) callconv(cc) Status,
+    _locateProtocol: *const fn (protocol: *const Guid, registration: ?EventRegistration, interface: *?*const anyopaque) callconv(cc) Status,
 
     /// Installs one or more protocol interfaces into the boot services environment
     // TODO: use callconv(cc) instead once that works
-    installMultipleProtocolInterfaces: *const fn (handle: *Handle, ...) callconv(.c) Status,
+    _installMultipleProtocolInterfaces: *const fn (handle: *Handle, ...) callconv(.c) Status,
 
     /// Removes one or more protocol interfaces into the boot services environment
     // TODO: use callconv(cc) instead once that works
-    uninstallMultipleProtocolInterfaces: *const fn (handle: *Handle, ...) callconv(.c) Status,
+    _uninstallMultipleProtocolInterfaces: *const fn (handle: *Handle, ...) callconv(.c) Status,
 
     /// Computes and returns a 32-bit CRC for a data buffer.
-    calculateCrc32: *const fn (data: [*]const u8, data_size: usize, *u32) callconv(cc) Status,
+    _calculateCrc32: *const fn (data: [*]const u8, data_size: usize, *u32) callconv(cc) Status,
 
     /// Copies the contents of one buffer to another buffer
-    copyMem: *const fn (dest: [*]u8, src: [*]const u8, len: usize) callconv(cc) void,
+    _copyMem: *const fn (dest: [*]u8, src: [*]const u8, len: usize) callconv(cc) void,
 
     /// Fills a buffer with a specified value
-    setMem: *const fn (buffer: [*]u8, size: usize, value: u8) callconv(cc) void,
+    _setMem: *const fn (buffer: [*]u8, size: usize, value: u8) callconv(cc) void,
 
     /// Creates an event in a group.
-    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,
+    _createEventEx: *const fn (type: u32, notify_tpl: usize, notify_func: EventNotify, notify_ctx: *const anyopaque, event_group: *const Guid, event: *Event) callconv(cc) Status,
+
+    pub const AllocatePagesError = uefi.UnexpectedError || error{
+        OutOfResources,
+        InvalidParameter,
+        NotFound,
+    };
+
+    pub const FreePagesError = uefi.UnexpectedError || error{
+        NotFound,
+        InvalidParameter,
+    };
+
+    pub const GetMemoryMapError = uefi.UnexpectedError || error{
+        InvalidParameter,
+        BufferTooSmall,
+    };
+
+    pub const AllocatePoolError = uefi.UnexpectedError || error{
+        OutOfResources,
+        InvalidParameter,
+    };
+
+    pub const FreePoolError = uefi.UnexpectedError || error{
+        InvalidParameter,
+    };
+
+    pub const CreateEventError = uefi.UnexpectedError || error{
+        InvalidParameter,
+        OutOfResources,
+    };
+
+    pub const SetTimerError = uefi.UnexpectedError || error{
+        InvalidParameter,
+    };
+
+    pub const WaitForEventError = uefi.UnexpectedError || error{
+        InvalidParameter,
+        Unsupported,
+    };
+
+    pub const CheckEventError = uefi.UnexpectedError || error{
+        InvalidParameter,
+    };
+
+    pub const ReinstallProtocolInterfaceError = uefi.UnexpectedError || error{
+        NotFound,
+        AccessDenied,
+        InvalidParameter,
+    };
+
+    pub const HandleProtocolError = uefi.UnexpectedError || error{
+        Unsupported,
+    };
+
+    pub const RegisterProtocolNotifyError = uefi.UnexpectedError || error{
+        OutOfResources,
+        InvalidParameter,
+    };
+
+    pub const NumHandlesError = uefi.UnexpectedError || error{
+        OutOfResources,
+    };
+
+    pub const LocateHandleError = uefi.UnexpectedError || error{
+        BufferTooSmall,
+        InvalidParameter,
+    };
+
+    pub const LocateDevicePathError = uefi.UnexpectedError || error{
+        NotFound,
+        InvalidParameter,
+    };
+
+    pub const InstallConfigurationTableError = uefi.UnexpectedError || error{
+        InvalidParameter,
+        OutOfResources,
+    };
+
+    pub const UninstallConfigurationTableError = InstallConfigurationTableError || error{
+        NotFound,
+    };
+
+    pub const LoadImageError = uefi.UnexpectedError || error{
+        NotFound,
+        InvalidParameter,
+        Unsupported,
+        OutOfResources,
+        LoadError,
+        DeviceError,
+        AccessDenied,
+        SecurityViolation,
+    };
+
+    pub const StartImageError = uefi.UnexpectedError || error{
+        InvalidParameter,
+        SecurityViolation,
+    };
+
+    pub const ExitError = uefi.UnexpectedError || error{
+        InvalidParameter,
+    };
+
+    pub const ExitBootServicesError = uefi.UnexpectedError || error{
+        InvalidParameter,
+    };
+
+    pub const GetNextMonotonicCountError = uefi.UnexpectedError || error{
+        DeviceError,
+        InvalidParameter,
+    };
+
+    pub const SetWatchdogTimerError = uefi.UnexpectedError || error{
+        InvalidParameter,
+        Unsupported,
+        DeviceError,
+    };
+
+    pub const ConnectControllerError = uefi.UnexpectedError || error{
+        InvalidParameter,
+        NotFound,
+        SecurityViolation,
+    };
+
+    pub const DisconnectControllerError = uefi.UnexpectedError || error{
+        InvalidParameter,
+        OutOfResources,
+        DeviceError,
+    };
+
+    pub const OpenProtocolError = uefi.UnexpectedError || error{
+        InvalidParameter,
+        Unsupported,
+        AccessDenied,
+        AlreadyStarted,
+    };
+
+    pub const CloseProtocolError = uefi.UnexpectedError || error{
+        InvalidParameter,
+        NotFound,
+    };
+
+    pub const OpenProtocolInformationError = uefi.UnexpectedError || error{
+        OutOfResources,
+    };
+
+    pub const ProtocolsPerHandleError = uefi.UnexpectedError || error{
+        InvalidParameter,
+        OutOfResources,
+    };
+
+    pub const LocateHandleBufferError = uefi.UnexpectedError || error{
+        InvalidParameter,
+        OutOfResources,
+    };
+
+    pub const LocateProtocolError = uefi.UnexpectedError || error{
+        InvalidParameter,
+    };
+
+    pub const InstallProtocolInterfacesError = uefi.UnexpectedError || error{
+        AlreadyStarted,
+        OutOfResources,
+        InvalidParameter,
+    };
+
+    pub const UninstallProtocolInterfacesError = uefi.UnexpectedError || error{
+        InvalidParameter,
+    };
+
+    pub const CalculateCrc32Error = uefi.UnexpectedError || error{
+        InvalidParameter,
+    };
+
+    /// Allocates pages of memory.
+    ///
+    /// This function scans the memory map to locate free pages. When it finds a
+    /// physically contiguous block of pages that is large enough and also satisfies
+    /// the allocation requirements of `alloc_type`, it changes the memory map to
+    /// indicate that the pages are now of type `mem_type`.
+    ///
+    /// In general, UEFI OS loaders and UEFI applications should allocate memory
+    /// (and pool) of type `.loader_data`. UEFI boot service drivers must allocate
+    /// memory (and pool) of type `.boot_services_data`. UREFI runtime drivers
+    /// should allocate memory (and pool) of type `.runtime_services_data`
+    /// (although such allocation can only be made during boot services time).
+    ///
+    /// Allocation requests of `.allocate_any_pages` allocate any available range
+    /// of pages that satisfies the request.
+    ///
+    /// Allocation requests of `.allocate_max_address` allocate any available range
+    /// of pages whose uppermost address is less than or equal to the address
+    /// pointed to by the input.
+    ///
+    /// Allocation requests of `.allocate_address` allocate pages at the address
+    /// pointed to by the input.
+    pub fn allocatePages(
+        self: *BootServices,
+        location: AllocateLocation,
+        mem_type: MemoryType,
+        pages: usize,
+    ) AllocatePagesError![]align(4096) Page {
+        var ptr: [*]align(4096) Page = switch (location) {
+            .any => undefined,
+            .address, .max_address => |ptr| ptr,
+        };
+
+        switch (self._allocatePages(
+            std.meta.activeTag(location),
+            mem_type,
+            pages,
+            &ptr,
+        )) {
+            .success => return ptr[0..pages],
+            .out_of_resources => return error.OutOfResources,
+            .invalid_parameter => return error.InvalidParameter,
+            .not_found => return error.NotFound,
+            else => |status| return uefi.unexpectedStatus(status),
+        }
+    }
+
+    pub fn freePages(self: *BootServices, pages: []align(4096) Page) FreePagesError!void {
+        switch (self._freePages(pages.ptr, pages.len)) {
+            .success => {},
+            .not_found => return error.NotFound,
+            .invalid_parameter => return error.InvalidParameter,
+            else => |status| return uefi.unexpectedStatus(status),
+        }
+    }
+
+    pub fn getMemoryMapInfo(self: *const BootServices) uefi.UnexpectedError!MemoryMapInfo {
+        var info: MemoryMapInfo = undefined;
+        info.len = 0;
+
+        switch (self._getMemoryMap(
+            &info.len,
+            null,
+            &info.key,
+            &info.descriptor_size,
+            &info.descriptor_version,
+        )) {
+            .success, .buffer_too_small => {
+                info.len = @divExact(info.len, info.descriptor_size);
+                return info;
+            },
+            else => |status| return uefi.unexpectedStatus(status),
+        }
+    }
+
+    pub fn getMemoryMap(
+        self: *const BootServices,
+        buffer: []align(@alignOf(MemoryDescriptor)) u8,
+    ) GetMemoryMapError!MemoryMapSlice {
+        var info: MemoryMapInfo = undefined;
+        info.len = buffer.len;
+
+        switch (self._getMemoryMap(
+            &info.len,
+            buffer.ptr,
+            &info.key,
+            &info.descriptor_size,
+            &info.descriptor_version,
+        )) {
+            .success => {
+                info.len = @divExact(info.len, info.descriptor_size);
+                return .{ .info = info, .ptr = buffer.ptr };
+            },
+            .buffer_too_small => return error.BufferTooSmall,
+            .invalid_parameter => return error.InvalidParameter,
+            else => |status| return uefi.unexpectedStatus(status),
+        }
+    }
+
+    /// Allocates a memory region of `size` bytes from memory of type `pool_type`
+    /// and returns the allocated memory. Allocates pages from `.conventional_memory`
+    /// as needed to grow the requested pool type.
+    pub fn allocatePool(
+        self: *BootServices,
+        pool_type: MemoryType,
+        size: usize,
+    ) AllocatePoolError![]align(8) u8 {
+        var ptr: [*]align(8) u8 = undefined;
+
+        switch (self._allocatePool(pool_type, size, &ptr)) {
+            .success => return ptr[0..size],
+            .out_of_resources => return error.OutOfResources,
+            .invalid_parameter => return error.InvalidParameter,
+            else => |status| return uefi.unexpectedStatus(status),
+        }
+    }
+
+    pub fn freePool(self: *BootServices, ptr: [*]align(8) u8) FreePoolError!void {
+        switch (self._freePool(ptr)) {
+            .success => {},
+            .invalid_parameter => return error.InvalidParameter,
+            else => |status| return uefi.unexpectedStatus(status),
+        }
+    }
+
+    pub fn createEvent(
+        self: *BootServices,
+        event_type: uefi.EventType,
+        notify_opts: NotifyOpts,
+    ) CreateEventError!Event {
+        var evt: Event = undefined;
+
+        switch (self._createEvent(
+            @bitCast(event_type),
+            notify_opts.tpl,
+            notify_opts.function,
+            notify_opts.context,
+            &evt,
+        )) {
+            .success => return evt,
+            .invalid_parameter => return error.InvalidParameter,
+            .out_of_resources => return error.OutOfResources,
+            else => |status| return uefi.unexpectedStatus(status),
+        }
+    }
+
+    /// Cancels any previous time trigger setting for the event, and sets a new
+    /// trigger timer for the event.
+    ///
+    /// Returns `error.InvalidParameter` if the event is not a timer event.
+    pub fn setTimer(
+        self: *BootServices,
+        event: Event,
+        @"type": TimerDelay,
+        trigger_time: u64,
+    ) SetTimerError!void {
+        switch (self._setTimer(event, @"type", trigger_time)) {
+            .success => {},
+            .invalid_parameter => return error.InvalidParameter,
+            else => |status| return uefi.unexpectedStatus(status),
+        }
+    }
+
+    /// Returns the event that was signaled, along with its index in the slice.
+    pub fn waitForEvent(
+        self: *BootServices,
+        events: []const Event,
+    ) WaitForEventError!struct { *const Event, usize } {
+        var idx: usize = undefined;
+        switch (self._waitForEvent(events.len, events.ptr, &idx)) {
+            .success => return .{ &events[idx], idx },
+            .invalid_parameter => return error.InvalidParameter,
+            .unsupported => return error.Unsupported,
+            else => |status| return uefi.unexpectedStatus(status),
+        }
+    }
+
+    /// If `event` is `EventType.signal`, then the event’s notification function
+    /// is scheduled to be invoked at the event’s notification task priority level.
+    /// This function may be invoked from any task priority level.
+    ///
+    /// If the supplied Event is a part of an event group, then all of the events
+    /// in the event group are also signaled and their notification functions are
+    /// scheduled.
+    ///
+    /// When signaling an event group, it is possible to create an event in the
+    /// group, signal it and then close the event to remove it from the group.
+    pub fn signalEvent(self: *BootServices, event: Event) uefi.UnexpectedError!void {
+        switch (self._signalEvent(event)) {
+            .success => {},
+            else => |status| return uefi.unexpectedStatus(status),
+        }
+    }
+
+    pub fn closeEvent(self: *BootServices, event: Event) uefi.UnexpectedError!void {
+        switch (self._closeEvent(event)) {
+            .success => {},
+            else => |status| return uefi.unexpectedStatus(status),
+        }
+    }
+
+    /// Checks to see whether an event is signaled.
+    ///
+    /// The underlying function is equivalent to this pseudo-code:
+    /// ```
+    /// if (event.type.signal)
+    ///     return error.InvalidParameter;
+    ///
+    /// if (event.signaled) {
+    ///     event.signaled = false;
+    ///     return true;
+    /// }
+    ///
+    /// const notify = event.notification_function orelse return false;
+    /// notify();
+    ///
+    /// if (event.signaled) {
+    ///     event.signaled = false;
+    ///     return true;
+    /// }
+    ///
+    /// return false;
+    /// ```
+    pub fn checkEvent(self: *BootServices, event: Event) CheckEventError!bool {
+        switch (self._checkEvent(event)) {
+            .success => return true,
+            .not_ready => return false,
+            .invalid_parameter => return error.InvalidParameter,
+            else => |status| return uefi.unexpectedStatus(status),
+        }
+    }
+
+    /// See `installProtocolInterfaces`.
+    ///
+    /// Does not call `self._installProtocolInterface`, because
+    /// `self._installMultipleProtocolInterfaces` performs more error checks.
+    pub fn installProtocolInterface(
+        self: *BootServices,
+        handle: ?Handle,
+        interface: anytype,
+    ) InstallProtocolInterfacesError!Handle {
+        return self.installProtocolInterfaces(handle, .{
+            interface,
+        });
+    }
+
+    /// Reinstalls a protocol interface on a device handle.
+    ///
+    /// `new` may be the same as `old`. If it is, the registered protocol notifications
+    /// occur for the handle without replacing the interface on the handle.
+    ///
+    /// Any process that has registered to wait for the installation of the interface
+    /// is notified.
+    ///
+    /// The caller is responsible for ensuring that there are no references to `old`
+    /// if it is being removed.
+    pub fn reinstallProtocolInterface(
+        self: *BootServices,
+        handle: Handle,
+        Protocol: type,
+        old: ?*const Protocol,
+        new: ?*const Protocol,
+    ) ReinstallProtocolInterfaceError!void {
+        if (!@hasDecl(Protocol, "guid"))
+            @compileError("protocol is missing guid");
+
+        switch (self._reinstallProtocolInterface(
+            handle,
+            &Protocol.guid,
+            old,
+            new,
+        )) {
+            .success => {},
+            .not_found => return error.NotFound,
+            .access_denied => return error.AccessDenied,
+            .invalid_parameter => return error.InvalidParameter,
+            else => |status| return uefi.unexpectedStatus(status),
+        }
+    }
+
+    /// See `uninstallProtocolInterfaces`.
+    ///
+    /// Does not call `self._uninstallProtocolInterface`, because
+    /// `self._uninstallMultipleProtocolInterfaces` performs more error checks.
+    pub fn uninstallProtocolInterface(
+        self: *BootServices,
+        handle: Handle,
+        interface: anytype,
+    ) UninstallProtocolInterfacesError!void {
+        return self.uninstallProtocolInterfaces(handle, .{
+            interface,
+        });
+    }
+
+    /// Returns a pointer to the `Protocol` interface if it's supported by the
+    /// handle.
+    ///
+    /// Note that UEFI implementations are no longer required to implement this
+    /// function, so it's implemented using `openProtocol` instead.
+    pub fn handleProtocol(
+        self: *BootServices,
+        Protocol: type,
+        handle: Handle,
+    ) HandleProtocolError!?*Protocol {
+        // per https://uefi.org/specs/UEFI/2.10/07_Services_Boot_Services.html#efi-boot-services-handleprotocol
+        // handleProtocol is basically `openProtocol` where:
+        // 1. agent_handle is `uefi.handle` (aka handle passed to `EfiMain`)
+        // 2. controller_handle is `null`
+        // 3. attributes is `EFI_OPEN_PROTOCOL_BY_HANDLE_PROTOCOL`
+
+        return self.openProtocol(
+            Protocol,
+            handle,
+            .{ .by_handle_protocol = .{ .agent = uefi.handle } },
+        ) catch |err| switch (err) {
+            error.AlreadyStarted => return uefi.unexpectedStatus(.already_started),
+            error.AccessDenied => return uefi.unexpectedStatus(.access_denied),
+            error.InvalidParameter => return uefi.unexpectedStatus(.invalid_parameter),
+            else => return @errorCast(err),
+        };
+    }
+
+    pub fn registerProtocolNotify(
+        self: *BootServices,
+        Protocol: type,
+        event: Event,
+    ) RegisterProtocolNotifyError!EventRegistration {
+        if (!@hasDecl(Protocol, "guid"))
+            @compileError("Protocol is missing guid");
+
+        var registration: EventRegistration = undefined;
+        switch (self._registerProtocolNotify(
+            &Protocol.guid,
+            event,
+            &registration,
+        )) {
+            .success => return registration,
+            .out_of_resources => return error.OutOfResources,
+            .invalid_parameter => return error.InvalidParameter,
+            else => |status| return uefi.unexpectedStatus(status),
+        }
+    }
+
+    /// Returns the number of handles that match the given search criteria.
+    pub fn locateHandleLen(self: *const BootServices, search: LocateSearch) NumHandlesError!usize {
+        var len: usize = 0;
+        switch (self._locateHandle(
+            std.meta.activeTag(search),
+            if (search == .by_protocol) search.by_protocol else null,
+            if (search == .by_register_notify) search.by_register_notify else null,
+            &len,
+            null,
+        )) {
+            .success => return @divExact(len, @sizeOf(Handle)),
+            .out_of_resources => return error.OutOfResources,
+            else => |status| return uefi.unexpectedStatus(status),
+        }
+    }
+
+    /// To determine the necessary size of `buffer`, call `locateHandleLen` first.
+    pub fn locateHandle(
+        self: *BootServices,
+        search: LocateSearch,
+        buffer: []Handle,
+    ) LocateHandleError![]Handle {
+        var len: usize = @sizeOf(Handle) * buffer.len;
+        switch (self._locateHandle(
+            std.meta.activeTag(search),
+            if (search == .by_protocol) search.by_protocol else null,
+            if (search == .by_register_notify) search.by_register_notify else null,
+            &len,
+            buffer.ptr,
+        )) {
+            .success => return buffer[0..@divExact(len, @sizeOf(Handle))],
+            .not_found => return buffer[0..0],
+            .buffer_too_small => return error.BufferTooSmall,
+            .invalid_parameter => return error.InvalidParameter,
+            else => |status| return uefi.unexpectedStatus(status),
+        }
+    }
+
+    /// Locates all devices on `device_path` that support `Protocol`. Once the closest
+    /// match to `device_path` is found, it returns the unmatched device path and handle.
+    pub fn locateDevicePath(
+        self: *const BootServices,
+        device_path: *const DevicePathProtocol,
+        Protocol: type,
+    ) LocateHandleError!?struct { *const DevicePathProtocol, Handle } {
+        if (!@hasDecl(Protocol, "guid"))
+            @compileError("Protocol is missing guid");
+
+        var dev_path = device_path;
+        var device: ?Handle = undefined;
+        switch (self._locateDevicePath(
+            &Protocol.guid,
+            &dev_path,
+            &device,
+        )) {
+            .success => return .{ dev_path, device.? },
+            .not_found => return null,
+            .invalid_parameter => return error.InvalidParameter,
+            else => |status| return uefi.unexpectedStatus(status),
+        }
+    }
+
+    pub fn installConfigurationTable(
+        self: *BootServices,
+        guid: *const Guid,
+        table: *anyopaque,
+    ) InstallConfigurationTableError!void {
+        switch (self._installConfigurationTable(
+            guid,
+            table,
+        )) {
+            .success => {},
+            .invalid_parameter => return error.InvalidParameter,
+            .out_of_resources => return error.OutOfResources,
+            else => |status| return uefi.unexpectedStatus(status),
+        }
+    }
+
+    pub fn uninstallConfigurationTable(
+        self: *BootServices,
+        guid: *const Guid,
+    ) UninstallConfigurationTableError!void {
+        switch (self._installConfigurationTable(
+            guid,
+            null,
+        )) {
+            .success => {},
+            .not_found => return error.NotFound,
+            .invalid_parameter => return error.InvalidParameter,
+            .out_of_resources => return error.OutOfResources,
+            else => |status| return uefi.unexpectedStatus(status),
+        }
+    }
+
+    pub const LoadImageSource = union(enum) {
+        buffer: []const u8,
+        device_path: *const DevicePathProtocol,
+    };
+
+    pub fn loadImage(
+        self: *BootServices,
+        boot_policy: bool,
+        parent_image: Handle,
+        source: LoadImageSource,
+    ) LoadImageError!Handle {
+        var handle: Handle = undefined;
+
+        switch (self._loadImage(
+            boot_policy,
+            parent_image,
+            if (source == .device_path) source.device_path else null,
+            if (source == .buffer) source.buffer.ptr else null,
+            if (source == .buffer) source.buffer.len else 0,
+            &handle,
+        )) {
+            .success => return handle,
+            .not_found => return error.NotFound,
+            .invalid_parameter => return error.InvalidParameter,
+            .unsupported => return error.Unsupported,
+            .out_of_resources => return error.OutOfResources,
+            .load_error => return error.LoadError,
+            .device_error => return error.DeviceError,
+            .access_denied => return error.AccessDenied,
+            .security_violation => return error.SecurityViolation,
+            else => |status| return uefi.unexpectedStatus(status),
+        }
+    }
+
+    pub fn startImage(self: *BootServices, image: Handle) StartImageError!ImageExitData {
+        var exit_data_size: usize = undefined;
+        var exit_data: [*]u16 = undefined;
+
+        const exit_code = switch (self._startImage(
+            image,
+            &exit_data_size,
+            &exit_data,
+        )) {
+            .invalid_parameter => return error.InvalidParameter,
+            .security_violation => return error.SecurityViolation,
+            else => |exit_code| exit_code,
+        };
+
+        if (exit_data_size == 0) return .{
+            .code = exit_code,
+            .description = null,
+            .data = null,
+        };
+
+        const description_ptr: [*:0]const u16 = @ptrCast(exit_data);
+        const description = std.mem.sliceTo(description_ptr, 0);
+
+        return ImageExitData{
+            .code = exit_code,
+            .description = description,
+            .data = exit_data[description.len + 1 .. exit_data_size],
+        };
+    }
+
+    /// `message` must be allocated using `allocatePool`.
+    pub fn exit(
+        self: *BootServices,
+        handle: Handle,
+        status: Status,
+        message: ?[:0]const u16,
+    ) ExitError!void {
+        switch (self._exit(
+            handle,
+            status,
+            if (message) |msg| (2 * msg.len) + 1 else 0,
+            if (message) |msg| @ptrCast(msg.ptr) else null,
+        )) {
+            .success => {},
+            .invalid_parameter => return error.InvalidParameter,
+            else => |exit_status| return uefi.unexpectedStatus(exit_status),
+        }
+    }
+
+    /// `message` should be a null-terminated u16 string followed by binary data
+    /// allocated using `allocatePool`.
+    pub fn exitWithData(
+        self: *BootServices,
+        handle: Handle,
+        status: Status,
+        data: []align(2) const u8,
+    ) ExitError!void {
+        switch (self._exit(handle, status, data.len, data.ptr)) {
+            .success => {},
+            .invalid_parameter => return error.InvalidParameter,
+            else => |exit_status| return uefi.unexpectedStatus(exit_status),
+        }
+    }
+
+    /// The result is the exit code of the unload handler. Any error codes are
+    /// `try/catch`-able, leaving only success and warning codes as the result.
+    pub fn unloadImage(
+        self: *BootServices,
+        image: Handle,
+    ) Status.Error!Status {
+        const status = self._unloadImage(image);
+        try status.err();
+        return status;
+    }
+
+    pub fn exitBootServices(
+        self: *BootServices,
+        image: Handle,
+        map_key: MemoryMapKey,
+    ) ExitBootServicesError!void {
+        switch (self._exitBootServices(image, map_key)) {
+            .success => {},
+            .invalid_parameter => return error.InvalidParameter,
+            else => |status| return uefi.unexpectedStatus(status),
+        }
+    }
+
+    pub fn getNextMonotonicCount(
+        self: *const BootServices,
+        count: *u64,
+    ) GetNextMonotonicCountError!void {
+        switch (self._getNextMonotonicCount(count)) {
+            .success => {},
+            .device_error => return error.DeviceError,
+            .invalid_parameter => return error.InvalidParameter,
+            else => |status| return uefi.unexpectedStatus(status),
+        }
+    }
+
+    pub fn stall(self: *const BootServices, microseconds: usize) uefi.UnexpectedError!void {
+        switch (self._stall(microseconds)) {
+            .success => {},
+            else => |status| return uefi.unexpectedStatus(status),
+        }
+    }
+
+    pub fn setWatchdogTimer(
+        self: *BootServices,
+        timeout: usize,
+        watchdog_code: u64,
+        data: ?[]const u16,
+    ) SetWatchdogTimerError!void {
+        switch (self._setWatchdogTimer(
+            timeout,
+            watchdog_code,
+            if (data) |d| d.len else 0,
+            if (data) |d| d.ptr else null,
+        )) {
+            .success => {},
+            .invalid_parameter => return error.InvalidParameter,
+            .unsupported => return error.Unsupported,
+            .device_error => return error.DeviceError,
+            else => |status| return uefi.unexpectedStatus(status),
+        }
+    }
+
+    /// `driver_image` should be a null-terminated ordered list of handles.
+    pub fn connectController(
+        self: *BootServices,
+        controller: Handle,
+        driver_image: ?[*:null]?Handle,
+        remaining_device_path: ?*const DevicePathProtocol,
+        recursive: bool,
+    ) ConnectControllerError!void {
+        switch (self._connectController(
+            controller,
+            driver_image,
+            remaining_device_path,
+            recursive,
+        )) {
+            .success => {},
+            .invalid_parameter => return error.InvalidParameter,
+            .not_found => return error.NotFound,
+            .security_violation => return error.SecurityViolation,
+            else => |status| return uefi.unexpectedStatus(status),
+        }
+    }
+
+    pub fn disconnectController(
+        self: *BootServices,
+        controller: Handle,
+        driver_image: ?Handle,
+        child: ?Handle,
+    ) DisconnectControllerError!void {
+        switch (self._disconnectController(
+            controller,
+            driver_image,
+            child,
+        )) {
+            .success => {},
+            .invalid_parameter => return error.InvalidParameter,
+            .out_of_resources => return error.OutOfResources,
+            .device_error => return error.DeviceError,
+            else => |status| return uefi.unexpectedStatus(status),
+        }
+    }
 
     /// Opens a protocol with a structure as the loaded image for a UEFI application
-    pub fn openProtocolSt(self: *BootServices, comptime protocol: type, handle: Handle) !*protocol {
-        if (!@hasDecl(protocol, "guid"))
-            @compileError("Protocol is missing guid!");
+    ///
+    /// If `flag` is `.test_protocol`, then the only valid return value is `null`,
+    /// and `Status.unsupported` is returned. Otherwise, if `_openProtocol` returns
+    /// `Status.unsupported`, then `null` is returned.
+    pub fn openProtocol(
+        self: *BootServices,
+        Protocol: type,
+        handle: Handle,
+        attributes: OpenProtocolArgs,
+    ) OpenProtocolError!?*Protocol {
+        if (!@hasDecl(Protocol, "guid"))
+            @compileError("Protocol is missing guid: " ++ @typeName(Protocol));
 
-        var ptr: ?*protocol = undefined;
+        const agent_handle: ?Handle, const controller_handle: ?Handle = switch (attributes) {
+            inline else => |arg| .{ arg.agent, arg.controller },
+        };
 
-        try self.openProtocol(
+        var ptr: ?*Protocol = undefined;
+
+        switch (self._openProtocol(
             handle,
-            &protocol.guid,
+            &Protocol.guid,
             @as(*?*anyopaque, @ptrCast(&ptr)),
-            // Invoking handle (loaded image)
-            uefi.handle,
-            // Control handle (null as not a driver)
-            null,
-            uefi.tables.OpenProtocolAttributes{ .by_handle_protocol = true },
-        ).err();
+            agent_handle,
+            controller_handle,
+            std.meta.activeTag(attributes),
+        )) {
+            .success => return if (attributes == .test_protocol) null else ptr,
+            .unsupported => return if (attributes == .test_protocol) error.Unsupported else null,
+            .access_denied => return error.AccessDenied,
+            .already_started => return error.AlreadyStarted,
+            else => |status| return uefi.unexpectedStatus(status),
+        }
+    }
+
+    pub fn closeProtocol(
+        self: *BootServices,
+        handle: Handle,
+        Protocol: type,
+        agent: Handle,
+        controller: ?Handle,
+    ) CloseProtocolError!void {
+        if (!@hasDecl(Protocol, "guid"))
+            @compileError("protocol is missing guid: " ++ @typeName(Protocol));
+
+        switch (self._closeProtocol(
+            handle,
+            &Protocol.guid,
+            agent,
+            controller,
+        )) {
+            .success => {},
+            .invalid_parameter => return error.InvalidParameter,
+            .not_found => return error.NotFound,
+            else => |status| return uefi.unexpectedStatus(status),
+        }
+    }
+
+    pub fn openProtocolInformation(
+        self: *const BootServices,
+        handle: Handle,
+        Protocol: type,
+    ) OpenProtocolInformationError!?[]ProtocolInformationEntry {
+        var entries: [*]ProtocolInformationEntry = undefined;
+        var len: usize = undefined;
+
+        switch (self._openProtocolInformation(
+            handle,
+            &Protocol.guid,
+            &entries,
+            &len,
+        )) {
+            .success => return entries[0..len],
+            .not_found => return null,
+            .out_of_resources => return error.OutOfResources,
+            else => |status| return uefi.unexpectedStatus(status),
+        }
+    }
+
+    pub fn protocolsPerHandle(
+        self: *const BootServices,
+        handle: Handle,
+    ) ProtocolsPerHandleError![]*const Guid {
+        var guids: [*]*const Guid = undefined;
+        var len: usize = undefined;
+
+        switch (self._protocolsPerHandle(
+            handle,
+            &guids,
+            &len,
+        )) {
+            .success => return guids[0..len],
+            .invalid_parameter => return error.InvalidParameter,
+            .out_of_resources => return error.OutOfResources,
+            else => |status| return uefi.unexpectedStatus(status),
+        }
+    }
+
+    pub fn locateHandleBuffer(
+        self: *const BootServices,
+        search: LocateSearch,
+    ) LocateHandleBufferError!?[]Handle {
+        var handles: [*]Handle = undefined;
+        var len: usize = undefined;
+
+        switch (self._locateHandleBuffer(
+            std.meta.activeTag(search),
+            if (search == .by_protocol) search.by_protocol else null,
+            if (search == .by_register_notify) search.by_register_notify else null,
+            &len,
+            &handles,
+        )) {
+            .success => return handles[0..len],
+            .invalid_parameter => return error.InvalidParameter,
+            .not_found => return null,
+            .out_of_resources => return error.OutOfResources,
+            else => |status| return uefi.unexpectedStatus(status),
+        }
+    }
+
+    pub fn locateProtocol(
+        self: *const BootServices,
+        Protocol: type,
+        registration: ?EventRegistration,
+    ) LocateProtocolError!?*Protocol {
+        var interface: *Protocol = undefined;
+
+        switch (self._locateProtocol(
+            &Protocol.guid,
+            registration,
+            @ptrCast(&interface),
+        )) {
+            .success => return interface,
+            .not_found => return null,
+            .invalid_parameter => return error.InvalidParameter,
+            else => |status| return uefi.unexpectedStatus(status),
+        }
+    }
+
+    /// Installs a set of protocol interfaces into the boot services environment.
+    ///
+    /// This function's final argument should be a tuple of pointers to protocol
+    /// interfaces. For example:
+    ///
+    /// ```
+    /// const handle = try boot_services.installProtocolInterfaces(null, .{
+    ///     &my_interface_1,
+    ///     &my_interface_2,
+    /// });
+    /// ```
+    ///
+    /// The underlying function accepts a vararg list of pairs of Guid pointers
+    /// and opaque pointers to the interface. To provide a guid, the interface
+    /// types should declare a `guid` constant like so:
+    ///
+    /// ```
+    /// pub const guid: uefi.Guid = .{ ... };
+    /// ```
+    ///
+    /// See `std.os.uefi.protocol` for examples of protocol type definitions.
+    pub fn installProtocolInterfaces(
+        self: *BootServices,
+        handle: ?Handle,
+        interfaces: anytype,
+    ) InstallProtocolInterfacesError!Handle {
+        var hdl: ?Handle = handle;
+        const args_tuple = protocolInterfaces(&hdl, interfaces);
+
+        switch (@call(
+            .auto,
+            self._installMultipleProtocolInterfaces,
+            args_tuple,
+        )) {
+            .success => return hdl.?,
+            .already_started => return error.AlreadyStarted,
+            .out_of_resources => return error.OutOfResources,
+            .invalid_parameter => return error.InvalidParameter,
+            else => |status| return uefi.unexpectedStatus(status),
+        }
+    }
+
+    pub fn uninstallProtocolInterfaces(
+        self: *BootServices,
+        handle: Handle,
+        interfaces: anytype,
+    ) UninstallProtocolInterfacesError!void {
+        const args_tuple = protocolInterfaces(handle, interfaces);
 
-        return ptr.?;
+        switch (@call(
+            .auto,
+            self._uninstallMultipleProtocolInterfaces,
+            args_tuple,
+        )) {
+            .success => {},
+            .invalid_parameter => return error.InvalidParameter,
+            else => |status| return uefi.unexpectedStatus(status),
+        }
+    }
+
+    pub fn calculateCrc32(
+        self: *const BootServices,
+        data: []const u8,
+    ) CalculateCrc32Error!u32 {
+        var value: u32 = undefined;
+        switch (self._calculateCrc32(data.ptr, data.len, &value)) {
+            .success => return value,
+            .invalid_parameter => return error.InvalidParameter,
+            else => |status| return uefi.unexpectedStatus(status),
+        }
     }
 
     pub const signature: u64 = 0x56524553544f4f42;
 
-    pub const event_timer: u32 = 0x80000000;
-    pub const event_runtime: u32 = 0x40000000;
-    pub const event_notify_wait: u32 = 0x00000100;
-    pub const event_notify_signal: u32 = 0x00000200;
-    pub const event_signal_exit_boot_services: u32 = 0x00000201;
-    pub const event_signal_virtual_address_change: u32 = 0x00000202;
-
-    pub const tpl_application: usize = 4;
-    pub const tpl_callback: usize = 8;
-    pub const tpl_notify: usize = 16;
-    pub const tpl_high_level: usize = 31;
+    pub const NotifyOpts = struct {
+        tpl: TaskPriorityLevel = .application,
+        function: ?*const fn (Event, ?*anyopaque) callconv(cc) void = null,
+        context: ?*anyopaque = null,
+    };
+
+    pub const TaskPriorityLevel = enum(usize) {
+        application = 4,
+        callback = 8,
+        notify = 16,
+        high_level = 31,
+        _,
+    };
+
+    pub const ImageExitData = struct {
+        code: Status,
+        description: ?[:0]const u16,
+        data: ?[]const u16,
+    };
 };
+
+fn protocolInterfaces(
+    handle_arg: anytype,
+    interfaces: anytype,
+) ProtocolInterfaces(@TypeOf(handle_arg), @TypeOf(interfaces)) {
+    var result: ProtocolInterfaces(
+        @TypeOf(handle_arg),
+        @TypeOf(interfaces),
+    ) = undefined;
+    result[0] = handle_arg;
+
+    var idx: usize = 1;
+    inline for (interfaces) |interface| {
+        const InterfacePtr = @TypeOf(interface);
+        const Interface = switch (@typeInfo(InterfacePtr)) {
+            .pointer => |pointer| pointer.child,
+            else => @compileError("expected tuple of '*const Protocol', got " ++ @typeName(InterfacePtr)),
+        };
+
+        if (!@hasDecl(Interface, "guid"))
+            @compileError("protocol interface '" ++ @typeName(Interface) ++
+                "' does not declare a 'const guid: uefi.Guid'.");
+
+        switch (@typeInfo(Interface)) {
+            .@"struct" => |struct_info| if (struct_info.layout != .@"extern")
+                @compileLog("protocol interface '" ++ @typeName(Interface) ++
+                    "' is not extern - this is likely a mistake"),
+            else => @compileError("protocol interface must be a struct, got " ++ @typeName(Interface)),
+        }
+
+        result[idx] = &Interface.guid;
+        result[idx + 1] = @ptrCast(interface);
+        idx += 2;
+    }
+
+    return result;
+}
+
+fn ProtocolInterfaces(HandleType: type, Interfaces: type) type {
+    const interfaces_type_info = @typeInfo(Interfaces);
+    if (interfaces_type_info != .@"struct" or !interfaces_type_info.@"struct".is_tuple)
+        @compileError("expected tuple of protocol interfaces, got " ++ @typeName(Interfaces));
+    const interfaces_info = interfaces_type_info.@"struct";
+
+    var tuple_types: [interfaces_info.fields.len * 2 + 1]type = undefined;
+    tuple_types[0] = HandleType;
+    var idx = 1;
+    while (idx < tuple_types.len) : (idx += 2) {
+        tuple_types[idx] = *const Guid;
+        tuple_types[idx + 1] = *const anyopaque;
+    }
+
+    return std.meta.Tuple(tuple_types[0..]);
+}
lib/std/os/uefi/tables/configuration_table.zig
@@ -5,7 +5,7 @@ pub const ConfigurationTable = extern struct {
     vendor_guid: Guid,
     vendor_table: *anyopaque,
 
-    pub const acpi_20_table_guid align(8) = Guid{
+    pub const acpi_20_table_guid: Guid = .{
         .time_low = 0x8868e871,
         .time_mid = 0xe4f1,
         .time_high_and_version = 0x11d3,
@@ -13,7 +13,7 @@ pub const ConfigurationTable = extern struct {
         .clock_seq_low = 0x22,
         .node = [_]u8{ 0x00, 0x80, 0xc7, 0x3c, 0x88, 0x81 },
     };
-    pub const acpi_10_table_guid align(8) = Guid{
+    pub const acpi_10_table_guid: Guid = .{
         .time_low = 0xeb9d2d30,
         .time_mid = 0x2d88,
         .time_high_and_version = 0x11d3,
@@ -21,7 +21,7 @@ pub const ConfigurationTable = extern struct {
         .clock_seq_low = 0x16,
         .node = [_]u8{ 0x00, 0x90, 0x27, 0x3f, 0xc1, 0x4d },
     };
-    pub const sal_system_table_guid align(8) = Guid{
+    pub const sal_system_table_guid: Guid = .{
         .time_low = 0xeb9d2d32,
         .time_mid = 0x2d88,
         .time_high_and_version = 0x113d,
@@ -29,7 +29,7 @@ pub const ConfigurationTable = extern struct {
         .clock_seq_low = 0x16,
         .node = [_]u8{ 0x00, 0x90, 0x27, 0x3f, 0xc1, 0x4d },
     };
-    pub const smbios_table_guid align(8) = Guid{
+    pub const smbios_table_guid: Guid = .{
         .time_low = 0xeb9d2d31,
         .time_mid = 0x2d88,
         .time_high_and_version = 0x11d3,
@@ -37,7 +37,7 @@ pub const ConfigurationTable = extern struct {
         .clock_seq_low = 0x16,
         .node = [_]u8{ 0x00, 0x90, 0x27, 0x3f, 0xc1, 0x4d },
     };
-    pub const smbios3_table_guid align(8) = Guid{
+    pub const smbios3_table_guid: Guid = .{
         .time_low = 0xf2fd1544,
         .time_mid = 0x9794,
         .time_high_and_version = 0x4a2c,
@@ -45,7 +45,7 @@ pub const ConfigurationTable = extern struct {
         .clock_seq_low = 0x2e,
         .node = [_]u8{ 0xe5, 0xbb, 0xcf, 0x20, 0xe3, 0x94 },
     };
-    pub const mps_table_guid align(8) = Guid{
+    pub const mps_table_guid: Guid = .{
         .time_low = 0xeb9d2d2f,
         .time_mid = 0x2d88,
         .time_high_and_version = 0x11d3,
@@ -53,7 +53,7 @@ pub const ConfigurationTable = extern struct {
         .clock_seq_low = 0x16,
         .node = [_]u8{ 0x00, 0x90, 0x27, 0x3f, 0xc1, 0x4d },
     };
-    pub const json_config_data_table_guid align(8) = Guid{
+    pub const json_config_data_table_guid: Guid = .{
         .time_low = 0x87367f87,
         .time_mid = 0x1119,
         .time_high_and_version = 0x41ce,
@@ -61,7 +61,7 @@ pub const ConfigurationTable = extern struct {
         .clock_seq_low = 0xec,
         .node = [_]u8{ 0x8b, 0xe0, 0x11, 0x1f, 0x55, 0x8a },
     };
-    pub const json_capsule_data_table_guid align(8) = Guid{
+    pub const json_capsule_data_table_guid: Guid = .{
         .time_low = 0x35e7a725,
         .time_mid = 0x8dd2,
         .time_high_and_version = 0x4cac,
@@ -69,7 +69,7 @@ pub const ConfigurationTable = extern struct {
         .clock_seq_low = 0x11,
         .node = [_]u8{ 0x33, 0xcd, 0xa8, 0x10, 0x90, 0x56 },
     };
-    pub const json_capsule_result_table_guid align(8) = Guid{
+    pub const json_capsule_result_table_guid: Guid = .{
         .time_low = 0xdbc461c3,
         .time_mid = 0xb3de,
         .time_high_and_version = 0x422a,
lib/std/os/uefi/tables/runtime_services.zig
@@ -6,10 +6,12 @@ const Time = uefi.Time;
 const TimeCapabilities = uefi.TimeCapabilities;
 const Status = uefi.Status;
 const MemoryDescriptor = uefi.tables.MemoryDescriptor;
+const MemoryMapSlice = uefi.tables.MemoryMapSlice;
 const ResetType = uefi.tables.ResetType;
 const CapsuleHeader = uefi.tables.CapsuleHeader;
 const PhysicalAddress = uefi.tables.PhysicalAddress;
 const cc = uefi.cc;
+const Error = Status.Error;
 
 /// Runtime services are provided by the firmware before and after exitBootServices has been called.
 ///
@@ -23,50 +25,511 @@ pub const RuntimeServices = extern struct {
     hdr: TableHeader,
 
     /// Returns the current time and date information, and the time-keeping capabilities of the hardware platform.
-    getTime: *const fn (time: *uefi.Time, capabilities: ?*TimeCapabilities) callconv(cc) Status,
+    _getTime: *const fn (time: *Time, capabilities: ?*TimeCapabilities) callconv(cc) Status,
 
     /// Sets the current local time and date information
-    setTime: *const fn (time: *uefi.Time) callconv(cc) Status,
+    _setTime: *const fn (time: *const Time) callconv(cc) Status,
 
     /// Returns the current wakeup alarm clock setting
-    getWakeupTime: *const fn (enabled: *bool, pending: *bool, time: *uefi.Time) callconv(cc) Status,
+    _getWakeupTime: *const fn (enabled: *bool, pending: *bool, time: *Time) callconv(cc) Status,
 
     /// Sets the system wakeup alarm clock time
-    setWakeupTime: *const fn (enable: *bool, time: ?*uefi.Time) callconv(cc) Status,
+    _setWakeupTime: *const fn (enable: bool, time: ?*const Time) callconv(cc) Status,
 
     /// Changes the runtime addressing mode of EFI firmware from physical to virtual.
-    setVirtualAddressMap: *const fn (mmap_size: usize, descriptor_size: usize, descriptor_version: u32, virtual_map: [*]MemoryDescriptor) callconv(cc) Status,
+    _setVirtualAddressMap: *const fn (mmap_size: usize, descriptor_size: usize, descriptor_version: u32, virtual_map: [*]align(@alignOf(MemoryDescriptor)) u8) callconv(cc) Status,
 
     /// Determines the new virtual address that is to be used on subsequent memory accesses.
-    convertPointer: *const fn (debug_disposition: usize, address: **anyopaque) callconv(cc) Status,
+    _convertPointer: *const fn (debug_disposition: DebugDisposition, address: *?*anyopaque) callconv(cc) Status,
 
     /// Returns the value of a variable.
-    getVariable: *const fn (var_name: [*:0]const u16, vendor_guid: *align(8) const Guid, attributes: ?*u32, data_size: *usize, data: ?*anyopaque) callconv(cc) Status,
+    _getVariable: *const fn (var_name: [*:0]const u16, vendor_guid: *const Guid, attributes: ?*VariableAttributes, data_size: *usize, data: ?*anyopaque) callconv(cc) Status,
 
     /// Enumerates the current variable names.
-    getNextVariableName: *const fn (var_name_size: *usize, var_name: [*:0]u16, vendor_guid: *align(8) Guid) callconv(cc) Status,
+    _getNextVariableName: *const fn (var_name_size: *usize, var_name: ?[*:0]const u16, vendor_guid: *Guid) callconv(cc) Status,
 
     /// Sets the value of a variable.
-    setVariable: *const fn (var_name: [*:0]const u16, vendor_guid: *align(8) const Guid, attributes: u32, data_size: usize, data: *anyopaque) callconv(cc) Status,
+    _setVariable: *const fn (var_name: [*:0]const u16, vendor_guid: *const Guid, attributes: VariableAttributes, data_size: usize, data: [*]const u8) callconv(cc) Status,
 
     /// Return the next high 32 bits of the platform's monotonic counter
-    getNextHighMonotonicCount: *const fn (high_count: *u32) callconv(cc) Status,
+    _getNextHighMonotonicCount: *const fn (high_count: *u32) callconv(cc) Status,
 
     /// Resets the entire platform.
-    resetSystem: *const fn (reset_type: ResetType, reset_status: Status, data_size: usize, reset_data: ?*const anyopaque) callconv(cc) noreturn,
+    _resetSystem: *const fn (reset_type: ResetType, reset_status: Status, data_size: usize, reset_data: ?[*]const u16) callconv(cc) noreturn,
 
     /// Passes capsules to the firmware with both virtual and physical mapping.
     /// Depending on the intended consumption, the firmware may process the capsule immediately.
     /// If the payload should persist across a system reset, the reset value returned from
     /// `queryCapsuleCapabilities` must be passed into resetSystem and will cause the capsule
     /// to be processed by the firmware as part of the reset process.
-    updateCapsule: *const fn (capsule_header_array: **CapsuleHeader, capsule_count: usize, scatter_gather_list: PhysicalAddress) callconv(cc) Status,
+    _updateCapsule: *const fn (capsule_header_array: [*]*const CapsuleHeader, capsule_count: usize, scatter_gather_list: PhysicalAddress) callconv(cc) Status,
 
     /// Returns if the capsule can be supported via `updateCapsule`
-    queryCapsuleCapabilities: *const fn (capsule_header_array: **CapsuleHeader, capsule_count: usize, maximum_capsule_size: *usize, reset_type: ResetType) callconv(cc) Status,
+    _queryCapsuleCapabilities: *const fn (capsule_header_array: [*]*const CapsuleHeader, capsule_count: usize, maximum_capsule_size: *usize, reset_type: *ResetType) callconv(cc) Status,
 
     /// Returns information about the EFI variables
-    queryVariableInfo: *const fn (attributes: *u32, maximum_variable_storage_size: *u64, remaining_variable_storage_size: *u64, maximum_variable_size: *u64) callconv(cc) Status,
+    _queryVariableInfo: *const fn (attributes: VariableAttributes, maximum_variable_storage_size: *u64, remaining_variable_storage_size: *u64, maximum_variable_size: *u64) callconv(cc) Status,
+
+    pub const GetTimeError = uefi.UnexpectedError || error{
+        DeviceError,
+        Unsupported,
+    };
+
+    pub const SetTimeError = uefi.UnexpectedError || error{
+        DeviceError,
+        Unsupported,
+    };
+
+    pub const GetWakeupTimeError = uefi.UnexpectedError || error{
+        DeviceError,
+        Unsupported,
+    };
+
+    pub const SetWakeupTimeError = uefi.UnexpectedError || error{
+        InvalidParameter,
+        DeviceError,
+        Unsupported,
+    };
+
+    pub const SetVirtualAddressMapError = uefi.UnexpectedError || error{
+        Unsupported,
+        NoMapping,
+        NotFound,
+    };
+
+    pub const ConvertPointerError = uefi.UnexpectedError || error{
+        InvalidParameter,
+        Unsupported,
+    };
+
+    pub const GetVariableSizeError = uefi.UnexpectedError || error{
+        DeviceError,
+        Unsupported,
+    };
+
+    pub const GetVariableError = GetVariableSizeError || error{
+        BufferTooSmall,
+    };
+
+    pub const SetVariableError = uefi.UnexpectedError || error{
+        InvalidParameter,
+        OutOfResources,
+        DeviceError,
+        WriteProtected,
+        SecurityViolation,
+        NotFound,
+        Unsupported,
+    };
+
+    pub const GetNextHighMonotonicCountError = uefi.UnexpectedError || error{
+        DeviceError,
+        Unsupported,
+    };
+
+    pub const UpdateCapsuleError = uefi.UnexpectedError || error{
+        InvalidParameter,
+        DeviceError,
+        Unsupported,
+        OutOfResources,
+    };
+
+    pub const QueryCapsuleCapabilitiesError = uefi.UnexpectedError || error{
+        Unsupported,
+        OutOfResources,
+    };
+
+    pub const QueryVariableInfoError = uefi.UnexpectedError || error{
+        InvalidParameter,
+        Unsupported,
+    };
+
+    /// Returns the current time and the time capabilities of the platform.
+    pub fn getTime(
+        self: *const RuntimeServices,
+    ) GetTimeError!struct { Time, TimeCapabilities } {
+        var time: Time = undefined;
+        var capabilities: TimeCapabilities = undefined;
+
+        switch (self._getTime(&time, &capabilities)) {
+            .success => return .{ time, capabilities },
+            .device_error => return error.DeviceError,
+            .unsupported => return error.Unsupported,
+            else => |status| return uefi.unexpectedStatus(status),
+        }
+    }
+
+    pub fn setTime(self: *RuntimeServices, time: *const Time) SetTimeError!void {
+        switch (self._setTime(time)) {
+            .success => {},
+            .device_error => return error.DeviceError,
+            .unsupported => return error.Unsupported,
+            else => |status| return uefi.unexpectedStatus(status),
+        }
+    }
+
+    pub const GetWakeupTime = struct {
+        enabled: bool,
+        pending: bool,
+        time: Time,
+    };
+
+    pub fn getWakeupTime(
+        self: *const RuntimeServices,
+    ) GetWakeupTimeError!GetWakeupTime {
+        var result: GetWakeupTime = undefined;
+        switch (self._getWakeupTime(
+            &result.enabled,
+            &result.pending,
+            &result.time,
+        )) {
+            .success => return result,
+            .device_error => return error.DeviceError,
+            .unsupported => return error.Unsupported,
+            else => |status| return uefi.unexpectedStatus(status),
+        }
+    }
+
+    pub const SetWakeupTime = union(enum) {
+        enabled: *const Time,
+        disabled,
+    };
+
+    pub fn setWakeupTime(
+        self: *RuntimeServices,
+        set: SetWakeupTime,
+    ) SetWakeupTimeError!void {
+        switch (self._setWakeupTime(
+            set != .disabled,
+            if (set == .enabled) set.enabled else null,
+        )) {
+            .success => {},
+            .invalid_parameter => return error.InvalidParameter,
+            .device_error => return error.DeviceError,
+            .unsupported => return error.Unsupported,
+            else => |status| return uefi.unexpectedStatus(status),
+        }
+    }
+
+    pub fn setVirtualAddressMap(
+        self: *RuntimeServices,
+        map: MemoryMapSlice,
+    ) SetVirtualAddressMapError!void {
+        switch (self._setVirtualAddressMap(
+            map.info.len * map.info.descriptor_size,
+            map.info.descriptor_size,
+            map.info.descriptor_version,
+            @ptrCast(map.ptr),
+        )) {
+            .success => {},
+            .unsupported => return error.Unsupported,
+            .no_mapping => return error.NoMapping,
+            .not_found => return error.NotFound,
+            else => |status| return uefi.unexpectedStatus(status),
+        }
+    }
+
+    pub fn convertPointer(
+        self: *const RuntimeServices,
+        comptime disposition: DebugDisposition,
+        cvt: @FieldType(PointerConversion, @tagName(disposition)),
+    ) ConvertPointerError!?@FieldType(PointerConversion, @tagName(disposition)) {
+        var pointer = cvt;
+
+        switch (self._convertPointer(disposition, @ptrCast(&pointer))) {
+            .success => return pointer,
+            .not_found => return null,
+            .invalid_parameter => return error.InvalidParameter,
+            .unsupported => return error.Unsupported,
+            else => |status| return uefi.unexpectedStatus(status),
+        }
+    }
+
+    /// Returns the length of the variable's data and its attributes.
+    pub fn getVariableSize(
+        self: *const RuntimeServices,
+        name: [*:0]const u16,
+        guid: *const Guid,
+    ) GetVariableSizeError!?struct { usize, VariableAttributes } {
+        var size: usize = 0;
+        var attrs: VariableAttributes = undefined;
+
+        switch (self._getVariable(
+            name,
+            guid,
+            &attrs,
+            &size,
+            null,
+        )) {
+            .buffer_too_small => return .{ size, attrs },
+            .not_found => return null,
+            .device_error => return error.DeviceError,
+            .unsupported => return error.Unsupported,
+            else => |status| return uefi.unexpectedStatus(status),
+        }
+    }
+
+    /// To determine the minimum necessary buffer size for the variable, call
+    /// `getVariableSize` first.
+    pub fn getVariable(
+        self: *const RuntimeServices,
+        name: [*:0]const u16,
+        guid: *const Guid,
+        buffer: []u8,
+    ) GetVariableError!?struct { []u8, VariableAttributes } {
+        var attrs: VariableAttributes = undefined;
+        var len = buffer.len;
+
+        switch (self._getVariable(
+            name,
+            guid,
+            &attrs,
+            &len,
+            buffer.ptr,
+        )) {
+            .success => return .{ buffer[0..len], attrs },
+            .not_found => return null,
+            .buffer_too_small => return error.BufferTooSmall,
+            .device_error => return error.DeviceError,
+            .unsupported => return error.Unsupported,
+            else => |status| return uefi.unexpectedStatus(status),
+        }
+    }
+
+    pub fn variableNameIterator(
+        self: *const RuntimeServices,
+        buffer: []u16,
+    ) VariableNameIterator {
+        buffer[0] = 0;
+        return .{
+            .services = self,
+            .buffer = buffer,
+            .guid = undefined,
+        };
+    }
+
+    pub fn setVariable(
+        self: *RuntimeServices,
+        name: [*:0]const u16,
+        guid: *const Guid,
+        attributes: VariableAttributes,
+        data: []const u8,
+    ) SetVariableError!void {
+        switch (self._setVariable(
+            name,
+            guid,
+            attributes,
+            data.len,
+            data.ptr,
+        )) {
+            .success => {},
+            .invalid_parameter => return error.InvalidParameter,
+            .out_of_resources => return error.OutOfResources,
+            .device_error => return error.DeviceError,
+            .write_protected => return error.WriteProtected,
+            .security_violation => return error.SecurityViolation,
+            .not_found => return error.NotFound,
+            .unsupported => return error.Unsupported,
+            else => |status| return uefi.unexpectedStatus(status),
+        }
+    }
+
+    pub fn getNextHighMonotonicCount(self: *const RuntimeServices) GetNextHighMonotonicCountError!u32 {
+        var cnt: u32 = undefined;
+        switch (self._getNextHighMonotonicCount(&cnt)) {
+            .success => return cnt,
+            .device_error => return error.DeviceError,
+            .unsupported => return error.Unsupported,
+            else => |status| return uefi.unexpectedStatus(status),
+        }
+    }
+
+    pub fn resetSystem(
+        self: *RuntimeServices,
+        reset_type: ResetType,
+        reset_status: Status,
+        data: ?[]align(2) const u8,
+    ) noreturn {
+        self._resetSystem(
+            reset_type,
+            reset_status,
+            if (data) |d| d.len else 0,
+            if (data) |d| @alignCast(@ptrCast(d.ptr)) else null,
+        );
+    }
+
+    pub fn updateCapsule(
+        self: *RuntimeServices,
+        capsules: []*const CapsuleHeader,
+        scatter_gather_list: PhysicalAddress,
+    ) UpdateCapsuleError!void {
+        switch (self._updateCapsule(
+            capsules.ptr,
+            capsules.len,
+            scatter_gather_list,
+        )) {
+            .success => {},
+            .invalid_parameter => return error.InvalidParameter,
+            .device_error => return error.DeviceError,
+            .unsupported => return error.Unsupported,
+            .out_of_resources => return error.OutOfResources,
+            else => |status| return uefi.unexpectedStatus(status),
+        }
+    }
+
+    pub fn queryCapsuleCapabilities(
+        self: *const RuntimeServices,
+        capsules: []*const CapsuleHeader,
+    ) QueryCapsuleCapabilitiesError!struct { u64, ResetType } {
+        var max_capsule_size: u64 = undefined;
+        var reset_type: ResetType = undefined;
+
+        switch (self._queryCapsuleCapabilities(
+            capsules.ptr,
+            capsules.len,
+            &max_capsule_size,
+            &reset_type,
+        )) {
+            .success => return .{ max_capsule_size, reset_type },
+            .unsupported => return error.Unsupported,
+            .out_of_resources => return error.OutOfResources,
+            else => |status| return uefi.unexpectedStatus(status),
+        }
+    }
+
+    pub fn queryVariableInfo(
+        self: *const RuntimeServices,
+        // Note: .append_write is ignored
+        attributes: VariableAttributes,
+    ) QueryVariableInfoError!VariableInfo {
+        var res: VariableInfo = undefined;
+
+        switch (self._queryVariableInfo(
+            attributes,
+            &res.max_variable_storage_size,
+            &res.remaining_variable_storage_size,
+            &res.max_variable_size,
+        )) {
+            .success => return res,
+            .invalid_parameter => return error.InvalidParameter,
+            .unsupported => return error.Unsupported,
+            else => |status| return uefi.unexpectedStatus(status),
+        }
+    }
+
+    pub const DebugDisposition = enum(usize) {
+        const Bits = packed struct(usize) {
+            optional_ptr: bool = false,
+            _pad: std.meta.Int(.unsigned, @bitSizeOf(usize) - 1) = 0,
+        };
+
+        pointer = @bitCast(Bits{}),
+        optional = @bitCast(Bits{ .optional_ptr = true }),
+        _,
+    };
+
+    pub const PointerConversion = union(DebugDisposition) {
+        pointer: *anyopaque,
+        optional: ?*anyopaque,
+    };
+
+    pub const VariableAttributes = packed struct(u32) {
+        non_volatile: bool = false,
+        bootservice_access: bool = false,
+        runtime_access: bool = false,
+        hardware_error_record: bool = false,
+        /// Note: deprecated and should be considered reserved.
+        authenticated_write_access: bool = false,
+        time_based_authenticated_write_access: bool = false,
+        append_write: bool = false,
+        /// Indicates that the variable payload begins with a EFI_VARIABLE_AUTHENTICATION_3
+        /// structure, and potentially more structures as indicated by fields of
+        /// this structure.
+        enhanced_authenticated_access: bool = false,
+        _pad: u24 = 0,
+    };
+
+    pub const VariableAuthentication3 = extern struct {
+        version: u8 = 1,
+        type: Type,
+        metadata_size: u32,
+        flags: Flags,
+
+        pub fn payloadConst(self: *const VariableAuthentication3) []const u8 {
+            return @constCast(self).payload();
+        }
+
+        pub fn payload(self: *VariableAuthentication3) []u8 {
+            var ptr: [*]u8 = @ptrCast(self);
+            return ptr[@sizeOf(VariableAuthentication3)..self.metadata_size];
+        }
+
+        pub const Flags = packed struct(u32) {
+            update_cert: bool = false,
+            _pad: u31 = 0,
+        };
+
+        pub const Type = enum(u8) {
+            timestamp = 1,
+            nonce = 2,
+            _,
+        };
+    };
+
+    pub const VariableInfo = struct {
+        max_variable_storage_size: u64,
+        remaining_variable_storage_size: u64,
+        max_variable_size: u64,
+    };
+
+    pub const VariableNameIterator = struct {
+        pub const NextSizeError = uefi.UnexpectedError || error{
+            DeviceError,
+            Unsupported,
+        };
+
+        pub const IterateVariableNameError = NextSizeError || error{
+            BufferTooSmall,
+        };
+
+        services: *const RuntimeServices,
+        buffer: []u16,
+        guid: Guid,
+
+        pub fn nextSize(self: *VariableNameIterator) NextSizeError!?usize {
+            var len: usize = 0;
+            switch (self.services._getNextVariableName(
+                &len,
+                null,
+                &self.guid,
+            )) {
+                .buffer_too_small => return len,
+                .not_found => return null,
+                .device_error => return error.DeviceError,
+                .unsupported => return error.Unsupported,
+                else => |status| return uefi.unexpectedStatus(status),
+            }
+        }
+
+        /// Call `nextSize` to get the length of the next variable name and check
+        /// if `buffer` is large enough to hold the name.
+        pub fn next(
+            self: *VariableNameIterator,
+        ) IterateVariableNameError!?[:0]const u16 {
+            var len = self.buffer.len;
+            switch (self.services._getNextVariableName(
+                &len,
+                @ptrCast(self.buffer.ptr),
+                &self.guid,
+            )) {
+                .success => return self.buffer[0 .. len - 1 :0],
+                .not_found => return null,
+                .buffer_too_small => return error.BufferTooSmall,
+                .device_error => return error.DeviceError,
+                .unsupported => return error.Unsupported,
+                else => |status| return uefi.unexpectedStatus(status),
+            }
+        }
+    };
 
     pub const signature: u64 = 0x56524553544e5552;
 };
lib/std/os/uefi/pool_allocator.zig
@@ -28,14 +28,16 @@ const UefiPoolAllocator = struct {
 
         const full_len = metadata_len + len;
 
-        var unaligned_ptr: [*]align(8) u8 = undefined;
-        if (uefi.system_table.boot_services.?.allocatePool(uefi.efi_pool_memory_type, full_len, &unaligned_ptr) != .success) return null;
+        const unaligned_slice = uefi.system_table.boot_services.?.allocatePool(
+            uefi.efi_pool_memory_type,
+            full_len,
+        ) catch return null;
 
-        const unaligned_addr = @intFromPtr(unaligned_ptr);
+        const unaligned_addr = @intFromPtr(unaligned_slice.ptr);
         const aligned_addr = mem.alignForward(usize, unaligned_addr + @sizeOf(usize), ptr_align);
 
-        const aligned_ptr = unaligned_ptr + (aligned_addr - unaligned_addr);
-        getHeader(aligned_ptr).* = unaligned_ptr;
+        const aligned_ptr = unaligned_slice.ptr + (aligned_addr - unaligned_addr);
+        getHeader(aligned_ptr).* = unaligned_slice.ptr;
 
         return aligned_ptr;
     }
@@ -76,7 +78,7 @@ const UefiPoolAllocator = struct {
     ) void {
         _ = alignment;
         _ = ret_addr;
-        _ = uefi.system_table.boot_services.?.freePool(getHeader(buf.ptr).*);
+        uefi.system_table.boot_services.?.freePool(getHeader(buf.ptr).*) catch unreachable;
     }
 };
 
@@ -117,10 +119,12 @@ fn uefi_alloc(
 
     std.debug.assert(@intFromEnum(alignment) <= 3);
 
-    var ptr: [*]align(8) u8 = undefined;
-    if (uefi.system_table.boot_services.?.allocatePool(uefi.efi_pool_memory_type, len, &ptr) != .success) return null;
+    const slice = uefi.system_table.boot_services.?.allocatePool(
+        uefi.efi_pool_memory_type,
+        len,
+    ) catch return null;
 
-    return ptr;
+    return slice.ptr;
 }
 
 fn uefi_resize(
@@ -161,5 +165,5 @@ fn uefi_free(
 ) void {
     _ = alignment;
     _ = ret_addr;
-    _ = uefi.system_table.boot_services.?.freePool(@alignCast(buf.ptr));
+    uefi.system_table.boot_services.?.freePool(@alignCast(buf.ptr)) catch unreachable;
 }
lib/std/os/uefi/tables.zig
@@ -1,3 +1,12 @@
+const std = @import("std");
+const uefi = std.os.uefi;
+const Handle = uefi.Handle;
+const Event = uefi.Event;
+const Guid = uefi.Guid;
+const cc = uefi.cc;
+const math = std.math;
+const assert = std.debug.assert;
+
 pub const BootServices = @import("tables/boot_services.zig").BootServices;
 pub const RuntimeServices = @import("tables/runtime_services.zig").RuntimeServices;
 pub const ConfigurationTable = @import("tables/configuration_table.zig").ConfigurationTable;
@@ -7,29 +16,90 @@ pub const TableHeader = @import("tables/table_header.zig").TableHeader;
 pub const EventNotify = *const fn (event: Event, ctx: *anyopaque) callconv(cc) void;
 
 pub const TimerDelay = enum(u32) {
-    timer_cancel,
-    timer_periodic,
-    timer_relative,
+    cancel,
+    periodic,
+    relative,
 };
 
 pub const MemoryType = enum(u32) {
+    pub const Oem = math.IntFittingRange(
+        0,
+        @intFromEnum(MemoryType.oem_end) - @intFromEnum(MemoryType.oem_start),
+    );
+    pub const Vendor = math.IntFittingRange(
+        0,
+        @intFromEnum(MemoryType.vendor_end) - @intFromEnum(MemoryType.vendor_start),
+    );
+
+    /// can only be allocated using .allocate_any_pages mode unless you are explicitly targeting an interface that states otherwise
     reserved_memory_type,
     loader_code,
     loader_data,
     boot_services_code,
     boot_services_data,
+    /// can only be allocated using .allocate_any_pages mode unless you are explicitly targeting an interface that states otherwise
     runtime_services_code,
+    /// can only be allocated using .allocate_any_pages mode unless you are explicitly targeting an interface that states otherwise
     runtime_services_data,
     conventional_memory,
     unusable_memory,
+    /// can only be allocated using .allocate_any_pages mode unless you are explicitly targeting an interface that states otherwise
     acpi_reclaim_memory,
+    /// can only be allocated using .allocate_any_pages mode unless you are explicitly targeting an interface that states otherwise
     acpi_memory_nvs,
     memory_mapped_io,
     memory_mapped_io_port_space,
     pal_code,
     persistent_memory,
+    unaccepted_memory,
     max_memory_type,
+    invalid_start,
+    invalid_end = 0x6FFFFFFF,
+    /// MemoryType values in the range 0x70000000..0x7FFFFFFF are reserved for OEM use.
+    oem_start = 0x70000000,
+    oem_end = 0x7FFFFFFF,
+    /// MemoryType values in the range 0x80000000..0xFFFFFFFF are reserved for use by UEFI
+    /// OS loaders that are provided by operating system vendors.
+    vendor_start = 0x80000000,
+    vendor_end = 0xFFFFFFFF,
     _,
+
+    pub fn fromOem(value: Oem) MemoryType {
+        const oem_start = @intFromEnum(MemoryType.oem_start);
+        return @enumFromInt(oem_start + value);
+    }
+
+    pub fn toOem(memtype: MemoryType) ?Oem {
+        const as_int = @intFromEnum(memtype);
+        const oem_start = @intFromEnum(MemoryType.oem_start);
+        if (as_int < oem_start) return null;
+        if (as_int > @intFromEnum(MemoryType.oem_end)) return null;
+        return @truncate(as_int - oem_start);
+    }
+
+    pub fn fromVendor(value: Vendor) MemoryType {
+        const vendor_start = @intFromEnum(MemoryType.vendor_start);
+        return @enumFromInt(vendor_start + value);
+    }
+
+    pub fn toVendor(memtype: MemoryType) ?Vendor {
+        const as_int = @intFromEnum(memtype);
+        const vendor_start = @intFromEnum(MemoryType.vendor_start);
+        if (as_int < @intFromEnum(MemoryType.vendor_end)) return null;
+        if (as_int > @intFromEnum(MemoryType.vendor_end)) return null;
+        return @truncate(as_int - vendor_start);
+    }
+
+    pub fn format(self: MemoryType, w: *std.io.Writer) std.io.WriteError!void {
+        if (self.toOem()) |oemval|
+            try w.print("OEM({X})", .{oemval})
+        else if (self.toVendor()) |vendorval|
+            try w.print("Vendor({X})", .{vendorval})
+        else if (std.enums.tagName(MemoryType, self)) |name|
+            try w.print("{s}", .{name})
+        else
+            try w.print("INVALID({X})", .{@intFromEnum(self)});
+    }
 };
 
 pub const MemoryDescriptorAttribute = packed struct(u64) {
@@ -51,6 +121,8 @@ pub const MemoryDescriptorAttribute = packed struct(u64) {
     memory_runtime: bool,
 };
 
+pub const MemoryMapKey = enum(usize) { _ };
+
 pub const MemoryDescriptor = extern struct {
     type: MemoryType,
     physical_start: u64,
@@ -59,20 +131,121 @@ pub const MemoryDescriptor = extern struct {
     attribute: MemoryDescriptorAttribute,
 };
 
+pub const MemoryMapInfo = struct {
+    key: MemoryMapKey,
+    descriptor_size: usize,
+    descriptor_version: u32,
+    /// The number of descriptors in the map.
+    len: usize,
+};
+
+pub const MemoryMapSlice = struct {
+    info: MemoryMapInfo,
+    ptr: [*]align(@alignOf(MemoryDescriptor)) u8,
+
+    pub fn iterator(self: MemoryMapSlice) MemoryDescriptorIterator {
+        return .{ .ctx = self };
+    }
+
+    pub fn get(self: MemoryMapSlice, index: usize) ?*MemoryDescriptor {
+        if (index >= self.info.len) return null;
+        return self.getUnchecked(index);
+    }
+
+    pub fn getUnchecked(self: MemoryMapSlice, index: usize) *MemoryDescriptor {
+        const offset: usize = index * self.info.descriptor_size;
+        return @alignCast(@ptrCast(self.ptr[offset..]));
+    }
+};
+
+pub const MemoryDescriptorIterator = struct {
+    ctx: MemoryMapSlice,
+    index: usize = 0,
+
+    pub fn next(self: *MemoryDescriptorIterator) ?*MemoryDescriptor {
+        const md = self.ctx.get(self.index) orelse return null;
+        self.index += 1;
+        return md;
+    }
+};
+
 pub const LocateSearchType = enum(u32) {
     all_handles,
     by_register_notify,
     by_protocol,
 };
 
-pub const OpenProtocolAttributes = packed struct(u32) {
-    by_handle_protocol: bool = false,
-    get_protocol: bool = false,
-    test_protocol: bool = false,
-    by_child_controller: bool = false,
-    by_driver: bool = false,
-    exclusive: bool = false,
-    reserved: u26 = 0,
+pub const LocateSearch = union(LocateSearchType) {
+    all_handles,
+    by_register_notify: uefi.EventRegistration,
+    by_protocol: *const Guid,
+};
+
+pub const OpenProtocolAttributes = enum(u32) {
+    pub const Bits = packed struct(u32) {
+        by_handle_protocol: bool = false,
+        get_protocol: bool = false,
+        test_protocol: bool = false,
+        by_child_controller: bool = false,
+        by_driver: bool = false,
+        exclusive: bool = false,
+        reserved: u26 = 0,
+    };
+
+    by_handle_protocol = @bitCast(Bits{ .by_handle_protocol = true }),
+    get_protocol = @bitCast(Bits{ .get_protocol = true }),
+    test_protocol = @bitCast(Bits{ .test_protocol = true }),
+    by_child_controller = @bitCast(Bits{ .by_child_controller = true }),
+    by_driver = @bitCast(Bits{ .by_driver = true }),
+    by_driver_exclusive = @bitCast(Bits{ .by_driver = true, .exclusive = true }),
+    exclusive = @bitCast(Bits{ .exclusive = true }),
+    _,
+
+    pub fn fromBits(bits: Bits) OpenProtocolAttributes {
+        return @bitCast(bits);
+    }
+
+    pub fn toBits(self: OpenProtocolAttributes) Bits {
+        return @bitCast(self);
+    }
+};
+
+pub const OpenProtocolArgs = union(OpenProtocolAttributes) {
+    /// Used in the implementation of `handleProtocol`.
+    by_handle_protocol: struct { agent: ?Handle = null, controller: ?Handle = null },
+    /// Used by a driver to get a protocol interface from a handle. Care must be
+    /// taken when using this open mode because the driver that opens a protocol
+    /// interface in this manner will not be informed if the protocol interface
+    /// is uninstalled or reinstalled. The caller is also not required to close
+    /// the protocol interface with `closeProtocol`.
+    get_protocol: struct { agent: ?Handle = null, controller: ?Handle = null },
+    /// Used by a driver to test for the existence of a protocol interface on a
+    /// handle. The caller only use the return status code. The caller is also
+    /// not required to close the protocol interface with `closeProtocol`.
+    test_protocol: struct { agent: ?Handle = null, controller: ?Handle = null },
+    /// Used by bus drivers to show that a protocol interface is being used by one
+    /// of the child controllers of a bus. This information is used by
+    /// `BootServices.connectController` to recursively connect all child controllers
+    /// and by `BootServices.disconnectController` to get the list of child
+    /// controllers that a bus driver created.
+    by_child_controller: struct { agent: Handle, controller: Handle },
+    /// Used by a driver to gain access to a protocol interface. When this mode
+    /// is used, the driver’s Stop() function will be called by
+    /// `BootServices.disconnectController` if the protocol interface is reinstalled
+    /// or uninstalled. Once a protocol interface is opened by a driver with this
+    /// attribute, no other drivers will be allowed to open the same protocol interface
+    /// with the `.by_driver` attribute.
+    by_driver: struct { agent: Handle, controller: Handle },
+    /// Used by a driver to gain exclusive access to a protocol interface. If any
+    /// other drivers have the protocol interface opened with an attribute of
+    /// `.by_driver`, then an attempt will be made to remove them with
+    /// `BootServices.disconnectController`.
+    by_driver_exclusive: struct { agent: Handle, controller: Handle },
+    /// Used by applications to gain exclusive access to a protocol interface. If
+    /// any drivers have the protocol interface opened with an attribute of
+    /// `.by_driver`, then an attempt will be made to remove them by calling the
+    /// driver’s Stop() function.
+    exclusive: struct { agent: Handle, controller: ?Handle = null },
 };
 
 pub const ProtocolInformationEntry = extern struct {
@@ -83,19 +256,25 @@ pub const ProtocolInformationEntry = extern struct {
 };
 
 pub const InterfaceType = enum(u32) {
-    efi_native_interface,
+    native,
+};
+
+pub const AllocateLocation = union(AllocateType) {
+    any,
+    max_address: [*]align(4096) uefi.Page,
+    address: [*]align(4096) uefi.Page,
 };
 
 pub const AllocateType = enum(u32) {
-    allocate_any_pages,
-    allocate_max_address,
-    allocate_address,
+    any,
+    max_address,
+    address,
 };
 
 pub const PhysicalAddress = u64;
 
 pub const CapsuleHeader = extern struct {
-    capsule_guid: Guid align(8),
+    capsule_guid: Guid,
     header_size: u32,
     flags: u32,
     capsule_image_size: u32,
@@ -110,13 +289,13 @@ pub const UefiCapsuleBlockDescriptor = extern struct {
 };
 
 pub const ResetType = enum(u32) {
-    reset_cold,
-    reset_warm,
-    reset_shutdown,
-    reset_platform_specific,
+    cold,
+    warm,
+    shutdown,
+    platform_specific,
 };
 
-pub const global_variable align(8) = Guid{
+pub const global_variable = Guid{
     .time_low = 0x8be4df61,
     .time_mid = 0x93ca,
     .time_high_and_version = 0x11d2,
@@ -128,10 +307,3 @@ pub const global_variable align(8) = Guid{
 test {
     std.testing.refAllDeclsRecursive(@This());
 }
-
-const std = @import("std");
-const uefi = std.os.uefi;
-const Handle = uefi.Handle;
-const Event = uefi.Event;
-const Guid = uefi.Guid;
-const cc = uefi.cc;
lib/std/os/uefi.zig
@@ -24,9 +24,51 @@ pub var handle: Handle = undefined;
 /// A pointer to the EFI System Table that is passed to the EFI image's entry point.
 pub var system_table: *tables.SystemTable = undefined;
 
+/// UEFI's memory interfaces exclusively act on 4096-byte pages.
+pub const Page = [4096]u8;
+
 /// A handle to an event structure.
 pub const Event = *opaque {};
 
+pub const EventRegistration = *const opaque {};
+
+pub const EventType = packed struct(u32) {
+    lo_context: u8 = 0,
+    /// If an event of this type is not already in the signaled state, then
+    /// the event’s NotificationFunction will be queued at the event’s NotifyTpl
+    /// whenever the event is being waited on via EFI_BOOT_SERVICES.WaitForEvent()
+    /// or EFI_BOOT_SERVICES.CheckEvent() .
+    wait: bool = false,
+    /// The event’s NotifyFunction is queued whenever the event is signaled.
+    signal: bool = false,
+    hi_context: u20 = 0,
+    /// The event is allocated from runtime memory. If an event is to be signaled
+    /// after the call to EFI_BOOT_SERVICES.ExitBootServices() the event’s data
+    /// structure and notification function need to be allocated from runtime
+    /// memory.
+    runtime: bool = false,
+    timer: bool = false,
+
+    /// This event should not be combined with any other event types. This event
+    /// type is functionally equivalent to the EFI_EVENT_GROUP_EXIT_BOOT_SERVICES
+    /// event group.
+    pub const signal_exit_boot_services: EventType = .{
+        .signal = true,
+        .lo_context = 1,
+    };
+
+    /// The event is to be notified by the system when SetVirtualAddressMap()
+    /// is performed. This event type is a composite of EVT_NOTIFY_SIGNAL,
+    /// EVT_RUNTIME, and EVT_RUNTIME_CONTEXT and should not be combined with
+    /// any other event types.
+    pub const signal_virtual_address_change: EventType = .{
+        .runtime = true,
+        .hi_context = 0x20000,
+        .signal = true,
+        .lo_context = 2,
+    };
+};
+
 /// The calling convention used for all external functions part of the UEFI API.
 pub const cc: std.builtin.CallingConvention = switch (@import("builtin").target.cpu.arch) {
     .x86_64 => .{ .x86_64_win = .{} },
@@ -52,7 +94,11 @@ pub const IpAddress = extern union {
 
 /// GUIDs are align(8) unless otherwise specified.
 pub const Guid = extern struct {
-    time_low: u32,
+    comptime {
+        std.debug.assert(std.mem.Alignment.of(Guid) == .@"8");
+    }
+
+    time_low: u32 align(8),
     time_mid: u16,
     time_high_and_version: u16,
     clock_seq_high_and_reserved: u8,
@@ -60,7 +106,7 @@ pub const Guid = extern struct {
     node: [6]u8,
 
     /// Format GUID into hexadecimal lowercase xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx format
-    pub fn format(self: @This(), writer: *std.io.Writer) std.io.Writer.Error!void {
+    pub fn format(self: Guid, writer: *std.io.Writer) std.io.Writer.Error!void {
         const time_low = @byteSwap(self.time_low);
         const time_mid = @byteSwap(self.time_mid);
         const time_high_and_version = @byteSwap(self.time_high_and_version);
@@ -75,7 +121,7 @@ pub const Guid = extern struct {
         });
     }
 
-    pub fn eql(a: std.os.uefi.Guid, b: std.os.uefi.Guid) bool {
+    pub fn eql(a: Guid, b: Guid) bool {
         return a.time_low == b.time_low and
             a.time_mid == b.time_mid and
             a.time_high_and_version == b.time_high_and_version and
lib/std/debug.zig
@@ -654,9 +654,8 @@ pub fn defaultPanic(
 
             if (uefi.system_table.boot_services) |bs| {
                 // ExitData buffer must be allocated using boot_services.allocatePool (spec: page 220)
-                const exit_data: []u16 = uefi.raw_pool_allocator.alloc(u16, exit_msg.len + 1) catch @trap();
-                @memcpy(exit_data, exit_msg[0..exit_data.len]); // Includes null terminator.
-                _ = bs.exit(uefi.handle, .aborted, exit_data.len, exit_data.ptr);
+                const exit_data = uefi.raw_pool_allocator.dupeZ(u16, exit_msg) catch @trap();
+                bs.exit(uefi.handle, .aborted, exit_data) catch {};
             }
             @trap();
         },
lib/std/posix.zig
@@ -772,12 +772,12 @@ pub fn exit(status: u8) noreturn {
     if (native_os == .uefi) {
         const uefi = std.os.uefi;
         // exit() is only available if exitBootServices() has not been called yet.
-        // This call to exit should not fail, so we don't care about its return value.
+        // This call to exit should not fail, so we catch-ignore errors.
         if (uefi.system_table.boot_services) |bs| {
-            _ = bs.exit(uefi.handle, @enumFromInt(status), 0, null);
+            bs.exit(uefi.handle, @enumFromInt(status), null) catch {};
         }
         // If we can't exit, reboot the system instead.
-        uefi.system_table.runtime_services.resetSystem(.reset_cold, @enumFromInt(status), 0, null);
+        uefi.system_table.runtime_services.resetSystem(.cold, @enumFromInt(status), null);
     }
     system.exit(status);
 }
lib/std/Thread.zig
@@ -58,7 +58,7 @@ pub fn sleep(nanoseconds: u64) void {
         const boot_services = std.os.uefi.system_table.boot_services.?;
         const us_from_ns = nanoseconds / std.time.ns_per_us;
         const us = math.cast(usize, us_from_ns) orelse math.maxInt(usize);
-        _ = boot_services.stall(us);
+        boot_services.stall(us) catch unreachable;
         return;
     }
 
lib/std/time.zig
@@ -56,9 +56,7 @@ pub fn nanoTimestamp() i128 {
             return ns;
         },
         .uefi => {
-            var value: std.os.uefi.Time = undefined;
-            const status = std.os.uefi.system_table.runtime_services.getTime(&value, null);
-            assert(status == .success);
+            const value, _ = std.os.uefi.system_table.runtime_services.getTime() catch return 0;
             return value.toEpoch();
         },
         else => {
@@ -141,9 +139,7 @@ pub const Instant = struct {
                 return .{ .timestamp = ns };
             },
             .uefi => {
-                var value: std.os.uefi.Time = undefined;
-                const status = std.os.uefi.system_table.runtime_services.getTime(&value, null);
-                if (status != .success) return error.Unsupported;
+                const value, _ = std.os.uefi.system_table.runtime_services.getTime() catch return error.Unsupported;
                 return .{ .timestamp = value.toEpoch() };
             },
             // On darwin, use UPTIME_RAW instead of MONOTONIC as it ticks while