Skip to content
Draft
Show file tree
Hide file tree
Changes from 6 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions uefi-raw/src/protocol/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,4 +16,5 @@ pub mod memory_protection;
pub mod misc;
pub mod network;
pub mod rng;
pub mod scsi;
pub mod shell_params;
326 changes: 326 additions & 0 deletions uefi-raw/src/protocol/scsi.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,326 @@
use core::ffi::c_void;

use bitflags::bitflags;

use crate::protocol::device_path::DevicePathProtocol;
use crate::{guid, Event, Guid, Status};

bitflags! {
/// DataDirection
#[repr(transparent)]
#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, PartialOrd, Ord)]
pub struct DataDirection: u8 {
const EFI_SCSI_IO_DATA_DIRECTION_READ = 0;
const EFI_SCSI_IO_DATA_DIRECTION_WRITE = 1;
const EFI_SCSI_IO_DATA_DIRECTION_BIDIRECTIONAL = 2;
}
}

bitflags! {
/// HostAdapterStatus
#[repr(transparent)]
#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, PartialOrd, Ord)]
pub struct HostAdapterStatus: u8 {
const EFI_SCSI_IO_STATUS_HOST_ADAPTER_OK = 0x00 ;
const EFI_SCSI_IO_STATUS_HOST_ADAPTER_TIMEOUT_COMMAND =0x09 ;
const EFI_SCSI_IO_STATUS_HOST_ADAPTER_TIMEOUT =0x0b ;
const EFI_SCSI_IO_STATUS_HOST_ADAPTER_MESSAGE_REJECT =0x0d ;
const EFI_SCSI_IO_STATUS_HOST_ADAPTER_BUS_RESET =0x0e ;
const EFI_SCSI_IO_STATUS_HOST_ADAPTER_PARITY_ERROR =0x0f ;
const EFI_SCSI_IO_STATUS_HOST_ADAPTER_REQUEST_SENSE_FAILED =0x10 ;
const EFI_SCSI_IO_STATUS_HOST_ADAPTER_SELECTION_TIMEOUT =0x11 ;
const EFI_SCSI_IO_STATUS_HOST_ADAPTER_DATA_OVERRUN_UNDERRUN =0x12 ;
const EFI_SCSI_IO_STATUS_HOST_ADAPTER_BUS_FREE =0x13 ;
const EFI_SCSI_IO_STATUS_HOST_ADAPTER_PHASE_ERROR =0x14 ;
const EFI_SCSI_IO_STATUS_HOST_ADAPTER_OTHER =0x7f ;

}
}

bitflags! {
/// TargetStatus
#[repr(transparent)]
#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, PartialOrd, Ord)]
pub struct TargetStatus: u8 {
const EFI_SCSI_IO_STATUS_TARGET_GOOD =0x00;
const EFI_SCSI_IO_STATUS_TARGET_CHECK_CONDITION =0x02;
const EFI_SCSI_IO_STATUS_TARGET_CONDITION_MET =0x04;
const EFI_SCSI_IO_STATUS_TARGET_BUSY =0x08;
const EFI_SCSI_IO_STATUS_TARGET_INTERMEDIATE =0x10;
const EFI_SCSI_IO_STATUS_TARGET_INTERMEDIATE_CONDITION_METn =0x14;
const EFI_SCSI_IO_STATUS_TARGET_RESERVATION_CONFLICT =0x18;
const EFI_SCSI_IO_STATUS_TARGET_COMMAND_TERMINATED =0x22;
const EFI_SCSI_IO_STATUS_TARGET_QUEUE_FULL =0x28;
}
}

/// EFI_SCSI_IO_SCSI_REQUEST_PACKET
#[derive(Debug)]
#[repr(C)]
pub struct ScsiIoScsiRequestPacket {
/// Timeout: The timeout, in 100 ns units, to use for the execution of this SCSI Request Packet.
/// A Timeout value of 0 means that this function will wait indefinitely for the SCSI Request Packet to execute.
/// If Timeout is greater than zero, then this function will return EFI_TIMEOUT if the time required to execute the SCSI Request Packet is greater than Timeout .
pub timeout: u64,

/// []DataBuffer: A pointer to the data buffer to transfer from or to the SCSI device.
/// InDataBuffer: A pointer to the data buffer to transfer between the SCSI controller and the SCSI device for SCSI READ command.
/// For all SCSI WRITE Commands this must point to NULL .
pub in_data_buffer: *mut c_void,
/// OutDataBuffer: A pointer to the data buffer to transfer between the SCSI controller and the SCSI device for SCSI WRITE command.
/// For all SCSI READ commands this field must point to NULL .
pub out_data_buffer: *mut c_void,
/// SenseData: A pointer to the sense data that was generated by the execution of the SCSI Request Packet.
pub sense_data: *mut c_void,
/// Cdb: A pointer to buffer that contains the Command Data Block to send to the SCSI device.
pub cdb: *mut c_void,

/// InTransferLength: On Input, the size, in bytes, of InDataBuffer .
/// On output, the number of bytes transferred between the SCSI controller and the SCSI device.
/// If InTransferLength is larger than the SCSI controller can handle, no data will be transferred,
/// InTransferLength will be updated to contain the number of bytes that the SCSI controller is able to transfer, and EFI_BAD_BUFFER_SIZE will be returned.
pub in_transfer_length: u32,
/// OutTransferLength: On Input, the size, in bytes of OutDataBuffer .
/// On Output, the Number of bytes transferred between SCSI Controller and the SCSI device.
/// If OutTransferLength is larger than the SCSI controller can handle, no data will be transferred,
/// OutTransferLength will be updated to contain the number of bytes that the SCSI controller is able to transfer, and EFI_BAD_BUFFER_SIZE will be returned.
pub out_transfer_length: u32,

/// CdbLength: The length, in bytes, of the buffer Cdb .
/// The standard values are 6, 10, 12, and 16, but other values are possible if a variable length CDB is used.
pub cdb_length: u8,
/// DataDirection: The direction of the data transfer. 0 for reads, 1 for writes.
/// A value of 2 is Reserved for Bi-Directional SCSI commands. For example XDREADWRITE.
/// All other values are reserved, and must not be used.
pub data_direction: DataDirection,
/// HostAdapterStatus: The status of the SCSI Host Controller that produces the SCSI bus
/// where the SCSI device attached when the SCSI Request Packet was executed on the SCSI Controller.
pub host_adapter_status: HostAdapterStatus,
/// TargetStatus: The status returned by the SCSI device when the SCSI Request Packet was executed.
pub target_status: TargetStatus,
/// SenseDataLength: On input, the length in bytes of the SenseData buffer.
/// On output, the number of bytes written to the SenseData buffer.
pub sense_data_length: u8,
}

bitflags! {
/// DeviceType
/// Defined in the SCSI Primary Commands standard (e.g., SPC-4)
#[repr(transparent)]
#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, PartialOrd, Ord)]
pub struct DeviceType: u8 {
const DISK = 0x00; // Disk device
const TAPE = 0x01; // Tape device
const PRINTER = 0x02;// Printer
const PROCESSOR = 0x03;// Processor
const WORM = 0x04;// Write-once read-multiple
const CDROM = 0x05;// CD or DVD device
const SCANNER = 0x06;// Scanner device
const OPTICAL = 0x07;// Optical memory device
const MEDIUMCHANGER = 0x08;// Medium Changer device
const COMMUNICATION = 0x09;// Communications device


const MFI_A = 0x0A; // Obsolete
const MFI_B = 0x0B; // Obsolete
const MFI_RAID = 0x0C; // Storage array controller

const MFI_SES = 0x0D; // Enclosure services device
const MFI_RBC = 0x0E; // Simplified direct-access


const MFI_OCRW = 0x0F; // Optical card reader/

const MFI_BRIDGE = 0x10; // Bridge Controller

const MFI_OSD = 0x11; // Object-based Storage

const RESERVED_LOW = 0x12; // Reserved (low)
const RESERVED_HIGH = 0x1E; // Reserved (high)
const UNKNOWN = 0x1F; // Unknown no device type
}
}

#[derive(Debug)]
#[repr(C)]
pub struct ScsiIoProtocol {
//TODO: return deviceType
pub get_device_type:
unsafe extern "efiapi" fn(this: *const Self, device_type: *mut DeviceType) -> Status,
//TODO: raw pointer need to fixed, see uefi-rs service code like pointer *u8
pub get_device_location:
unsafe extern "efiapi" fn(this: *const Self, target: *mut *mut u8, lun: *mut u64) -> Status,
pub reset_bus: unsafe extern "efiapi" fn(this: *mut Self) -> Status,
pub reset_device: unsafe extern "efiapi" fn(this: *mut Self) -> Status,
pub execute_scsi_command: unsafe extern "efiapi" fn(
this: *const Self,
packet: *mut ScsiIoScsiRequestPacket,
event: Event,
) -> Status,
pub io_align: u32,
}

/// 15.4. EFI SCSI I/O Protocol
impl ScsiIoProtocol {
pub const GUID: Guid = guid!("932f47e6-2362-4002-803e-3cd54b138f85");
}

// TODO: see device_path.rs, then see 15.5. SCSI Device Paths and 15.6. SCSI Pass Thru Device Paths

#[derive(Debug)]
#[repr(C)]
pub struct ExtScsiPassThruProtocol {
pub mode: ExtScsiPassThruMode,
pub pass_thru: unsafe extern "efiapi" fn(
this: *const Self,
target: *mut u8,
lun: u64,
packet: *mut ExtScsiIoScsiRequestPacket,
event: Event,
) -> Status,
pub get_next_target_lun:
unsafe extern "efiapi" fn(this: *const Self, target: *mut *mut u8, lun: *mut u64) -> Status,
pub build_device_path: unsafe extern "efiapi" fn(
this: *mut Self,
target: *mut u8,
lun: u64,
device_path: *mut *mut DevicePathProtocol,
) -> Status,
pub get_target_lun: unsafe extern "efiapi" fn(
this: *const Self,
device_path: *const DevicePathProtocol,
target: *mut *mut u8,
lun: *mut u64,
) -> Status,

pub reset_channel: unsafe extern "efiapi" fn(this: *mut Self) -> Status,
pub reset_target_lun:
unsafe extern "efiapi" fn(this: *mut Self, target: *mut u8, lun: u64) -> Status,
pub get_next_target:
unsafe extern "efiapi" fn(this: *const Self, target: *mut *mut u8) -> Status,
}
/// 15.7. Extended SCSI Pass Thru Protocol
impl ExtScsiPassThruProtocol {
pub const GUID: Guid = guid!("143b7632-b81b-4cb7-abd3-b625a5b9bffe");
}

bitflags! {
/// Attributes
/// TODO: #define TARGET_MAX_BYTES 0x10
#[repr(transparent)]
#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, PartialOrd, Ord)]
pub struct Attributes: u32 {
const EFI_EXT_SCSI_PASS_THRU_ATTRIBUTES_PHYSICAL = 0x0001;
const EFI_EXT_SCSI_PASS_THRU_ATTRIBUTES_LOGICAL = 0x0002;
const EFI_EXT_SCSI_PASS_THRU_ATTRIBUTES_NONBLOCKIO = 0x0004;
}
}

#[derive(Clone, Copy, Debug, Default, Eq, PartialEq)]
#[repr(C)]
pub struct ExtScsiPassThruMode {
pub adapter_id: u32,
pub attributes: Attributes,
pub io_align: u32,
}

/// EFI_EXT_SCSI_PASS_THRU_SCSI_REQUEST_PACKET
#[derive(Debug)]
#[repr(C)]
pub struct ExtScsiIoScsiRequestPacket {
/// Timeout: The timeout, in 100 ns units, to use for the execution of this SCSI Request Packet.
/// A Timeout value of 0 means that this function will wait indefinitely for the SCSI Request Packet to execute.
/// If Timeout is greater than zero, then this function will return EFI_TIMEOUT if the time required to execute the SCSI Request Packet is greater than Timeout .
pub timeout: u64,

/// InDataBuffer: A pointer to the data buffer to transfer between the SCSI controller and the SCSI device for read and bidirectional commands.
/// For all write and non data commands where InTransferLength is 0 this field is optional and may be NULL .
/// If this field is not NULL , then it must be aligned on the boundary specified by the IoAlign field in the EFI_EXT_SCSI_PASS_THRU_MODE structure.
pub in_data_buffer: *mut c_void,
/// OutDataBuffer: A pointer to the data buffer to transfer between the SCSI controller and the SCSI device for write or bidirectional commands.
/// For all read and non data commands where OutTransferLength is 0 this field is optional and may be NULL .
/// If this field is not NULL , then it must be aligned on the boundary specified by the IoAlign field in the EFI_EXT_SCSI_PASS_THRU_MODE structure.
pub out_data_buffer: *mut c_void,
/// SenseData: A pointer to the sense data that was generated by the execution of the SCSI Request Packet.
/// If SenseDataLength is 0, then this field is optional and may be NULL .
/// It is strongly recommended that a sense data buffer of at least 252 bytes be provided to guarantee the entire sense data buffer
/// generated from the execution of the SCSI Request Packet can be returned.
/// If this field is not NULL , then it must be aligned to the boundary specified in the IoAlign field in the EFI_EXT_SCSI_PASS_THRU_MODE structure.
pub sense_data: *mut c_void,
/// Cdb: A pointer to buffer that contains the Command Data Block to send to the SCSI device specified by Target and Lun .
pub cdb: *mut c_void,

/// InTransferLength: On Input, the size, in bytes, of InDataBuffer .
/// On output, the number of bytes transferred between the SCSI controller and the SCSI device.
/// If InTransferLength is larger than the SCSI controller can handle, no data will be transferred,
/// InTransferLength will be updated to contain the number of bytes that the SCSI controller is able to transfer, and EFI_BAD_BUFFER_SIZE will be returned.
pub in_transfer_length: u32,
/// OutTransferLength: On Input, the size, in bytes of OutDataBuffer . On Output, the Number of bytes transferred between SCSI Controller and the SCSI device.
/// If OutTransferLength is larger than the SCSI controller can handle, no data will be transferred,
/// OutTransferLength will be updated to contain the number of bytes that the SCSI controller is able to transfer,
/// and EFI_BAD_BUFFER_SIZE will be returned.
pub out_transfer_length: u32,

/// CdbLength: The length, in bytes, of the buffer Cdb . The standard values are 6, 10, 12, and 16, but other values are possible if a variable length CDB is used.
pub cdb_length: u8,
/// DataDirection: The direction of the data transfer. 0 for reads, 1 for writes. A value of 2 is Reserved for Bi-Directional SCSI commands.
/// For example XDREADWRITE. All other values are reserved, and must not be used.
pub data_direction: ExtDataDirection,
/// HostAdapterStatus: The status of the host adapter specified by This when the SCSI Request Packet was executed on the target device.
/// If bit 7 of this field is set, then HostAdapterStatus is a vendor defined error code.
pub host_adapter_status: ExtHostAdapterStatus,
/// TargetStatus: The status returned by the device specified by Target and Lun when the SCSI Request Packet was executed.
pub target_status: ExtTargetStatus,
/// SenseDataLength: On input, the length in bytes of the SenseData buffer.
/// On output, the number of bytes written to the SenseData buffer.
pub sense_data_length: u8,
}

bitflags! {
/// Ext DataDirection
#[repr(transparent)]
#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, PartialOrd, Ord)]
pub struct ExtDataDirection: u8 {
const EFI_EXT_SCSI_DATA_DIRECTION_READ = 0;
const EFI_EXT_SCSI_DATA_DIRECTION_WRITE = 1;
const EFI_EXT_SCSI_DATA_DIRECTION_BIDIRECTIONAL = 2;
}
}

bitflags! {
/// Ext HostAdapterStatus
#[repr(transparent)]
#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, PartialOrd, Ord)]
pub struct ExtHostAdapterStatus: u8 {
const EFI_EXT_SCSI_STATUS_HOST_ADAPTER_OK =0x00;
const EFI_EXT_SCSI_STATUS_HOST_ADAPTER_TIMEOUT_COMMAND =0x09;
const EFI_EXT_SCSI_STATUS_HOST_ADAPTER_TIMEOUT =0x0b;
const EFI_EXT_SCSI_STATUS_HOST_ADAPTER_MESSAGE_REJECT =0x0d;
const EFI_EXT_SCSI_STATUS_HOST_ADAPTER_BUS_RESET =0x0e;
const EFI_EXT_SCSI_STATUS_HOST_ADAPTER_PARITY_ERROR =0x0f;
const EFI_EXT_SCSI_STATUS_HOST_ADAPTER_REQUEST_SENSE_FAILED =0x10;
const EFI_EXT_SCSI_STATUS_HOST_ADAPTER_SELECTION_TIMEOUT =0x11;
const EFI_EXT_SCSI_STATUS_HOST_ADAPTER_DATA_OVERRUN_UNDERRUN =0x12;
const EFI_EXT_SCSI_STATUS_HOST_ADAPTER_BUS_FREE =0x13;
const EFI_EXT_SCSI_STATUS_HOST_ADAPTER_PHASE_ERROR =0x14;
const EFI_EXT_SCSI_STATUS_HOST_ADAPTER_OTHER =0x7f;
}
}

bitflags! {
/// ExtTargetStatus
#[repr(transparent)]
#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, PartialOrd, Ord)]
pub struct ExtTargetStatus: u8 {
const EFI_EXT_SCSI_STATUS_TARGET_GOOD = 0x00;
const EFI_EXT_SCSI_STATUS_TARGET_CHECK_CONDITION = 0x02;
const EFI_EXT_SCSI_STATUS_TARGET_CONDITION_MET = 0x04;
const EFI_EXT_SCSI_STATUS_TARGET_BUSY = 0x08;
const EFI_EXT_SCSI_STATUS_TARGET_INTERMEDIATE = 0x10;
const EFI_EXT_SCSI_STATUS_TARGET_INTERMEDIATE_CONDITION_MET = 0x14;
const EFI_EXT_SCSI_STATUS_TARGET_RESERVATION_CONFLICT = 0x18;
const EFI_EXT_SCSI_STATUS_TARGET_TASK_SET_FULL = 0x28;
const EFI_EXT_SCSI_STATUS_TARGET_ACA_ACTIVE = 0x30;
const EFI_EXT_SCSI_STATUS_TARGET_TASK_ABORTED = 0x40;
}
}
8 changes: 5 additions & 3 deletions uefi/src/proto/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,12 @@
//!
//! [`BootServices`]: crate::table::boot::BootServices#accessing-protocols

use crate::Identify;
use core::ffi::c_void;

pub use uefi_macros::unsafe_protocol;

use crate::Identify;

/// Common trait implemented by all standard UEFI protocols.
///
/// You can derive the `Protocol` trait and specify the protocol's GUID using
Expand Down Expand Up @@ -64,8 +67,6 @@ where
}
}

pub use uefi_macros::unsafe_protocol;

pub mod console;
pub mod debug;
pub mod device_path;
Expand All @@ -76,6 +77,7 @@ pub mod misc;
pub mod network;
pub mod pi;
pub mod rng;
pub mod scsi;
pub mod security;
pub mod shell_params;
pub mod shim;
Expand Down
Loading