uefi: Use unsafe_protocol! for all protocol impls

Switch all uses of `unsafe_guid!` + `derive(Protocol)` to using
`unsafe_protocol!`.

Also update the docstrings for the `Identify` and `Protocol` traits.
This commit is contained in:
Nicholas Bishop 2022-12-11 04:27:08 -05:00
parent dc7d765f06
commit be7a20cce1
26 changed files with 90 additions and 115 deletions

View file

@ -81,7 +81,7 @@ in the order the UEFI spec requires.
Each protocol also has a Globally Unique Identifier (in the C API, they're usually
found in a `EFI_*_PROTOCOL_GUID` define). In Rust, we store the GUID as an associated
constant, by implementing the unsafe trait `uefi::proto::Identify`. For convenience,
this is done through the `unsafe_guid` macro.
this is done through the `unsafe_protocol` macro.
Finally, you should derive the `Protocol` trait. This is a marker trait,
extending `Identify`, which is used as a generic bound in the functions which retrieve
@ -92,8 +92,7 @@ An example protocol declaration:
```rust
/// Protocol which does something.
#[repr(C)]
#[unsafe_guid("abcdefgh-1234-5678-9012-123456789abc")]
#[derive(Protocol)]
#[unsafe_protocol("abcdefgh-1234-5678-9012-123456789abc")]
pub struct NewProtocol {
some_entry_point: extern "efiapi" fn(
this: *const NewProtocol,

View file

@ -1,9 +1,9 @@
use core::ffi::c_void;
use core::ptr::{self, NonNull};
use uefi::proto::Protocol;
use uefi::proto::unsafe_protocol;
use uefi::table::boot::{BootServices, EventType, SearchType, TimerTrigger, Tpl};
use uefi::{unsafe_guid, Event, Identify};
use uefi::{Event, Identify};
pub fn test(bt: &BootServices) {
info!("Testing timer...");
@ -80,8 +80,7 @@ fn test_watchdog(bt: &BootServices) {
}
/// Dummy protocol for tests
#[unsafe_guid("1a972918-3f69-4b5d-8cb4-cece2309c7f5")]
#[derive(Protocol)]
#[unsafe_protocol("1a972918-3f69-4b5d-8cb4-cece2309c7f5")]
struct TestProtocol {}
unsafe extern "efiapi" fn _test_notify(_event: Event, _context: Option<NonNull<c_void>>) {

View file

@ -114,24 +114,20 @@ impl fmt::Display for Guid {
/// this trait is a building block to interface them in uefi-rs.
///
/// You should never need to use the `Identify` trait directly, but instead go
/// for more specific traits such as `Protocol` or `FileProtocolInfo`, which
/// for more specific traits such as [`Protocol`] or [`FileProtocolInfo`], which
/// indicate in which circumstances an `Identify`-tagged type should be used.
///
/// For the common case of implementing this trait for a protocol, use
/// the [`unsafe_protocol`] macro.
///
/// # Safety
///
/// Implementing `Identify` is unsafe because attaching an incorrect GUID to a
/// type can lead to type unsafety on both the Rust and UEFI side.
///
/// You can derive `Identify` for a type using the `unsafe_guid` procedural
/// macro, which is exported by this module. This macro mostly works like a
/// custom derive, but also supports type aliases. It takes a GUID in canonical
/// textual format as an argument, and is used in the following way:
///
/// ```
/// use uefi::unsafe_guid;
/// #[unsafe_guid("12345678-9abc-def0-1234-56789abcdef0")]
/// struct Emptiness;
/// ```
/// [`Protocol`]: crate::proto::Protocol
/// [`FileProtocolInfo`]: crate::proto::media::file::FileProtocolInfo
/// [`unsafe_protocol`]: crate::proto::unsafe_protocol
pub unsafe trait Identify {
/// Unique protocol identifier.
const GUID: Guid;

View file

@ -54,8 +54,8 @@
//! You will have to implement your own double buffering if you want to
//! avoid tearing with animations.
use crate::proto::Protocol;
use crate::{unsafe_guid, Result, Status};
use crate::proto::unsafe_protocol;
use crate::{Result, Status};
use core::marker::PhantomData;
use core::mem;
use core::ptr;
@ -65,8 +65,7 @@ use core::ptr;
/// The GOP can be used to set the properties of the frame buffer,
/// and also allows the app to access the in-memory buffer.
#[repr(C)]
#[unsafe_guid("9042a9de-23dc-4a38-96fb-7aded080516a")]
#[derive(Protocol)]
#[unsafe_protocol("9042a9de-23dc-4a38-96fb-7aded080516a")]
pub struct GraphicsOutput<'boot> {
query_mode: extern "efiapi" fn(
&GraphicsOutput,

View file

@ -1,13 +1,12 @@
//! Pointer device access.
use crate::proto::Protocol;
use crate::{unsafe_guid, Event, Result, Status};
use crate::proto::unsafe_protocol;
use crate::{Event, Result, Status};
use core::mem::MaybeUninit;
/// Provides information about a pointer device.
#[repr(C)]
#[unsafe_guid("31878c87-0b75-11d5-9a4f-0090273fc14d")]
#[derive(Protocol)]
#[unsafe_protocol("31878c87-0b75-11d5-9a4f-0090273fc14d")]
pub struct Pointer<'boot> {
reset: extern "efiapi" fn(this: &mut Pointer, ext_verif: bool) -> Status,
get_state: extern "efiapi" fn(this: &Pointer, state: *mut PointerState) -> Status,

View file

@ -2,8 +2,8 @@
use core::fmt::Write;
use crate::proto::Protocol;
use crate::{unsafe_guid, Result, Status};
use crate::proto::unsafe_protocol;
use crate::{Result, Status};
use bitflags::bitflags;
/// Provides access to a serial I/O device.
@ -14,8 +14,7 @@ use bitflags::bitflags;
/// Since UEFI drivers are implemented through polling, if you fail to regularly
/// check for input/output, some data might be lost.
#[repr(C)]
#[unsafe_guid("bb25cf6f-f1d4-11d2-9a0c-0090273fc1fd")]
#[derive(Protocol)]
#[unsafe_protocol("bb25cf6f-f1d4-11d2-9a0c-0090273fc1fd")]
pub struct Serial<'boot> {
// Revision of this protocol, only 1.0 is currently defined.
// Future versions will be backwards compatible.

View file

@ -1,11 +1,10 @@
use crate::proto::Protocol;
use crate::{unsafe_guid, Char16, Event, Result, Status};
use crate::proto::unsafe_protocol;
use crate::{Char16, Event, Result, Status};
use core::mem::MaybeUninit;
/// Interface for text-based input devices.
#[repr(C)]
#[unsafe_guid("387477c1-69c7-11d2-8e39-00a0c969723b")]
#[derive(Protocol)]
#[unsafe_protocol("387477c1-69c7-11d2-8e39-00a0c969723b")]
pub struct Input {
reset: extern "efiapi" fn(this: &mut Input, extended: bool) -> Status,
read_key_stroke: extern "efiapi" fn(this: &mut Input, key: *mut RawKey) -> Status,

View file

@ -1,5 +1,5 @@
use crate::proto::Protocol;
use crate::{unsafe_guid, CStr16, Char16, Result, ResultExt, Status};
use crate::proto::unsafe_protocol;
use crate::{CStr16, Char16, Result, ResultExt, Status};
use core::fmt;
use core::fmt::{Debug, Formatter};
@ -21,8 +21,7 @@ use core::fmt::{Debug, Formatter};
/// [`SystemTable::stderr`]: crate::table::SystemTable::stderr
/// [`BootServices`]: crate::table::boot::BootServices#accessing-protocols
#[repr(C)]
#[unsafe_guid("387477c2-69c7-11d2-8e39-00a0c969723b")]
#[derive(Protocol)]
#[unsafe_protocol("387477c2-69c7-11d2-8e39-00a0c969723b")]
pub struct Output<'boot> {
reset: extern "efiapi" fn(this: &Output, extended: bool) -> Status,
output_string: unsafe extern "efiapi" fn(this: &Output, string: *const Char16) -> Status,

View file

@ -11,8 +11,8 @@
use core::ffi::c_void;
use crate::proto::Protocol;
use crate::{unsafe_guid, Result, Status};
use crate::proto::unsafe_protocol;
use crate::{Result, Status};
// re-export for ease of use
pub use self::context::SystemContext;
@ -30,8 +30,7 @@ mod exception;
///
/// NOTE: OVMF only implements this protocol interface for the virtual EBC processor
#[repr(C)]
#[unsafe_guid("2755590c-6f3c-42fa-9ea4-a3ba543cda25")]
#[derive(Protocol)]
#[unsafe_protocol("2755590c-6f3c-42fa-9ea4-a3ba543cda25")]
pub struct DebugSupport {
isa: ProcessorArch,
get_maximum_processor_index:

View file

@ -69,6 +69,7 @@
//!
//! [`END_ENTIRE`]: DeviceSubType::END_ENTIRE
//! [`END_INSTANCE`]: DeviceSubType::END_INSTANCE
//! [`Protocol`]: crate::proto::Protocol
//! [`device_type`]: DevicePathNode::device_type
//! [`sub_type`]: DevicePathNode::sub_type
@ -80,8 +81,7 @@ pub use device_path_gen::{
acpi, bios_boot_spec, end, hardware, media, messaging, DevicePathNodeEnum,
};
use crate::proto::{Protocol, ProtocolPointer};
use crate::unsafe_guid;
use crate::proto::{unsafe_protocol, ProtocolPointer};
use core::ffi::c_void;
use core::marker::{PhantomData, PhantomPinned};
use core::{mem, ptr};
@ -225,8 +225,8 @@ impl DevicePathInstance {
/// [module-level documentation]: crate::proto::device_path
/// [`END_ENTIRE`]: DeviceSubType::END_ENTIRE
#[repr(C, packed)]
#[unsafe_guid("09576e91-6d3f-11d2-8e39-00a0c969723b")]
#[derive(Debug, Eq, PartialEq, Protocol)]
#[unsafe_protocol("09576e91-6d3f-11d2-8e39-00a0c969723b")]
#[derive(Debug, Eq, PartialEq)]
pub struct DevicePath {
data: [u8],
}

View file

@ -10,9 +10,9 @@
use crate::{
proto::device_path::{DevicePath, DevicePathNode, FfiDevicePath},
proto::Protocol,
proto::unsafe_protocol,
table::boot::BootServices,
unsafe_guid, CStr16, Char16, Result, Status,
CStr16, Char16, Result, Status,
};
use core::ops::Deref;
@ -82,8 +82,7 @@ impl Drop for PoolString<'_> {
/// This protocol provides common utility functions for converting device
/// nodes and device paths to a text representation.
#[repr(C)]
#[unsafe_guid("8b843e20-8132-4852-90cc-551a4e4a7f1c")]
#[derive(Protocol)]
#[unsafe_protocol("8b843e20-8132-4852-90cc-551a4e4a7f1c")]
pub struct DevicePathToText {
convert_device_node_to_text: unsafe extern "efiapi" fn(
device_node: *const FfiDevicePath,
@ -150,8 +149,7 @@ impl DevicePathToText {
/// This protocol provides common utilities for converting text to
/// device paths and device nodes.
#[repr(C)]
#[unsafe_guid("05c99a21-c70f-4ad2-8a5f-35df3343f51e")]
#[derive(Protocol)]
#[unsafe_protocol("05c99a21-c70f-4ad2-8a5f-35df3343f51e")]
pub struct DevicePathFromText {
convert_text_to_device_node:
unsafe extern "efiapi" fn(text_device_node: *const Char16) -> *const FfiDevicePath,

View file

@ -3,16 +3,15 @@
use crate::{
data_types::FromSliceWithNulError,
proto::device_path::{DevicePath, FfiDevicePath},
proto::Protocol,
proto::unsafe_protocol,
table::boot::MemoryType,
unsafe_guid, CStr16, Handle, Status,
CStr16, Handle, Status,
};
use core::{ffi::c_void, mem, slice};
/// The LoadedImage protocol. This can be opened on any image handle using the `HandleProtocol` boot service.
#[repr(C)]
#[unsafe_guid("5b1b31a1-9562-11d2-8e3f-00a0c969723b")]
#[derive(Protocol)]
#[unsafe_protocol("5b1b31a1-9562-11d2-8e3f-00a0c969723b")]
pub struct LoadedImage {
revision: u32,
parent_handle: Handle,

View file

@ -1,12 +1,11 @@
//! Block I/O protocols.
use crate::proto::Protocol;
use crate::{unsafe_guid, Result, Status};
use crate::proto::unsafe_protocol;
use crate::{Result, Status};
/// The Block I/O protocol.
#[repr(C)]
#[unsafe_guid("964e5b21-6459-11d2-8e39-00a0c969723b")]
#[derive(Protocol)]
#[unsafe_protocol("964e5b21-6459-11d2-8e39-00a0c969723b")]
pub struct BlockIO {
revision: u64,
media: *const BlockIOMedia,

View file

@ -1,7 +1,7 @@
//! Disk I/O protocols.
use crate::proto::Protocol;
use crate::{unsafe_guid, Event, Result, Status};
use crate::proto::unsafe_protocol;
use crate::{Event, Result, Status};
use core::ptr::NonNull;
/// The disk I/O protocol.
@ -11,8 +11,7 @@ use core::ptr::NonNull;
/// reponsible for adding this protocol to any block I/O interface that
/// appears in the system that does not already have a disk I/O protocol.
#[repr(C)]
#[unsafe_guid("ce345171-ba0b-11d2-8e4f-00a0c969723b")]
#[derive(Protocol)]
#[unsafe_protocol("ce345171-ba0b-11d2-8e4f-00a0c969723b")]
pub struct DiskIo {
revision: u64,
read_disk: extern "efiapi" fn(
@ -84,8 +83,7 @@ pub struct DiskIo2Token {
/// This protocol provides an extension to the disk I/O protocol to enable
/// non-blocking / asynchronous byte-oriented disk operation.
#[repr(C)]
#[unsafe_guid("151c8eae-7f2c-472c-9e54-9828194f6a88")]
#[derive(Protocol)]
#[unsafe_protocol("151c8eae-7f2c-472c-9e54-9828194f6a88")]
pub struct DiskIo2 {
revision: u64,
cancel: extern "efiapi" fn(this: &mut DiskIo2) -> Status,

View file

@ -1,8 +1,8 @@
//! File system support protocols.
use super::file::{Directory, FileHandle, FileImpl};
use crate::proto::Protocol;
use crate::{unsafe_guid, Result, Status};
use crate::proto::unsafe_protocol;
use crate::{Result, Status};
use core::ptr;
/// Allows access to a FAT-12/16/32 file system.
@ -20,8 +20,7 @@ use core::ptr;
/// [`BootServices::get_image_file_system`]: crate::table::boot::BootServices::get_image_file_system
/// [`BootServices`]: crate::table::boot::BootServices#accessing-protocols
#[repr(C)]
#[unsafe_guid("964e5b22-6459-11d2-8e39-00a0c969723b")]
#[derive(Protocol)]
#[unsafe_protocol("964e5b22-6459-11d2-8e39-00a0c969723b")]
pub struct SimpleFileSystem {
revision: u64,
open_volume:

View file

@ -1,7 +1,7 @@
//! Partition information protocol.
use crate::proto::Protocol;
use crate::{guid, unsafe_guid, Char16, Guid};
use crate::proto::unsafe_protocol;
use crate::{guid, Char16, Guid};
use bitflags::bitflags;
newtype_enum! {
@ -175,8 +175,7 @@ newtype_enum! {
/// Protocol for accessing partition information.
#[repr(C)]
#[repr(packed)]
#[unsafe_guid("8cf2f62c-bc9b-4821-808d-ec9ec421a1a0")]
#[derive(Clone, Copy, Protocol)]
#[unsafe_protocol("8cf2f62c-bc9b-4821-808d-ec9ec421a1a0")]
pub struct PartitionInfo {
/// Revision of the partition info protocol.
pub revision: PartitionInfoRevision,

View file

@ -12,19 +12,23 @@
use crate::Identify;
use core::ffi::c_void;
/// Common trait implemented by all standard UEFI protocols
/// Common trait implemented by all standard UEFI protocols.
///
/// According to the UEFI's specification, protocols are `!Send` (they expect to
/// be run on the bootstrap processor) and `!Sync` (they are not thread-safe).
/// You can derive the `Protocol` trait, add these bounds and specify the
/// protocol's GUID using the following syntax:
/// You can derive the `Protocol` trait, add these bounds, and specify the
/// protocol's GUID using the [`unsafe_protocol`] macro.
///
/// # Example
///
/// ```
/// #![feature(negative_impls)]
/// use uefi::{proto::Protocol, unsafe_guid};
/// #[unsafe_guid("12345678-9abc-def0-1234-56789abcdef0")]
/// #[derive(Protocol)]
/// struct DummyProtocol {}
/// use uefi::{Identify, guid};
/// use uefi::proto::unsafe_protocol;
///
/// #[unsafe_protocol("12345678-9abc-def0-1234-56789abcdef0")]
/// struct ExampleProtocol {}
///
/// assert_eq!(ExampleProtocol::GUID, guid!("12345678-9abc-def0-1234-56789abcdef0"));
/// ```
pub trait Protocol: Identify {}
@ -62,7 +66,7 @@ where
}
}
pub use uefi_macros::{unsafe_protocol, Protocol};
pub use uefi_macros::unsafe_protocol;
pub mod console;
pub mod debug;

View file

@ -6,8 +6,8 @@ use core::{
ptr::{null, null_mut},
};
use crate::proto::unsafe_protocol;
use bitflags::bitflags;
use uefi_macros::{unsafe_guid, Protocol};
use crate::{CStr8, Char8, Result, Status};
@ -15,8 +15,7 @@ use super::{IpAddress, MacAddress};
/// PXE Base Code protocol
#[repr(C)]
#[unsafe_guid("03c4e603-ac28-11d3-9a2d-0090273fc14d")]
#[derive(Protocol)]
#[unsafe_protocol("03c4e603-ac28-11d3-9a2d-0090273fc14d")]
#[allow(clippy::type_complexity)]
pub struct BaseCode {
revision: u64,

View file

@ -14,12 +14,11 @@ use bitflags::bitflags;
use core::ffi::c_void;
use core::ptr;
use core::ptr::NonNull;
use uefi_macros::{unsafe_guid, Protocol};
use uefi_macros::unsafe_protocol;
/// The Simple Network Protocol
#[repr(C)]
#[unsafe_guid("a19832b9-ac25-11d3-9a2d-0090273fc14d")]
#[derive(Protocol)]
#[unsafe_protocol("a19832b9-ac25-11d3-9a2d-0090273fc14d")]
pub struct SimpleNetwork {
revision: u64,
start: extern "efiapi" fn(this: &Self) -> Status,

View file

@ -11,8 +11,8 @@
//! * dispatching user-provided function to APs
//! * maintaining MP-related processor status
use crate::proto::Protocol;
use crate::{unsafe_guid, Result, Status};
use crate::proto::unsafe_protocol;
use crate::{Result, Status};
use bitflags::bitflags;
use core::ffi::c_void;
use core::ptr;
@ -93,8 +93,7 @@ pub struct CpuPhysicalLocation {
/// Protocol that provides services needed for multi-processor management.
#[repr(C)]
#[unsafe_guid("3fdda605-a76e-4f46-ad29-12f4531b3d08")]
#[derive(Protocol)]
#[unsafe_protocol("3fdda605-a76e-4f46-ad29-12f4531b3d08")]
pub struct MpServices {
get_number_of_processors: extern "efiapi" fn(
this: *const MpServices,

View file

@ -1,6 +1,6 @@
//! `Rng` protocol.
use crate::{data_types::Guid, guid, proto::Protocol, unsafe_guid, Result, Status};
use crate::{data_types::Guid, guid, proto::unsafe_protocol, Result, Status};
use core::{mem, ptr};
newtype_enum! {
@ -35,8 +35,7 @@ newtype_enum! {
/// Rng protocol
#[repr(C)]
#[unsafe_guid("3152bca5-eade-433d-862e-c01cdc291f44")]
#[derive(Protocol)]
#[unsafe_protocol("3152bca5-eade-433d-862e-c01cdc291f44")]
pub struct Rng {
get_info: unsafe extern "efiapi" fn(
this: &Rng,

View file

@ -1,7 +1,7 @@
use crate::data_types::PhysicalAddress;
use crate::proto::Protocol;
use crate::proto::unsafe_protocol;
use crate::table::boot::MemoryAttribute;
use crate::{unsafe_guid, Result, Status};
use crate::{Result, Status};
use core::ops::Range;
/// Protocol for getting and setting memory protection attributes.
@ -10,8 +10,7 @@ use core::ops::Range;
///
/// [proposal]: https://bugzilla.tianocore.org/show_bug.cgi?id=3519
#[repr(C)]
#[unsafe_guid("f4560cf6-40ec-4b4a-a192-bf1d57d0b189")]
#[derive(Protocol)]
#[unsafe_protocol("f4560cf6-40ec-4b4a-a192-bf1d57d0b189")]
pub struct MemoryProtection {
get_memory_attributes: unsafe extern "efiapi" fn(
this: *const Self,

View file

@ -7,9 +7,9 @@
target_arch = "aarch64"
))]
use crate::proto::Protocol;
use crate::proto::unsafe_protocol;
use crate::result::Error;
use crate::{unsafe_guid, Result, Status};
use crate::{Result, Status};
use core::ffi::c_void;
use core::mem::MaybeUninit;
@ -65,8 +65,7 @@ macro_rules! shim_function {
/// another EFI application before running it, and the shim lock
/// protocol exists to support that.
#[repr(C)]
#[unsafe_guid("605dab50-e046-4300-abb6-3dd810dd8b23")]
#[derive(Protocol)]
#[unsafe_protocol("605dab50-e046-4300-abb6-3dd810dd8b23")]
pub struct ShimLock {
verify: shim_function! { fn(buffer: *const u8, size: u32) -> Status },
hash: shim_function! {

View file

@ -3,16 +3,15 @@
//! This protocol is used in the boot services environment to perform
//! lexical comparison functions on Unicode strings for given languages.
use crate::proto::unsafe_protocol;
use core::cmp::Ordering;
use uefi::data_types::{CStr16, CStr8, Char16, Char8};
use uefi_macros::{unsafe_guid, Protocol};
/// The Unicode Collation Protocol.
///
/// Used to perform case-insensitive comaprisons of strings.
#[repr(C)]
#[unsafe_guid("a4c751fc-23ae-4c3e-92e9-4964cf63f349")]
#[derive(Protocol)]
#[unsafe_protocol("a4c751fc-23ae-4c3e-92e9-4964cf63f349")]
pub struct UnicodeCollation {
stri_coll: extern "efiapi" fn(this: &Self, s1: *const Char16, s2: *const Char16) -> isize,
metai_match:

View file

@ -10,8 +10,8 @@
use super::{usize_from_u32, EventType, HashAlgorithm, PcrIndex};
use crate::data_types::PhysicalAddress;
use crate::proto::Protocol;
use crate::{unsafe_guid, Result, Status};
use crate::proto::unsafe_protocol;
use crate::{Result, Status};
use core::fmt::{self, Debug, Formatter};
use core::marker::PhantomData;
use core::{mem, ptr};
@ -249,8 +249,7 @@ impl<'a> Iterator for EventLogIter<'a> {
///
/// The corresponding C type is `EFI_TCG_PROTOCOL`.
#[repr(C)]
#[unsafe_guid("f541796d-a62e-4954-a775-9584f61b9cdd")]
#[derive(Protocol)]
#[unsafe_protocol("f541796d-a62e-4954-a775-9584f61b9cdd")]
pub struct Tcg {
status_check: unsafe extern "efiapi" fn(
this: *mut Tcg,

View file

@ -11,8 +11,8 @@
//! [TPM]: https://en.wikipedia.org/wiki/Trusted_Platform_Module
use super::HashAlgorithm;
use crate::proto::Protocol;
use crate::{unsafe_guid, Result, Status};
use crate::proto::unsafe_protocol;
use crate::{Result, Status};
use bitflags::bitflags;
use core::mem;
@ -124,8 +124,7 @@ impl BootServiceCapability {
///
/// The corresponding C type is `EFI_TCG2_PROTOCOL`.
#[repr(C)]
#[unsafe_guid("607f766c-7455-42be-930b-e4d76db2720f")]
#[derive(Protocol)]
#[unsafe_protocol("607f766c-7455-42be-930b-e4d76db2720f")]
pub struct Tcg {
get_capability: unsafe extern "efiapi" fn(
this: *mut Tcg,