uefi_raw/protocol/
scsi.rs

1// SPDX-License-Identifier: MIT OR Apache-2.0
2
3use super::device_path::DevicePathProtocol;
4use crate::{guid, Event, Guid, Status};
5use core::ffi::c_void;
6
7pub const SCSI_TARGET_MAX_BYTES: usize = 0x10;
8
9newtype_enum! {
10    /// Corresponds to the `EFI_SCSI_IO_TYPE_*` defines.
11    #[derive(Default)]
12    pub enum ScsiIoType: u8  => {
13        DISK = 0x00,
14        TAPE = 0x01,
15        PRINTER = 0x02,
16        PROCESSOR = 0x03,
17        WRITE_ONCE_READ_MULTIPLE = 0x04,
18        CDROM = 0x05,
19        SCANNER = 0x06,
20        OPTICAL = 0x07,
21        MEDIUM_CHANGER = 0x08,
22        COMMUNICATION = 0x09,
23        RAID = 0x0c,
24        ENCLOSURE_SERVICES = 0x0d,
25        REDUCED_BLOCK_COMMANDS = 0x0e,
26        OPTICAL_CARD_READER_WRITER = 0x0f,
27        BRIDGE_CONTROLLER = 0x10,
28        OBJECT_BASED_STORAGE = 0x11,
29        RESERVED_LOW = 0x12,
30        RESERVED_HIGH = 0x1e,
31        UNKNOWN = 0x1f,
32    }
33}
34
35newtype_enum! {
36    /// Corresponds to the `EFI_SCSI_IO_DATA_DIRECTION_*` defines.
37    #[derive(Default)]
38    pub enum ScsiIoDataDirection: u8 => {
39        READ = 0,
40        WRITE = 1,
41        BIDIRECTIONAL = 2,
42    }
43}
44
45newtype_enum! {
46    /// Corresponds to the `EFI_SCSI_IO_STATUS_HOST_ADAPTER_*` defines.
47    #[derive(Default)]
48    pub enum ScsiIoHostAdapterStatus: u8 => {
49       OK = 0x00,
50       TIMEOUT_COMMAND = 0x09,
51       TIMEOUT = 0x0b,
52       MESSAGE_REJECT = 0x0d,
53       BUS_RESET = 0x0e,
54       PARITY_ERROR = 0x0f,
55       REQUEST_SENSE_FAILED = 0x10,
56       SELECTION_TIMEOUT = 0x11,
57       DATA_OVERRUN_UNDERRUN = 0x12,
58       BUS_FREE = 0x13,
59       PHASE_ERROR = 0x14,
60       OTHER = 0x7f,
61    }
62}
63
64newtype_enum! {
65    /// Corresponds to the `EFI_SCSI_IO_STATUS_TARGET_*` defines.
66    #[derive(Default)]
67    pub enum ScsiIoTargetStatus: u8 => {
68        GOOD = 0x00,
69        CHECK_CONDITION = 0x02,
70        CONDITION_MET = 0x04,
71        BUSY = 0x08,
72        INTERMEDIATE = 0x10,
73        INTERMEDIATE_CONDITION_MET = 0x14,
74        RESERVATION_CONFLICT = 0x18,
75        COMMAND_TERMINATED = 0x22,
76        QUEUE_FULL = 0x28,
77    }
78}
79
80#[derive(Debug, Copy, Clone)]
81#[repr(C)]
82pub struct ScsiIoScsiRequestPacket {
83    /// The timeout, in 100 ns units, for the execution of this SCSI Request Packet.
84    ///
85    /// A `timeout` value of 0 indicates that the function will wait indefinitely for
86    /// the execution to complete. If the execution time exceeds the specified `timeout`
87    /// (greater than 0), the function will return `EFI_TIMEOUT`.
88    pub timeout: u64,
89
90    /// A pointer to the data buffer for reading from the device in read and bidirectional commands.
91    ///
92    /// - For write and non-data commands where `in_transfer_length` is 0, this field is optional and may be `NULL`.
93    /// - If not `NULL`, the buffer must meet the alignment requirement specified by the `IoAlign` field
94    ///   in the `EFI_EXT_SCSI_PASS_THRU_MODE` structure.
95    pub in_data_buffer: *mut c_void,
96
97    /// A pointer to the data buffer for writing to the device in write and bidirectional commands.
98    ///
99    /// - For read and non-data commands where `out_transfer_length` is 0, this field is optional and may be `NULL`.
100    /// - If not `NULL`, the buffer must meet the alignment requirement specified by the `IoAlign` field
101    ///   in the `EFI_EXT_SCSI_PASS_THRU_MODE` structure.
102    pub out_data_buffer: *mut c_void,
103
104    /// A pointer to the sense data generated during execution of the SCSI Request Packet.
105    ///
106    /// - If `sense_data_length` is 0, this field is optional and may be `NULL`.
107    /// - It is recommended to allocate a buffer of at least 252 bytes to ensure the entire sense data can be captured.
108    /// - If not `NULL`, the buffer must meet the alignment requirement specified by the `IoAlign` field
109    ///   in the `EFI_EXT_SCSI_PASS_THRU_MODE` structure.
110    pub sense_data: *mut c_void,
111
112    /// A pointer to the Command Data Block (CDB) buffer to be sent to the SCSI device.
113    ///
114    /// The CDB contains the SCSI command to be executed by the device.
115    pub cdb: *mut c_void,
116
117    /// The input size (in bytes) of the `in_data_buffer`, and the number of bytes transferred on output.
118    ///
119    /// - On input: Specifies the size of `in_data_buffer`.
120    /// - On output: Specifies the number of bytes successfully transferred.
121    /// - If the size exceeds the controller's capability, no data is transferred, the field is updated
122    ///   with the number of transferable bytes, and `EFI_BAD_BUFFER_SIZE` is returned.
123    pub in_transfer_length: u32,
124
125    /// The input size (in bytes) of the `out_data_buffer`, and the number of bytes transferred on output.
126    ///
127    /// - On input: Specifies the size of `out_data_buffer`.
128    /// - On output: Specifies the number of bytes successfully transferred.
129    /// - If the size exceeds the controller's capability, no data is transferred, the field is updated
130    ///   with the number of transferable bytes, and `EFI_BAD_BUFFER_SIZE` is returned.
131    pub out_transfer_length: u32,
132
133    /// The length (in bytes) of the Command Data Block (CDB).
134    ///
135    /// Standard values for CDB length are typically 6, 10, 12, or 16 bytes. Other values are possible
136    /// for variable-length CDBs.
137    pub cdb_length: u8,
138
139    /// The direction of data transfer for the SCSI Request Packet.
140    pub data_direction: ScsiIoDataDirection,
141
142    /// The status of the host adapter when the SCSI Request Packet was executed.
143    pub host_adapter_status: ScsiIoHostAdapterStatus,
144
145    /// The status of the target device when the SCSI Request Packet was executed.
146    pub target_status: ScsiIoTargetStatus,
147
148    /// The size (in bytes) of the `sense_data` buffer on input, and the number of bytes written on output.
149    ///
150    /// - On input: Specifies the size of the `sense_data` buffer.
151    /// - On output: Specifies the number of bytes written to the buffer.
152    pub sense_data_length: u8,
153}
154
155#[derive(Debug)]
156#[repr(C)]
157pub struct ScsiIoProtocol {
158    pub get_device_type:
159        unsafe extern "efiapi" fn(this: *const Self, device_type: *mut ScsiIoType) -> Status,
160    pub get_device_location:
161        unsafe extern "efiapi" fn(this: *const Self, target: *mut *mut u8, lun: *mut u64) -> Status,
162    pub reset_bus: unsafe extern "efiapi" fn(this: *mut Self) -> Status,
163    pub reset_device: unsafe extern "efiapi" fn(this: *mut Self) -> Status,
164    pub execute_scsi_command: unsafe extern "efiapi" fn(
165        this: *const Self,
166        packet: *mut ScsiIoScsiRequestPacket,
167        event: Event,
168    ) -> Status,
169    pub io_align: u32,
170}
171
172impl ScsiIoProtocol {
173    pub const GUID: Guid = guid!("932f47e6-2362-4002-803e-3cd54b138f85");
174}
175
176#[derive(Clone, Debug)]
177#[repr(C)]
178pub struct ExtScsiPassThruMode {
179    pub adapter_id: u32,
180    pub attributes: u32,
181    pub io_align: u32,
182}
183
184#[derive(Debug)]
185#[repr(C)]
186pub struct ExtScsiPassThruProtocol {
187    pub passthru_mode: *const ExtScsiPassThruMode,
188    pub pass_thru: unsafe extern "efiapi" fn(
189        this: *mut Self,
190        target: *const u8,
191        lun: u64,
192        packet: *mut ScsiIoScsiRequestPacket,
193        event: Event,
194    ) -> Status,
195    pub get_next_target_lun:
196        unsafe extern "efiapi" fn(this: *const Self, target: *mut *mut u8, lun: *mut u64) -> Status,
197    pub build_device_path: unsafe extern "efiapi" fn(
198        this: *const Self,
199        target: *const u8,
200        lun: u64,
201        device_path: *mut *const DevicePathProtocol,
202    ) -> Status,
203    pub get_target_lun: unsafe extern "efiapi" fn(
204        this: *const Self,
205        device_path: *const DevicePathProtocol,
206        target: *mut *const u8,
207        lun: *mut u64,
208    ) -> Status,
209    pub reset_channel: unsafe extern "efiapi" fn(this: *mut Self) -> Status,
210    pub reset_target_lun:
211        unsafe extern "efiapi" fn(this: *mut Self, target: *const u8, lun: u64) -> Status,
212    pub get_next_target:
213        unsafe extern "efiapi" fn(this: *const Self, target: *mut *mut u8) -> Status,
214}
215
216impl ExtScsiPassThruProtocol {
217    pub const GUID: Guid = guid!("143b7632-b81b-4cb7-abd3-b625a5b9bffe");
218}