Skip to content

Commit fd1a9ca

Browse files
committed
test: add load_image integration test
1 parent e82de9d commit fd1a9ca

File tree

1 file changed

+76
-5
lines changed
  • uefi-test-runner/src/boot

1 file changed

+76
-5
lines changed

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

Lines changed: 76 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,20 @@
1+
use alloc::string::ToString;
12
use uefi::proto::console::text::Output;
2-
use uefi::table::boot::{BootServices, SearchType};
3-
use uefi::Identify;
3+
use uefi::proto::device_path::{DevicePath, DeviceSubType, DeviceType, LoadedImageDevicePath};
4+
use uefi::table::boot::{BootServices, LoadImageSource, SearchType};
5+
use uefi::{CStr16, CString16, Identify};
6+
7+
mod memory;
8+
mod misc;
49

510
pub fn test(bt: &BootServices) {
611
info!("Testing boot services");
712
memory::test(bt);
813
misc::test(bt);
914
test_locate_handle_buffer(bt);
15+
test_load_image(bt);
1016
}
1117

12-
mod memory;
13-
mod misc;
14-
1518
fn test_locate_handle_buffer(bt: &BootServices) {
1619
info!("Testing the `locate_handle_buffer` function");
1720

@@ -34,3 +37,71 @@ fn test_locate_handle_buffer(bt: &BootServices) {
3437
);
3538
}
3639
}
40+
41+
/// This test loads the "self image" again into memory using the `load_image`
42+
/// boot service function. The image is not started but just loaded into memory.
43+
///
44+
/// It transitively tests the protocols [`LoadedImageDevicePath`] which is
45+
/// required as helper.
46+
fn test_load_image(bt: &BootServices) {
47+
info!("Testing the `load_image` function");
48+
49+
let image_device_path_protocol = bt
50+
.open_protocol_exclusive::<LoadedImageDevicePath>(bt.image_handle())
51+
.expect("should open LoadedImage protocol");
52+
53+
// Note: This is the full device path. The LoadedImage protocol would only
54+
// provide us with the file-path portion of the device path.
55+
let image_device_path: &DevicePath = &image_device_path_protocol;
56+
57+
// Get the file-path portion of the device path which is typically behind
58+
// device path node (0x4, 0x4).
59+
// TODO we need an abstraction in the UEFI crate for this.
60+
let image_device_path_file_path = image_device_path
61+
.node_iter()
62+
.filter(|node| {
63+
node.device_type() == DeviceType::MEDIA /* 0x4 */
64+
&& node.sub_type() == DeviceSubType::HARDWARE_VENDOR /* 0x4 */
65+
})
66+
.next()
67+
.map(|node| unsafe { CStr16::from_ptr(node.data().as_ptr().cast()) })
68+
// to Rust string
69+
.map(|cstr16| cstr16.to_string().to_uppercase())
70+
.expect("should have file-path portion in device path");
71+
72+
// On x86_64, this will be `\EFI\BOOT\BOOTX64.EFI` for example.
73+
assert!(image_device_path_file_path
74+
.as_str()
75+
.starts_with(r"\EFI\BOOT\BOOT"));
76+
assert!(image_device_path_file_path.as_str().ends_with(".EFI"));
77+
78+
// Variant A: FromBuffer
79+
{
80+
let mut fs = bt
81+
.get_image_file_system(bt.image_handle())
82+
.expect("should open file system");
83+
let path = CString16::try_from(image_device_path_file_path.as_str()).unwrap();
84+
let image_data = fs.read(&*path).expect("should read file content");
85+
let load_source = LoadImageSource::FromBuffer {
86+
buffer: image_data.as_slice(),
87+
file_path: None,
88+
};
89+
let _ = bt
90+
.load_image(bt.image_handle(), load_source)
91+
.expect("should load image");
92+
93+
log::debug!("load_image with FromBuffer strategy works");
94+
}
95+
// Variant B: FromFilePath
96+
{
97+
let load_source = LoadImageSource::FromFilePath {
98+
file_path: image_device_path,
99+
from_boot_manager: false,
100+
};
101+
let _ = bt
102+
.load_image(bt.image_handle(), load_source)
103+
.expect("should load image");
104+
105+
log::debug!("load_image with FromFilePath strategy works");
106+
}
107+
}

0 commit comments

Comments
 (0)