diff --git a/uefi-raw/CHANGELOG.md b/uefi-raw/CHANGELOG.md index 314daabf6..4f5d3130b 100644 --- a/uefi-raw/CHANGELOG.md +++ b/uefi-raw/CHANGELOG.md @@ -10,6 +10,7 @@ - Added `DiskInfoProtocol`. - Added `ExtScsiPassThruProtocol`. - Added `NvmExpressPassThruProtocol`. +- Added `AtaPassThruProtocol`. # uefi-raw - 0.10.0 (2025-02-07) diff --git a/uefi-raw/src/protocol/ata.rs b/uefi-raw/src/protocol/ata.rs new file mode 100644 index 000000000..c982f4d66 --- /dev/null +++ b/uefi-raw/src/protocol/ata.rs @@ -0,0 +1,161 @@ +// SPDX-License-Identifier: MIT OR Apache-2.0 + +use super::device_path::DevicePathProtocol; +use crate::{Event, Status}; +use core::ffi::c_void; +use uguid::{guid, Guid}; + +bitflags::bitflags! { + /// ATA Controller attributes. + /// + /// These flags defines attributes that describe the nature and capabilities + /// of the ATA controller represented by this `EFI_ATA_PASS_THRU_PROTOCOL` instance. + #[derive(Clone, Copy, Debug, Default, PartialEq, Eq, PartialOrd, Ord)] + #[repr(transparent)] + pub struct AtaPassThruAttributes: u32 { + /// The protocol interface is for physical devices on the ATA controller. + /// + /// This allows access to hardware-level details of devices directly attached to the controller. + const PHYSICAL = 0x0001; + + /// The protocol interface is for logical devices on the ATA controller. + /// + /// Logical devices include RAID volumes and other high-level abstractions. + const LOGICAL = 0x0002; + + /// The protocol interface supports non-blocking I/O in addition to blocking I/O. + /// + /// While all protocol interfaces must support blocking I/O, this attribute indicates + /// the additional capability for non-blocking operations. + const NONBLOCKIO = 0x0004; + } +} + +#[derive(Debug)] +#[repr(C)] +pub struct AtaPassThruMode { + pub attributes: AtaPassThruAttributes, + pub io_align: u32, +} + +newtype_enum! { + /// Corresponds to the `EFI_ATA_PASS_THRU_PROTOCOL_*` defines. + #[derive(Default)] + pub enum AtaPassThruCommandProtocol: u8 => { + ATA_HARDWARE_RESET = 0x00, + ATA_SOFTWARE_RESET = 0x01, + ATA_NON_DATA = 0x02, + PIO_DATA_IN = 0x04, + PIO_DATA_OUT = 0x05, + DMA = 0x06, + DMA_QUEUED = 0x07, + DEVICE_DIAGNOSTIC = 0x08, + DEVICE_RESET = 0x09, + UDMA_DATA_IN = 0x0A, + UDMA_DATA_OUT = 0x0B, + FPDMA = 0x0C, + RETURN_RESPONSE = 0xFF, + } +} + +newtype_enum! { + /// Corresponds to the `EFI_ATA_PASS_THRU_LENGTH_*` defines. + #[derive(Default)] + pub enum AtaPassThruLength: u8 => { + BYTES = 0x80, + MASK = 0x70, + NO_DATA_TRANSFER = 0x00, + FEATURES = 0x10, + SECTOR_COUNT = 0x20, + TPSIU = 0x30, + COUNT = 0x0F, + } +} + +#[derive(Debug)] +#[repr(C)] +pub struct AtaStatusBlock { + pub reserved1: [u8; 2], + pub ata_status: u8, + pub ata_error: u8, + pub ata_sector_number: u8, + pub ata_cylinder_low: u8, + pub ata_cylinder_high: u8, + pub ata_device_head: u8, + pub ata_sector_number_exp: u8, + pub ata_cylinder_low_exp: u8, + pub ata_cylinder_high_exp: u8, + pub reserved2: u8, + pub ata_sector_count: u8, + pub ata_sector_count_exp: u8, + pub reserved3: [u8; 6], +} + +#[derive(Debug)] +#[repr(C)] +pub struct AtaCommandBlock { + pub reserved1: [u8; 2], + pub ata_command: u8, + pub ata_features: u8, + pub ata_sector_number: u8, + pub ata_cylinder_low: u8, + pub ata_cylinder_high: u8, + pub ata_device_head: u8, + pub ata_sector_number_exp: u8, + pub ata_cylinder_low_exp: u8, + pub ata_cylinder_high_exp: u8, + pub ata_features_exp: u8, + pub ata_sector_count: u8, + pub ata_sector_count_exp: u8, + pub reserved2: [u8; 6], +} + +#[derive(Debug)] +#[repr(C)] +pub struct AtaPassThruCommandPacket { + pub asb: *mut AtaStatusBlock, + pub acb: *const AtaCommandBlock, + pub timeout: u64, + pub in_data_buffer: *mut c_void, + pub out_data_buffer: *const c_void, + pub protocol: AtaPassThruCommandProtocol, + pub length: AtaPassThruLength, +} + +#[derive(Debug)] +#[repr(C)] +pub struct AtaPassThruProtocol { + pub mode: *const AtaPassThruMode, + pub pass_thru: unsafe extern "efiapi" fn( + this: *mut Self, + port: u16, + port_multiplier_port: u16, + packet: *mut AtaPassThruCommandPacket, + event: *mut Event, + ) -> Status, + pub get_next_port: unsafe extern "efiapi" fn(this: *const Self, port: *mut u16) -> Status, + pub get_next_device: unsafe extern "efiapi" fn( + this: *const Self, + port: u16, + port_multiplier_port: *mut u16, + ) -> Status, + pub build_device_path: unsafe extern "efiapi" fn( + this: *const Self, + port: u16, + port_multiplier_port: u16, + device_path: *mut *mut DevicePathProtocol, + ) -> Status, + pub get_device: unsafe extern "efiapi" fn( + this: *const Self, + device_path: *const DevicePathProtocol, + port: *mut u16, + port_multiplier_port: *mut u16, + ) -> Status, + pub reset_port: unsafe extern "efiapi" fn(this: *mut Self, port: u16) -> Status, + pub reset_device: + unsafe extern "efiapi" fn(this: *mut Self, port: u16, port_multiplier_port: u16) -> Status, +} + +impl AtaPassThruProtocol { + pub const GUID: Guid = guid!("1d3de7f0-0807-424f-aa69-11a54e19a46f"); +} diff --git a/uefi-raw/src/protocol/mod.rs b/uefi-raw/src/protocol/mod.rs index 4e250a226..38cf2471f 100644 --- a/uefi-raw/src/protocol/mod.rs +++ b/uefi-raw/src/protocol/mod.rs @@ -6,6 +6,7 @@ //! ID. They can be implemented by a UEFI driver or occasionally by a //! UEFI application. +pub mod ata; pub mod block; pub mod console; pub mod device_path; diff --git a/uefi/src/proto/media/disk_info.rs b/uefi/src/proto/media/disk_info.rs index 13a3dbdb4..bba5dbcc9 100644 --- a/uefi/src/proto/media/disk_info.rs +++ b/uefi/src/proto/media/disk_info.rs @@ -48,7 +48,7 @@ pub struct DeviceLocationInfo { /// For AHCI, this returns the port. pub channel: u32, /// For IDE, this contains whether the device is master or slave. - /// For AHCI, this returns the port-multiplier. + /// For AHCI, this returns the port multiplier port. pub device: u32, }