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};