| 1 | const std = @import("std"); |
| 2 | const uefi = std.os.uefi; |
| 3 | const Status = uefi.Status; |
| 4 | const cc = uefi.cc; |
| 5 | |
| 6 | pub 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 | }; |