Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

std.os.uefi.protocol: ziggify function signatures #23214

Open
wants to merge 24 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
29c91b7
std.os.uefi.protocol: ziggify function signatures
dotcarmen Mar 11, 2025
da26164
address some feedback
dotcarmen Mar 13, 2025
7c21d60
explicit error unions
dotcarmen Mar 13, 2025
3e1aea5
finish unexpectedErr -> unexpectedStatus
dotcarmen Mar 15, 2025
5938b73
use undefined and null-unwrap in getEdid
dotcarmen Mar 15, 2025
65b98d3
some more signature updates
dotcarmen Mar 15, 2025
6fc4b2b
a few fixes
dotcarmen Mar 15, 2025
abf2b0c
almost there...
dotcarmen Mar 16, 2025
f535ed9
finished initial implementations
dotcarmen Mar 17, 2025
c2dadaf
various changes from self-review
dotcarmen Mar 17, 2025
a7b3533
File.open - typed `mode` and `create_attributes` args
dotcarmen Mar 17, 2025
08653d2
CreateAttributes => Attributes
dotcarmen Mar 17, 2025
3a558f8
more updates to ip6
dotcarmen Mar 17, 2025
60f6778
proper simple_text_output attribute type
dotcarmen Mar 17, 2025
0b2eb4c
more nitty gritty mcpicky
dotcarmen Mar 17, 2025
5221eec
oops, foreground bright and darkgray are the same
dotcarmen Mar 17, 2025
a40d2bf
compiler error fixes
dotcarmen Mar 17, 2025
78b46ae
quick code review fixes
dotcarmen Mar 18, 2025
c55e1e7
historical typing error
dotcarmen Mar 18, 2025
063f431
move file info stuff to file.zig
dotcarmen Mar 18, 2025
4bc3d97
nicky mcpickwickitty
dotcarmen Mar 18, 2025
dc2df7c
typed File.getInfo and setInfo
dotcarmen Mar 18, 2025
478bae7
typed Ip6Config.getData and setData
dotcarmen Mar 18, 2025
5205b19
DevicePath.next should return null if the next node is the end
dotcarmen Mar 19, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
66 changes: 13 additions & 53 deletions lib/std/os/uefi.zig
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,11 @@ pub const Ipv6Address = extern struct {
address: [16]u8,
};

pub const IpAddress = extern union {
v4: Ipv4Address,
v6: Ipv6Address,
};

/// GUIDs are align(8) unless otherwise specified.
pub const Guid = extern struct {
time_low: u32,
Expand Down Expand Up @@ -190,60 +195,15 @@ test "GUID formatting" {
try std.testing.expect(std.mem.eql(u8, str, "32cb3c89-8080-427c-ba13-5049873bc287"));
}

pub const FileInfo = extern struct {
size: u64,
file_size: u64,
physical_size: u64,
create_time: Time,
last_access_time: Time,
modification_time: Time,
attribute: u64,

pub fn getFileName(self: *const FileInfo) [*:0]const u16 {
return @ptrCast(@alignCast(@as([*]const u8, @ptrCast(self)) + @sizeOf(FileInfo)));
}

pub const efi_file_read_only: u64 = 0x0000000000000001;
pub const efi_file_hidden: u64 = 0x0000000000000002;
pub const efi_file_system: u64 = 0x0000000000000004;
pub const efi_file_reserved: u64 = 0x0000000000000008;
pub const efi_file_directory: u64 = 0x0000000000000010;
pub const efi_file_archive: u64 = 0x0000000000000020;
pub const efi_file_valid_attr: u64 = 0x0000000000000037;

pub const guid align(8) = Guid{
.time_low = 0x09576e92,
.time_mid = 0x6d3f,
.time_high_and_version = 0x11d2,
.clock_seq_high_and_reserved = 0x8e,
.clock_seq_low = 0x39,
.node = [_]u8{ 0x00, 0xa0, 0xc9, 0x69, 0x72, 0x3b },
};
};

pub const FileSystemInfo = extern struct {
size: u64,
read_only: bool,
volume_size: u64,
free_space: u64,
block_size: u32,
_volume_label: u16,

pub fn getVolumeLabel(self: *const FileSystemInfo) [*:0]const u16 {
return @as([*:0]const u16, @ptrCast(&self._volume_label));
}

pub const guid align(8) = Guid{
.time_low = 0x09576e93,
.time_mid = 0x6d3f,
.time_high_and_version = 0x11d2,
.clock_seq_high_and_reserved = 0x8e,
.clock_seq_low = 0x39,
.node = [_]u8{ 0x00, 0xa0, 0xc9, 0x69, 0x72, 0x3b },
};
};

test {
_ = tables;
_ = protocol;
}

pub const UnexpectedError = error{Unexpected};

pub fn unexpectedStatus(status: Status) UnexpectedError {
// TODO: debug printing the encountered error? maybe handle warnings?
_ = status;
return error.Unexpected;
}
23 changes: 21 additions & 2 deletions lib/std/os/uefi/protocol.zig
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
const std = @import("std");
const uefi = std.os.uefi;

pub const ServiceBinding = @import("protocol/service_binding.zig").ServiceBinding;

pub const LoadedImage = @import("protocol/loaded_image.zig").LoadedImage;
pub const DevicePath = @import("protocol/device_path.zig").DevicePath;
pub const Rng = @import("protocol/rng.zig").Rng;
Expand All @@ -23,11 +28,25 @@ pub const edid = @import("protocol/edid.zig");
pub const SimpleNetwork = @import("protocol/simple_network.zig").SimpleNetwork;
pub const ManagedNetwork = @import("protocol/managed_network.zig").ManagedNetwork;

pub const Ip6ServiceBinding = @import("protocol/ip6_service_binding.zig").Ip6ServiceBinding;
pub const Ip6ServiceBinding = ServiceBinding(.{
.time_low = 0xec835dd3,
.time_mid = 0xfe0f,
.time_high_and_version = 0x617b,
.clock_seq_high_and_reserved = 0xa6,
.clock_seq_low = 0x21,
.node = [_]u8{ 0xb3, 0x50, 0xc3, 0xe1, 0x33, 0x88 },
});
pub const Ip6 = @import("protocol/ip6.zig").Ip6;
pub const Ip6Config = @import("protocol/ip6_config.zig").Ip6Config;

pub const Udp6ServiceBinding = @import("protocol/udp6_service_binding.zig").Udp6ServiceBinding;
pub const Udp6ServiceBinding = ServiceBinding(.{
.time_low = 0x66ed4721,
.time_mid = 0x3c98,
.time_high_and_version = 0x4d3e,
.clock_seq_high_and_reserved = 0x81,
.clock_seq_low = 0xe3,
.node = [_]u8{ 0xd0, 0x3d, 0xd3, 0x9a, 0x72, 0x54 },
});
pub const Udp6 = @import("protocol/udp6.zig").Udp6;

pub const HiiDatabase = @import("protocol/hii_database.zig").HiiDatabase;
Expand Down
24 changes: 19 additions & 5 deletions lib/std/os/uefi/protocol/absolute_pointer.zig
Original file line number Diff line number Diff line change
Expand Up @@ -4,22 +4,36 @@ const Event = uefi.Event;
const Guid = uefi.Guid;
const Status = uefi.Status;
const cc = uefi.cc;
const Error = Status.Error;

/// Protocol for touchscreens.
pub const AbsolutePointer = extern struct {
_reset: *const fn (*const AbsolutePointer, bool) callconv(cc) Status,
_reset: *const fn (*AbsolutePointer, bool) callconv(cc) Status,
_get_state: *const fn (*const AbsolutePointer, *State) callconv(cc) Status,
wait_for_input: Event,
mode: *Mode,

pub const ResetError = uefi.UnexpectedError || error{DeviceError};
pub const GetStateError = uefi.UnexpectedError || error{ NotReady, DeviceError };

/// Resets the pointer device hardware.
pub fn reset(self: *const AbsolutePointer, verify: bool) Status {
return self._reset(self, verify);
pub fn reset(self: *AbsolutePointer, verify: bool) ResetError!void {
switch (self._reset(self, verify)) {
.success => {},
.device_error => return Error.DeviceError,
else => |status| return uefi.unexpectedStatus(status),
}
}

/// Retrieves the current state of a pointer device.
pub fn getState(self: *const AbsolutePointer, state: *State) Status {
return self._get_state(self, state);
pub fn getState(self: *const AbsolutePointer) GetStateError!State {
var state: State = undefined;
switch (self._get_state(self, &state)) {
.success => return state,
.not_ready => return Error.NotReady,
.device_error => return Error.DeviceError,
else => |status| return uefi.unexpectedStatus(status),
}
}

pub const guid align(8) = Guid{
Expand Down
64 changes: 55 additions & 9 deletions lib/std/os/uefi/protocol/block_io.zig
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ const std = @import("std");
const uefi = std.os.uefi;
const Status = uefi.Status;
const cc = uefi.cc;
const Error = Status.Error;

pub const BlockIo = extern struct {
const Self = @This();
Expand All @@ -11,27 +12,72 @@ pub const BlockIo = extern struct {

_reset: *const fn (*BlockIo, extended_verification: bool) callconv(cc) Status,
_read_blocks: *const fn (*BlockIo, media_id: u32, lba: u64, buffer_size: usize, buf: [*]u8) callconv(cc) Status,
_write_blocks: *const fn (*BlockIo, media_id: u32, lba: u64, buffer_size: usize, buf: [*]u8) callconv(cc) Status,
_write_blocks: *const fn (*BlockIo, media_id: u32, lba: u64, buffer_size: usize, buf: [*]const u8) callconv(cc) Status,
_flush_blocks: *const fn (*BlockIo) callconv(cc) Status,

pub const ResetError = uefi.UnexpectedError || error{DeviceError};
pub const ReadBlocksError = uefi.UnexpectedError || error{
DeviceError,
NoMedia,
BadBufferSize,
InvalidParameter,
};
pub const WriteBlocksError = uefi.UnexpectedError || error{
WriteProtected,
NoMedia,
MediaChanged,
DeviceError,
BadBufferSize,
InvalidParameter,
};
pub const FlushBlocksError = uefi.UnexpectedError || error{
DeviceError,
NoMedia,
};

/// Resets the block device hardware.
pub fn reset(self: *Self, extended_verification: bool) Status {
return self._reset(self, extended_verification);
pub fn reset(self: *Self, extended_verification: bool) ResetError!void {
switch (self._reset(self, extended_verification)) {
.success => {},
.device_error => return Error.DeviceError,
else => |status| return uefi.unexpectedStatus(status),
}
}

/// Reads the number of requested blocks from the device.
pub fn readBlocks(self: *Self, media_id: u32, lba: u64, buffer_size: usize, buf: [*]u8) Status {
return self._read_blocks(self, media_id, lba, buffer_size, buf);
pub fn readBlocks(self: *Self, media_id: u32, lba: u64, buf: []u8) ReadBlocksError!void {
switch (self._read_blocks(self, media_id, lba, buf.len, buf.ptr)) {
.success => {},
.device_error => return Error.DeviceError,
.no_media => return Error.NoMedia,
.bad_buffer_size => return Error.BadBufferSize,
.invalid_parameter => return Error.InvalidParameter,
else => |status| return uefi.unexpectedStatus(status),
}
}

/// Writes a specified number of blocks to the device.
pub fn writeBlocks(self: *Self, media_id: u32, lba: u64, buffer_size: usize, buf: [*]u8) Status {
return self._write_blocks(self, media_id, lba, buffer_size, buf);
pub fn writeBlocks(self: *Self, media_id: u32, lba: u64, buf: []const u8) WriteBlocksError!void {
switch (self._write_blocks(self, media_id, lba, buf.len, buf.ptr)) {
.success => {},
.write_protected => return Error.WriteProtected,
.no_media => return Error.NoMedia,
.media_changed => return Error.MediaChanged,
.device_error => return Error.DeviceError,
.bad_buffer_size => return Error.BadBufferSize,
.invalid_parameter => return Error.InvalidParameter,
else => |status| return uefi.unexpectedStatus(status),
}
}

/// Flushes all modified data to a physical block device.
pub fn flushBlocks(self: *Self) Status {
return self._flush_blocks(self);
pub fn flushBlocks(self: *Self) FlushBlocksError!void {
switch (self._flush_blocks(self)) {
.success => {},
.device_error => return Error.DeviceError,
.no_media => return Error.NoMedia,
else => |status| return uefi.unexpectedStatus(status),
}
}

pub const guid align(8) = uefi.Guid{
Expand Down
20 changes: 14 additions & 6 deletions lib/std/os/uefi/protocol/device_path.zig
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ pub const DevicePath = extern struct {
subtype: u8,
length: u16 align(1),

pub const CreateFileDevicePathError = Allocator.Error;

pub const guid align(8) = Guid{
.time_low = 0x09576e91,
.time_mid = 0x6d3f,
Expand All @@ -23,15 +25,17 @@ pub const DevicePath = extern struct {
};

/// Returns the next DevicePath node in the sequence, if any.
pub fn next(self: *DevicePath) ?*DevicePath {
if (self.type == .end and @as(uefi.DevicePath.End.Subtype, @enumFromInt(self.subtype)) == .end_entire)
pub fn next(self: *const DevicePath) ?*const DevicePath {
const bytes: [*]const u8 = @ptrCast(self);
const next_node: *const DevicePath = @ptrCast(bytes + self.length);
if (next_node.type == .end and @as(uefi.DevicePath.End.Subtype, @enumFromInt(self.subtype)) == .end_entire)
return null;

return @as(*DevicePath, @ptrCast(@as([*]u8, @ptrCast(self)) + self.length));
return next_node;
}

/// Calculates the total length of the device path structure in bytes, including the end of device path node.
pub fn size(self: *DevicePath) usize {
pub fn size(self: *const DevicePath) usize {
var node = self;

while (node.next()) |next_node| {
Expand All @@ -42,7 +46,11 @@ pub const DevicePath = extern struct {
}

/// Creates a file device path from the existing device path and a file path.
pub fn create_file_device_path(self: *DevicePath, allocator: Allocator, path: [:0]align(1) const u16) !*DevicePath {
pub fn createFileDevicePath(
self: *const DevicePath,
allocator: Allocator,
path: []const u16,
) CreateFileDevicePathError!*const DevicePath {
const path_size = self.size();

// 2 * (path.len + 1) for the path and its null terminator, which are u16s
Expand All @@ -67,7 +75,7 @@ pub const DevicePath = extern struct {

ptr[path.len] = 0;

var end = @as(*uefi.DevicePath.End.EndEntireDevicePath, @ptrCast(@as(*DevicePath, @ptrCast(new)).next().?));
var end = @as(*uefi.DevicePath.End.EndEntireDevicePath, @ptrCast(@constCast(@as(*DevicePath, @ptrCast(new)).next().?)));
end.type = .end;
end.subtype = .end_entire;
end.length = @sizeOf(uefi.DevicePath.End.EndEntireDevicePath);
Expand Down
34 changes: 25 additions & 9 deletions lib/std/os/uefi/protocol/edid.zig
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ const Guid = uefi.Guid;
const Handle = uefi.Handle;
const Status = uefi.Status;
const cc = uefi.cc;
const Error = Status.Error;

/// EDID information for an active video output device
pub const Active = extern struct {
Expand Down Expand Up @@ -37,17 +38,27 @@ pub const Discovered = extern struct {

/// Override EDID information
pub const Override = extern struct {
_get_edid: *const fn (*const Override, Handle, *Attributes, *usize, *?[*]u8) callconv(cc) Status,
_get_edid: *const fn (*const Override, *const Handle, *Attributes, *usize, *?[*]u8) callconv(cc) Status,

pub const GetEdidError = uefi.UnexpectedError || error{
Unsupported,
};

/// Returns policy information and potentially a replacement EDID for the specified video output device.
pub fn getEdid(
self: *const Override,
handle: Handle,
attributes: *Attributes,
edid_size: *usize,
edid: *?[*]u8,
) Status {
return self._get_edid(self, handle, attributes, edid_size, edid);
pub fn getEdid(self: *const Override, handle: Handle) GetEdidError!Edid {
var size: usize = undefined;
var ptr: ?[*]u8 = undefined;
var attributes: Attributes = undefined;
switch (self._get_edid(self, &handle, &attributes, &size, &ptr)) {
.success => {},
.unsupported => return Error.Unsupported,
else => |status| return uefi.unexpectedStatus(status),
}

return .{
.attributes = attributes,
.edid = if (ptr) |p| p[0..size] else null,
};
}

pub const guid align(8) = Guid{
Expand All @@ -59,6 +70,11 @@ pub const Override = extern struct {
.node = [_]u8{ 0xf4, 0x58, 0xfe, 0x04, 0x0b, 0xd5 },
};

pub const Edid = struct {
attributes: Attributes,
edid: ?[]u8,
};

pub const Attributes = packed struct(u32) {
dont_override: bool,
enable_hot_plug: bool,
Expand Down
Loading
Loading