@@ -181,71 +181,79 @@ fn test_raw_disk_io(handle: Handle, image: Handle, bt: &BootServices) {
181181 bt. free_pool ( buf) . unwrap ( ) ;
182182}
183183
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+
184193/// Asynchronous disk I/O 2 transaction callback
185194unsafe 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 ;
187196
188197 // 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 ( ) ;
197209}
198210
199211/// Tests raw disk I/O through the DiskIo2 protocol.
200212fn test_raw_disk_io2 ( handle : Handle , image : Handle , bt : & BootServices ) {
201213 info ! ( "Testing raw disk I/O 2" ) ;
202214
203215 // 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 > (
205217 OpenProtocolParams {
206218 handle,
207219 agent : image,
208220 controller : None ,
209221 } ,
210222 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+ }
234254
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" ) ;
245256 }
246-
247- info ! ( "Raw disk I/O 2 succeeded" ) ;
248- bt. free_pool ( buf) . unwrap ( ) ;
249257}
250258
251259/// Run various tests on a special test disk. The disk is created by
0 commit comments