commit 2c24bf2f79af8d258956d3169e0c64ac8e71e51d (tree)
parent 60bb1d4e1c262ff36c18cefe974aa2f773483af4
Author: Andrew Kelley <andrew@ziglang.org>
Date: Fri, 18 Feb 2022 14:16:30 -0500
Merge pull request #10604 from fifty-six/master
std/os/uefi: additional improvements/fixes
Diffstat:
13 files changed, 663 insertions(+), 289 deletions(-)
diff --git a/lib/std/builtin.zig b/lib/std/builtin.zig
@@ -758,7 +758,52 @@ pub fn default_panic(msg: []const u8, error_return_trace: ?*StackTrace) noreturn
std.os.abort();
},
.uefi => {
- // TODO look into using the debug info and logging helpful messages
+ const uefi = std.os.uefi;
+
+ const ExitData = struct {
+ pub fn create_exit_data(exit_msg: []const u8, exit_size: *usize) ![*:0]u16 {
+ // Need boot services for pool allocation
+ if (uefi.system_table.boot_services == null) {
+ return error.BootServicesUnavailable;
+ }
+
+ // ExitData buffer must be allocated using boot_services.allocatePool
+ var utf16: []u16 = try uefi.raw_pool_allocator.alloc(u16, 256);
+ errdefer uefi.raw_pool_allocator.free(utf16);
+
+ if (exit_msg.len > 255) {
+ return error.MessageTooLong;
+ }
+
+ var fmt: [256]u8 = undefined;
+ var slice = try std.fmt.bufPrint(&fmt, "\r\nerr: {s}\r\n", .{exit_msg});
+
+ var len = try std.unicode.utf8ToUtf16Le(utf16, slice);
+
+ utf16[len] = 0;
+
+ exit_size.* = 256;
+
+ return @ptrCast([*:0]u16, utf16.ptr);
+ }
+ };
+
+ var exit_size: usize = 0;
+ var exit_data = ExitData.create_exit_data(msg, &exit_size) catch null;
+
+ if (exit_data) |data| {
+ if (uefi.system_table.std_err) |out| {
+ _ = out.setAttribute(uefi.protocols.SimpleTextOutputProtocol.red);
+ _ = out.outputString(data);
+ _ = out.setAttribute(uefi.protocols.SimpleTextOutputProtocol.white);
+ }
+ }
+
+ if (uefi.system_table.boot_services) |bs| {
+ _ = bs.exit(uefi.handle, .Aborted, exit_size, exit_data);
+ }
+
+ // Didn't have boot_services, just fallback to whatever.
std.os.abort();
},
else => {
diff --git a/lib/std/os/uefi.zig b/lib/std/os/uefi.zig
@@ -23,6 +23,18 @@ pub var system_table: *tables.SystemTable = undefined;
/// A handle to an event structure.
pub const Event = *opaque {};
+pub const MacAddress = extern struct {
+ address: [32]u8,
+};
+
+pub const Ipv4Address = extern struct {
+ address: [4]u8,
+};
+
+pub const Ipv6Address = extern struct {
+ address: [16]u8,
+};
+
/// GUIDs must be align(8)
pub const Guid = extern struct {
time_low: u32,
@@ -86,7 +98,6 @@ pub const Time = extern struct {
/// 0 - 59
second: u8,
- _pad1: u8,
/// 0 - 999999999
nanosecond: u32,
@@ -103,7 +114,6 @@ pub const Time = extern struct {
/// If true, the time is affected by daylight savings time.
adjust_daylight: bool,
},
- _pad2: u8,
/// Time is to be interpreted as local time
pub const unspecified_timezone: i16 = 0x7ff;
diff --git a/lib/std/os/uefi/protocols.zig b/lib/std/os/uefi/protocols.zig
@@ -1,100 +1,44 @@
-pub const LoadedImageProtocol = @import("protocols/loaded_image_protocol.zig").LoadedImageProtocol;
-pub const loaded_image_device_path_protocol_guid = @import("protocols/loaded_image_protocol.zig").loaded_image_device_path_protocol_guid;
-
-pub const AcpiDevicePath = @import("protocols/device_path_protocol.zig").AcpiDevicePath;
-pub const BiosBootSpecificationDevicePath = @import("protocols/device_path_protocol.zig").BiosBootSpecificationDevicePath;
-pub const DevicePath = @import("protocols/device_path_protocol.zig").DevicePath;
-pub const DevicePathProtocol = @import("protocols/device_path_protocol.zig").DevicePathProtocol;
-pub const DevicePathType = @import("protocols/device_path_protocol.zig").DevicePathType;
-pub const EndDevicePath = @import("protocols/device_path_protocol.zig").EndDevicePath;
-pub const HardwareDevicePath = @import("protocols/device_path_protocol.zig").HardwareDevicePath;
-pub const MediaDevicePath = @import("protocols/device_path_protocol.zig").MediaDevicePath;
-pub const MessagingDevicePath = @import("protocols/device_path_protocol.zig").MessagingDevicePath;
-
-pub const SimpleFileSystemProtocol = @import("protocols/simple_file_system_protocol.zig").SimpleFileSystemProtocol;
-pub const FileProtocol = @import("protocols/file_protocol.zig").FileProtocol;
-pub const FileInfo = @import("protocols/file_protocol.zig").FileInfo;
-pub const FileSystemInfo = @import("protocols/file_protocol.zig").FileSystemInfo;
-
-pub const InputKey = @import("protocols/simple_text_input_ex_protocol.zig").InputKey;
-pub const KeyData = @import("protocols/simple_text_input_ex_protocol.zig").KeyData;
-pub const KeyState = @import("protocols/simple_text_input_ex_protocol.zig").KeyState;
-pub const SimpleTextInputProtocol = @import("protocols/simple_text_input_protocol.zig").SimpleTextInputProtocol;
-pub const SimpleTextInputExProtocol = @import("protocols/simple_text_input_ex_protocol.zig").SimpleTextInputExProtocol;
-
-pub const SimpleTextOutputMode = @import("protocols/simple_text_output_protocol.zig").SimpleTextOutputMode;
-pub const SimpleTextOutputProtocol = @import("protocols/simple_text_output_protocol.zig").SimpleTextOutputProtocol;
-
-pub const SimplePointerMode = @import("protocols/simple_pointer_protocol.zig").SimplePointerMode;
-pub const SimplePointerProtocol = @import("protocols/simple_pointer_protocol.zig").SimplePointerProtocol;
-pub const SimplePointerState = @import("protocols/simple_pointer_protocol.zig").SimplePointerState;
-
-pub const AbsolutePointerMode = @import("protocols/absolute_pointer_protocol.zig").AbsolutePointerMode;
-pub const AbsolutePointerProtocol = @import("protocols/absolute_pointer_protocol.zig").AbsolutePointerProtocol;
-pub const AbsolutePointerState = @import("protocols/absolute_pointer_protocol.zig").AbsolutePointerState;
-
-pub const GraphicsOutputBltPixel = @import("protocols/graphics_output_protocol.zig").GraphicsOutputBltPixel;
-pub const GraphicsOutputBltOperation = @import("protocols/graphics_output_protocol.zig").GraphicsOutputBltOperation;
-pub const GraphicsOutputModeInformation = @import("protocols/graphics_output_protocol.zig").GraphicsOutputModeInformation;
-pub const GraphicsOutputProtocol = @import("protocols/graphics_output_protocol.zig").GraphicsOutputProtocol;
-pub const GraphicsOutputProtocolMode = @import("protocols/graphics_output_protocol.zig").GraphicsOutputProtocolMode;
-pub const GraphicsPixelFormat = @import("protocols/graphics_output_protocol.zig").GraphicsPixelFormat;
-pub const PixelBitmask = @import("protocols/graphics_output_protocol.zig").PixelBitmask;
-
-pub const EdidDiscoveredProtocol = @import("protocols/edid_discovered_protocol.zig").EdidDiscoveredProtocol;
-
-pub const EdidActiveProtocol = @import("protocols/edid_active_protocol.zig").EdidActiveProtocol;
-
-pub const EdidOverrideProtocol = @import("protocols/edid_override_protocol.zig").EdidOverrideProtocol;
-pub const EdidOverrideProtocolAttributes = @import("protocols/edid_override_protocol.zig").EdidOverrideProtocolAttributes;
-
-pub const SimpleNetworkProtocol = @import("protocols/simple_network_protocol.zig").SimpleNetworkProtocol;
-pub const MacAddress = @import("protocols/simple_network_protocol.zig").MacAddress;
-pub const SimpleNetworkMode = @import("protocols/simple_network_protocol.zig").SimpleNetworkMode;
-pub const SimpleNetworkReceiveFilter = @import("protocols/simple_network_protocol.zig").SimpleNetworkReceiveFilter;
-pub const SimpleNetworkState = @import("protocols/simple_network_protocol.zig").SimpleNetworkState;
-pub const NetworkStatistics = @import("protocols/simple_network_protocol.zig").NetworkStatistics;
-pub const SimpleNetworkInterruptStatus = @import("protocols/simple_network_protocol.zig").SimpleNetworkInterruptStatus;
-
-pub const ManagedNetworkServiceBindingProtocol = @import("protocols/managed_network_service_binding_protocol.zig").ManagedNetworkServiceBindingProtocol;
-pub const ManagedNetworkProtocol = @import("protocols/managed_network_protocol.zig").ManagedNetworkProtocol;
-pub const ManagedNetworkConfigData = @import("protocols/managed_network_protocol.zig").ManagedNetworkConfigData;
-pub const ManagedNetworkCompletionToken = @import("protocols/managed_network_protocol.zig").ManagedNetworkCompletionToken;
-pub const ManagedNetworkReceiveData = @import("protocols/managed_network_protocol.zig").ManagedNetworkReceiveData;
-pub const ManagedNetworkTransmitData = @import("protocols/managed_network_protocol.zig").ManagedNetworkTransmitData;
-pub const ManagedNetworkFragmentData = @import("protocols/managed_network_protocol.zig").ManagedNetworkFragmentData;
-
-pub const Ip6ServiceBindingProtocol = @import("protocols/ip6_service_binding_protocol.zig").Ip6ServiceBindingProtocol;
-pub const Ip6Protocol = @import("protocols/ip6_protocol.zig").Ip6Protocol;
-pub const Ip6ModeData = @import("protocols/ip6_protocol.zig").Ip6ModeData;
-pub const Ip6ConfigData = @import("protocols/ip6_protocol.zig").Ip6ConfigData;
-pub const Ip6Address = @import("protocols/ip6_protocol.zig").Ip6Address;
-pub const Ip6AddressInfo = @import("protocols/ip6_protocol.zig").Ip6AddressInfo;
-pub const Ip6RouteTable = @import("protocols/ip6_protocol.zig").Ip6RouteTable;
-pub const Ip6NeighborState = @import("protocols/ip6_protocol.zig").Ip6NeighborState;
-pub const Ip6NeighborCache = @import("protocols/ip6_protocol.zig").Ip6NeighborCache;
-pub const Ip6IcmpType = @import("protocols/ip6_protocol.zig").Ip6IcmpType;
-pub const Ip6CompletionToken = @import("protocols/ip6_protocol.zig").Ip6CompletionToken;
-
-pub const Ip6ConfigProtocol = @import("protocols/ip6_config_protocol.zig").Ip6ConfigProtocol;
-pub const Ip6ConfigDataType = @import("protocols/ip6_config_protocol.zig").Ip6ConfigDataType;
-
-pub const Udp6ServiceBindingProtocol = @import("protocols/udp6_service_binding_protocol.zig").Udp6ServiceBindingProtocol;
-pub const Udp6Protocol = @import("protocols/udp6_protocol.zig").Udp6Protocol;
-pub const Udp6ConfigData = @import("protocols/udp6_protocol.zig").Udp6ConfigData;
-pub const Udp6CompletionToken = @import("protocols/udp6_protocol.zig").Udp6CompletionToken;
-pub const Udp6ReceiveData = @import("protocols/udp6_protocol.zig").Udp6ReceiveData;
-pub const Udp6TransmitData = @import("protocols/udp6_protocol.zig").Udp6TransmitData;
-pub const Udp6SessionData = @import("protocols/udp6_protocol.zig").Udp6SessionData;
-pub const Udp6FragmentData = @import("protocols/udp6_protocol.zig").Udp6FragmentData;
-
+// Misc
+pub usingnamespace @import("protocols/loaded_image_protocol.zig");
+pub usingnamespace @import("protocols/device_path_protocol.zig");
+pub usingnamespace @import("protocols/rng_protocol.zig");
+pub usingnamespace @import("protocols/shell_parameters_protocol.zig");
+
+// Files
+pub usingnamespace @import("protocols/simple_file_system_protocol.zig");
+pub usingnamespace @import("protocols/file_protocol.zig");
+
+// Text
+pub usingnamespace @import("protocols/simple_text_input_protocol.zig");
+pub usingnamespace @import("protocols/simple_text_input_ex_protocol.zig");
+pub usingnamespace @import("protocols/simple_text_output_protocol.zig");
+
+// Pointer
+pub usingnamespace @import("protocols/simple_pointer_protocol.zig");
+pub usingnamespace @import("protocols/absolute_pointer_protocol.zig");
+
+pub usingnamespace @import("protocols/graphics_output_protocol.zig");
+
+// edid
+pub usingnamespace @import("protocols/edid_discovered_protocol.zig");
+pub usingnamespace @import("protocols/edid_active_protocol.zig");
+pub usingnamespace @import("protocols/edid_override_protocol.zig");
+
+// Network
+pub usingnamespace @import("protocols/simple_network_protocol.zig");
+pub usingnamespace @import("protocols/managed_network_service_binding_protocol.zig");
+pub usingnamespace @import("protocols/managed_network_protocol.zig");
+
+// ip6
+pub usingnamespace @import("protocols/ip6_service_binding_protocol.zig");
+pub usingnamespace @import("protocols/ip6_protocol.zig");
+pub usingnamespace @import("protocols/ip6_config_protocol.zig");
+
+// udp6
+pub usingnamespace @import("protocols/udp6_service_binding_protocol.zig");
+pub usingnamespace @import("protocols/udp6_protocol.zig");
+
+// hii
pub const hii = @import("protocols/hii.zig");
-pub const HIIDatabaseProtocol = @import("protocols/hii_database_protocol.zig").HIIDatabaseProtocol;
-pub const HIIPopupProtocol = @import("protocols/hii_popup_protocol.zig").HIIPopupProtocol;
-pub const HIIPopupStyle = @import("protocols/hii_popup_protocol.zig").HIIPopupStyle;
-pub const HIIPopupType = @import("protocols/hii_popup_protocol.zig").HIIPopupType;
-pub const HIIPopupSelection = @import("protocols/hii_popup_protocol.zig").HIIPopupSelection;
-
-pub const RNGProtocol = @import("protocols/rng_protocol.zig").RNGProtocol;
-
-pub const ShellParametersProtocol = @import("protocols/shell_parameters_protocol.zig").ShellParametersProtocol;
+pub usingnamespace @import("protocols/hii_database_protocol.zig");
+pub usingnamespace @import("protocols/hii_popup_protocol.zig");
diff --git a/lib/std/os/uefi/protocols/absolute_pointer_protocol.zig b/lib/std/os/uefi/protocols/absolute_pointer_protocol.zig
@@ -40,9 +40,7 @@ pub const AbsolutePointerMode = extern struct {
attributes: packed struct {
supports_alt_active: bool,
supports_pressure_as_z: bool,
- _pad1: u6,
- _pad2: u8,
- _pad3: u16,
+ _pad: u30 = 0,
},
};
@@ -53,8 +51,6 @@ pub const AbsolutePointerState = extern struct {
active_buttons: packed struct {
touch_active: bool,
alt_active: bool,
- _pad1: u6,
- _pad2: u8,
- _pad3: u16,
+ _pad: u30 = 0,
},
};
diff --git a/lib/std/os/uefi/protocols/device_path_protocol.zig b/lib/std/os/uefi/protocols/device_path_protocol.zig
@@ -72,63 +72,39 @@ pub const DevicePathProtocol = packed struct {
}
pub fn getDevicePath(self: *const DevicePathProtocol) ?DevicePath {
- return switch (self.type) {
- .Hardware => blk: {
- const hardware: ?HardwareDevicePath = switch (@intToEnum(HardwareDevicePath.Subtype, self.subtype)) {
- .Pci => .{ .Pci = @ptrCast(*const HardwareDevicePath.PciDevicePath, self) },
- .PcCard => .{ .PcCard = @ptrCast(*const HardwareDevicePath.PcCardDevicePath, self) },
- .MemoryMapped => .{ .MemoryMapped = @ptrCast(*const HardwareDevicePath.MemoryMappedDevicePath, self) },
- .Vendor => .{ .Vendor = @ptrCast(*const HardwareDevicePath.VendorDevicePath, self) },
- .Controller => .{ .Controller = @ptrCast(*const HardwareDevicePath.ControllerDevicePath, self) },
- .Bmc => .{ .Bmc = @ptrCast(*const HardwareDevicePath.BmcDevicePath, self) },
- _ => null,
- };
- break :blk if (hardware) |h| .{ .Hardware = h } else null;
- },
- .Acpi => blk: {
- const acpi: ?AcpiDevicePath = switch (@intToEnum(AcpiDevicePath.Subtype, self.subtype)) {
- else => null, // TODO
- };
- break :blk if (acpi) |a| .{ .Acpi = a } else null;
- },
- .Messaging => blk: {
- const messaging: ?MessagingDevicePath = switch (@intToEnum(MessagingDevicePath.Subtype, self.subtype)) {
- else => null, // TODO
- };
- break :blk if (messaging) |m| .{ .Messaging = m } else null;
- },
- .Media => blk: {
- const media: ?MediaDevicePath = switch (@intToEnum(MediaDevicePath.Subtype, self.subtype)) {
- .HardDrive => .{ .HardDrive = @ptrCast(*const MediaDevicePath.HardDriveDevicePath, self) },
- .Cdrom => .{ .Cdrom = @ptrCast(*const MediaDevicePath.CdromDevicePath, self) },
- .Vendor => .{ .Vendor = @ptrCast(*const MediaDevicePath.VendorDevicePath, self) },
- .FilePath => .{ .FilePath = @ptrCast(*const MediaDevicePath.FilePathDevicePath, self) },
- .MediaProtocol => .{ .MediaProtocol = @ptrCast(*const MediaDevicePath.MediaProtocolDevicePath, self) },
- .PiwgFirmwareFile => .{ .PiwgFirmwareFile = @ptrCast(*const MediaDevicePath.PiwgFirmwareFileDevicePath, self) },
- .PiwgFirmwareVolume => .{ .PiwgFirmwareVolume = @ptrCast(*const MediaDevicePath.PiwgFirmwareVolumeDevicePath, self) },
- .RelativeOffsetRange => .{ .RelativeOffsetRange = @ptrCast(*const MediaDevicePath.RelativeOffsetRangeDevicePath, self) },
- .RamDisk => .{ .RamDisk = @ptrCast(*const MediaDevicePath.RamDiskDevicePath, self) },
- _ => null,
- };
- break :blk if (media) |m| .{ .Media = m } else null;
- },
- .BiosBootSpecification => blk: {
- const bbs: ?BiosBootSpecificationDevicePath = switch (@intToEnum(BiosBootSpecificationDevicePath.Subtype, self.subtype)) {
- .BBS101 => .{ .BBS101 = @ptrCast(*const BiosBootSpecificationDevicePath.BBS101DevicePath, self) },
- _ => null,
- };
- break :blk if (bbs) |b| .{ .BiosBootSpecification = b } else null;
- },
- .End => blk: {
- const end: ?EndDevicePath = switch (@intToEnum(EndDevicePath.Subtype, self.subtype)) {
- .EndEntire => .{ .EndEntire = @ptrCast(*const EndDevicePath.EndEntireDevicePath, self) },
- .EndThisInstance => .{ .EndThisInstance = @ptrCast(*const EndDevicePath.EndThisInstanceDevicePath, self) },
- _ => null,
- };
- break :blk if (end) |e| .{ .End = e } else null;
- },
- _ => null,
- };
+ inline for (@typeInfo(DevicePath).Union.fields) |ufield| {
+ const enum_value = std.meta.stringToEnum(DevicePathType, ufield.name);
+
+ // Got the associated union type for self.type, now
+ // we need to initialize it and its subtype
+ if (self.type == enum_value) {
+ var subtype = self.initSubtype(ufield.field_type);
+
+ if (subtype) |sb| {
+ // e.g. return .{ .Hardware = .{ .Pci = @ptrCast(...) } }
+ return @unionInit(DevicePath, ufield.name, sb);
+ }
+ }
+ }
+
+ return null;
+ }
+
+ pub fn initSubtype(self: *const DevicePathProtocol, comptime TUnion: type) ?TUnion {
+ const type_info = @typeInfo(TUnion).Union;
+ const TTag = type_info.tag_type.?;
+
+ inline for (type_info.fields) |subtype| {
+ // The tag names match the union names, so just grab that off the enum
+ const tag_val: u8 = @enumToInt(@field(TTag, subtype.name));
+
+ if (self.subtype == tag_val) {
+ // e.g. expr = .{ .Pci = @ptrCast(...) }
+ return @unionInit(TUnion, subtype.name, @ptrCast(subtype.field_type, self));
+ }
+ }
+
+ return null;
}
};
@@ -173,79 +149,113 @@ pub const HardwareDevicePath = union(Subtype) {
type: DevicePathType,
subtype: Subtype,
length: u16,
- // TODO
+ function: u8,
+ device: u8,
};
pub const PcCardDevicePath = packed struct {
type: DevicePathType,
subtype: Subtype,
length: u16,
- // TODO
+ function_number: u8,
};
pub const MemoryMappedDevicePath = packed struct {
type: DevicePathType,
subtype: Subtype,
length: u16,
- // TODO
+ memory_type: u32,
+ start_address: u64,
+ end_address: u64,
};
pub const VendorDevicePath = packed struct {
type: DevicePathType,
subtype: Subtype,
length: u16,
- // TODO
+ vendor_guid: Guid,
};
pub const ControllerDevicePath = packed struct {
type: DevicePathType,
subtype: Subtype,
length: u16,
- // TODO
+ controller_number: u32,
};
pub const BmcDevicePath = packed struct {
type: DevicePathType,
subtype: Subtype,
length: u16,
- // TODO
+ interface_type: u8,
+ base_address: usize,
};
};
pub const AcpiDevicePath = union(Subtype) {
- Acpi: void, // TODO
- ExpandedAcpi: void, // TODO
- Adr: void, // TODO
- Nvdimm: void, // TODO
+ Acpi: *const BaseAcpiDevicePath,
+ ExpandedAcpi: *const ExpandedAcpiDevicePath,
+ Adr: *const AdrDevicePath,
pub const Subtype = enum(u8) {
Acpi = 1,
ExpandedAcpi = 2,
Adr = 3,
- Nvdimm = 4,
_,
};
+
+ pub const BaseAcpiDevicePath = packed struct {
+ type: DevicePathType,
+ subtype: Subtype,
+ length: u16,
+ hid: u32,
+ uid: u32,
+ };
+
+ pub const ExpandedAcpiDevicePath = packed struct {
+ type: DevicePathType,
+ subtype: Subtype,
+ length: u16,
+ hid: u32,
+ uid: u32,
+ cid: u32,
+ // variable length u16[*:0] strings
+ // hid_str, uid_str, cid_str
+ };
+
+ pub const AdrDevicePath = packed struct {
+ type: DevicePathType,
+ subtype: Subtype,
+ length: u16,
+ adr: u32,
+ // multiple adr entries can optionally follow
+ pub fn adrs(self: *const AdrDevicePath) []const u32 {
+ // self.length is a minimum of 8 with one adr which is size 4.
+ var entries = (self.length - 4) / @sizeOf(u32);
+ return @ptrCast([*]const u32, &self.adr)[0..entries];
+ }
+ };
};
pub const MessagingDevicePath = union(Subtype) {
- Atapi: void, // TODO
- Scsi: void, // TODO
- FibreChannel: void, // TODO
- FibreChannelEx: void, // TODO
- @"1394": void, // TODO
- Usb: void, // TODO
- Sata: void, // TODO
- UsbWwid: void, // TODO
- Lun: void, // TODO
- UsbClass: void, // TODO
- I2o: void, // TODO
- MacAddress: void, // TODO
- Ipv4: void, // TODO
- Ipv6: void, // TODO
- Vlan: void, // TODO
- InfiniBand: void, // TODO
- Uart: void, // TODO
- Vendor: void, // TODO
+ Atapi: *const AtapiDevicePath,
+ Scsi: *const ScsiDevicePath,
+ FibreChannel: *const FibreChannelDevicePath,
+ FibreChannelEx: *const FibreChannelExDevicePath,
+ @"1394": *const F1394DevicePath,
+ Usb: *const UsbDevicePath,
+ Sata: *const SataDevicePath,
+ UsbWwid: *const UsbWwidDevicePath,
+ Lun: *const DeviceLogicalUnitDevicePath,
+ UsbClass: *const UsbClassDevicePath,
+ I2o: *const I2oDevicePath,
+ MacAddress: *const MacAddressDevicePath,
+ Ipv4: *const Ipv4DevicePath,
+ Ipv6: *const Ipv6DevicePath,
+ Vlan: *const VlanDevicePath,
+ InfiniBand: *const InfiniBandDevicePath,
+ Uart: *const UartDevicePath,
+ Vendor: *const VendorDefinedDevicePath,
pub const Subtype = enum(u8) {
Atapi = 1,
@@ -268,6 +278,232 @@ pub const MessagingDevicePath = union(Subtype) {
Vendor = 10,
_,
};
+
+ pub const AtapiDevicePath = packed struct {
+ const Role = enum(u8) {
+ Master = 0,
+ Slave = 1,
+ };
+
+ const Rank = enum(u8) {
+ Primary = 0,
+ Secondary = 1,
+ };
+
+ type: DevicePathType,
+ subtype: Subtype,
+ length: u16,
+ primary_secondary: Rank,
+ slave_master: Role,
+ logical_unit_number: u16,
+ };
+
+ pub const ScsiDevicePath = packed struct {
+ type: DevicePathType,
+ subtype: Subtype,
+ length: u16,
+ target_id: u16,
+ logical_unit_number: u16,
+ };
+
+ pub const FibreChannelDevicePath = packed struct {
+ type: DevicePathType,
+ subtype: Subtype,
+ length: u16,
+ reserved: u32,
+ world_wide_name: u64,
+ logical_unit_number: u64,
+ };
+
+ pub const FibreChannelExDevicePath = packed struct {
+ type: DevicePathType,
+ subtype: Subtype,
+ length: u16,
+ reserved: u32,
+ world_wide_name: [8]u8,
+ logical_unit_number: [8]u8,
+ };
+
+ pub const F1394DevicePath = packed struct {
+ type: DevicePathType,
+ subtype: Subtype,
+ length: u16,
+ reserved: u32,
+ guid: u64,
+ };
+
+ pub const UsbDevicePath = packed struct {
+ type: DevicePathType,
+ subtype: Subtype,
+ length: u16,
+ parent_port_number: u8,
+ interface_number: u8,
+ };
+
+ pub const SataDevicePath = packed struct {
+ type: DevicePathType,
+ subtype: Subtype,
+ length: u16,
+ hba_port_number: u16,
+ port_multiplier_port_number: u16,
+ logical_unit_number: u16,
+ };
+
+ pub const UsbWwidDevicePath = packed struct {
+ type: DevicePathType,
+ subtype: Subtype,
+ length: u16,
+ interface_number: u16,
+ device_vendor_id: u16,
+ device_product_id: u16,
+
+ pub fn serial_number(self: *const UsbWwidDevicePath) []const u16 {
+ var serial_len = (self.length - @sizeOf(UsbWwidDevicePath)) / @sizeOf(u16);
+ return @ptrCast([*]u16, @ptrCast([*]u8, self) + @sizeOf(UsbWwidDevicePath))[0..serial_len];
+ }
+ };
+
+ pub const DeviceLogicalUnitDevicePath = packed struct {
+ type: DevicePathType,
+ subtype: Subtype,
+ length: u16,
+ lun: u8,
+ };
+
+ pub const UsbClassDevicePath = packed struct {
+ type: DevicePathType,
+ subtype: Subtype,
+ length: u16,
+ vendor_id: u16,
+ product_id: u16,
+ device_class: u8,
+ device_subclass: u8,
+ device_protocol: u8,
+ };
+
+ pub const I2oDevicePath = packed struct {
+ type: DevicePathType,
+ subtype: Subtype,
+ length: u16,
+ tid: u32,
+ };
+
+ pub const MacAddressDevicePath = packed struct {
+ type: DevicePathType,
+ subtype: Subtype,
+ length: u16,
+ mac_address: uefi.MacAddress,
+ if_type: u8,
+ };
+
+ pub const Ipv4DevicePath = packed struct {
+ pub const IpType = enum(u8) {
+ Dhcp = 0,
+ Static = 1,
+ };
+
+ type: DevicePathType,
+ subtype: Subtype,
+ length: u16,
+ local_ip_address: uefi.Ipv4Address,
+ remote_ip_address: uefi.Ipv4Address,
+ local_port: u16,
+ remote_port: u16,
+ network_protocol: u16,
+ static_ip_address: IpType,
+ gateway_ip_address: u32,
+ subnet_mask: u32,
+ };
+
+ pub const Ipv6DevicePath = packed struct {
+ pub const Origin = enum(u8) {
+ Manual = 0,
+ AssignedStateless = 1,
+ AssignedStateful = 2,
+ };
+
+ type: DevicePathType,
+ subtype: Subtype,
+ length: u16,
+ local_ip_address: uefi.Ipv6Address,
+ remote_ip_address: uefi.Ipv6Address,
+ local_port: u16,
+ remote_port: u16,
+ protocol: u16,
+ ip_address_origin: Origin,
+ prefix_length: u8,
+ gateway_ip_address: uefi.Ipv6Address,
+ };
+
+ pub const VlanDevicePath = packed struct {
+ type: DevicePathType,
+ subtype: Subtype,
+ length: u16,
+ vlan_id: u16,
+ };
+
+ pub const InfiniBandDevicePath = packed struct {
+ pub const ResourceFlags = packed struct {
+ pub const ControllerType = enum(u1) {
+ Ioc = 0,
+ Service = 1,
+ };
+
+ ioc_or_service: ControllerType,
+ extend_boot_environment: bool,
+ console_protocol: bool,
+ storage_protocol: bool,
+ network_protocol: bool,
+
+ // u1 + 4 * bool = 5 bits, we need a total of 32 bits
+ reserved: u27,
+ };
+
+ type: DevicePathType,
+ subtype: Subtype,
+ length: u16,
+ resource_flags: ResourceFlags,
+ port_gid: [16]u8,
+ service_id: u64,
+ target_port_id: u64,
+ device_id: u64,
+ };
+
+ pub const UartDevicePath = packed struct {
+ pub const Parity = enum(u8) {
+ Default = 0,
+ None = 1,
+ Even = 2,
+ Odd = 3,
+ Mark = 4,
+ Space = 5,
+ _,
+ };
+
+ pub const StopBits = enum(u8) {
+ Default = 0,
+ One = 1,
+ OneAndAHalf = 2,
+ Two = 3,
+ _,
+ };
+
+ type: DevicePathType,
+ subtype: Subtype,
+ length: u16,
+ reserved: u16,
+ baud_rate: u32,
+ data_bits: u8,
+ parity: Parity,
+ stop_bits: StopBits,
+ };
+
+ pub const VendorDefinedDevicePath = packed struct {
+ type: DevicePathType,
+ subtype: Subtype,
+ length: u16,
+ vendor_guid: Guid,
+ };
};
pub const MediaDevicePath = union(Subtype) {
@@ -295,24 +531,44 @@ pub const MediaDevicePath = union(Subtype) {
};
pub const HardDriveDevicePath = packed struct {
+ pub const Format = enum(u8) {
+ LegacyMbr = 0x01,
+ GuidPartitionTable = 0x02,
+ };
+
+ pub const SignatureType = enum(u8) {
+ NoSignature = 0x00,
+ /// "32-bit signature from address 0x1b8 of the type 0x01 MBR"
+ MbrSignature = 0x01,
+ GuidSignature = 0x02,
+ };
+
type: DevicePathType,
subtype: Subtype,
length: u16,
- // TODO
+ partition_number: u32,
+ partition_start: u64,
+ partition_size: u64,
+ partition_signature: [16]u8,
+ partition_format: Format,
+ signature_type: SignatureType,
};
pub const CdromDevicePath = packed struct {
type: DevicePathType,
subtype: Subtype,
length: u16,
- // TODO
+ boot_entry: u32,
+ partition_start: u64,
+ partition_size: u64,
};
pub const VendorDevicePath = packed struct {
type: DevicePathType,
subtype: Subtype,
length: u16,
- // TODO
+ guid: Guid,
+ // vendor-defined variable data
};
pub const FilePathDevicePath = packed struct {
@@ -329,19 +585,21 @@ pub const MediaDevicePath = union(Subtype) {
type: DevicePathType,
subtype: Subtype,
length: u16,
- // TODO
+ guid: Guid,
};
pub const PiwgFirmwareFileDevicePath = packed struct {
type: DevicePathType,
subtype: Subtype,
length: u16,
+ fv_filename: Guid,
};
pub const PiwgFirmwareVolumeDevicePath = packed struct {
type: DevicePathType,
subtype: Subtype,
length: u16,
+ fv_name: Guid,
};
pub const RelativeOffsetRangeDevicePath = packed struct {
@@ -359,7 +617,7 @@ pub const MediaDevicePath = union(Subtype) {
length: u16,
start: u64,
end: u64,
- disk_type: uefi.Guid,
+ disk_type: Guid,
instance: u16,
};
};
diff --git a/lib/std/os/uefi/protocols/edid_override_protocol.zig b/lib/std/os/uefi/protocols/edid_override_protocol.zig
@@ -8,9 +8,8 @@ pub const EdidOverrideProtocol = extern struct {
_get_edid: fn (*const EdidOverrideProtocol, Handle, *u32, *usize, *?[*]u8) callconv(.C) Status,
/// Returns policy information and potentially a replacement EDID for the specified video output device.
- /// attributes must be align(4)
pub fn getEdid(self: *const EdidOverrideProtocol, handle: Handle, attributes: *EdidOverrideProtocolAttributes, edid_size: *usize, edid: *?[*]u8) Status {
- return self._get_edid(self, handle, attributes, edid_size, edid);
+ return self._get_edid(self, handle, @ptrCast(*u32, attributes), edid_size, edid);
}
pub const guid align(8) = Guid{
@@ -24,9 +23,7 @@ pub const EdidOverrideProtocol = extern struct {
};
pub const EdidOverrideProtocolAttributes = packed struct {
- dont_override: bool,
+ dont_override: bool align(4),
enable_hot_plug: bool,
- _pad1: u6,
- _pad2: u8,
- _pad3: u16,
+ _pad: u30 = 0,
};
diff --git a/lib/std/os/uefi/protocols/hii.zig b/lib/std/os/uefi/protocols/hii.zig
@@ -48,7 +48,7 @@ pub const NarrowGlyph = extern struct {
attributes: packed struct {
non_spacing: bool,
wide: bool,
- _pad: u6,
+ _pad: u6 = 0,
},
glyph_col_1: [19]u8,
};
@@ -62,7 +62,7 @@ pub const WideGlyph = extern struct {
},
glyph_col_1: [19]u8,
glyph_col_2: [19]u8,
- _pad: [3]u8,
+ _pad: [3]u8 = [_]u8{0} ** 3,
};
pub const HIIStringPackage = extern struct {
diff --git a/lib/std/os/uefi/protocols/simple_network_protocol.zig b/lib/std/os/uefi/protocols/simple_network_protocol.zig
@@ -126,9 +126,7 @@ pub const SimpleNetworkReceiveFilter = packed struct {
receive_broadcast: bool,
receive_promiscuous: bool,
receive_promiscuous_multicast: bool,
- _pad1: u3 = undefined,
- _pad2: u8 = undefined,
- _pad3: u16 = undefined,
+ _pad: u27 = 0,
};
pub const SimpleNetworkState = enum(u32) {
@@ -171,7 +169,5 @@ pub const SimpleNetworkInterruptStatus = packed struct {
transmit_interrupt: bool,
command_interrupt: bool,
software_interrupt: bool,
- _pad1: u4,
- _pad2: u8,
- _pad3: u16,
+ _pad: u28 = 0,
};
diff --git a/lib/std/os/uefi/protocols/simple_text_input_ex_protocol.zig b/lib/std/os/uefi/protocols/simple_text_input_ex_protocol.zig
@@ -64,14 +64,14 @@ pub const KeyState = extern struct {
left_logo_pressed: bool,
menu_key_pressed: bool,
sys_req_pressed: bool,
- _pad1: u21,
+ _pad: u21 = 0,
shift_state_valid: bool,
},
key_toggle_state: packed struct {
scroll_lock_active: bool,
num_lock_active: bool,
caps_lock_active: bool,
- _pad1: u3,
+ _pad: u3 = 0,
key_state_exposed: bool,
toggle_state_valid: bool,
},
diff --git a/lib/std/os/uefi/status.zig b/lib/std/os/uefi/status.zig
@@ -1,3 +1,5 @@
+const testing = @import("std").testing;
+
const high_bit = 1 << @typeInfo(usize).Int.bits - 1;
pub const Status = enum(usize) {
@@ -139,4 +141,64 @@ pub const Status = enum(usize) {
WarnResetRequired = 7,
_,
+
+ pub const EfiError = error{
+ LoadError,
+ InvalidParameter,
+ Unsupported,
+ BadBufferSize,
+ BufferTooSmall,
+ NotReady,
+ DeviceError,
+ WriteProtected,
+ OutOfResources,
+ VolumeCorrupted,
+ VolumeFull,
+ NoMedia,
+ MediaChanged,
+ NotFound,
+ AccessDenied,
+ NoResponse,
+ NoMapping,
+ Timeout,
+ NotStarted,
+ AlreadyStarted,
+ Aborted,
+ IcmpError,
+ TftpError,
+ ProtocolError,
+ IncompatibleVersion,
+ SecurityViolation,
+ CrcError,
+ EndOfMedia,
+ EndOfFile,
+ InvalidLanguage,
+ CompromisedData,
+ IpAddressConflict,
+ HttpError,
+ NetworkUnreachable,
+ HostUnreachable,
+ ProtocolUnreachable,
+ PortUnreachable,
+ ConnectionFin,
+ ConnectionReset,
+ ConnectionRefused,
+ };
+
+ pub fn err(self: Status) EfiError!void {
+ inline for (@typeInfo(EfiError).ErrorSet.?) |efi_err| {
+ if (self == @field(Status, efi_err.name)) {
+ return @field(EfiError, efi_err.name);
+ }
+ }
+ // self is .Success or Warning
+ }
};
+
+test "status" {
+ var st: Status = .DeviceError;
+ try testing.expectError(error.DeviceError, st.err());
+
+ st = .Success;
+ try st.err();
+}
diff --git a/lib/std/os/uefi/tables.zig b/lib/std/os/uefi/tables.zig
@@ -1,14 +1,5 @@
-pub const AllocateType = @import("tables/boot_services.zig").AllocateType;
-pub const BootServices = @import("tables/boot_services.zig").BootServices;
-pub const ConfigurationTable = @import("tables/configuration_table.zig").ConfigurationTable;
-pub const global_variable align(8) = @import("tables/runtime_services.zig").global_variable;
-pub const LocateSearchType = @import("tables/boot_services.zig").LocateSearchType;
-pub const MemoryDescriptor = @import("tables/boot_services.zig").MemoryDescriptor;
-pub const MemoryType = @import("tables/boot_services.zig").MemoryType;
-pub const OpenProtocolAttributes = @import("tables/boot_services.zig").OpenProtocolAttributes;
-pub const ProtocolInformationEntry = @import("tables/boot_services.zig").ProtocolInformationEntry;
-pub const ResetType = @import("tables/runtime_services.zig").ResetType;
-pub const RuntimeServices = @import("tables/runtime_services.zig").RuntimeServices;
-pub const SystemTable = @import("tables/system_table.zig").SystemTable;
-pub const TableHeader = @import("tables/table_header.zig").TableHeader;
-pub const TimerDelay = @import("tables/boot_services.zig").TimerDelay;
+pub usingnamespace @import("tables/boot_services.zig");
+pub usingnamespace @import("tables/runtime_services.zig");
+pub usingnamespace @import("tables/configuration_table.zig");
+pub usingnamespace @import("tables/system_table.zig");
+pub usingnamespace @import("tables/table_header.zig");
diff --git a/lib/std/os/uefi/tables/boot_services.zig b/lib/std/os/uefi/tables/boot_services.zig
@@ -21,120 +21,159 @@ pub const BootServices = extern struct {
hdr: TableHeader,
/// Raises a task's priority level and returns its previous level.
- raiseTpl: fn (usize) callconv(.C) usize,
+ raiseTpl: fn (new_tpl: usize) callconv(.C) usize,
/// Restores a task's priority level to its previous value.
- restoreTpl: fn (usize) callconv(.C) void,
+ restoreTpl: fn (old_tpl: usize) callconv(.C) void,
/// Allocates memory pages from the system.
- allocatePages: fn (AllocateType, MemoryType, usize, *[*]align(4096) u8) callconv(.C) Status,
+ allocatePages: fn (alloc_type: AllocateType, mem_type: MemoryType, pages: usize, memory: *[*]align(4096) u8) callconv(.C) Status,
/// Frees memory pages.
- freePages: fn ([*]align(4096) u8, usize) callconv(.C) Status,
+ freePages: fn (memory: [*]align(4096) u8, pages: usize) callconv(.C) Status,
/// Returns the current memory map.
- getMemoryMap: fn (*usize, [*]MemoryDescriptor, *usize, *usize, *u32) callconv(.C) Status,
+ getMemoryMap: fn (mmap_size: *usize, mmap: [*]MemoryDescriptor, mapKey: *usize, descriptor_size: *usize, descriptor_version: *u32) callconv(.C) Status,
/// Allocates pool memory.
- allocatePool: fn (MemoryType, usize, *[*]align(8) u8) callconv(.C) Status,
+ allocatePool: fn (pool_type: MemoryType, size: usize, buffer: *[*]align(8) u8) callconv(.C) Status,
/// Returns pool memory to the system.
- freePool: fn ([*]align(8) u8) callconv(.C) Status,
+ freePool: fn (buffer: [*]align(8) u8) callconv(.C) Status,
/// Creates an event.
- createEvent: fn (u32, usize, ?fn (Event, ?*anyopaque) callconv(.C) void, ?*const anyopaque, *Event) callconv(.C) Status,
+ createEvent: fn (type: u32, notify_tpl: usize, notify_func: ?fn (Event, ?*anyopaque) callconv(.C) void, notifyCtx: ?*const anyopaque, event: *Event) callconv(.C) Status,
/// Sets the type of timer and the trigger time for a timer event.
- setTimer: fn (Event, TimerDelay, u64) callconv(.C) Status,
+ setTimer: fn (event: Event, type: TimerDelay, triggerTime: u64) callconv(.C) Status,
/// Stops execution until an event is signaled.
- waitForEvent: fn (usize, [*]const Event, *usize) callconv(.C) Status,
+ waitForEvent: fn (event_len: usize, events: [*]const Event, index: *usize) callconv(.C) Status,
/// Signals an event.
- signalEvent: fn (Event) callconv(.C) Status,
+ signalEvent: fn (event: Event) callconv(.C) Status,
/// Closes an event.
- closeEvent: fn (Event) callconv(.C) Status,
+ closeEvent: fn (event: Event) callconv(.C) Status,
/// Checks whether an event is in the signaled state.
- checkEvent: fn (Event) callconv(.C) Status,
+ checkEvent: fn (event: Event) callconv(.C) Status,
- installProtocolInterface: Status, // TODO
- reinstallProtocolInterface: Status, // TODO
- uninstallProtocolInterface: Status, // TODO
+ /// Installs a protocol interface on a device handle. If the handle does not exist, it is created
+ /// and added to the list of handles in the system. installMultipleProtocolInterfaces()
+ /// performs more error checking than installProtocolInterface(), so its use is recommended over this.
+ installProtocolInterface: fn (handle: Handle, protocol: *align(8) const Guid, interface_type: EfiInterfaceType, interface: *anyopaque) callconv(.C) Status,
+
+ /// Reinstalls a protocol interface on a device handle
+ reinstallProtocolInterface: fn (handle: Handle, protocol: *align(8) const Guid, old_interface: *anyopaque, new_interface: *anyopaque) callconv(.C) Status,
+
+ /// Removes a protocol interface from a device handle. Usage of
+ /// uninstallMultipleProtocolInterfaces is recommended over this.
+ uninstallProtocolInterface: fn (handle: Handle, protocol: *align(8) const Guid, interface: *anyopaque) callconv(.C) Status,
/// Queries a handle to determine if it supports a specified protocol.
- handleProtocol: fn (Handle, *align(8) const Guid, *?*anyopaque) callconv(.C) Status,
+ handleProtocol: fn (handle: Handle, protocol: *align(8) const Guid, interface: *?*anyopaque) callconv(.C) Status,
reserved: *anyopaque,
- registerProtocolNotify: Status, // TODO
+ /// Creates an event that is to be signaled whenever an interface is installed for a specified protocol.
+ registerProtocolNotify: fn (protocol: *align(8) const Guid, event: Event, registration: **anyopaque) callconv(.C) Status,
/// Returns an array of handles that support a specified protocol.
- locateHandle: fn (LocateSearchType, ?*align(8) const Guid, ?*const anyopaque, *usize, [*]Handle) callconv(.C) Status,
+ locateHandle: fn (search_type: LocateSearchType, protocol: ?*align(8) const Guid, search_key: ?*const anyopaque, bufferSize: *usize, buffer: [*]Handle) callconv(.C) Status,
/// Locates the handle to a device on the device path that supports the specified protocol
- locateDevicePath: fn (*align(8) const Guid, **const DevicePathProtocol, *?Handle) callconv(.C) Status,
- installConfigurationTable: Status, // TODO
+ locateDevicePath: fn (protocols: *align(8) const Guid, device_path: **const DevicePathProtocol, device: *?Handle) callconv(.C) Status,
+
+ /// Adds, updates, or removes a configuration table entry from the EFI System Table.
+ installConfigurationTable: fn (guid: *align(8) const Guid, table: ?*anyopaque) callconv(.C) Status,
/// Loads an EFI image into memory.
- loadImage: fn (bool, Handle, ?*const DevicePathProtocol, ?[*]const u8, usize, *?Handle) callconv(.C) Status,
+ loadImage: fn (boot_policy: bool, parent_image_handle: Handle, device_path: ?*const DevicePathProtocol, source_buffer: ?[*]const u8, source_size: usize, imageHandle: *?Handle) callconv(.C) Status,
/// Transfers control to a loaded image's entry point.
- startImage: fn (Handle, ?*usize, ?*[*]u16) callconv(.C) Status,
+ startImage: fn (image_handle: Handle, exit_data_size: ?*usize, exit_data: ?*[*]u16) callconv(.C) Status,
/// Terminates a loaded EFI image and returns control to boot services.
- exit: fn (Handle, Status, usize, ?*const anyopaque) callconv(.C) Status,
+ exit: fn (image_handle: Handle, exit_status: Status, exit_data_size: usize, exit_data: ?*const anyopaque) callconv(.C) Status,
/// Unloads an image.
- unloadImage: fn (Handle) callconv(.C) Status,
+ unloadImage: fn (image_handle: Handle) callconv(.C) Status,
/// Terminates all boot services.
- exitBootServices: fn (Handle, usize) callconv(.C) Status,
+ exitBootServices: fn (image_handle: Handle, map_key: usize) callconv(.C) Status,
/// Returns a monotonically increasing count for the platform.
- getNextMonotonicCount: fn (*u64) callconv(.C) Status,
+ getNextMonotonicCount: fn (count: *u64) callconv(.C) Status,
/// Induces a fine-grained stall.
- stall: fn (usize) callconv(.C) Status,
+ stall: fn (microseconds: usize) callconv(.C) Status,
/// Sets the system's watchdog timer.
- setWatchdogTimer: fn (usize, u64, usize, ?[*]const u16) callconv(.C) Status,
+ setWatchdogTimer: fn (timeout: usize, watchdogCode: u64, data_size: usize, watchdog_data: ?[*]const u16) callconv(.C) Status,
- connectController: Status, // TODO
- disconnectController: Status, // TODO
+ /// Connects one or more drives to a controller.
+ connectController: fn (controller_handle: Handle, driver_image_handle: ?Handle, remaining_device_path: ?*DevicePathProtocol, recursive: bool) callconv(.C) Status,
+
+ // Disconnects one or more drivers from a controller
+ disconnectController: fn (controller_handle: Handle, driver_image_handle: ?Handle, child_handle: ?Handle) callconv(.C) Status,
/// Queries a handle to determine if it supports a specified protocol.
- openProtocol: fn (Handle, *align(8) const Guid, *?*anyopaque, ?Handle, ?Handle, OpenProtocolAttributes) callconv(.C) Status,
+ openProtocol: fn (handle: Handle, protocol: *align(8) const Guid, interface: *?*anyopaque, agent_handle: ?Handle, controller_handle: ?Handle, attributes: OpenProtocolAttributes) callconv(.C) Status,
/// Closes a protocol on a handle that was opened using openProtocol().
- closeProtocol: fn (Handle, *align(8) const Guid, Handle, ?Handle) callconv(.C) Status,
+ closeProtocol: fn (handle: Handle, protocol: *align(8) const Guid, agentHandle: Handle, controller_handle: ?Handle) callconv(.C) Status,
/// Retrieves the list of agents that currently have a protocol interface opened.
- openProtocolInformation: fn (Handle, *align(8) const Guid, *[*]ProtocolInformationEntry, *usize) callconv(.C) Status,
+ openProtocolInformation: fn (handle: Handle, protocol: *align(8) const Guid, entry_buffer: *[*]ProtocolInformationEntry, entry_count: *usize) callconv(.C) Status,
/// Retrieves the list of protocol interface GUIDs that are installed on a handle in a buffer allocated from pool.
- protocolsPerHandle: fn (Handle, *[*]*align(8) const Guid, *usize) callconv(.C) Status,
+ protocolsPerHandle: fn (handle: Handle, protocol_buffer: *[*]*align(8) const Guid, protocol_buffer_count: *usize) callconv(.C) Status,
/// Returns an array of handles that support the requested protocol in a buffer allocated from pool.
- locateHandleBuffer: fn (LocateSearchType, ?*align(8) const Guid, ?*const anyopaque, *usize, *[*]Handle) callconv(.C) Status,
+ locateHandleBuffer: fn (search_type: LocateSearchType, protocol: ?*align(8) const Guid, search_key: ?*const anyopaque, num_handles: *usize, buffer: *[*]Handle) callconv(.C) Status,
/// Returns the first protocol instance that matches the given protocol.
- locateProtocol: fn (*align(8) const Guid, ?*const anyopaque, *?*anyopaque) callconv(.C) Status,
+ locateProtocol: fn (protocol: *align(8) const Guid, registration: ?*const anyopaque, interface: *?*anyopaque) callconv(.C) Status,
+
+ /// Installs one or more protocol interfaces into the boot services environment
+ installMultipleProtocolInterfaces: fn (handle: *Handle, ...) callconv(.C) Status,
- installMultipleProtocolInterfaces: Status, // TODO
- uninstallMultipleProtocolInterfaces: Status, // TODO
+ /// Removes one or more protocol interfaces into the boot services environment
+ uninstallMultipleProtocolInterfaces: fn (handle: *Handle, ...) callconv(.C) Status,
/// Computes and returns a 32-bit CRC for a data buffer.
- calculateCrc32: fn ([*]const u8, usize, *u32) callconv(.C) Status,
+ calculateCrc32: fn (data: [*]const u8, data_size: usize, *u32) callconv(.C) Status,
/// Copies the contents of one buffer to another buffer
- copyMem: fn ([*]u8, [*]const u8, usize) callconv(.C) void,
+ copyMem: fn (dest: [*]u8, src: [*]const u8, len: usize) callconv(.C) void,
/// Fills a buffer with a specified value
- setMem: fn ([*]u8, usize, u8) callconv(.C) void,
+ setMem: fn (buffer: [*]u8, size: usize, value: u8) callconv(.C) void,
+
+ /// Creates an event in a group.
+ createEventEx: fn (type: u32, notify_tpl: usize, notify_func: EfiEventNotify, notify_ctx: *const anyopaque, event_group: *align(8) const Guid, event: *Event) callconv(.C) Status,
- createEventEx: Status, // TODO
+ /// Opens a protocol with a structure as the loaded image for a UEFI application
+ pub fn openProtocolSt(self: *BootServices, comptime protocol: type, handle: Handle) !*protocol {
+ if (!@hasDecl(protocol, "guid"))
+ @compileError("Protocol is missing guid!");
+
+ var ptr: ?*protocol = undefined;
+
+ try self.openProtocol(
+ handle,
+ &protocol.guid,
+ @ptrCast(*?*anyopaque, &ptr),
+ // Invoking handle (loaded image)
+ uefi.handle,
+ // Control handle (null as not a driver)
+ null,
+ uefi.tables.OpenProtocolAttributes{ .by_handle_protocol = true },
+ ).err();
+
+ return ptr.?;
+ }
pub const signature: u64 = 0x56524553544f4f42;
@@ -151,6 +190,8 @@ pub const BootServices = extern struct {
pub const tpl_high_level: usize = 31;
};
+pub const EfiEventNotify = fn (event: Event, ctx: *anyopaque) callconv(.C) void;
+
pub const TimerDelay = enum(u32) {
TimerCancel,
TimerPeriodic,
@@ -219,9 +260,7 @@ pub const OpenProtocolAttributes = packed struct {
by_child_controller: bool = false,
by_driver: bool = false,
exclusive: bool = false,
- _pad1: u2 = undefined,
- _pad2: u8 = undefined,
- _pad3: u16 = undefined,
+ _pad: u26 = 0,
};
pub const ProtocolInformationEntry = extern struct {
@@ -231,6 +270,10 @@ pub const ProtocolInformationEntry = extern struct {
open_count: u32,
};
+pub const EfiInterfaceType = enum(u32) {
+ EfiNativeInterface,
+};
+
pub const AllocateType = enum(u32) {
AllocateAnyPages,
AllocateMaxAddress,
diff --git a/lib/std/os/uefi/tables/runtime_services.zig b/lib/std/os/uefi/tables/runtime_services.zig
@@ -18,39 +18,71 @@ pub const RuntimeServices = extern struct {
hdr: TableHeader,
/// Returns the current time and date information, and the time-keeping capabilities of the hardware platform.
- getTime: fn (*uefi.Time, ?*TimeCapabilities) callconv(.C) Status,
+ getTime: fn (time: *uefi.Time, capabilities: ?*TimeCapabilities) callconv(.C) Status,
- setTime: Status, // TODO
- getWakeupTime: Status, // TODO
- setWakeupTime: Status, // TODO
+ /// Sets the current local time and date information
+ setTime: fn (time: *uefi.Time) callconv(.C) Status,
+
+ /// Returns the current wakeup alarm clock setting
+ getWakeupTime: fn (enabled: *bool, pending: *bool, time: *uefi.Time) callconv(.C) Status,
+
+ /// Sets the system wakeup alarm clock time
+ setWakeupTime: fn (enable: *bool, time: ?*uefi.Time) callconv(.C) Status,
/// Changes the runtime addressing mode of EFI firmware from physical to virtual.
- setVirtualAddressMap: fn (usize, usize, u32, [*]MemoryDescriptor) callconv(.C) Status,
+ setVirtualAddressMap: fn (mmap_size: usize, descriptor_size: usize, descriptor_version: u32, virtual_map: [*]MemoryDescriptor) callconv(.C) Status,
/// Determines the new virtual address that is to be used on subsequent memory accesses.
- convertPointer: fn (usize, **anyopaque) callconv(.C) Status,
+ convertPointer: fn (debug_disposition: usize, address: **anyopaque) callconv(.C) Status,
/// Returns the value of a variable.
- getVariable: fn ([*:0]const u16, *align(8) const Guid, ?*u32, *usize, ?*anyopaque) callconv(.C) Status,
+ getVariable: fn (var_name: [*:0]const u16, vendor_guid: *align(8) const Guid, attributes: ?*u32, data_size: *usize, data: ?*anyopaque) callconv(.C) Status,
/// Enumerates the current variable names.
- getNextVariableName: fn (*usize, [*:0]u16, *align(8) Guid) callconv(.C) Status,
+ getNextVariableName: fn (var_name_size: *usize, var_name: [*:0]u16, vendor_guid: *align(8) Guid) callconv(.C) Status,
/// Sets the value of a variable.
- setVariable: fn ([*:0]const u16, *align(8) const Guid, u32, usize, *anyopaque) callconv(.C) Status,
+ setVariable: fn (var_name: [*:0]const u16, vendor_guid: *align(8) const Guid, attributes: u32, data_size: usize, data: *anyopaque) callconv(.C) Status,
- getNextHighMonotonicCount: Status, // TODO
+ /// Return the next high 32 bits of the platform's monotonic counter
+ getNextHighMonotonicCount: fn (high_count: *u32) callconv(.C) Status,
/// Resets the entire platform.
- resetSystem: fn (ResetType, Status, usize, ?*const anyopaque) callconv(.C) noreturn,
+ resetSystem: fn (reset_type: ResetType, reset_status: Status, data_size: usize, reset_data: ?*const anyopaque) callconv(.C) noreturn,
+
+ /// Passes capsules to the firmware with both virtual and physical mapping.
+ /// Depending on the intended consumption, the firmware may process the capsule immediately.
+ /// If the payload should persist across a system reset, the reset value returned from
+ /// `queryCapsuleCapabilities` must be passed into resetSystem and will cause the capsule
+ /// to be processed by the firmware as part of the reset process.
+ updateCapsule: fn (capsule_header_array: **CapsuleHeader, capsule_count: usize, scatter_gather_list: EfiPhysicalAddress) callconv(.C) Status,
- updateCapsule: Status, // TODO
- queryCapsuleCapabilities: Status, // TODO
- queryVariableInfo: Status, // TODO
+ /// Returns if the capsule can be supported via `updateCapsule`
+ queryCapsuleCapabilities: fn (capsule_header_array: **CapsuleHeader, capsule_count: usize, maximum_capsule_size: *usize, resetType: ResetType) callconv(.C) Status,
+
+ /// Returns information about the EFI variables
+ queryVariableInfo: fn (attributes: *u32, maximum_variable_storage_size: *u64, remaining_variable_storage_size: *u64, maximum_variable_size: *u64) callconv(.C) Status,
pub const signature: u64 = 0x56524553544e5552;
};
+const EfiPhysicalAddress = u64;
+
+pub const CapsuleHeader = extern struct {
+ capsuleGuid: Guid align(8),
+ headerSize: u32,
+ flags: u32,
+ capsuleImageSize: u32,
+};
+
+pub const UefiCapsuleBlockDescriptor = extern struct {
+ length: u64,
+ address: union {
+ dataBlock: EfiPhysicalAddress,
+ continuationPointer: EfiPhysicalAddress,
+ },
+};
+
pub const ResetType = enum(u32) {
ResetCold,
ResetWarm,