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