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:: { DevicePath , DeviceSubType , DeviceType , LoadedImageDevicePath } ;
4
+ use uefi:: table:: boot:: { BootServices , LoadImageSource , SearchType } ;
3
5
use uefi:: table:: { Boot , SystemTable } ;
4
- use uefi:: Identify ;
6
+ use uefi:: { CStr16 , CString16 , Identify } ;
7
+
8
+ mod memory;
9
+ mod misc;
5
10
6
11
pub fn test ( st : & SystemTable < Boot > ) {
7
12
let bt = st. boot_services ( ) ;
8
13
info ! ( "Testing boot services" ) ;
9
14
memory:: test ( bt) ;
10
15
misc:: test ( st) ;
11
16
test_locate_handle_buffer ( bt) ;
17
+ test_load_image ( bt) ;
12
18
}
13
19
14
- mod memory;
15
- mod misc;
16
-
17
20
fn test_locate_handle_buffer ( bt : & BootServices ) {
18
21
info ! ( "Testing the `locate_handle_buffer` function" ) ;
19
22
@@ -36,3 +39,72 @@ fn test_locate_handle_buffer(bt: &BootServices) {
36
39
) ;
37
40
}
38
41
}
42
+
43
+ /// This test loads the "self image" again into memory using the `load_image`
44
+ /// boot service function. The image is not started but just loaded into memory.
45
+ ///
46
+ /// It transitively tests the protocol [`LoadedImageDevicePath`] which is
47
+ /// required as helper.
48
+ fn test_load_image ( bt : & BootServices ) {
49
+ info ! ( "Testing the `load_image` function" ) ;
50
+
51
+ let image_device_path_protocol = bt
52
+ . open_protocol_exclusive :: < LoadedImageDevicePath > ( bt. image_handle ( ) )
53
+ . expect ( "should open LoadedImage protocol" ) ;
54
+
55
+ // Note: This is the full device path. The LoadedImage protocol would only
56
+ // provide us with the file-path portion of the device path.
57
+ let image_device_path: & DevicePath = & image_device_path_protocol;
58
+
59
+ // Get the file-path portion of the device path which is typically behind
60
+ // device path node (0x4, 0x4).
61
+ // TODO we need an abstraction in the UEFI crate for this.
62
+ let image_device_path_file_path = image_device_path
63
+ . node_iter ( )
64
+ . find ( |node| {
65
+ node. device_type ( ) == DeviceType :: MEDIA /* 0x4 */
66
+ && node. sub_type ( ) == DeviceSubType :: HARDWARE_VENDOR /* 0x4 */
67
+ } )
68
+ . map ( |node| {
69
+ CStr16 :: from_u16_with_nul ( node. data_u16 ( ) . unwrap ( ) ) . expect ( "should be valid CCtr16" )
70
+ } )
71
+ // to Rust string
72
+ . map ( |cstr16| cstr16. to_string ( ) . to_uppercase ( ) )
73
+ . expect ( "should have file-path portion in device path" ) ;
74
+
75
+ // On x86_64, this will be `\EFI\BOOT\BOOTX64.EFI` for example.
76
+ assert ! ( image_device_path_file_path
77
+ . as_str( )
78
+ . starts_with( r"\EFI\BOOT\BOOT" ) ) ;
79
+ assert ! ( image_device_path_file_path. as_str( ) . ends_with( ".EFI" ) ) ;
80
+
81
+ // Variant A: FromBuffer
82
+ {
83
+ let mut fs = bt
84
+ . get_image_file_system ( bt. image_handle ( ) )
85
+ . expect ( "should open file system" ) ;
86
+ let path = CString16 :: try_from ( image_device_path_file_path. as_str ( ) ) . unwrap ( ) ;
87
+ let image_data = fs. read ( & * path) . expect ( "should read file content" ) ;
88
+ let load_source = LoadImageSource :: FromBuffer {
89
+ buffer : image_data. as_slice ( ) ,
90
+ file_path : None ,
91
+ } ;
92
+ let _ = bt
93
+ . load_image ( bt. image_handle ( ) , load_source)
94
+ . expect ( "should load image" ) ;
95
+
96
+ log:: debug!( "load_image with FromBuffer strategy works" ) ;
97
+ }
98
+ // Variant B: FromFilePath
99
+ {
100
+ let load_source = LoadImageSource :: FromFilePath {
101
+ file_path : image_device_path,
102
+ from_boot_manager : false ,
103
+ } ;
104
+ let _ = bt
105
+ . load_image ( bt. image_handle ( ) , load_source)
106
+ . expect ( "should load image" ) ;
107
+
108
+ log:: debug!( "load_image with FromFilePath strategy works" ) ;
109
+ }
110
+ }
0 commit comments