1const std = @import("std");
2const uefi = std.os.uefi;
3const Status = uefi.Status;
4const cc = uefi.cc;
5
6pub const BlockIo = extern struct {
7 const Self = @This();
8
9 revision: u64,
10 media: *BlockMedia,
11
12 _reset: *const fn (*BlockIo, extended_verification: bool) callconv(cc) Status,
13 _read_blocks: *const fn (*BlockIo, media_id: u32, lba: u64, buffer_size: usize, buf: [*]u8) callconv(cc) Status,
14 _write_blocks: *const fn (*BlockIo, media_id: u32, lba: u64, buffer_size: usize, buf: [*]const u8) callconv(cc) Status,
15 _flush_blocks: *const fn (*BlockIo) callconv(cc) Status,
16
17 pub const ResetError = uefi.UnexpectedError || error{DeviceError};
18 pub const ReadBlocksError = uefi.UnexpectedError || error{
19 DeviceError,
20 NoMedia,
21 BadBufferSize,
22 InvalidParameter,
23 };
24 pub const WriteBlocksError = uefi.UnexpectedError || error{
25 WriteProtected,
26 NoMedia,
27 MediaChanged,
28 DeviceError,
29 BadBufferSize,
30 InvalidParameter,
31 };
32 pub const FlushBlocksError = uefi.UnexpectedError || error{
33 DeviceError,
34 NoMedia,
35 };
36
37 /// Resets the block device hardware.
38 pub fn reset(self: *Self, extended_verification: bool) ResetError!void {
39 switch (self._reset(self, extended_verification)) {
40 .success => {},
41 .device_error => return error.DeviceError,
42 else => |status| return uefi.unexpectedStatus(status),
43 }
44 }
45
46 /// Reads the number of requested blocks from the device.
47 pub fn readBlocks(self: *Self, media_id: u32, lba: u64, buf: []u8) ReadBlocksError!void {
48 switch (self._read_blocks(self, media_id, lba, buf.len, buf.ptr)) {
49 .success => {},
50 .device_error => return error.DeviceError,
51 .no_media => return error.NoMedia,
52 .bad_buffer_size => return error.BadBufferSize,
53 .invalid_parameter => return error.InvalidParameter,
54 else => |status| return uefi.unexpectedStatus(status),
55 }
56 }
57
58 /// Writes a specified number of blocks to the device.
59 pub fn writeBlocks(self: *Self, media_id: u32, lba: u64, buf: []const u8) WriteBlocksError!void {
60 switch (self._write_blocks(self, media_id, lba, buf.len, buf.ptr)) {
61 .success => {},
62 .write_protected => return error.WriteProtected,
63 .no_media => return error.NoMedia,
64 .media_changed => return error.MediaChanged,
65 .device_error => return error.DeviceError,
66 .bad_buffer_size => return error.BadBufferSize,
67 .invalid_parameter => return error.InvalidParameter,
68 else => |status| return uefi.unexpectedStatus(status),
69 }
70 }
71
72 /// Flushes all modified data to a physical block device.
73 pub fn flushBlocks(self: *Self) FlushBlocksError!void {
74 switch (self._flush_blocks(self)) {
75 .success => {},
76 .device_error => return error.DeviceError,
77 .no_media => return error.NoMedia,
78 else => |status| return uefi.unexpectedStatus(status),
79 }
80 }
81
82 pub const guid align(8) = uefi.Guid{
83 .time_low = 0x964e5b21,
84 .time_mid = 0x6459,
85 .time_high_and_version = 0x11d2,
86 .clock_seq_high_and_reserved = 0x8e,
87 .clock_seq_low = 0x39,
88 .node = [_]u8{ 0x00, 0xa0, 0xc9, 0x69, 0x72, 0x3b },
89 };
90
91 pub const BlockMedia = extern struct {
92 /// The current media ID. If the media changes, this value is changed.
93 media_id: u32,
94
95 /// `true` if the media is removable; otherwise, `false`.
96 removable_media: bool,
97 /// `true` if there is a media currently present in the device
98 media_present: bool,
99 /// `true` if the `BlockIo` was produced to abstract
100 /// partition structures on the disk. `false` if the `BlockIo` was
101 /// produced to abstract the logical blocks on a hardware device.
102 logical_partition: bool,
103 /// `true` if the media is marked read-only otherwise, `false`. This field
104 /// shows the read-only status as of the most recent `WriteBlocks()`
105 read_only: bool,
106 /// `true` if the WriteBlocks() function caches write data.
107 write_caching: bool,
108
109 /// The intrinsic block size of the device. If the media changes, then this
110 // field is updated. Returns the number of bytes per logical block.
111 block_size: u32,
112 /// Supplies the alignment requirement for any buffer used in a data
113 /// transfer. IoAlign values of 0 and 1 mean that the buffer can be
114 /// placed anywhere in memory. Otherwise, IoAlign must be a power of
115 /// 2, and the requirement is that the start address of a buffer must be
116 /// evenly divisible by IoAlign with no remainder.
117 io_align: u32,
118 /// The last LBA on the device. If the media changes, then this field is updated.
119 last_block: u64,
120
121 // Revision 2
122 lowest_aligned_lba: u64,
123 logical_blocks_per_physical_block: u32,
124 optimal_transfer_length_granularity: u32,
125 };
126};