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