Merge pull request #10604 from fifty-six/master

std/os/uefi: additional improvements/fixes
This commit is contained in:
Andrew Kelley 2022-02-18 14:16:30 -05:00 committed by GitHub
commit 2c24bf2f79
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
13 changed files with 654 additions and 280 deletions

View File

@ -758,7 +758,52 @@ pub fn default_panic(msg: []const u8, error_return_trace: ?*StackTrace) noreturn
std.os.abort(); std.os.abort();
}, },
.uefi => { .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(); std.os.abort();
}, },
else => { else => {

View File

@ -23,6 +23,18 @@ pub var system_table: *tables.SystemTable = undefined;
/// A handle to an event structure. /// A handle to an event structure.
pub const Event = *opaque {}; 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) /// GUIDs must be align(8)
pub const Guid = extern struct { pub const Guid = extern struct {
time_low: u32, time_low: u32,
@ -86,7 +98,6 @@ pub const Time = extern struct {
/// 0 - 59 /// 0 - 59
second: u8, second: u8,
_pad1: u8,
/// 0 - 999999999 /// 0 - 999999999
nanosecond: u32, nanosecond: u32,
@ -103,7 +114,6 @@ pub const Time = extern struct {
/// If true, the time is affected by daylight savings time. /// If true, the time is affected by daylight savings time.
adjust_daylight: bool, adjust_daylight: bool,
}, },
_pad2: u8,
/// Time is to be interpreted as local time /// Time is to be interpreted as local time
pub const unspecified_timezone: i16 = 0x7ff; pub const unspecified_timezone: i16 = 0x7ff;

View File

@ -1,100 +1,44 @@
pub const LoadedImageProtocol = @import("protocols/loaded_image_protocol.zig").LoadedImageProtocol; // Misc
pub const loaded_image_device_path_protocol_guid = @import("protocols/loaded_image_protocol.zig").loaded_image_device_path_protocol_guid; 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");
pub const AcpiDevicePath = @import("protocols/device_path_protocol.zig").AcpiDevicePath; // Files
pub const BiosBootSpecificationDevicePath = @import("protocols/device_path_protocol.zig").BiosBootSpecificationDevicePath; pub usingnamespace @import("protocols/simple_file_system_protocol.zig");
pub const DevicePath = @import("protocols/device_path_protocol.zig").DevicePath; pub usingnamespace @import("protocols/file_protocol.zig");
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; // Text
pub const FileProtocol = @import("protocols/file_protocol.zig").FileProtocol; pub usingnamespace @import("protocols/simple_text_input_protocol.zig");
pub const FileInfo = @import("protocols/file_protocol.zig").FileInfo; pub usingnamespace @import("protocols/simple_text_input_ex_protocol.zig");
pub const FileSystemInfo = @import("protocols/file_protocol.zig").FileSystemInfo; pub usingnamespace @import("protocols/simple_text_output_protocol.zig");
pub const InputKey = @import("protocols/simple_text_input_ex_protocol.zig").InputKey; // Pointer
pub const KeyData = @import("protocols/simple_text_input_ex_protocol.zig").KeyData; pub usingnamespace @import("protocols/simple_pointer_protocol.zig");
pub const KeyState = @import("protocols/simple_text_input_ex_protocol.zig").KeyState; pub usingnamespace @import("protocols/absolute_pointer_protocol.zig");
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 usingnamespace @import("protocols/graphics_output_protocol.zig");
pub const SimpleTextOutputProtocol = @import("protocols/simple_text_output_protocol.zig").SimpleTextOutputProtocol;
pub const SimplePointerMode = @import("protocols/simple_pointer_protocol.zig").SimplePointerMode; // edid
pub const SimplePointerProtocol = @import("protocols/simple_pointer_protocol.zig").SimplePointerProtocol; pub usingnamespace @import("protocols/edid_discovered_protocol.zig");
pub const SimplePointerState = @import("protocols/simple_pointer_protocol.zig").SimplePointerState; pub usingnamespace @import("protocols/edid_active_protocol.zig");
pub usingnamespace @import("protocols/edid_override_protocol.zig");
pub const AbsolutePointerMode = @import("protocols/absolute_pointer_protocol.zig").AbsolutePointerMode; // Network
pub const AbsolutePointerProtocol = @import("protocols/absolute_pointer_protocol.zig").AbsolutePointerProtocol; pub usingnamespace @import("protocols/simple_network_protocol.zig");
pub const AbsolutePointerState = @import("protocols/absolute_pointer_protocol.zig").AbsolutePointerState; pub usingnamespace @import("protocols/managed_network_service_binding_protocol.zig");
pub usingnamespace @import("protocols/managed_network_protocol.zig");
pub const GraphicsOutputBltPixel = @import("protocols/graphics_output_protocol.zig").GraphicsOutputBltPixel; // ip6
pub const GraphicsOutputBltOperation = @import("protocols/graphics_output_protocol.zig").GraphicsOutputBltOperation; pub usingnamespace @import("protocols/ip6_service_binding_protocol.zig");
pub const GraphicsOutputModeInformation = @import("protocols/graphics_output_protocol.zig").GraphicsOutputModeInformation; pub usingnamespace @import("protocols/ip6_protocol.zig");
pub const GraphicsOutputProtocol = @import("protocols/graphics_output_protocol.zig").GraphicsOutputProtocol; pub usingnamespace @import("protocols/ip6_config_protocol.zig");
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; // udp6
pub usingnamespace @import("protocols/udp6_service_binding_protocol.zig");
pub const EdidActiveProtocol = @import("protocols/edid_active_protocol.zig").EdidActiveProtocol; pub usingnamespace @import("protocols/udp6_protocol.zig");
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;
// hii
pub const hii = @import("protocols/hii.zig"); pub const hii = @import("protocols/hii.zig");
pub const HIIDatabaseProtocol = @import("protocols/hii_database_protocol.zig").HIIDatabaseProtocol; pub usingnamespace @import("protocols/hii_database_protocol.zig");
pub const HIIPopupProtocol = @import("protocols/hii_popup_protocol.zig").HIIPopupProtocol; pub usingnamespace @import("protocols/hii_popup_protocol.zig");
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;

View File

@ -40,9 +40,7 @@ pub const AbsolutePointerMode = extern struct {
attributes: packed struct { attributes: packed struct {
supports_alt_active: bool, supports_alt_active: bool,
supports_pressure_as_z: bool, supports_pressure_as_z: bool,
_pad1: u6, _pad: u30 = 0,
_pad2: u8,
_pad3: u16,
}, },
}; };
@ -53,8 +51,6 @@ pub const AbsolutePointerState = extern struct {
active_buttons: packed struct { active_buttons: packed struct {
touch_active: bool, touch_active: bool,
alt_active: bool, alt_active: bool,
_pad1: u6, _pad: u30 = 0,
_pad2: u8,
_pad3: u16,
}, },
}; };

View File

@ -72,63 +72,39 @@ pub const DevicePathProtocol = packed struct {
} }
pub fn getDevicePath(self: *const DevicePathProtocol) ?DevicePath { pub fn getDevicePath(self: *const DevicePathProtocol) ?DevicePath {
return switch (self.type) { inline for (@typeInfo(DevicePath).Union.fields) |ufield| {
.Hardware => blk: { const enum_value = std.meta.stringToEnum(DevicePathType, ufield.name);
const hardware: ?HardwareDevicePath = switch (@intToEnum(HardwareDevicePath.Subtype, self.subtype)) {
.Pci => .{ .Pci = @ptrCast(*const HardwareDevicePath.PciDevicePath, self) }, // Got the associated union type for self.type, now
.PcCard => .{ .PcCard = @ptrCast(*const HardwareDevicePath.PcCardDevicePath, self) }, // we need to initialize it and its subtype
.MemoryMapped => .{ .MemoryMapped = @ptrCast(*const HardwareDevicePath.MemoryMappedDevicePath, self) }, if (self.type == enum_value) {
.Vendor => .{ .Vendor = @ptrCast(*const HardwareDevicePath.VendorDevicePath, self) }, var subtype = self.initSubtype(ufield.field_type);
.Controller => .{ .Controller = @ptrCast(*const HardwareDevicePath.ControllerDevicePath, self) },
.Bmc => .{ .Bmc = @ptrCast(*const HardwareDevicePath.BmcDevicePath, self) }, if (subtype) |sb| {
_ => null, // e.g. return .{ .Hardware = .{ .Pci = @ptrCast(...) } }
}; return @unionInit(DevicePath, ufield.name, sb);
break :blk if (hardware) |h| .{ .Hardware = h } else null; }
}, }
.Acpi => blk: { }
const acpi: ?AcpiDevicePath = switch (@intToEnum(AcpiDevicePath.Subtype, self.subtype)) {
else => null, // TODO return null;
}; }
break :blk if (acpi) |a| .{ .Acpi = a } else null;
}, pub fn initSubtype(self: *const DevicePathProtocol, comptime TUnion: type) ?TUnion {
.Messaging => blk: { const type_info = @typeInfo(TUnion).Union;
const messaging: ?MessagingDevicePath = switch (@intToEnum(MessagingDevicePath.Subtype, self.subtype)) { const TTag = type_info.tag_type.?;
else => null, // TODO
}; inline for (type_info.fields) |subtype| {
break :blk if (messaging) |m| .{ .Messaging = m } else null; // The tag names match the union names, so just grab that off the enum
}, const tag_val: u8 = @enumToInt(@field(TTag, subtype.name));
.Media => blk: {
const media: ?MediaDevicePath = switch (@intToEnum(MediaDevicePath.Subtype, self.subtype)) { if (self.subtype == tag_val) {
.HardDrive => .{ .HardDrive = @ptrCast(*const MediaDevicePath.HardDriveDevicePath, self) }, // e.g. expr = .{ .Pci = @ptrCast(...) }
.Cdrom => .{ .Cdrom = @ptrCast(*const MediaDevicePath.CdromDevicePath, self) }, return @unionInit(TUnion, subtype.name, @ptrCast(subtype.field_type, 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) }, return null;
.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,
};
} }
}; };
@ -173,79 +149,113 @@ pub const HardwareDevicePath = union(Subtype) {
type: DevicePathType, type: DevicePathType,
subtype: Subtype, subtype: Subtype,
length: u16, length: u16,
// TODO function: u8,
device: u8,
}; };
pub const PcCardDevicePath = packed struct { pub const PcCardDevicePath = packed struct {
type: DevicePathType, type: DevicePathType,
subtype: Subtype, subtype: Subtype,
length: u16, length: u16,
// TODO function_number: u8,
}; };
pub const MemoryMappedDevicePath = packed struct { pub const MemoryMappedDevicePath = packed struct {
type: DevicePathType, type: DevicePathType,
subtype: Subtype, subtype: Subtype,
length: u16, length: u16,
// TODO memory_type: u32,
start_address: u64,
end_address: u64,
}; };
pub const VendorDevicePath = packed struct { pub const VendorDevicePath = packed struct {
type: DevicePathType, type: DevicePathType,
subtype: Subtype, subtype: Subtype,
length: u16, length: u16,
// TODO vendor_guid: Guid,
}; };
pub const ControllerDevicePath = packed struct { pub const ControllerDevicePath = packed struct {
type: DevicePathType, type: DevicePathType,
subtype: Subtype, subtype: Subtype,
length: u16, length: u16,
// TODO controller_number: u32,
}; };
pub const BmcDevicePath = packed struct { pub const BmcDevicePath = packed struct {
type: DevicePathType, type: DevicePathType,
subtype: Subtype, subtype: Subtype,
length: u16, length: u16,
// TODO interface_type: u8,
base_address: usize,
}; };
}; };
pub const AcpiDevicePath = union(Subtype) { pub const AcpiDevicePath = union(Subtype) {
Acpi: void, // TODO Acpi: *const BaseAcpiDevicePath,
ExpandedAcpi: void, // TODO ExpandedAcpi: *const ExpandedAcpiDevicePath,
Adr: void, // TODO Adr: *const AdrDevicePath,
Nvdimm: void, // TODO
pub const Subtype = enum(u8) { pub const Subtype = enum(u8) {
Acpi = 1, Acpi = 1,
ExpandedAcpi = 2, ExpandedAcpi = 2,
Adr = 3, 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) { pub const MessagingDevicePath = union(Subtype) {
Atapi: void, // TODO Atapi: *const AtapiDevicePath,
Scsi: void, // TODO Scsi: *const ScsiDevicePath,
FibreChannel: void, // TODO FibreChannel: *const FibreChannelDevicePath,
FibreChannelEx: void, // TODO FibreChannelEx: *const FibreChannelExDevicePath,
@"1394": void, // TODO @"1394": *const F1394DevicePath,
Usb: void, // TODO Usb: *const UsbDevicePath,
Sata: void, // TODO Sata: *const SataDevicePath,
UsbWwid: void, // TODO UsbWwid: *const UsbWwidDevicePath,
Lun: void, // TODO Lun: *const DeviceLogicalUnitDevicePath,
UsbClass: void, // TODO UsbClass: *const UsbClassDevicePath,
I2o: void, // TODO I2o: *const I2oDevicePath,
MacAddress: void, // TODO MacAddress: *const MacAddressDevicePath,
Ipv4: void, // TODO Ipv4: *const Ipv4DevicePath,
Ipv6: void, // TODO Ipv6: *const Ipv6DevicePath,
Vlan: void, // TODO Vlan: *const VlanDevicePath,
InfiniBand: void, // TODO InfiniBand: *const InfiniBandDevicePath,
Uart: void, // TODO Uart: *const UartDevicePath,
Vendor: void, // TODO Vendor: *const VendorDefinedDevicePath,
pub const Subtype = enum(u8) { pub const Subtype = enum(u8) {
Atapi = 1, Atapi = 1,
@ -268,6 +278,232 @@ pub const MessagingDevicePath = union(Subtype) {
Vendor = 10, 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) { pub const MediaDevicePath = union(Subtype) {
@ -295,24 +531,44 @@ pub const MediaDevicePath = union(Subtype) {
}; };
pub const HardDriveDevicePath = packed struct { 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, type: DevicePathType,
subtype: Subtype, subtype: Subtype,
length: u16, 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 { pub const CdromDevicePath = packed struct {
type: DevicePathType, type: DevicePathType,
subtype: Subtype, subtype: Subtype,
length: u16, length: u16,
// TODO boot_entry: u32,
partition_start: u64,
partition_size: u64,
}; };
pub const VendorDevicePath = packed struct { pub const VendorDevicePath = packed struct {
type: DevicePathType, type: DevicePathType,
subtype: Subtype, subtype: Subtype,
length: u16, length: u16,
// TODO guid: Guid,
// vendor-defined variable data
}; };
pub const FilePathDevicePath = packed struct { pub const FilePathDevicePath = packed struct {
@ -329,19 +585,21 @@ pub const MediaDevicePath = union(Subtype) {
type: DevicePathType, type: DevicePathType,
subtype: Subtype, subtype: Subtype,
length: u16, length: u16,
// TODO guid: Guid,
}; };
pub const PiwgFirmwareFileDevicePath = packed struct { pub const PiwgFirmwareFileDevicePath = packed struct {
type: DevicePathType, type: DevicePathType,
subtype: Subtype, subtype: Subtype,
length: u16, length: u16,
fv_filename: Guid,
}; };
pub const PiwgFirmwareVolumeDevicePath = packed struct { pub const PiwgFirmwareVolumeDevicePath = packed struct {
type: DevicePathType, type: DevicePathType,
subtype: Subtype, subtype: Subtype,
length: u16, length: u16,
fv_name: Guid,
}; };
pub const RelativeOffsetRangeDevicePath = packed struct { pub const RelativeOffsetRangeDevicePath = packed struct {
@ -359,7 +617,7 @@ pub const MediaDevicePath = union(Subtype) {
length: u16, length: u16,
start: u64, start: u64,
end: u64, end: u64,
disk_type: uefi.Guid, disk_type: Guid,
instance: u16, instance: u16,
}; };
}; };

View File

@ -8,9 +8,8 @@ pub const EdidOverrideProtocol = extern struct {
_get_edid: fn (*const EdidOverrideProtocol, Handle, *u32, *usize, *?[*]u8) callconv(.C) Status, _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. /// 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 { 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{ pub const guid align(8) = Guid{
@ -24,9 +23,7 @@ pub const EdidOverrideProtocol = extern struct {
}; };
pub const EdidOverrideProtocolAttributes = packed struct { pub const EdidOverrideProtocolAttributes = packed struct {
dont_override: bool, dont_override: bool align(4),
enable_hot_plug: bool, enable_hot_plug: bool,
_pad1: u6, _pad: u30 = 0,
_pad2: u8,
_pad3: u16,
}; };

View File

@ -48,7 +48,7 @@ pub const NarrowGlyph = extern struct {
attributes: packed struct { attributes: packed struct {
non_spacing: bool, non_spacing: bool,
wide: bool, wide: bool,
_pad: u6, _pad: u6 = 0,
}, },
glyph_col_1: [19]u8, glyph_col_1: [19]u8,
}; };
@ -62,7 +62,7 @@ pub const WideGlyph = extern struct {
}, },
glyph_col_1: [19]u8, glyph_col_1: [19]u8,
glyph_col_2: [19]u8, glyph_col_2: [19]u8,
_pad: [3]u8, _pad: [3]u8 = [_]u8{0} ** 3,
}; };
pub const HIIStringPackage = extern struct { pub const HIIStringPackage = extern struct {

View File

@ -126,9 +126,7 @@ pub const SimpleNetworkReceiveFilter = packed struct {
receive_broadcast: bool, receive_broadcast: bool,
receive_promiscuous: bool, receive_promiscuous: bool,
receive_promiscuous_multicast: bool, receive_promiscuous_multicast: bool,
_pad1: u3 = undefined, _pad: u27 = 0,
_pad2: u8 = undefined,
_pad3: u16 = undefined,
}; };
pub const SimpleNetworkState = enum(u32) { pub const SimpleNetworkState = enum(u32) {
@ -171,7 +169,5 @@ pub const SimpleNetworkInterruptStatus = packed struct {
transmit_interrupt: bool, transmit_interrupt: bool,
command_interrupt: bool, command_interrupt: bool,
software_interrupt: bool, software_interrupt: bool,
_pad1: u4, _pad: u28 = 0,
_pad2: u8,
_pad3: u16,
}; };

View File

@ -64,14 +64,14 @@ pub const KeyState = extern struct {
left_logo_pressed: bool, left_logo_pressed: bool,
menu_key_pressed: bool, menu_key_pressed: bool,
sys_req_pressed: bool, sys_req_pressed: bool,
_pad1: u21, _pad: u21 = 0,
shift_state_valid: bool, shift_state_valid: bool,
}, },
key_toggle_state: packed struct { key_toggle_state: packed struct {
scroll_lock_active: bool, scroll_lock_active: bool,
num_lock_active: bool, num_lock_active: bool,
caps_lock_active: bool, caps_lock_active: bool,
_pad1: u3, _pad: u3 = 0,
key_state_exposed: bool, key_state_exposed: bool,
toggle_state_valid: bool, toggle_state_valid: bool,
}, },

View File

@ -1,3 +1,5 @@
const testing = @import("std").testing;
const high_bit = 1 << @typeInfo(usize).Int.bits - 1; const high_bit = 1 << @typeInfo(usize).Int.bits - 1;
pub const Status = enum(usize) { pub const Status = enum(usize) {
@ -139,4 +141,64 @@ pub const Status = enum(usize) {
WarnResetRequired = 7, 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();
}

View File

@ -1,14 +1,5 @@
pub const AllocateType = @import("tables/boot_services.zig").AllocateType; pub usingnamespace @import("tables/boot_services.zig");
pub const BootServices = @import("tables/boot_services.zig").BootServices; pub usingnamespace @import("tables/runtime_services.zig");
pub const ConfigurationTable = @import("tables/configuration_table.zig").ConfigurationTable; pub usingnamespace @import("tables/configuration_table.zig");
pub const global_variable align(8) = @import("tables/runtime_services.zig").global_variable; pub usingnamespace @import("tables/system_table.zig");
pub const LocateSearchType = @import("tables/boot_services.zig").LocateSearchType; pub usingnamespace @import("tables/table_header.zig");
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;

View File

@ -21,120 +21,159 @@ pub const BootServices = extern struct {
hdr: TableHeader, hdr: TableHeader,
/// Raises a task's priority level and returns its previous level. /// 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. /// 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. /// 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. /// 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. /// 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. /// 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. /// 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. /// 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. /// 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. /// 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. /// Signals an event.
signalEvent: fn (Event) callconv(.C) Status, signalEvent: fn (event: Event) callconv(.C) Status,
/// Closes an event. /// 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. /// 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 /// Installs a protocol interface on a device handle. If the handle does not exist, it is created
reinstallProtocolInterface: Status, // TODO /// and added to the list of handles in the system. installMultipleProtocolInterfaces()
uninstallProtocolInterface: Status, // TODO /// 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. /// 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, 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. /// 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 /// 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, locateDevicePath: fn (protocols: *align(8) const Guid, device_path: **const DevicePathProtocol, device: *?Handle) callconv(.C) Status,
installConfigurationTable: Status, // TODO
/// 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. /// 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. /// 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. /// 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. /// Unloads an image.
unloadImage: fn (Handle) callconv(.C) Status, unloadImage: fn (image_handle: Handle) callconv(.C) Status,
/// Terminates all boot services. /// 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. /// 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. /// Induces a fine-grained stall.
stall: fn (usize) callconv(.C) Status, stall: fn (microseconds: usize) callconv(.C) Status,
/// Sets the system's watchdog timer. /// 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 /// Connects one or more drives to a controller.
disconnectController: Status, // TODO 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. /// 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(). /// 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. /// 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. /// 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. /// 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. /// 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,
installMultipleProtocolInterfaces: Status, // TODO /// Installs one or more protocol interfaces into the boot services environment
uninstallMultipleProtocolInterfaces: Status, // TODO installMultipleProtocolInterfaces: fn (handle: *Handle, ...) callconv(.C) Status,
/// 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. /// 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 /// 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 /// 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,
createEventEx: Status, // TODO /// 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,
/// 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; pub const signature: u64 = 0x56524553544f4f42;
@ -151,6 +190,8 @@ pub const BootServices = extern struct {
pub const tpl_high_level: usize = 31; pub const tpl_high_level: usize = 31;
}; };
pub const EfiEventNotify = fn (event: Event, ctx: *anyopaque) callconv(.C) void;
pub const TimerDelay = enum(u32) { pub const TimerDelay = enum(u32) {
TimerCancel, TimerCancel,
TimerPeriodic, TimerPeriodic,
@ -219,9 +260,7 @@ pub const OpenProtocolAttributes = packed struct {
by_child_controller: bool = false, by_child_controller: bool = false,
by_driver: bool = false, by_driver: bool = false,
exclusive: bool = false, exclusive: bool = false,
_pad1: u2 = undefined, _pad: u26 = 0,
_pad2: u8 = undefined,
_pad3: u16 = undefined,
}; };
pub const ProtocolInformationEntry = extern struct { pub const ProtocolInformationEntry = extern struct {
@ -231,6 +270,10 @@ pub const ProtocolInformationEntry = extern struct {
open_count: u32, open_count: u32,
}; };
pub const EfiInterfaceType = enum(u32) {
EfiNativeInterface,
};
pub const AllocateType = enum(u32) { pub const AllocateType = enum(u32) {
AllocateAnyPages, AllocateAnyPages,
AllocateMaxAddress, AllocateMaxAddress,

View File

@ -18,39 +18,71 @@ pub const RuntimeServices = extern struct {
hdr: TableHeader, hdr: TableHeader,
/// Returns the current time and date information, and the time-keeping capabilities of the hardware platform. /// 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 /// Sets the current local time and date information
getWakeupTime: Status, // TODO setTime: fn (time: *uefi.Time) callconv(.C) Status,
setWakeupTime: Status, // TODO
/// 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. /// 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. /// 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. /// 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. /// 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. /// 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. /// 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,
updateCapsule: Status, // TODO /// Passes capsules to the firmware with both virtual and physical mapping.
queryCapsuleCapabilities: Status, // TODO /// Depending on the intended consumption, the firmware may process the capsule immediately.
queryVariableInfo: Status, // TODO /// 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,
/// 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; 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) { pub const ResetType = enum(u32) {
ResetCold, ResetCold,
ResetWarm, ResetWarm,