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}