From ea2df2601e81aa9e490459ad9c65b03de2be61d0 Mon Sep 17 00:00:00 2001 From: fifty-six Date: Thu, 13 Jan 2022 05:21:42 -0500 Subject: [PATCH 01/14] std/os/uefi: Use `usingnamespace` to re-export symbols `uefi/protocols.zig` and `uefi/tables.zig` just re-exported all the public symbols, which is basically the purpose of `usingnamespace` import-wise. --- lib/std/os/uefi/protocols.zig | 142 ++++++++++------------------------ lib/std/os/uefi/tables.zig | 19 ++--- 2 files changed, 48 insertions(+), 113 deletions(-) diff --git a/lib/std/os/uefi/protocols.zig b/lib/std/os/uefi/protocols.zig index 4192b4a545ebc44157efa632d1a79c5af2111d77..0c027f046b540b665b49df50a6eb6a6c23cd45c6 100644 --- 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/tables.zig b/lib/std/os/uefi/tables.zig index 0011c80a9cd20b6976c1a33a5591095cfd0bc0f0..a65e5789c72ee16066488234db3c6a908b25118b 100644 --- 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"); -- 2.54.0 From 649b872450689511ac3c5526d063c89fff7d898a Mon Sep 17 00:00:00 2001 From: fifty-six Date: Thu, 13 Jan 2022 05:23:39 -0500 Subject: [PATCH 02/14] std/builtin: improve panic handler for uefi Writes the panic message to stderr as well as passing it to boot_services.exit when boot_services is available. --- lib/std/builtin.zig | 47 ++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 46 insertions(+), 1 deletion(-) diff --git a/lib/std/builtin.zig b/lib/std/builtin.zig index 7fcd9a369b58a48d42f7fb04c12676c1a678fb43..b69b31ae17abf0539b3d99fd57845c7de9ffe666 100644 --- a/lib/std/builtin.zig +++ b/lib/std/builtin.zig @@ -769,7 +769,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 => { -- 2.54.0 From fe28cb8261eeb7e3094d38f2c5fb2012fbf205d6 Mon Sep 17 00:00:00 2001 From: fifty-six Date: Thu, 13 Jan 2022 05:54:24 -0500 Subject: [PATCH 03/14] std/os/uefi: Fill out remaining function signatures and docs on boot_services --- lib/std/os/uefi/tables/boot_services.zig | 44 ++++++++++++++++++------ 1 file changed, 34 insertions(+), 10 deletions(-) diff --git a/lib/std/os/uefi/tables/boot_services.zig b/lib/std/os/uefi/tables/boot_services.zig index 75daf6feb23e8645511bc1f9e97046b176d28d39..a41f2dcdb9cb209bf86b2eae182cf08c9fe24b02 100644 --- a/lib/std/os/uefi/tables/boot_services.zig +++ b/lib/std/os/uefi/tables/boot_services.zig @@ -59,23 +59,34 @@ pub const BootServices = extern struct { /// Checks whether an event is in the signaled state. checkEvent: fn (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, *align(8) const Guid, EfiInterfaceType, *anyopaque) callconv(.C) Status, + + /// Reinstalls a protocol interface on a device handle + reinstallProtocolInterface: fn (Handle, *align(8) const Guid, *anyopaque, *anyopaque) callconv(.C) Status, + + /// Removes a protocol interface from a device handle. Usage of + /// uninstallMultipleProtocolInterfaces is recommended over this. + uninstallProtocolInterface: fn (Handle, *align(8) const Guid, *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, reserved: *anyopaque, - registerProtocolNotify: Status, // TODO + /// Creates an event that is to be signaled whenever an interface is installed for a specified protocol. + registerProtocolNotify: fn (*align(8) const Guid, Event, **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, /// 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 + + /// Adds, updates, or removes a configuration table entry from the EFI System Table. + installConfigurationTable: fn (*align(8) const Guid, ?*anyopaque) callconv(.C) Status, /// Loads an EFI image into memory. loadImage: fn (bool, Handle, ?*const DevicePathProtocol, ?[*]const u8, usize, *?Handle) callconv(.C) Status, @@ -101,8 +112,11 @@ pub const BootServices = extern struct { /// Sets the system's watchdog timer. setWatchdogTimer: fn (usize, u64, usize, ?[*]const u16) callconv(.C) Status, - connectController: Status, // TODO - disconnectController: Status, // TODO + /// Connects one or more drives to a controller. + connectController: fn (Handle, ?Handle, ?*DevicePathProtocol, bool) callconv(.C) Status, + + // Disconnects one or more drivers from a controller + disconnectController: fn (Handle, ?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, @@ -122,8 +136,11 @@ pub const BootServices = extern struct { /// Returns the first protocol instance that matches the given protocol. locateProtocol: fn (*align(8) const Guid, ?*const anyopaque, *?*anyopaque) callconv(.C) Status, - installMultipleProtocolInterfaces: Status, // TODO - uninstallMultipleProtocolInterfaces: Status, // TODO + /// Installs one or more protocol interfaces into the boot services environment + installMultipleProtocolInterfaces: fn (*Handle, ...) callconv(.C) Status, + + /// Removes one or more protocol interfaces into the boot services environment + uninstallMultipleProtocolInterfaces: fn (*Handle, ...) callconv(.C) Status, /// Computes and returns a 32-bit CRC for a data buffer. calculateCrc32: fn ([*]const u8, usize, *u32) callconv(.C) Status, @@ -134,7 +151,8 @@ pub const BootServices = extern struct { /// Fills a buffer with a specified value setMem: fn ([*]u8, usize, u8) callconv(.C) void, - createEventEx: Status, // TODO + /// Creates an event in a group. + createEventEx: fn (u32, usize, EfiEventNotify, *const anyopaque, *align(8) const Guid, *Event) callconv(.C) Status, pub const signature: u64 = 0x56524553544f4f42; @@ -151,6 +169,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, @@ -231,6 +251,10 @@ pub const ProtocolInformationEntry = extern struct { open_count: u32, }; +pub const EfiInterfaceType = enum(u32) { + EfiNativeInterface, +}; + pub const AllocateType = enum(u32) { AllocateAnyPages, AllocateMaxAddress, -- 2.54.0 From 88687645b2a5c34304c36ded31d5164784aa207a Mon Sep 17 00:00:00 2001 From: fifty-six Date: Thu, 13 Jan 2022 11:19:22 -0500 Subject: [PATCH 04/14] std/os/uefi: Fill out remaining runtime services and add parameter names --- lib/std/os/uefi/tables/runtime_services.zig | 60 ++++++++++++++++----- 1 file changed, 46 insertions(+), 14 deletions(-) diff --git a/lib/std/os/uefi/tables/runtime_services.zig b/lib/std/os/uefi/tables/runtime_services.zig index 1250894180e6a0f38bee568146d8a56c959fbd2f..f238951553849c60ca7886209c326e8bb1449534 100644 --- 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, - updateCapsule: Status, // TODO - queryCapsuleCapabilities: Status, // TODO - queryVariableInfo: Status, // TODO + /// 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, + + /// 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, -- 2.54.0 From 322757c4e13acbe866e6b3431cd3b6b8ce68efb7 Mon Sep 17 00:00:00 2001 From: fifty-six Date: Thu, 13 Jan 2022 11:48:25 -0500 Subject: [PATCH 05/14] std/os/uefi: Add parameter names to boot_services --- lib/std/os/uefi/tables/boot_services.zig | 86 ++++++++++++------------ 1 file changed, 43 insertions(+), 43 deletions(-) diff --git a/lib/std/os/uefi/tables/boot_services.zig b/lib/std/os/uefi/tables/boot_services.zig index a41f2dcdb9cb209bf86b2eae182cf08c9fe24b02..7da007b05dc19217c9b5bdb8980c8289a5099733 100644 --- a/lib/std/os/uefi/tables/boot_services.zig +++ b/lib/std/os/uefi/tables/boot_services.zig @@ -21,138 +21,138 @@ 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, /// 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, *align(8) const Guid, EfiInterfaceType, *anyopaque) callconv(.C) Status, + 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, *align(8) const Guid, *anyopaque, *anyopaque) callconv(.C) Status, + 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, *align(8) const Guid, *anyopaque) callconv(.C) Status, + 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, /// Creates an event that is to be signaled whenever an interface is installed for a specified protocol. - registerProtocolNotify: fn (*align(8) const Guid, Event, **anyopaque) callconv(.C) Status, + 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, + 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 (*align(8) const Guid, ?*anyopaque) callconv(.C) Status, + 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, /// Connects one or more drives to a controller. - connectController: fn (Handle, ?Handle, ?*DevicePathProtocol, bool) callconv(.C) Status, + 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 (Handle, ?Handle, ?Handle) callconv(.C) Status, + 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, ...) callconv(.C) Status, + installMultipleProtocolInterfaces: fn (handle: *Handle, ...) callconv(.C) Status, /// Removes one or more protocol interfaces into the boot services environment - uninstallMultipleProtocolInterfaces: fn (*Handle, ...) callconv(.C) Status, + 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 (u32, usize, EfiEventNotify, *const anyopaque, *align(8) const Guid, *Event) callconv(.C) Status, + 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, pub const signature: u64 = 0x56524553544f4f42; -- 2.54.0 From ae084c5f59b0436a8fcb1b924008a16d90a9fe86 Mon Sep 17 00:00:00 2001 From: fifty-six Date: Thu, 13 Jan 2022 15:44:29 -0500 Subject: [PATCH 06/14] std/os/uefi: Complete AcpiDevicePath and HardwareDevicePaths --- .../uefi/protocols/device_path_protocol.zig | 61 +++++++++++++++---- 1 file changed, 49 insertions(+), 12 deletions(-) diff --git a/lib/std/os/uefi/protocols/device_path_protocol.zig b/lib/std/os/uefi/protocols/device_path_protocol.zig index df3812451c7bfd5f48c4b6cf4091705ee0623447..7a31b923ac901a900f4a56037757431b1bd4f1a1 100644 --- a/lib/std/os/uefi/protocols/device_path_protocol.zig +++ b/lib/std/os/uefi/protocols/device_path_protocol.zig @@ -87,7 +87,10 @@ pub const DevicePathProtocol = packed struct { }, .Acpi => blk: { const acpi: ?AcpiDevicePath = switch (@intToEnum(AcpiDevicePath.Subtype, self.subtype)) { - else => null, // TODO + .Acpi => .{ .Acpi = @ptrCast(*const AcpiDevicePath.BaseAcpiDevicePath, self) }, + .ExpandedAcpi => .{ .ExpandedAcpi = @ptrCast(*const AcpiDevicePath.ExpandedAcpiDevicePath, self) }, + .Adr => .{ .Adr = @ptrCast(*const AcpiDevicePath.AdrDevicePath, self) }, + _ => null, }; break :blk if (acpi) |a| .{ .Acpi = a } else null; }, @@ -173,58 +176,92 @@ 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) { -- 2.54.0 From a2a2601da577dd424ea585da0449288a439871fe Mon Sep 17 00:00:00 2001 From: fifty-six Date: Fri, 14 Jan 2022 07:02:34 -0500 Subject: [PATCH 07/14] std/os/uefi: Complete DevicePathProtocol types --- lib/std/os/uefi.zig | 12 + .../uefi/protocols/device_path_protocol.zig | 294 ++++++++++++++++-- 2 files changed, 283 insertions(+), 23 deletions(-) diff --git a/lib/std/os/uefi.zig b/lib/std/os/uefi.zig index 4c034ed45678cf815ffac79371cabe26c4edf6c4..1bceab5b2ace7563205f693287bbd73c0d81fcb7 100644 --- 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, diff --git a/lib/std/os/uefi/protocols/device_path_protocol.zig b/lib/std/os/uefi/protocols/device_path_protocol.zig index 7a31b923ac901a900f4a56037757431b1bd4f1a1..a6509bb14f6b8a12b3292764f44285e34489c29f 100644 --- a/lib/std/os/uefi/protocols/device_path_protocol.zig +++ b/lib/std/os/uefi/protocols/device_path_protocol.zig @@ -265,24 +265,24 @@ pub const AcpiDevicePath = union(Subtype) { }; 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: 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, @@ -305,6 +305,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) { @@ -332,24 +558,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 { @@ -366,19 +612,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 { @@ -396,7 +644,7 @@ pub const MediaDevicePath = union(Subtype) { length: u16, start: u64, end: u64, - disk_type: uefi.Guid, + disk_type: Guid, instance: u16, }; }; -- 2.54.0 From dab4c63684ca951049fb8e8f6b2415857eb6652b Mon Sep 17 00:00:00 2001 From: fifty-six Date: Fri, 14 Jan 2022 08:53:56 -0500 Subject: [PATCH 08/14] std/os/uefi: Refactor getDevicePath() Uses comptime loops over the types instead of writing out a large switch. --- .../uefi/protocols/device_path_protocol.zig | 95 +++++++------------ 1 file changed, 34 insertions(+), 61 deletions(-) diff --git a/lib/std/os/uefi/protocols/device_path_protocol.zig b/lib/std/os/uefi/protocols/device_path_protocol.zig index a6509bb14f6b8a12b3292764f44285e34489c29f..ae5822ba352a242864c602ae2738245deb0b4061 100644 --- a/lib/std/os/uefi/protocols/device_path_protocol.zig +++ b/lib/std/os/uefi/protocols/device_path_protocol.zig @@ -72,66 +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)) { - .Acpi => .{ .Acpi = @ptrCast(*const AcpiDevicePath.BaseAcpiDevicePath, self) }, - .ExpandedAcpi => .{ .ExpandedAcpi = @ptrCast(*const AcpiDevicePath.ExpandedAcpiDevicePath, self) }, - .Adr => .{ .Adr = @ptrCast(*const AcpiDevicePath.AdrDevicePath, self) }, - _ => null, - }; - 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; } }; @@ -268,7 +241,7 @@ pub const MessagingDevicePath = union(Subtype) { Atapi: *const AtapiDevicePath, Scsi: *const ScsiDevicePath, FibreChannel: *const FibreChannelDevicePath, - FibreChannelEx: FibreChannelExDevicePath, + FibreChannelEx: *const FibreChannelExDevicePath, @"1394": *const F1394DevicePath, Usb: *const UsbDevicePath, Sata: *const SataDevicePath, -- 2.54.0 From 4771ac298b0c692750524cb7e94eaf0b4343ce2b Mon Sep 17 00:00:00 2001 From: fifty-six Date: Sun, 16 Jan 2022 01:44:15 -0500 Subject: [PATCH 09/14] std/os/uefi: Simplify packed struct padding and default zero-initialize Beyond adding default zero-initialization, this commit changes undefined initialization to zero, as some cases reserved the padding and on other cases, I've found some systems act strange when giving uninit instead of zero even when it shouldn't be an issue, one example being FileProtocol.Open's attributes, which *should* be ignored when not creating a file, but ended up giving an unrelated error. --- lib/std/os/uefi.zig | 2 -- lib/std/os/uefi/protocols/absolute_pointer_protocol.zig | 8 ++------ lib/std/os/uefi/protocols/edid_override_protocol.zig | 4 +--- lib/std/os/uefi/protocols/hii.zig | 4 ++-- lib/std/os/uefi/protocols/simple_network_protocol.zig | 8 ++------ .../os/uefi/protocols/simple_text_input_ex_protocol.zig | 4 ++-- lib/std/os/uefi/tables/boot_services.zig | 4 +--- 7 files changed, 10 insertions(+), 24 deletions(-) diff --git a/lib/std/os/uefi.zig b/lib/std/os/uefi.zig index 1bceab5b2ace7563205f693287bbd73c0d81fcb7..4644130e7f9a9126845e78d3a897ab01b907063c 100644 --- a/lib/std/os/uefi.zig +++ b/lib/std/os/uefi.zig @@ -98,7 +98,6 @@ pub const Time = extern struct { /// 0 - 59 second: u8, - _pad1: u8, /// 0 - 999999999 nanosecond: u32, @@ -115,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/absolute_pointer_protocol.zig b/lib/std/os/uefi/protocols/absolute_pointer_protocol.zig index ee795692338c3a6ac88e444ed0be43c137d26d6b..11a5008d9a412f9952c5fc40d4619919201d7ccd 100644 --- 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/edid_override_protocol.zig b/lib/std/os/uefi/protocols/edid_override_protocol.zig index 8bf848c59abd7e5ec46aaf1b7166c623ba0a8160..9540cdc5d493a516a486100c73a4529f514d07f5 100644 --- a/lib/std/os/uefi/protocols/edid_override_protocol.zig +++ b/lib/std/os/uefi/protocols/edid_override_protocol.zig @@ -26,7 +26,5 @@ pub const EdidOverrideProtocol = extern struct { pub const EdidOverrideProtocolAttributes = packed struct { dont_override: bool, 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 index 5e3c23d22ab810bfa0eaedb3c2e2bf029216e762..b0b0418611b88112bc2b4bc515f7195737ef4ab2 100644 --- 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 index 01e5986c2d077b34b1d26497c54aad5b5d3ccbcc..283d944d3498bfb33ce320c00881e8c3a5418fcd 100644 --- 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 index d816deb8cbfc064a8fe379b6c2efc39a7c3acc87..fbcebf1121342ecd454f343095702beeeb72bd45 100644 --- 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/tables/boot_services.zig b/lib/std/os/uefi/tables/boot_services.zig index 7da007b05dc19217c9b5bdb8980c8289a5099733..468aaf4cf7fb3f7a9055a83aa59b9800d8c64b2a 100644 --- a/lib/std/os/uefi/tables/boot_services.zig +++ b/lib/std/os/uefi/tables/boot_services.zig @@ -239,9 +239,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 { -- 2.54.0 From d276a1189de15f85523a0e6844d0fd316306838a Mon Sep 17 00:00:00 2001 From: fifty-six Date: Sun, 16 Jan 2022 01:50:02 -0500 Subject: [PATCH 10/14] std/os/uefi: Align first field of EdidOverrideProtocolAttributes to 4 This makes the struct align(4), which allows it to be passed as flags more easily. --- lib/std/os/uefi/protocols/edid_override_protocol.zig | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/lib/std/os/uefi/protocols/edid_override_protocol.zig b/lib/std/os/uefi/protocols/edid_override_protocol.zig index 9540cdc5d493a516a486100c73a4529f514d07f5..800c269c67203e73dbc1e636c533296231bca123 100644 --- a/lib/std/os/uefi/protocols/edid_override_protocol.zig +++ b/lib/std/os/uefi/protocols/edid_override_protocol.zig @@ -8,7 +8,6 @@ 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); } @@ -24,7 +23,7 @@ pub const EdidOverrideProtocol = extern struct { }; pub const EdidOverrideProtocolAttributes = packed struct { - dont_override: bool, + dont_override: bool align(4), enable_hot_plug: bool, _pad: u30 = 0, }; -- 2.54.0 From 628a7f85deb500624fb75f83014d3bc1a1c03cf4 Mon Sep 17 00:00:00 2001 From: fifty-six Date: Sun, 16 Jan 2022 02:35:22 -0500 Subject: [PATCH 11/14] std/os/uefi: Add conversion from Status to EfiError Allows handling uefi function errors in a more zig-style way with try and catch, using `try f().err()` when a `Status` is returned. --- lib/std/os/uefi/status.zig | 69 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 69 insertions(+) diff --git a/lib/std/os/uefi/status.zig b/lib/std/os/uefi/status.zig index 09bc5030eb71e5c8ccb53802c32aaefeae6098c6..e6f2024f7db76683e15c6477ea551aa3e322236c 100644 --- 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,71 @@ 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, + WarnUnknownGlyph, + WarnDeleteFailure, + WarnWriteFailure, + WarnBufferTooSmall, + WarnStaleData, + WarnFileSystem, + WarnResetRequired, + }; + + 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 + } }; + +test "status" { + var st: Status = .DeviceError; + try testing.expectError(error.DeviceError, st.err()); + + st = .Success; + try st.err(); +} -- 2.54.0 From c727bd1bb68917f39f03f68765c5db7572069729 Mon Sep 17 00:00:00 2001 From: fifty-six Date: Sun, 16 Jan 2022 02:52:45 -0500 Subject: [PATCH 12/14] std/os/uefi: Fix parameter type mismatch in edid_override_protocol --- lib/std/os/uefi/protocols/edid_override_protocol.zig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/std/os/uefi/protocols/edid_override_protocol.zig b/lib/std/os/uefi/protocols/edid_override_protocol.zig index 800c269c67203e73dbc1e636c533296231bca123..3eb39330f471e1f5e04835dd9bda7f577cd17e75 100644 --- a/lib/std/os/uefi/protocols/edid_override_protocol.zig +++ b/lib/std/os/uefi/protocols/edid_override_protocol.zig @@ -9,7 +9,7 @@ pub const EdidOverrideProtocol = extern struct { /// Returns policy information and potentially a replacement EDID for the specified video output device. 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{ -- 2.54.0 From 03347114c3e5f6238d7871e878e1d2295bdf0260 Mon Sep 17 00:00:00 2001 From: fifty-six Date: Sun, 16 Jan 2022 03:04:37 -0500 Subject: [PATCH 13/14] std/os/uefi: Add util function for opening protocols --- lib/std/os/uefi/tables/boot_services.zig | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/lib/std/os/uefi/tables/boot_services.zig b/lib/std/os/uefi/tables/boot_services.zig index 468aaf4cf7fb3f7a9055a83aa59b9800d8c64b2a..ee1e72f09400499e57b22e60f5cec9fab5a2b17d 100644 --- a/lib/std/os/uefi/tables/boot_services.zig +++ b/lib/std/os/uefi/tables/boot_services.zig @@ -154,6 +154,27 @@ pub const BootServices = extern struct { /// 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 event_timer: u32 = 0x80000000; -- 2.54.0 From ff6ece3811a1cb44a90986d543d1583a40629edf Mon Sep 17 00:00:00 2001 From: fifty-six Date: Sun, 16 Jan 2022 03:50:50 -0500 Subject: [PATCH 14/14] std/os/uefi: Don't treat efi status warnings as errors --- lib/std/os/uefi/status.zig | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/lib/std/os/uefi/status.zig b/lib/std/os/uefi/status.zig index e6f2024f7db76683e15c6477ea551aa3e322236c..e975b92a150d06b30ea189f257485d87e19f1a75 100644 --- a/lib/std/os/uefi/status.zig +++ b/lib/std/os/uefi/status.zig @@ -183,13 +183,6 @@ pub const Status = enum(usize) { ConnectionFin, ConnectionReset, ConnectionRefused, - WarnUnknownGlyph, - WarnDeleteFailure, - WarnWriteFailure, - WarnBufferTooSmall, - WarnStaleData, - WarnFileSystem, - WarnResetRequired, }; pub fn err(self: Status) EfiError!void { @@ -198,7 +191,7 @@ pub const Status = enum(usize) { return @field(EfiError, efi_err.name); } } - // self is .Success + // self is .Success or Warning } }; -- 2.54.0