Skip to content

Commit 27487c2

Browse files
Merge pull request #1595 from seijikun/mr-atapt
uefi: Add safe protocol wrapper for EFI_ATA_PASS_THRU_PROTOCOL
2 parents 0e2a9d1 + 0ce684c commit 27487c2

File tree

9 files changed

+686
-0
lines changed

9 files changed

+686
-0
lines changed

Diff for: uefi-test-runner/src/proto/ata/mod.rs

+7
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
// SPDX-License-Identifier: MIT OR Apache-2.0
2+
3+
mod pass_thru;
4+
5+
pub fn test() {
6+
pass_thru::test();
7+
}

Diff for: uefi-test-runner/src/proto/ata/pass_thru.rs

+59
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
// SPDX-License-Identifier: MIT OR Apache-2.0
2+
3+
use uefi::boot;
4+
use uefi::boot::{OpenProtocolAttributes, OpenProtocolParams};
5+
use uefi::proto::ata::pass_thru::AtaPassThru;
6+
use uefi::proto::ata::AtaRequestBuilder;
7+
8+
pub fn test() {
9+
info!("Running ATA PassThru tests");
10+
11+
assert!(is_testdrive_present());
12+
}
13+
14+
const ATACMD_IDENTIFY: u8 = 0xEC;
15+
16+
fn is_testdrive_present() -> bool {
17+
let ata_ctrl_handles = boot::find_handles::<AtaPassThru>().unwrap();
18+
assert_eq!(ata_ctrl_handles.len(), 1);
19+
20+
for handle in ata_ctrl_handles {
21+
let params = OpenProtocolParams {
22+
handle,
23+
agent: boot::image_handle(),
24+
controller: None,
25+
};
26+
let ata_pt = unsafe {
27+
// don't open exclusive! That would break other tests
28+
boot::open_protocol::<AtaPassThru>(params, OpenProtocolAttributes::GetProtocol).unwrap()
29+
};
30+
for mut device in ata_pt.iter_devices() {
31+
// ATA IDENTIFY command
32+
let request = AtaRequestBuilder::read_udma(ata_pt.io_align(), ATACMD_IDENTIFY)
33+
.unwrap()
34+
.with_timeout(core::time::Duration::from_millis(500))
35+
.with_read_buffer(255)
36+
.unwrap()
37+
.build();
38+
if let Ok(result) = device.execute_command(request) {
39+
let bfr = result.read_buffer().unwrap();
40+
// ATA uses wchar16 big endian strings for serial numbers
41+
let mut serial_bfr = [0u8; 20];
42+
bfr[20..40]
43+
.chunks_exact(2)
44+
.zip(serial_bfr.chunks_exact_mut(2))
45+
.for_each(|(src, dst)| {
46+
dst[0] = src[1];
47+
dst[1] = src[0];
48+
});
49+
let serial = core::str::from_utf8(&serial_bfr).unwrap().trim();
50+
if serial == "AtaPassThru" {
51+
info!("Found Testdisk at handle: {:?}", handle);
52+
return true; // found our testdrive!
53+
}
54+
}
55+
}
56+
}
57+
58+
false
59+
}

Diff for: uefi-test-runner/src/proto/media.rs

+8
Original file line numberDiff line numberDiff line change
@@ -398,7 +398,15 @@ fn test_partition_info(disk_handle: Handle) {
398398
fn find_test_disk() -> (Handle, ScopedProtocol<SimpleFileSystem>) {
399399
let handles = boot::find_handles::<SimpleFileSystem>()
400400
.expect("Failed to get handles for `SimpleFileSystem` protocol");
401+
402+
// This branch is due to the qemu machine type we use based on the architecture.
403+
// - *Q35* by default uses a SATA-Controller to connect disks.
404+
// - *virt* by default uses virtio to connect disks.
405+
// The aarch64 UEFI Firmware does not yet seem to support SATA-Controllers.
406+
#[cfg(any(target_arch = "arm", target_arch = "aarch64"))]
401407
assert_eq!(handles.len(), 2);
408+
#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
409+
assert_eq!(handles.len(), 3);
402410

403411
for handle in handles {
404412
let mut sfs = boot::open_protocol_exclusive::<SimpleFileSystem>(handle)

Diff for: uefi-test-runner/src/proto/mod.rs

+7
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,11 @@ pub fn test() {
2525
shell_params::test();
2626
string::test();
2727
misc::test();
28+
29+
// disable the ATA test on aarch64 for now. The aarch64 UEFI Firmware does not yet seem
30+
// to support SATA controllers (and providing an AtaPassThru protocol instance for them).
31+
#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
32+
ata::test();
2833
scsi::test();
2934
nvme::test();
3035

@@ -64,6 +69,8 @@ fn test_test_protocol() {
6469
.unwrap());
6570
}
6671

72+
#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
73+
mod ata;
6774
mod console;
6875
mod debug;
6976
mod device_path;

Diff for: uefi/CHANGELOG.md

+1
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
- Added `proto::device_path::DevicePath::append_node()`.
1111
- Added `proto::scsi::pass_thru::ExtScsiPassThru`.
1212
- Added `proto::nvme::pass_thru::NvmePassThru`.
13+
- Added `proto::ata::pass_thru::AtaPassThru`.
1314

1415
## Changed
1516
- **Breaking:** Removed `BootPolicyError` as `BootPolicy` construction is no

0 commit comments

Comments
 (0)