1
1
use alloc:: string:: ToString ;
2
+ use core:: ffi:: c_void;
3
+ use core:: ptr:: NonNull ;
2
4
use uefi:: prelude:: * ;
5
+ use uefi:: proto:: media:: disk:: { DiskIo , DiskIo2 , DiskIo2Token } ;
3
6
use uefi:: proto:: media:: file:: {
4
7
Directory , File , FileAttribute , FileInfo , FileMode , FileSystemInfo ,
5
8
} ;
6
9
use uefi:: proto:: media:: fs:: SimpleFileSystem ;
7
- use uefi:: table:: boot:: { OpenProtocolAttributes , OpenProtocolParams } ;
10
+ use uefi:: table:: boot:: { EventType , MemoryType , OpenProtocolAttributes , OpenProtocolParams , Tpl } ;
8
11
use uefi:: table:: runtime:: { Daylight , Time , TimeParams } ;
12
+ use uefi:: Event ;
9
13
10
14
/// Test directory entry iteration.
11
15
fn test_existing_dir ( directory : & mut Directory ) {
@@ -138,6 +142,103 @@ fn test_create_file(directory: &mut Directory) {
138
142
file. write ( b"test output data" ) . unwrap ( ) ;
139
143
}
140
144
145
+ /// Tests raw disk I/O.
146
+ fn test_raw_disk_io ( handle : Handle , image : Handle , bt : & BootServices ) {
147
+ info ! ( "Testing raw disk I/O" ) ;
148
+
149
+ // Open the disk I/O protocol on the input handle
150
+ let disk_io = bt
151
+ . open_protocol :: < DiskIo > (
152
+ OpenProtocolParams {
153
+ handle,
154
+ agent : image,
155
+ controller : None ,
156
+ } ,
157
+ OpenProtocolAttributes :: GetProtocol ,
158
+ )
159
+ . expect ( "Failed to get disk I/O protocol" ) ;
160
+
161
+ // Allocate a temporary buffer to read into
162
+ const SIZE : usize = 512 ;
163
+ let buf = bt
164
+ . allocate_pool ( MemoryType :: LOADER_DATA , SIZE )
165
+ . expect ( "Failed to allocate temporary buffer" ) ;
166
+
167
+ // SAFETY: A valid buffer of `SIZE` bytes was allocated above
168
+ let slice = unsafe { core:: slice:: from_raw_parts_mut ( buf, SIZE ) } ;
169
+
170
+ // Read from the first sector of the disk into the buffer
171
+ disk_io
172
+ . read_disk ( 0 , 0 , slice)
173
+ . expect ( "Failed to read from disk" ) ;
174
+
175
+ // Verify that the disk's MBR signature is correct
176
+ assert_eq ! ( slice[ 510 ] , 0x55 ) ;
177
+ assert_eq ! ( slice[ 511 ] , 0xaa ) ;
178
+
179
+ info ! ( "Raw disk I/O succeeded" ) ;
180
+ bt. free_pool ( buf) . unwrap ( ) ;
181
+ }
182
+
183
+ /// Asynchronous disk I/O 2 transaction callback
184
+ unsafe extern "efiapi" fn disk_io2_callback ( _event : Event , ctx : Option < NonNull < c_void > > ) {
185
+ let ptr = ctx. unwrap ( ) . as_ptr ( ) as * const u8 ;
186
+
187
+ // Verify that the disk's MBR signature is correct
188
+ assert_eq ! ( * ptr. offset( 510 ) , 0x55 ) ;
189
+ assert_eq ! ( * ptr. offset( 511 ) , 0xaa ) ;
190
+ }
191
+
192
+ /// Tests raw disk I/O through the DiskIo2 protocol.
193
+ fn test_raw_disk_io2 ( handle : Handle , image : Handle , bt : & BootServices ) {
194
+ info ! ( "Testing raw disk I/O 2" ) ;
195
+
196
+ // Open the disk I/O protocol on the input handle
197
+ let disk_io2 = bt
198
+ . open_protocol :: < DiskIo2 > (
199
+ OpenProtocolParams {
200
+ handle,
201
+ agent : image,
202
+ controller : None ,
203
+ } ,
204
+ OpenProtocolAttributes :: GetProtocol ,
205
+ )
206
+ . expect ( "Failed to get disk I/O 2 protocol" ) ;
207
+
208
+ // Allocate a temporary buffer to read into
209
+ const SIZE : usize = 512 ;
210
+ let buf = bt
211
+ . allocate_pool ( MemoryType :: LOADER_DATA , SIZE )
212
+ . expect ( "Failed to allocate temporary buffer" ) ;
213
+
214
+ // Create an event callback for the disk read completion
215
+ let event = unsafe {
216
+ bt. create_event (
217
+ EventType :: NOTIFY_SIGNAL ,
218
+ Tpl :: NOTIFY ,
219
+ Some ( disk_io2_callback) ,
220
+ NonNull :: new ( buf as * mut c_void ) ,
221
+ )
222
+ . expect ( "Failed to create event for disk I/O 2 transaction" )
223
+ } ;
224
+
225
+ // Read from the first sector of the disk into the buffer
226
+ // SAFETY: The cloned `event` is only used for this transaction
227
+ unsafe {
228
+ let mut token = DiskIo2Token {
229
+ event : Some ( event. unsafe_clone ( ) ) ,
230
+ transaction_status : uefi:: Status :: SUCCESS ,
231
+ } ;
232
+ disk_io2
233
+ . read_disk_raw ( 0 , 0 , & mut token, SIZE , buf)
234
+ . expect ( "Failed to read from disk" ) ;
235
+ }
236
+
237
+ info ! ( "Raw disk I/O 2 succeeded" ) ;
238
+ bt. close_event ( event) . unwrap ( ) ;
239
+ bt. free_pool ( buf) . unwrap ( ) ;
240
+ }
241
+
141
242
/// Run various tests on a special test disk. The disk is created by
142
243
/// xtask/src/disk.rs.
143
244
pub fn test_known_disk ( image : Handle , bt : & BootServices ) {
@@ -154,6 +255,10 @@ pub fn test_known_disk(image: Handle, bt: &BootServices) {
154
255
155
256
let mut found_test_disk = false ;
156
257
for handle in handles {
258
+ // Test raw disk I/O first
259
+ test_raw_disk_io ( handle, image, bt) ;
260
+ test_raw_disk_io2 ( handle, image, bt) ;
261
+
157
262
let mut sfs = bt
158
263
. open_protocol :: < SimpleFileSystem > (
159
264
OpenProtocolParams {
0 commit comments