Skip to content

uefi-raw: Add EFI_ATA_PASS_THRU_PROTOCOL bindings #1592

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Mar 26, 2025
Merged
Show file tree
Hide file tree
Changes from all 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/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
- Added `DiskInfoProtocol`.
- Added `ExtScsiPassThruProtocol`.
- Added `NvmExpressPassThruProtocol`.
- Added `AtaPassThruProtocol`.


# uefi-raw - 0.10.0 (2025-02-07)
Expand Down
161 changes: 161 additions & 0 deletions uefi-raw/src/protocol/ata.rs
Original file line number Diff line number Diff line change
@@ -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");
}
1 change: 1 addition & 0 deletions uefi-raw/src/protocol/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
2 changes: 1 addition & 1 deletion uefi/src/proto/media/disk_info.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
}

Expand Down