@@ -181,71 +181,79 @@ fn test_raw_disk_io(handle: Handle, image: Handle, bt: &BootServices) {
181
181
bt. free_pool ( buf) . unwrap ( ) ;
182
182
}
183
183
184
+ /// Asynchronous disk I/O task context
185
+ #[ repr( C ) ]
186
+ struct DiskIoTask {
187
+ /// Token for the transaction
188
+ token : DiskIo2Token ,
189
+ /// Pointer to a buffer holding the read data
190
+ buffer : * mut u8 ,
191
+ }
192
+
184
193
/// Asynchronous disk I/O 2 transaction callback
185
194
unsafe extern "efiapi" fn disk_io2_callback ( event : Event , ctx : Option < NonNull < c_void > > ) {
186
- let ptr = ctx. unwrap ( ) . as_ptr ( ) as * const u8 ;
195
+ let task = ctx. unwrap ( ) . as_ptr ( ) as * mut DiskIoTask ;
187
196
188
197
// Verify that the disk's MBR signature is correct
189
- assert_eq ! ( * ptr. offset( 510 ) , 0x55 ) ;
190
- assert_eq ! ( * ptr. offset( 511 ) , 0xaa ) ;
191
-
192
- system_table ( )
193
- . as_ref ( )
194
- . boot_services ( )
195
- . close_event ( event)
196
- . unwrap ( ) ;
198
+ assert_eq ! ( ( * task) . token. transaction_status, uefi:: Status :: SUCCESS ) ;
199
+ assert_eq ! ( * ( * task) . buffer. offset( 510 ) , 0x55 ) ;
200
+ assert_eq ! ( * ( * task) . buffer. offset( 511 ) , 0xaa ) ;
201
+
202
+ // Close the completion event
203
+ let bt = system_table ( ) . as_ref ( ) . boot_services ( ) ;
204
+ bt. close_event ( event) . unwrap ( ) ;
205
+
206
+ // Free the disk data buffer & task context
207
+ bt. free_pool ( ( * task) . buffer ) . unwrap ( ) ;
208
+ bt. free_pool ( task as * mut u8 ) . unwrap ( ) ;
197
209
}
198
210
199
211
/// Tests raw disk I/O through the DiskIo2 protocol.
200
212
fn test_raw_disk_io2 ( handle : Handle , image : Handle , bt : & BootServices ) {
201
213
info ! ( "Testing raw disk I/O 2" ) ;
202
214
203
215
// Open the disk I/O protocol on the input handle
204
- let disk_io2 = bt. open_protocol :: < DiskIo2 > (
216
+ if let Ok ( disk_io2) = bt. open_protocol :: < DiskIo2 > (
205
217
OpenProtocolParams {
206
218
handle,
207
219
agent : image,
208
220
controller : None ,
209
221
} ,
210
222
OpenProtocolAttributes :: GetProtocol ,
211
- ) ;
212
- if disk_io2. is_err ( ) {
213
- return ;
214
- }
215
-
216
- let disk_io2 = disk_io2. unwrap ( ) ;
217
-
218
- // Allocate a temporary buffer to read into
219
- const SIZE : usize = 512 ;
220
- let buf = bt
221
- . allocate_pool ( MemoryType :: LOADER_DATA , SIZE )
222
- . expect ( "Failed to allocate temporary buffer" ) ;
223
-
224
- // Create an event callback for the disk read completion
225
- let event = unsafe {
226
- bt. create_event (
227
- EventType :: NOTIFY_SIGNAL ,
228
- Tpl :: NOTIFY ,
229
- Some ( disk_io2_callback) ,
230
- NonNull :: new ( buf as * mut c_void ) ,
231
- )
232
- . expect ( "Failed to create event for disk I/O 2 transaction" )
233
- } ;
223
+ ) {
224
+ // Allocate the task context structure
225
+ let task = bt
226
+ . allocate_pool ( MemoryType :: LOADER_DATA , core:: mem:: size_of :: < DiskIoTask > ( ) )
227
+ . expect ( "Failed to allocate task struct for disk I/O" )
228
+ as * mut DiskIoTask ;
229
+
230
+ // SAFETY: `task` refers to a valid allocation of at least `size_of::<DiskIoTask>()`
231
+ unsafe {
232
+ // Create the completion event as part of the disk I/O token
233
+ ( * task) . token . event = Some (
234
+ bt. create_event (
235
+ EventType :: NOTIFY_SIGNAL ,
236
+ Tpl :: NOTIFY ,
237
+ Some ( disk_io2_callback) ,
238
+ NonNull :: new ( task as * mut c_void ) ,
239
+ )
240
+ . expect ( "Failed to create disk I/O completion event" ) ,
241
+ ) ;
242
+
243
+ // Allocate a buffer for the transaction to read into
244
+ const SIZE_TO_READ : usize = 512 ;
245
+ ( * task) . buffer = bt
246
+ . allocate_pool ( MemoryType :: LOADER_DATA , SIZE_TO_READ )
247
+ . expect ( "Failed to allocate buffer for disk I/O" ) ;
248
+
249
+ // Initiate the asynchronous read operation
250
+ disk_io2
251
+ . read_disk_raw ( 0 , 0 , & mut ( * task) . token , SIZE_TO_READ , ( * task) . buffer )
252
+ . expect ( "Failed to initiate asynchronous disk I/O read" ) ;
253
+ }
234
254
235
- // Read from the first sector of the disk into the buffer
236
- // SAFETY: The cloned `event` is only used for this transaction
237
- unsafe {
238
- let mut token = DiskIo2Token {
239
- event : Some ( event. unsafe_clone ( ) ) ,
240
- transaction_status : uefi:: Status :: SUCCESS ,
241
- } ;
242
- disk_io2
243
- . read_disk_raw ( 0 , 0 , & mut token, SIZE , buf)
244
- . expect ( "Failed to read from disk" ) ;
255
+ info ! ( "Raw disk I/O 2 succeeded" ) ;
245
256
}
246
-
247
- info ! ( "Raw disk I/O 2 succeeded" ) ;
248
- bt. free_pool ( buf) . unwrap ( ) ;
249
257
}
250
258
251
259
/// Run various tests on a special test disk. The disk is created by
0 commit comments