| 
 | 1 | +// SPDX-License-Identifier: MIT OR Apache-2.0  | 
 | 2 | + | 
 | 3 | +use uefi::proto::scsi::pass_thru::ExtScsiPassThru;  | 
 | 4 | +use uefi::proto::scsi::ScsiRequestBuilder;  | 
 | 5 | + | 
 | 6 | +pub fn test() {  | 
 | 7 | +    info!("Running extended SCSI Pass Thru tests");  | 
 | 8 | +    test_allocating_api();  | 
 | 9 | +    test_reusing_buffer_api();  | 
 | 10 | +}  | 
 | 11 | + | 
 | 12 | +fn test_allocating_api() {  | 
 | 13 | +    let scsi_ctrl_handles = uefi::boot::find_handles::<ExtScsiPassThru>().unwrap();  | 
 | 14 | +    assert_eq!(scsi_ctrl_handles.len(), 2);  | 
 | 15 | + | 
 | 16 | +    let mut found_drive = false;  | 
 | 17 | + | 
 | 18 | +    for handle in scsi_ctrl_handles {  | 
 | 19 | +        let scsi_pt = uefi::boot::open_protocol_exclusive::<ExtScsiPassThru>(handle).unwrap();  | 
 | 20 | +        for device in scsi_pt.iter_devices() {  | 
 | 21 | +            // see: https://www.seagate.com/files/staticfiles/support/docs/manual/Interface%20manuals/100293068j.pdf  | 
 | 22 | +            // 3.6 INQUIRY command  | 
 | 23 | +            let request = ScsiRequestBuilder::read(scsi_pt.io_align())  | 
 | 24 | +                .with_timeout(core::time::Duration::from_millis(500))  | 
 | 25 | +                .with_command_data(&[0x12, 0x00, 0x00, 0x00, 0xFF, 0x00])  | 
 | 26 | +                .unwrap()  | 
 | 27 | +                .with_read_buffer(255)  | 
 | 28 | +                .unwrap()  | 
 | 29 | +                .build();  | 
 | 30 | +            let Ok(response) = device.execute_command(request) else {  | 
 | 31 | +                continue; // no device  | 
 | 32 | +            };  | 
 | 33 | +            let bfr = response.read_buffer().unwrap();  | 
 | 34 | +            // more no device checks  | 
 | 35 | +            if bfr.len() < 32 {  | 
 | 36 | +                continue;  | 
 | 37 | +            }  | 
 | 38 | +            if bfr[0] & 0b00011111 == 0x1F {  | 
 | 39 | +                continue;  | 
 | 40 | +            }  | 
 | 41 | + | 
 | 42 | +            // found device  | 
 | 43 | +            let vendor_id = core::str::from_utf8(&bfr[8..16]).unwrap().trim();  | 
 | 44 | +            let product_id = core::str::from_utf8(&bfr[16..32]).unwrap().trim();  | 
 | 45 | +            if vendor_id == "uefi-rs" && product_id == "ExtScsiPassThru" {  | 
 | 46 | +                info!(  | 
 | 47 | +                    "Found Testdisk at: {:?} | {}",  | 
 | 48 | +                    device.target(),  | 
 | 49 | +                    device.lun()  | 
 | 50 | +                );  | 
 | 51 | +                found_drive = true;  | 
 | 52 | +            }  | 
 | 53 | +        }  | 
 | 54 | +    }  | 
 | 55 | + | 
 | 56 | +    assert!(found_drive);  | 
 | 57 | +}  | 
 | 58 | + | 
 | 59 | +fn test_reusing_buffer_api() {  | 
 | 60 | +    let scsi_ctrl_handles = uefi::boot::find_handles::<ExtScsiPassThru>().unwrap();  | 
 | 61 | +    assert_eq!(scsi_ctrl_handles.len(), 2);  | 
 | 62 | + | 
 | 63 | +    let mut found_drive = false;  | 
 | 64 | + | 
 | 65 | +    for handle in scsi_ctrl_handles {  | 
 | 66 | +        let scsi_pt = uefi::boot::open_protocol_exclusive::<ExtScsiPassThru>(handle).unwrap();  | 
 | 67 | +        let mut cmd_bfr = scsi_pt.alloc_io_buffer(6).unwrap();  | 
 | 68 | +        cmd_bfr.copy_from(&[0x12, 0x00, 0x00, 0x00, 0xFF, 0x00]);  | 
 | 69 | +        let mut read_bfr = scsi_pt.alloc_io_buffer(255).unwrap();  | 
 | 70 | + | 
 | 71 | +        for device in scsi_pt.iter_devices() {  | 
 | 72 | +            // see: https://www.seagate.com/files/staticfiles/support/docs/manual/Interface%20manuals/100293068j.pdf  | 
 | 73 | +            // 3.6 INQUIRY command  | 
 | 74 | +            let request = ScsiRequestBuilder::read(scsi_pt.io_align())  | 
 | 75 | +                .with_timeout(core::time::Duration::from_millis(500))  | 
 | 76 | +                .use_command_buffer(&mut cmd_bfr)  | 
 | 77 | +                .unwrap()  | 
 | 78 | +                .use_read_buffer(&mut read_bfr)  | 
 | 79 | +                .unwrap()  | 
 | 80 | +                .build();  | 
 | 81 | +            let Ok(response) = device.execute_command(request) else {  | 
 | 82 | +                continue; // no device  | 
 | 83 | +            };  | 
 | 84 | +            let bfr = response.read_buffer().unwrap();  | 
 | 85 | +            // more no device checks  | 
 | 86 | +            if bfr.len() < 32 {  | 
 | 87 | +                continue;  | 
 | 88 | +            }  | 
 | 89 | +            if bfr[0] & 0b00011111 == 0x1F {  | 
 | 90 | +                continue;  | 
 | 91 | +            }  | 
 | 92 | + | 
 | 93 | +            // found device  | 
 | 94 | +            let vendor_id = core::str::from_utf8(&bfr[8..16]).unwrap().trim();  | 
 | 95 | +            let product_id = core::str::from_utf8(&bfr[16..32]).unwrap().trim();  | 
 | 96 | +            if vendor_id == "uefi-rs" && product_id == "ExtScsiPassThru" {  | 
 | 97 | +                info!(  | 
 | 98 | +                    "Found Testdisk at: {:?} | {}",  | 
 | 99 | +                    device.target(),  | 
 | 100 | +                    device.lun()  | 
 | 101 | +                );  | 
 | 102 | +                found_drive = true;  | 
 | 103 | +            }  | 
 | 104 | +        }  | 
 | 105 | +    }  | 
 | 106 | + | 
 | 107 | +    assert!(found_drive);  | 
 | 108 | +}  | 
0 commit comments