1
+ use alloc:: string:: ToString ;
1
2
use uefi:: proto:: console:: text:: Output ;
2
- use uefi:: table:: boot:: { BootServices , SearchType } ;
3
+ use uefi:: proto:: device_path:: media:: FilePath ;
4
+ use uefi:: proto:: device_path:: { DevicePath , LoadedImageDevicePath } ;
5
+ use uefi:: table:: boot:: { BootServices , LoadImageSource , SearchType } ;
3
6
use uefi:: table:: { Boot , SystemTable } ;
4
- use uefi:: Identify ;
7
+ use uefi:: { CString16 , Identify } ;
8
+
9
+ mod memory;
10
+ mod misc;
5
11
6
12
pub fn test ( st : & SystemTable < Boot > ) {
7
13
let bt = st. boot_services ( ) ;
8
14
info ! ( "Testing boot services" ) ;
9
15
memory:: test ( bt) ;
10
16
misc:: test ( st) ;
11
17
test_locate_handle_buffer ( bt) ;
18
+ test_load_image ( bt) ;
12
19
}
13
20
14
- mod memory;
15
- mod misc;
16
-
17
21
fn test_locate_handle_buffer ( bt : & BootServices ) {
18
22
info ! ( "Testing the `locate_handle_buffer` function" ) ;
19
23
@@ -36,3 +40,67 @@ fn test_locate_handle_buffer(bt: &BootServices) {
36
40
) ;
37
41
}
38
42
}
43
+
44
+ /// This test loads the "self image" again into memory using the `load_image`
45
+ /// boot service function. The image is not started but just loaded into memory.
46
+ ///
47
+ /// It transitively tests the protocol [`LoadedImageDevicePath`] which is
48
+ /// required as helper.
49
+ fn test_load_image ( bt : & BootServices ) {
50
+ /// The path of the loaded image executing this integration test.
51
+ const LOADED_IMAGE_PATH : & str = r"\EFI\BOOT\TEST_RUNNER.EFI" ;
52
+
53
+ info ! ( "Testing the `load_image` function" ) ;
54
+
55
+ let image_device_path_protocol = bt
56
+ . open_protocol_exclusive :: < LoadedImageDevicePath > ( bt. image_handle ( ) )
57
+ . expect ( "should open LoadedImage protocol" ) ;
58
+
59
+ // Note: This is the full device path. The LoadedImage protocol would only
60
+ // provide us with the file-path portion of the device path.
61
+ let image_device_path: & DevicePath = & image_device_path_protocol;
62
+
63
+ // Get the file-path portion of the device path which is typically behind
64
+ // device path node (0x4, 0x4). The string is in upper case.
65
+
66
+ let image_device_path_file_path = image_device_path
67
+ . node_iter ( )
68
+ . find_map ( |node| {
69
+ let node: & FilePath = node. try_into ( ) . ok ( ) ?;
70
+ let path = node. path_name ( ) . to_cstring16 ( ) . ok ( ) ?;
71
+ Some ( path. to_string ( ) . to_uppercase ( ) )
72
+ } )
73
+ . expect ( "should have file-path portion in device path" ) ;
74
+
75
+ assert_eq ! ( image_device_path_file_path. as_str( ) , LOADED_IMAGE_PATH ) ;
76
+
77
+ // Variant A: FromBuffer
78
+ {
79
+ let mut fs = bt
80
+ . get_image_file_system ( bt. image_handle ( ) )
81
+ . expect ( "should open file system" ) ;
82
+ let path = CString16 :: try_from ( image_device_path_file_path. as_str ( ) ) . unwrap ( ) ;
83
+ let image_data = fs. read ( & * path) . expect ( "should read file content" ) ;
84
+ let load_source = LoadImageSource :: FromBuffer {
85
+ buffer : image_data. as_slice ( ) ,
86
+ file_path : None ,
87
+ } ;
88
+ let _ = bt
89
+ . load_image ( bt. image_handle ( ) , load_source)
90
+ . expect ( "should load image" ) ;
91
+
92
+ log:: debug!( "load_image with FromBuffer strategy works" ) ;
93
+ }
94
+ // Variant B: FromFilePath
95
+ {
96
+ let load_source = LoadImageSource :: FromFilePath {
97
+ file_path : image_device_path,
98
+ from_boot_manager : false ,
99
+ } ;
100
+ let _ = bt
101
+ . load_image ( bt. image_handle ( ) , load_source)
102
+ . expect ( "should load image" ) ;
103
+
104
+ log:: debug!( "load_image with FromFilePath strategy works" ) ;
105
+ }
106
+ }
0 commit comments