Skip to content

Commit ad64eeb

Browse files
committed
uefi: Add integration-test for EFI_NVME_PASS_THRU_PROTOCOL
1 parent 0b9e474 commit ad64eeb

File tree

4 files changed

+71
-0
lines changed

4 files changed

+71
-0
lines changed

uefi-test-runner/src/proto/mod.rs

+2
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ pub fn test() {
2525
shell_params::test();
2626
string::test();
2727
misc::test();
28+
nvme::test();
2829

2930
#[cfg(any(
3031
target_arch = "x86",
@@ -71,6 +72,7 @@ mod loaded_image;
7172
mod media;
7273
mod misc;
7374
mod network;
75+
mod nvme;
7476
mod pi;
7577
mod rng;
7678
mod shell_params;
+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+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
// SPDX-License-Identifier: MIT OR Apache-2.0
2+
3+
use core::time::Duration;
4+
use uefi::boot;
5+
use uefi::proto::device_path::text::{AllowShortcuts, DisplayOnly};
6+
use uefi::proto::device_path::DevicePath;
7+
use uefi::proto::media::block::BlockIO;
8+
use uefi::proto::nvme::pass_thru::NvmePassThru;
9+
use uefi::proto::nvme::{NvmeQueueType, NvmeRequestBuilder};
10+
11+
pub fn test() {
12+
info!("Running NVMe PassThru tests");
13+
14+
assert!(try_find_drive());
15+
}
16+
17+
fn try_find_drive() -> bool {
18+
let block_io_handles = boot::find_handles::<BlockIO>().unwrap();
19+
for handle in block_io_handles {
20+
let Ok(device_path) = boot::open_protocol_exclusive::<DevicePath>(handle) else {
21+
continue;
22+
};
23+
let mut device_path = &*device_path;
24+
25+
let Ok(nvme_pt_handle) = boot::locate_device_path::<NvmePassThru>(&mut device_path) else {
26+
continue;
27+
};
28+
let mut nvme_pt = boot::open_protocol_exclusive::<NvmePassThru>(nvme_pt_handle).unwrap();
29+
let device_path_str = device_path
30+
.to_string(DisplayOnly(true), AllowShortcuts(false))
31+
.unwrap();
32+
info!("- Successfully opened NVMe: {}", device_path_str);
33+
34+
let request = NvmeRequestBuilder::new(nvme_pt.io_align(), 0x06, NvmeQueueType::ADMIN)
35+
.with_timeout(Duration::from_millis(500))
36+
.with_cdw10(1) // we want info about controller
37+
.with_transfer_buffer(4096)
38+
.unwrap()
39+
.build();
40+
let result = nvme_pt.execute_command(request);
41+
if let Ok(result) = result {
42+
let bfr = result.transfer_buffer().unwrap();
43+
let serial = core::str::from_utf8(&bfr[4..24]).unwrap().trim();
44+
info!("Found NVMe with serial: '{}'", serial);
45+
if serial == "uefi-rsNvmePassThru" {
46+
return true;
47+
}
48+
}
49+
}
50+
51+
false
52+
}

xtask/src/qemu.rs

+10
Original file line numberDiff line numberDiff line change
@@ -489,6 +489,16 @@ pub fn run_qemu(arch: UefiArch, opt: &QemuOpt) -> Result<()> {
489489
cmd.arg("-device"); // attach disk to SCSI controller
490490
cmd.arg("scsi-hd,drive=scsidisk0,vendor=uefi-rs,product=ExtScsiPassThru");
491491

492+
// Fourth (NVMe) disk for NvmePassThru tests
493+
let nvme_test_disk = tmp_dir.join("test_disk3.empty.img");
494+
std::fs::File::create(&nvme_test_disk)?.set_len(1024 * 1024 * 10)?;
495+
cmd.arg("-drive");
496+
let mut drive_arg = OsString::from("if=none,id=nvmedisk0,format=raw,file=");
497+
drive_arg.push(nvme_test_disk.clone());
498+
cmd.arg(drive_arg);
499+
cmd.arg("-device");
500+
cmd.arg("nvme,drive=nvmedisk0,serial=uefi-rsNvmePassThru");
501+
492502
let qemu_monitor_pipe = Pipe::new(tmp_dir, "qemu-monitor")?;
493503
let serial_pipe = Pipe::new(tmp_dir, "serial")?;
494504

0 commit comments

Comments
 (0)