Skip to content

Commit 9e1840d

Browse files
authored
Merge pull request #895 from nicholasbishop/bishop-raw-disk
Add raw disk protocols and use them in `uefi`
2 parents f41a34a + cac3a3b commit 9e1840d

File tree

5 files changed

+114
-54
lines changed

5 files changed

+114
-54
lines changed

uefi-raw/src/protocol/disk.rs

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
use crate::{guid, Event, Guid, Status};
2+
use core::ffi::c_void;
3+
4+
#[repr(C)]
5+
pub struct DiskIoProtocol {
6+
pub revision: u64,
7+
pub read_disk: unsafe extern "efiapi" fn(
8+
this: *const Self,
9+
media_id: u32,
10+
offset: u64,
11+
buffer_size: usize,
12+
buffer: *mut c_void,
13+
) -> Status,
14+
pub write_disk: unsafe extern "efiapi" fn(
15+
this: *mut Self,
16+
media_id: u32,
17+
offset: u64,
18+
buffer_size: usize,
19+
buffer: *const c_void,
20+
) -> Status,
21+
}
22+
23+
impl DiskIoProtocol {
24+
pub const GUID: Guid = guid!("ce345171-ba0b-11d2-8e4f-00a0c969723b");
25+
pub const REVISION: u64 = 0x00010000;
26+
}
27+
28+
#[repr(C)]
29+
#[derive(Clone, Copy, Debug, Eq, PartialEq, Ord, PartialOrd)]
30+
pub struct DiskIo2Token {
31+
pub event: Event,
32+
pub transaction_status: Status,
33+
}
34+
35+
#[repr(C)]
36+
pub struct DiskIo2Protocol {
37+
pub revision: u64,
38+
pub cancel: unsafe extern "efiapi" fn(this: *mut Self) -> Status,
39+
pub read_disk_ex: unsafe extern "efiapi" fn(
40+
this: *const Self,
41+
media_id: u32,
42+
offset: u64,
43+
token: *mut DiskIo2Token,
44+
buffer_size: usize,
45+
buffer: *mut c_void,
46+
) -> Status,
47+
pub write_disk_ex: unsafe extern "efiapi" fn(
48+
this: *mut Self,
49+
media_id: u32,
50+
offset: u64,
51+
token: *mut DiskIo2Token,
52+
buffer_size: usize,
53+
buffer: *const c_void,
54+
) -> Status,
55+
pub flush_disk_ex:
56+
unsafe extern "efiapi" fn(this: *mut Self, token: *mut DiskIo2Token) -> Status,
57+
}
58+
59+
impl DiskIo2Protocol {
60+
pub const GUID: Guid = guid!("151c8eae-7f2c-472c-9e54-9828194f6a88");
61+
pub const REVISION: u64 = 0x00020000;
62+
}

uefi-raw/src/protocol/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,5 +6,6 @@
66
77
pub mod console;
88
pub mod device_path;
9+
pub mod disk;
910
pub mod loaded_image;
1011
pub mod rng;

uefi/src/proto/media/disk.rs

Lines changed: 44 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -1,34 +1,20 @@
11
//! Disk I/O protocols.
22
33
use crate::proto::unsafe_protocol;
4+
use crate::util::opt_nonnull_to_ptr;
45
use crate::{Event, Result, Status, StatusExt};
56
use core::ptr::NonNull;
7+
use uefi_raw::protocol::disk::{DiskIo2Protocol, DiskIoProtocol};
68

79
/// The disk I/O protocol.
810
///
911
/// This protocol is used to abstract the block accesses of the block I/O
1012
/// protocol to a more general offset-length protocol. Firmware is
1113
/// responsible for adding this protocol to any block I/O interface that
1214
/// appears in the system that does not already have a disk I/O protocol.
13-
#[repr(C)]
14-
#[unsafe_protocol("ce345171-ba0b-11d2-8e4f-00a0c969723b")]
15-
pub struct DiskIo {
16-
revision: u64,
17-
read_disk: extern "efiapi" fn(
18-
this: &DiskIo,
19-
media_id: u32,
20-
offset: u64,
21-
len: usize,
22-
buffer: *mut u8,
23-
) -> Status,
24-
write_disk: extern "efiapi" fn(
25-
this: &mut DiskIo,
26-
media_id: u32,
27-
offset: u64,
28-
len: usize,
29-
buffer: *const u8,
30-
) -> Status,
31-
}
15+
#[repr(transparent)]
16+
#[unsafe_protocol(DiskIoProtocol::GUID)]
17+
pub struct DiskIo(DiskIoProtocol);
3218

3319
impl DiskIo {
3420
/// Reads bytes from the disk device.
@@ -46,7 +32,16 @@ impl DiskIo {
4632
/// * `uefi::status::NO_MEDIA` There is no medium in the device.
4733
/// * `uefi::status::MEDIA_CHANGED` `media_id` is not for the current medium.
4834
pub fn read_disk(&self, media_id: u32, offset: u64, buffer: &mut [u8]) -> Result {
49-
(self.read_disk)(self, media_id, offset, buffer.len(), buffer.as_mut_ptr()).to_result()
35+
unsafe {
36+
(self.0.read_disk)(
37+
&self.0,
38+
media_id,
39+
offset,
40+
buffer.len(),
41+
buffer.as_mut_ptr().cast(),
42+
)
43+
}
44+
.to_result()
5045
}
5146

5247
/// Writes bytes to the disk device.
@@ -65,7 +60,16 @@ impl DiskIo {
6560
/// * `uefi::status::MEDIA_CHANGED` `media_id` is not for the current medium.
6661
/// * `uefi::status::WRITE_PROTECTED` The device cannot be written to.
6762
pub fn write_disk(&mut self, media_id: u32, offset: u64, buffer: &[u8]) -> Result {
68-
(self.write_disk)(self, media_id, offset, buffer.len(), buffer.as_ptr()).to_result()
63+
unsafe {
64+
(self.0.write_disk)(
65+
&mut self.0,
66+
media_id,
67+
offset,
68+
buffer.len(),
69+
buffer.as_ptr().cast(),
70+
)
71+
}
72+
.to_result()
6973
}
7074
}
7175

@@ -83,30 +87,9 @@ pub struct DiskIo2Token {
8387
///
8488
/// This protocol provides an extension to the disk I/O protocol to enable
8589
/// non-blocking / asynchronous byte-oriented disk operation.
86-
#[repr(C)]
87-
#[unsafe_protocol("151c8eae-7f2c-472c-9e54-9828194f6a88")]
88-
pub struct DiskIo2 {
89-
revision: u64,
90-
cancel: extern "efiapi" fn(this: &mut DiskIo2) -> Status,
91-
read_disk_ex: extern "efiapi" fn(
92-
this: &DiskIo2,
93-
media_id: u32,
94-
offset: u64,
95-
token: Option<NonNull<DiskIo2Token>>,
96-
len: usize,
97-
buffer: *mut u8,
98-
) -> Status,
99-
write_disk_ex: extern "efiapi" fn(
100-
this: &mut DiskIo2,
101-
media_id: u32,
102-
offset: u64,
103-
token: Option<NonNull<DiskIo2Token>>,
104-
len: usize,
105-
buffer: *const u8,
106-
) -> Status,
107-
flush_disk_ex:
108-
extern "efiapi" fn(this: &mut DiskIo2, token: Option<NonNull<DiskIo2Token>>) -> Status,
109-
}
90+
#[repr(transparent)]
91+
#[unsafe_protocol(DiskIo2Protocol::GUID)]
92+
pub struct DiskIo2(DiskIo2Protocol);
11093

11194
impl DiskIo2 {
11295
/// Terminates outstanding asynchronous requests to the device.
@@ -115,7 +98,7 @@ impl DiskIo2 {
11598
/// * `uefi::status::DEVICE_ERROR` The device reported an error while performing
11699
/// the cancel operation.
117100
pub fn cancel(&mut self) -> Result {
118-
(self.cancel)(self).to_result()
101+
unsafe { (self.0.cancel)(&mut self.0) }.to_result()
119102
}
120103

121104
/// Reads bytes from the disk device.
@@ -149,7 +132,9 @@ impl DiskIo2 {
149132
len: usize,
150133
buffer: *mut u8,
151134
) -> Result {
152-
(self.read_disk_ex)(self, media_id, offset, token, len, buffer).to_result()
135+
let token = opt_nonnull_to_ptr(token);
136+
(self.0.read_disk_ex)(&self.0, media_id, offset, token.cast(), len, buffer.cast())
137+
.to_result()
153138
}
154139

155140
/// Writes bytes to the disk device.
@@ -184,7 +169,16 @@ impl DiskIo2 {
184169
len: usize,
185170
buffer: *const u8,
186171
) -> Result {
187-
(self.write_disk_ex)(self, media_id, offset, token, len, buffer).to_result()
172+
let token = opt_nonnull_to_ptr(token);
173+
(self.0.write_disk_ex)(
174+
&mut self.0,
175+
media_id,
176+
offset,
177+
token.cast(),
178+
len,
179+
buffer.cast(),
180+
)
181+
.to_result()
188182
}
189183

190184
/// Flushes all modified data to the physical device.
@@ -202,6 +196,7 @@ impl DiskIo2 {
202196
/// the flush operation.
203197
/// * `uefi::status::WRITE_PROTECTED` The device cannot be written to.
204198
pub fn flush_disk(&mut self, token: Option<NonNull<DiskIo2Token>>) -> Result {
205-
(self.flush_disk_ex)(self, token).to_result()
199+
let token = opt_nonnull_to_ptr(token);
200+
unsafe { (self.0.flush_disk_ex)(&mut self.0, token.cast()) }.to_result()
206201
}
207202
}

uefi/src/table/boot.rs

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ use crate::proto::device_path::DevicePath;
66
use crate::proto::loaded_image::LoadedImage;
77
use crate::proto::media::fs::SimpleFileSystem;
88
use crate::proto::{Protocol, ProtocolPointer};
9+
use crate::util::opt_nonnull_to_ptr;
910
use crate::{Char16, Error, Event, Guid, Handle, Result, Status, StatusExt};
1011
use core::cell::UnsafeCell;
1112
use core::ffi::c_void;
@@ -42,11 +43,6 @@ static IMAGE_HANDLE: GlobalImageHandle = GlobalImageHandle {
4243
/// size is always 4 KiB.
4344
pub const PAGE_SIZE: usize = 4096;
4445

45-
/// Get the raw pointer from `opt`, defaulting to `null_mut`.
46-
fn opt_nonnull_to_ptr<T>(opt: Option<NonNull<T>>) -> *mut T {
47-
opt.map(NonNull::as_ptr).unwrap_or(ptr::null_mut())
48-
}
49-
5046
/// Contains pointers to all of the boot services.
5147
///
5248
/// # Accessing `BootServices`

uefi/src/util.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
use core::mem;
2+
use core::ptr::{self, NonNull};
23

34
/// Copy the bytes of `val` to `ptr`, then advance pointer to just after the
45
/// newly-copied bytes.
@@ -24,6 +25,11 @@ pub const fn usize_from_u32(val: u32) -> usize {
2425
}
2526
}
2627

28+
/// Get the raw pointer from `opt`, defaulting to `null_mut`.
29+
pub fn opt_nonnull_to_ptr<T>(opt: Option<NonNull<T>>) -> *mut T {
30+
opt.map(NonNull::as_ptr).unwrap_or(ptr::null_mut())
31+
}
32+
2733
#[cfg(test)]
2834
mod tests {
2935
use super::*;

0 commit comments

Comments
 (0)