Skip to content

Commit 559d612

Browse files
committed
Rework disk I/O API and test
1 parent 89b7654 commit 559d612

File tree

2 files changed

+49
-58
lines changed

2 files changed

+49
-58
lines changed

src/proto/media/disk.rs

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
33
use crate::proto::Protocol;
44
use crate::{unsafe_guid, Event, Result, Status};
5+
use core::ptr::NonNull;
56

67
/// The disk I/O protocol.
78
///
@@ -73,7 +74,7 @@ impl DiskIo {
7374
#[repr(C)]
7475
pub struct DiskIo2Token {
7576
/// Event to be signalled when an asynchronous disk I/O operation completes.
76-
pub event: Option<Event>,
77+
pub event: Event,
7778
/// Transaction status code.
7879
pub transaction_status: Status,
7980
}
@@ -92,19 +93,20 @@ pub struct DiskIo2 {
9293
this: &DiskIo2,
9394
media_id: u32,
9495
offset: u64,
95-
token: &mut DiskIo2Token,
96+
token: Option<NonNull<DiskIo2Token>>,
9697
len: usize,
9798
buffer: *mut u8,
9899
) -> Status,
99100
write_disk_ex: extern "efiapi" fn(
100101
this: &mut DiskIo2,
101102
media_id: u32,
102103
offset: u64,
103-
token: &mut DiskIo2Token,
104+
token: Option<NonNull<DiskIo2Token>>,
104105
len: usize,
105106
buffer: *const u8,
106107
) -> Status,
107-
flush_disk_ex: extern "efiapi" fn(this: &mut DiskIo2, token: &mut DiskIo2Token) -> Status,
108+
flush_disk_ex:
109+
extern "efiapi" fn(this: &mut DiskIo2, token: Option<NonNull<DiskIo2Token>>) -> Status,
108110
}
109111

110112
impl DiskIo2 {
@@ -144,11 +146,11 @@ impl DiskIo2 {
144146
&self,
145147
media_id: u32,
146148
offset: u64,
147-
token: *mut DiskIo2Token,
149+
token: Option<NonNull<DiskIo2Token>>,
148150
len: usize,
149151
buffer: *mut u8,
150152
) -> Result {
151-
(self.read_disk_ex)(self, media_id, offset, &mut *token, len, buffer).into()
153+
(self.read_disk_ex)(self, media_id, offset, token, len, buffer).into()
152154
}
153155

154156
/// Writes bytes to the disk device.
@@ -179,11 +181,11 @@ impl DiskIo2 {
179181
&mut self,
180182
media_id: u32,
181183
offset: u64,
182-
token: *mut DiskIo2Token,
184+
token: Option<NonNull<DiskIo2Token>>,
183185
len: usize,
184186
buffer: *const u8,
185187
) -> Result {
186-
(self.write_disk_ex)(self, media_id, offset, &mut *token, len, buffer).into()
188+
(self.write_disk_ex)(self, media_id, offset, token, len, buffer).into()
187189
}
188190

189191
/// Flushes all modified data to the physical device.
@@ -200,7 +202,7 @@ impl DiskIo2 {
200202
/// * `uefi::status::DEVICE_ERROR` The device reported an error while performing
201203
/// the flush operation.
202204
/// * `uefi::status::WRITE_PROTECTED` The device cannot be written to.
203-
pub fn flush_disk(&mut self, token: &mut DiskIo2Token) -> Result {
205+
pub fn flush_disk(&mut self, token: Option<NonNull<DiskIo2Token>>) -> Result {
204206
(self.flush_disk_ex)(self, token).into()
205207
}
206208
}

uefi-test-runner/src/proto/media/known_disk.rs

Lines changed: 38 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
use alloc::string::ToString;
2-
use core::ffi::c_void;
32
use core::ptr::NonNull;
43
use uefi::prelude::*;
54
use uefi::proto::media::block::BlockIO;
@@ -8,10 +7,8 @@ use uefi::proto::media::file::{
87
Directory, File, FileAttribute, FileInfo, FileMode, FileSystemInfo,
98
};
109
use uefi::proto::media::fs::SimpleFileSystem;
11-
use uefi::table::boot::{EventType, MemoryType, OpenProtocolAttributes, OpenProtocolParams, Tpl};
10+
use uefi::table::boot::{EventType, OpenProtocolAttributes, OpenProtocolParams, Tpl};
1211
use uefi::table::runtime::{Daylight, Time, TimeParams};
13-
use uefi::Event;
14-
use uefi_services::system_table;
1512

1613
/// Test directory entry iteration.
1714
fn test_existing_dir(directory: &mut Directory) {
@@ -190,26 +187,8 @@ fn test_raw_disk_io(handle: Handle, image: Handle, bt: &BootServices) {
190187
struct DiskIoTask {
191188
/// Token for the transaction
192189
token: DiskIo2Token,
193-
/// Pointer to a buffer holding the read data
194-
buffer: *mut u8,
195-
}
196-
197-
/// Asynchronous disk I/O 2 transaction callback
198-
unsafe extern "efiapi" fn disk_io2_callback(event: Event, ctx: Option<NonNull<c_void>>) {
199-
let task = ctx.unwrap().as_ptr() as *mut DiskIoTask;
200-
201-
// Verify that the disk's MBR signature is correct
202-
assert_eq!((*task).token.transaction_status, uefi::Status::SUCCESS);
203-
assert_eq!(*(*task).buffer.offset(510), 0x55);
204-
assert_eq!(*(*task).buffer.offset(511), 0xaa);
205-
206-
// Close the completion event
207-
let bt = system_table().as_ref().boot_services();
208-
bt.close_event(event).unwrap();
209-
210-
// Free the disk data buffer & task context
211-
bt.free_pool((*task).buffer).unwrap();
212-
bt.free_pool(task as *mut u8).unwrap();
190+
/// Buffer holding the read data
191+
buffer: [u8; 512],
213192
}
214193

215194
/// Tests raw disk I/O through the DiskIo2 protocol.
@@ -237,44 +216,54 @@ fn test_raw_disk_io2(handle: Handle, image: Handle, bt: &BootServices) {
237216
)
238217
.expect("Failed to get block I/O protocol");
239218

240-
// Allocate the task context structure
241-
let task = bt
242-
.allocate_pool(MemoryType::LOADER_DATA, core::mem::size_of::<DiskIoTask>())
243-
.expect("Failed to allocate task struct for disk I/O")
244-
as *mut DiskIoTask;
245-
246-
// SAFETY: `task` refers to a valid allocation of at least `size_of::<DiskIoTask>()`
247219
unsafe {
248-
// Create the completion event as part of the disk I/O token
249-
(*task).token.event = Some(
250-
bt.create_event(
251-
EventType::NOTIFY_SIGNAL,
220+
// Create the task context structure
221+
let mut task = core::mem::MaybeUninit::uninit();
222+
223+
// Create the completion event
224+
let mut event = bt
225+
.create_event(
226+
EventType::empty(),
252227
Tpl::NOTIFY,
253-
Some(disk_io2_callback),
254-
NonNull::new(task as *mut c_void),
228+
None,
229+
NonNull::new(task.as_mut_ptr() as _),
255230
)
256-
.expect("Failed to create disk I/O completion event"),
257-
);
231+
.expect("Failed to create disk I/O completion event");
232+
233+
// Initialise the task context
234+
task.write(DiskIoTask {
235+
token: DiskIo2Token {
236+
event: event.unsafe_clone(),
237+
transaction_status: uefi::Status::NOT_READY,
238+
},
239+
buffer: [0; 512],
240+
});
258241

259-
// Allocate a buffer for the transaction to read into
260-
const SIZE_TO_READ: usize = 512;
261-
(*task).buffer = bt
262-
.allocate_pool(MemoryType::LOADER_DATA, SIZE_TO_READ)
263-
.expect("Failed to allocate buffer for disk I/O");
242+
// Get a mutable reference to the task to not move it
243+
let task_ref = task.assume_init_mut();
264244

265245
// Initiate the asynchronous read operation
266246
disk_io2
267247
.read_disk_raw(
268248
block_io.media().media_id(),
269249
0,
270-
&mut (*task).token,
271-
SIZE_TO_READ,
272-
(*task).buffer,
250+
NonNull::new(&mut task_ref.token as _),
251+
task_ref.buffer.len(),
252+
task_ref.buffer.as_mut_ptr(),
273253
)
274254
.expect("Failed to initiate asynchronous disk I/O read");
275-
}
276255

277-
info!("Raw disk I/O 2 succeeded");
256+
// Wait for the transaction to complete
257+
bt.wait_for_event(core::slice::from_mut(&mut event))
258+
.expect("Failed to wait on completion event");
259+
260+
// Verify that the disk's MBR signature is correct
261+
assert_eq!(task_ref.token.transaction_status, uefi::Status::SUCCESS);
262+
assert_eq!(task_ref.buffer[510], 0x55);
263+
assert_eq!(task_ref.buffer[511], 0xaa);
264+
265+
info!("Raw disk I/O 2 succeeded");
266+
}
278267
}
279268
}
280269

0 commit comments

Comments
 (0)