From 1d0a08191c36b4a58a346cf01d37f9e8a020432f Mon Sep 17 00:00:00 2001 From: Nicholas Bishop Date: Sun, 11 Dec 2022 13:45:54 -0500 Subject: [PATCH 1/7] uefi-macros: Refactor GUID tests Switch the tests from using `unsafe_guid!` to `guid!`. Both use the same internal code, so we're testing more or less the same thing, but `guid!` is a little more direct. Also, as we previously did with the entry macro, split the GUID tests into multiple files to make it easier to visually inspect the error output. The "good" test case has been removed since that's already covered in plenty of places elsewhere. --- uefi-macros/tests/ui/guid.rs | 19 ------------------- uefi-macros/tests/ui/guid.stderr | 17 ----------------- uefi-macros/tests/ui/guid_bad_hex_group2.rs | 7 +++++++ .../tests/ui/guid_bad_hex_group2.stderr | 5 +++++ uefi-macros/tests/ui/guid_bad_hex_group5.rs | 7 +++++++ .../tests/ui/guid_bad_hex_group5.stderr | 5 +++++ uefi-macros/tests/ui/guid_bad_length.rs | 7 +++++++ uefi-macros/tests/ui/guid_bad_length.stderr | 5 +++++ 8 files changed, 36 insertions(+), 36 deletions(-) delete mode 100644 uefi-macros/tests/ui/guid.rs delete mode 100644 uefi-macros/tests/ui/guid.stderr create mode 100644 uefi-macros/tests/ui/guid_bad_hex_group2.rs create mode 100644 uefi-macros/tests/ui/guid_bad_hex_group2.stderr create mode 100644 uefi-macros/tests/ui/guid_bad_hex_group5.rs create mode 100644 uefi-macros/tests/ui/guid_bad_hex_group5.stderr create mode 100644 uefi-macros/tests/ui/guid_bad_length.rs create mode 100644 uefi-macros/tests/ui/guid_bad_length.stderr diff --git a/uefi-macros/tests/ui/guid.rs b/uefi-macros/tests/ui/guid.rs deleted file mode 100644 index 4f18b21af..000000000 --- a/uefi-macros/tests/ui/guid.rs +++ /dev/null @@ -1,19 +0,0 @@ -use uefi_macros::unsafe_guid; - -// The GUID here is OK. -#[unsafe_guid("aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa")] -struct Good; - -// Fail because the length is wrong. -#[unsafe_guid("aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaa")] -struct TooShort; - -// Error span should point to the second group. -#[unsafe_guid("aaaaaaaa-Gaaa-aaaa-aaaa-aaaaaaaaaaaa")] -struct BadHexGroup2; - -// Error span should point to the fifth group. -#[unsafe_guid("aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaG")] -struct BadHexGroup5; - -fn main() {} diff --git a/uefi-macros/tests/ui/guid.stderr b/uefi-macros/tests/ui/guid.stderr deleted file mode 100644 index 8337be27e..000000000 --- a/uefi-macros/tests/ui/guid.stderr +++ /dev/null @@ -1,17 +0,0 @@ -error: "aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaa" is not a canonical GUID string (expected 36 bytes, found 35) - --> $DIR/guid.rs:8:15 - | -8 | #[unsafe_guid("aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaa")] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: GUID component "Gaaa" is not a hexadecimal number - --> $DIR/guid.rs:12:25 - | -12 | #[unsafe_guid("aaaaaaaa-Gaaa-aaaa-aaaa-aaaaaaaaaaaa")] - | ^^^^ - -error: GUID component "aaaaaaaaaaaG" is not a hexadecimal number - --> $DIR/guid.rs:16:40 - | -16 | #[unsafe_guid("aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaG")] - | ^^^^^^^^^^^^ diff --git a/uefi-macros/tests/ui/guid_bad_hex_group2.rs b/uefi-macros/tests/ui/guid_bad_hex_group2.rs new file mode 100644 index 000000000..c13466974 --- /dev/null +++ b/uefi-macros/tests/ui/guid_bad_hex_group2.rs @@ -0,0 +1,7 @@ +use uefi::Guid; +use uefi_macros::guid; + +// Error span should point to the second group. +const BadHexGroup2: Guid = guid!("aaaaaaaa-Gaaa-aaaa-aaaa-aaaaaaaaaaaa"); + +fn main() {} diff --git a/uefi-macros/tests/ui/guid_bad_hex_group2.stderr b/uefi-macros/tests/ui/guid_bad_hex_group2.stderr new file mode 100644 index 000000000..4daacf765 --- /dev/null +++ b/uefi-macros/tests/ui/guid_bad_hex_group2.stderr @@ -0,0 +1,5 @@ +error: GUID component "Gaaa" is not a hexadecimal number + --> tests/ui/guid_bad_hex_group2.rs:5:44 + | +5 | const BadHexGroup2: Guid = guid!("aaaaaaaa-Gaaa-aaaa-aaaa-aaaaaaaaaaaa"); + | ^^^^ diff --git a/uefi-macros/tests/ui/guid_bad_hex_group5.rs b/uefi-macros/tests/ui/guid_bad_hex_group5.rs new file mode 100644 index 000000000..928fb382c --- /dev/null +++ b/uefi-macros/tests/ui/guid_bad_hex_group5.rs @@ -0,0 +1,7 @@ +use uefi::Guid; +use uefi_macros::guid; + +// Error span should point to the fifth group. +const BadHexGroup5: Guid = guid!("aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaG"); + +fn main() {} diff --git a/uefi-macros/tests/ui/guid_bad_hex_group5.stderr b/uefi-macros/tests/ui/guid_bad_hex_group5.stderr new file mode 100644 index 000000000..bac7fc803 --- /dev/null +++ b/uefi-macros/tests/ui/guid_bad_hex_group5.stderr @@ -0,0 +1,5 @@ +error: GUID component "aaaaaaaaaaaG" is not a hexadecimal number + --> tests/ui/guid_bad_hex_group5.rs:5:59 + | +5 | const BadHexGroup5: Guid = guid!("aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaG"); + | ^^^^^^^^^^^^ diff --git a/uefi-macros/tests/ui/guid_bad_length.rs b/uefi-macros/tests/ui/guid_bad_length.rs new file mode 100644 index 000000000..0d70ff34a --- /dev/null +++ b/uefi-macros/tests/ui/guid_bad_length.rs @@ -0,0 +1,7 @@ +use uefi::Guid; +use uefi_macros::guid; + +// Fail because the length is wrong. +const TooShort: Guid = guid!("aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaa"); + +fn main() {} diff --git a/uefi-macros/tests/ui/guid_bad_length.stderr b/uefi-macros/tests/ui/guid_bad_length.stderr new file mode 100644 index 000000000..77fbfb790 --- /dev/null +++ b/uefi-macros/tests/ui/guid_bad_length.stderr @@ -0,0 +1,5 @@ +error: "aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaa" is not a canonical GUID string (expected 36 bytes, found 35) + --> tests/ui/guid_bad_length.rs:5:30 + | +5 | const TooShort: Guid = guid!("aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaa"); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ From d095403a3e930be7dd999ecd1dc28dba29868107 Mon Sep 17 00:00:00 2001 From: Nicholas Bishop Date: Sun, 11 Dec 2022 13:55:01 -0500 Subject: [PATCH 2/7] uefi: Remove non-protocol uses of `unsafe_guid` The `unsafe_guid` macro is almost always used for creating protocols. There are three other uses though, for identifying file info types. Replace these with explicit impls of the `Identify` trait. Now that we have a `guid!` macro, this doesn't reduce the clarity of the code at all. --- uefi/src/proto/media/file/info.rs | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/uefi/src/proto/media/file/info.rs b/uefi/src/proto/media/file/info.rs index afe021273..b49bc2942 100644 --- a/uefi/src/proto/media/file/info.rs +++ b/uefi/src/proto/media/file/info.rs @@ -1,7 +1,7 @@ use super::FileAttribute; use crate::data_types::Align; use crate::table::runtime::Time; -use crate::{unsafe_guid, CStr16, Char16, Identify}; +use crate::{guid, CStr16, Char16, Guid, Identify}; use core::ffi::c_void; use core::{mem, ptr}; @@ -142,7 +142,6 @@ pub enum FileInfoCreationError { /// attribute. Other changes must be carried out in a separate transaction. #[derive(Debug, Eq, PartialEq)] #[repr(C)] -#[unsafe_guid("09576e92-6d3f-11d2-8e39-00a0c969723b")] pub struct FileInfo { size: u64, file_size: u64, @@ -237,6 +236,10 @@ impl Align for FileInfo { } } +unsafe impl Identify for FileInfo { + const GUID: Guid = guid!("09576e92-6d3f-11d2-8e39-00a0c969723b"); +} + impl InfoInternal for FileInfo { fn name_offset() -> usize { 80 @@ -253,7 +256,6 @@ impl FileProtocolInfo for FileInfo {} /// this information structure. Consider using `FileSystemVolumeLabel` instead. #[derive(Debug, Eq, PartialEq)] #[repr(C)] -#[unsafe_guid("09576e93-6d3f-11d2-8e39-00a0c969723b")] pub struct FileSystemInfo { size: u64, read_only: bool, @@ -329,6 +331,10 @@ impl Align for FileSystemInfo { } } +unsafe impl Identify for FileSystemInfo { + const GUID: Guid = guid!("09576e93-6d3f-11d2-8e39-00a0c969723b"); +} + impl InfoInternal for FileSystemInfo { fn name_offset() -> usize { 36 @@ -342,7 +348,6 @@ impl FileProtocolInfo for FileSystemInfo {} /// May only be obtained on the root directory's file handle. #[derive(Debug, Eq, PartialEq)] #[repr(C)] -#[unsafe_guid("db47d7d3-fe81-11d3-9a35-0090273fc14d")] pub struct FileSystemVolumeLabel { volume_label: [Char16], } @@ -377,6 +382,10 @@ impl Align for FileSystemVolumeLabel { } } +unsafe impl Identify for FileSystemVolumeLabel { + const GUID: Guid = guid!("db47d7d3-fe81-11d3-9a35-0090273fc14d"); +} + impl InfoInternal for FileSystemVolumeLabel { fn name_offset() -> usize { 0 From dc7d765f065ac0520b6a19f4767efd1a93d9e840 Mon Sep 17 00:00:00 2001 From: Nicholas Bishop Date: Sun, 11 Dec 2022 04:06:43 -0500 Subject: [PATCH 3/7] uefi-macros: Add `unsafe_protocol` macro This attribute macro combines the functionality of the `unsafe_guid` attribute macro and the `Protocol` derive macro. It impls the `Protocol` and `Identify` traits, and it also marks the type as `!Send` and `!Sync`. This provides a slightly nicer API for protocols (`unsafe_protocol` is a clearer name than `unsafe_guid`, and only one macro is needed instead of two), but more importantly it does the `!Send` and `!Sync` part via a hidden `PhantomData` field rather than relying on the unstable `negative_impls` feature. --- uefi-macros/src/lib.rs | 81 +++++++++++++++++++++++++++++++++++++++++- uefi/src/proto/mod.rs | 2 +- 2 files changed, 81 insertions(+), 2 deletions(-) diff --git a/uefi-macros/src/lib.rs b/uefi-macros/src/lib.rs index d6f7d11c5..7c06ef0e3 100644 --- a/uefi-macros/src/lib.rs +++ b/uefi-macros/src/lib.rs @@ -10,7 +10,8 @@ use syn::{ parse::{Parse, ParseStream}, parse_macro_input, parse_quote, spanned::Spanned, - DeriveInput, Error, FnArg, Generics, Ident, ItemFn, ItemType, LitStr, Pat, Visibility, + DeriveInput, Error, Fields, FnArg, Generics, Ident, ItemFn, ItemStruct, ItemType, LitStr, Pat, + Visibility, }; /// Parses a type definition, extracts its identifier and generic parameters @@ -80,6 +81,84 @@ pub fn unsafe_guid(args: TokenStream, input: TokenStream) -> TokenStream { result.into() } +/// Attribute macro for marking structs as UEFI protocols. +/// +/// The macro takes one argument, a GUID string. +/// +/// The macro can only be applied to a struct, and the struct must have +/// named fields (i.e. not a unit or tuple struct). It implements the +/// [`Protocol`] trait and the `unsafe` [`Identify`] trait for the +/// struct. It also adds a hidden field that causes the struct to be +/// marked as [`!Send` and `!Sync`][send-and-sync]. +/// +/// # Safety +/// +/// The caller must ensure that the correct GUID is attached to the +/// type. An incorrect GUID could lead to invalid casts and other +/// unsound behavior. +/// +/// # Example +/// +/// ``` +/// 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")); +/// ``` +/// +/// [`Identify`]: https://docs.rs/uefi/latest/uefi/trait.Identify.html +/// [`Protocol`]: https://docs.rs/uefi/latest/uefi/proto/trait.Protocol.html +/// [send-and-sync]: https://doc.rust-lang.org/nomicon/send-and-sync.html +#[proc_macro_attribute] +pub fn unsafe_protocol(args: TokenStream, input: TokenStream) -> TokenStream { + // Parse `args` as a GUID string. + let (time_low, time_mid, time_high_and_version, clock_seq_and_variant, node) = + match parse_guid(parse_macro_input!(args as LitStr)) { + Ok(data) => data, + Err(tokens) => return tokens.into(), + }; + + let item_struct = parse_macro_input!(input as ItemStruct); + + let ident = &item_struct.ident; + let struct_attrs = &item_struct.attrs; + let struct_vis = &item_struct.vis; + let struct_fields = if let Fields::Named(struct_fields) = &item_struct.fields { + &struct_fields.named + } else { + return err!(item_struct, "Protocol struct must used named fields").into(); + }; + let struct_generics = &item_struct.generics; + let (impl_generics, ty_generics, where_clause) = item_struct.generics.split_for_impl(); + + quote! { + #(#struct_attrs)* + #struct_vis struct #ident #struct_generics { + // Add a hidden field with `PhantomData` of a raw + // pointer. This has the implicit side effect of making the + // struct !Send and !Sync. + _no_send_or_sync: ::core::marker::PhantomData<*const u8>, + #struct_fields + } + + unsafe impl #impl_generics ::uefi::Identify for #ident #ty_generics #where_clause { + const GUID: ::uefi::Guid = ::uefi::Guid::from_values( + #time_low, + #time_mid, + #time_high_and_version, + #clock_seq_and_variant, + #node, + ); + } + + impl #impl_generics ::uefi::proto::Protocol for #ident #ty_generics #where_clause {} + } + .into() +} + /// Create a `Guid` at compile time. /// /// # Example diff --git a/uefi/src/proto/mod.rs b/uefi/src/proto/mod.rs index 6984150ff..1d2665c88 100644 --- a/uefi/src/proto/mod.rs +++ b/uefi/src/proto/mod.rs @@ -62,7 +62,7 @@ where } } -pub use uefi_macros::Protocol; +pub use uefi_macros::{unsafe_protocol, Protocol}; pub mod console; pub mod debug; From be7a20cce1e59404ddcc8cedfd98bc6fbdb64101 Mon Sep 17 00:00:00 2001 From: Nicholas Bishop Date: Sun, 11 Dec 2022 04:27:08 -0500 Subject: [PATCH 4/7] 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. --- CONTRIBUTING.md | 5 ++--- uefi-test-runner/src/boot/misc.rs | 7 +++---- uefi/src/data_types/guid.rs | 18 +++++++--------- uefi/src/proto/console/gop.rs | 7 +++---- uefi/src/proto/console/pointer/mod.rs | 7 +++---- uefi/src/proto/console/serial.rs | 7 +++---- uefi/src/proto/console/text/input.rs | 7 +++---- uefi/src/proto/console/text/output.rs | 7 +++---- uefi/src/proto/debug/mod.rs | 7 +++---- uefi/src/proto/device_path/mod.rs | 8 +++---- uefi/src/proto/device_path/text.rs | 10 ++++----- uefi/src/proto/loaded_image.rs | 7 +++---- uefi/src/proto/media/block.rs | 7 +++---- uefi/src/proto/media/disk.rs | 10 ++++----- uefi/src/proto/media/fs.rs | 7 +++---- uefi/src/proto/media/partition.rs | 7 +++---- uefi/src/proto/mod.rs | 22 ++++++++++++-------- uefi/src/proto/network/pxe.rs | 5 ++--- uefi/src/proto/network/snp.rs | 5 ++--- uefi/src/proto/pi/mp.rs | 7 +++---- uefi/src/proto/rng.rs | 5 ++--- uefi/src/proto/security/memory_protection.rs | 7 +++---- uefi/src/proto/shim/mod.rs | 7 +++---- uefi/src/proto/string/unicode_collation.rs | 5 ++--- uefi/src/proto/tcg/v1.rs | 7 +++---- uefi/src/proto/tcg/v2.rs | 7 +++---- 26 files changed, 90 insertions(+), 115 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 899e28e7b..e5a12cad0 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -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, diff --git a/uefi-test-runner/src/boot/misc.rs b/uefi-test-runner/src/boot/misc.rs index 8f45aeaf0..7ee9d6581 100644 --- a/uefi-test-runner/src/boot/misc.rs +++ b/uefi-test-runner/src/boot/misc.rs @@ -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>) { diff --git a/uefi/src/data_types/guid.rs b/uefi/src/data_types/guid.rs index 8f718606b..95354483e 100644 --- a/uefi/src/data_types/guid.rs +++ b/uefi/src/data_types/guid.rs @@ -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; diff --git a/uefi/src/proto/console/gop.rs b/uefi/src/proto/console/gop.rs index bc6735bd9..c2e87052d 100644 --- a/uefi/src/proto/console/gop.rs +++ b/uefi/src/proto/console/gop.rs @@ -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, diff --git a/uefi/src/proto/console/pointer/mod.rs b/uefi/src/proto/console/pointer/mod.rs index ea4112232..0ef123263 100644 --- a/uefi/src/proto/console/pointer/mod.rs +++ b/uefi/src/proto/console/pointer/mod.rs @@ -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, diff --git a/uefi/src/proto/console/serial.rs b/uefi/src/proto/console/serial.rs index ed436edbf..a17403d05 100644 --- a/uefi/src/proto/console/serial.rs +++ b/uefi/src/proto/console/serial.rs @@ -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. diff --git a/uefi/src/proto/console/text/input.rs b/uefi/src/proto/console/text/input.rs index cc8f64004..5e4315ff6 100644 --- a/uefi/src/proto/console/text/input.rs +++ b/uefi/src/proto/console/text/input.rs @@ -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, diff --git a/uefi/src/proto/console/text/output.rs b/uefi/src/proto/console/text/output.rs index d6b5d78b3..8e6b5addd 100644 --- a/uefi/src/proto/console/text/output.rs +++ b/uefi/src/proto/console/text/output.rs @@ -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, diff --git a/uefi/src/proto/debug/mod.rs b/uefi/src/proto/debug/mod.rs index 403e3287b..776b43497 100644 --- a/uefi/src/proto/debug/mod.rs +++ b/uefi/src/proto/debug/mod.rs @@ -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: diff --git a/uefi/src/proto/device_path/mod.rs b/uefi/src/proto/device_path/mod.rs index e60cd916e..4fc863356 100644 --- a/uefi/src/proto/device_path/mod.rs +++ b/uefi/src/proto/device_path/mod.rs @@ -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], } diff --git a/uefi/src/proto/device_path/text.rs b/uefi/src/proto/device_path/text.rs index 42c8408ca..5cfdc8e36 100644 --- a/uefi/src/proto/device_path/text.rs +++ b/uefi/src/proto/device_path/text.rs @@ -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, diff --git a/uefi/src/proto/loaded_image.rs b/uefi/src/proto/loaded_image.rs index b659c04c1..ff820a184 100644 --- a/uefi/src/proto/loaded_image.rs +++ b/uefi/src/proto/loaded_image.rs @@ -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, diff --git a/uefi/src/proto/media/block.rs b/uefi/src/proto/media/block.rs index 6861699fe..4d90deaa3 100644 --- a/uefi/src/proto/media/block.rs +++ b/uefi/src/proto/media/block.rs @@ -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, diff --git a/uefi/src/proto/media/disk.rs b/uefi/src/proto/media/disk.rs index 56e54b6ef..8d0562f33 100644 --- a/uefi/src/proto/media/disk.rs +++ b/uefi/src/proto/media/disk.rs @@ -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, diff --git a/uefi/src/proto/media/fs.rs b/uefi/src/proto/media/fs.rs index 32df63da3..c016388c7 100644 --- a/uefi/src/proto/media/fs.rs +++ b/uefi/src/proto/media/fs.rs @@ -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: diff --git a/uefi/src/proto/media/partition.rs b/uefi/src/proto/media/partition.rs index 7243decd7..b2e353ee7 100644 --- a/uefi/src/proto/media/partition.rs +++ b/uefi/src/proto/media/partition.rs @@ -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, diff --git a/uefi/src/proto/mod.rs b/uefi/src/proto/mod.rs index 1d2665c88..51f69b783 100644 --- a/uefi/src/proto/mod.rs +++ b/uefi/src/proto/mod.rs @@ -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; diff --git a/uefi/src/proto/network/pxe.rs b/uefi/src/proto/network/pxe.rs index 7acd5a2e8..b13757439 100644 --- a/uefi/src/proto/network/pxe.rs +++ b/uefi/src/proto/network/pxe.rs @@ -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, diff --git a/uefi/src/proto/network/snp.rs b/uefi/src/proto/network/snp.rs index 6554455c3..8f55c0cb4 100644 --- a/uefi/src/proto/network/snp.rs +++ b/uefi/src/proto/network/snp.rs @@ -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, diff --git a/uefi/src/proto/pi/mp.rs b/uefi/src/proto/pi/mp.rs index 52b5b5fb6..b450d2c22 100644 --- a/uefi/src/proto/pi/mp.rs +++ b/uefi/src/proto/pi/mp.rs @@ -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, diff --git a/uefi/src/proto/rng.rs b/uefi/src/proto/rng.rs index cc3363cf0..6ab53f9c4 100644 --- a/uefi/src/proto/rng.rs +++ b/uefi/src/proto/rng.rs @@ -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, diff --git a/uefi/src/proto/security/memory_protection.rs b/uefi/src/proto/security/memory_protection.rs index 0f548fc6c..38c229547 100644 --- a/uefi/src/proto/security/memory_protection.rs +++ b/uefi/src/proto/security/memory_protection.rs @@ -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, diff --git a/uefi/src/proto/shim/mod.rs b/uefi/src/proto/shim/mod.rs index c2a52b604..7dac6853a 100644 --- a/uefi/src/proto/shim/mod.rs +++ b/uefi/src/proto/shim/mod.rs @@ -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! { diff --git a/uefi/src/proto/string/unicode_collation.rs b/uefi/src/proto/string/unicode_collation.rs index 0bce35750..78866cdc8 100644 --- a/uefi/src/proto/string/unicode_collation.rs +++ b/uefi/src/proto/string/unicode_collation.rs @@ -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: diff --git a/uefi/src/proto/tcg/v1.rs b/uefi/src/proto/tcg/v1.rs index 055b7efd9..0ab59ac14 100644 --- a/uefi/src/proto/tcg/v1.rs +++ b/uefi/src/proto/tcg/v1.rs @@ -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, diff --git a/uefi/src/proto/tcg/v2.rs b/uefi/src/proto/tcg/v2.rs index cc199818e..f44c65a33 100644 --- a/uefi/src/proto/tcg/v2.rs +++ b/uefi/src/proto/tcg/v2.rs @@ -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, From c2de574dd3def459e56b35be6c016a4bf7ca6714 Mon Sep 17 00:00:00 2001 From: Nicholas Bishop Date: Sun, 11 Dec 2022 04:27:23 -0500 Subject: [PATCH 5/7] uefi-macros: Drop the unsafe_guid and Protocol macros These are no longer used anywhere. --- uefi-macros/src/lib.rs | 87 +------------------------------------ uefi/src/data_types/guid.rs | 15 +------ uefi/src/data_types/mod.rs | 2 +- uefi/src/lib.rs | 2 +- 4 files changed, 5 insertions(+), 101 deletions(-) diff --git a/uefi-macros/src/lib.rs b/uefi-macros/src/lib.rs index 7c06ef0e3..08c6df093 100644 --- a/uefi-macros/src/lib.rs +++ b/uefi-macros/src/lib.rs @@ -7,37 +7,10 @@ use proc_macro::TokenStream; use proc_macro2::{TokenStream as TokenStream2, TokenTree}; use quote::{quote, ToTokens, TokenStreamExt}; use syn::{ - parse::{Parse, ParseStream}, - parse_macro_input, parse_quote, - spanned::Spanned, - DeriveInput, Error, Fields, FnArg, Generics, Ident, ItemFn, ItemStruct, ItemType, LitStr, Pat, - Visibility, + parse_macro_input, parse_quote, spanned::Spanned, Error, Fields, FnArg, Ident, ItemFn, + ItemStruct, LitStr, Pat, Visibility, }; -/// Parses a type definition, extracts its identifier and generic parameters -struct TypeDefinition { - ident: Ident, - generics: Generics, -} - -impl Parse for TypeDefinition { - fn parse(input: ParseStream) -> syn::Result { - if let Ok(d) = DeriveInput::parse(input) { - Ok(Self { - ident: d.ident, - generics: d.generics, - }) - } else if let Ok(t) = ItemType::parse(input) { - Ok(Self { - ident: t.ident, - generics: t.generics, - }) - } else { - Err(input.error("Input is not an alias, enum, struct or union definition")) - } - } -} - macro_rules! err { ($span:expr, $message:expr $(,)?) => { Error::new($span.span(), $message).to_compile_error() @@ -47,40 +20,6 @@ macro_rules! err { }; } -/// `unsafe_guid` attribute macro, implements the `Identify` trait for any type -/// (mostly works like a custom derive, but also supports type aliases) -#[proc_macro_attribute] -pub fn unsafe_guid(args: TokenStream, input: TokenStream) -> TokenStream { - // Parse the arguments and input using Syn - let (time_low, time_mid, time_high_and_version, clock_seq_and_variant, node) = - match parse_guid(parse_macro_input!(args as LitStr)) { - Ok(data) => data, - Err(tokens) => return tokens.into(), - }; - - let mut result: TokenStream2 = input.clone().into(); - - let type_definition = parse_macro_input!(input as TypeDefinition); - - // At this point, we know everything we need to implement Identify - let ident = &type_definition.ident; - let (impl_generics, ty_generics, where_clause) = type_definition.generics.split_for_impl(); - - result.append_all(quote! { - unsafe impl #impl_generics ::uefi::Identify for #ident #ty_generics #where_clause { - #[doc(hidden)] - const GUID: ::uefi::Guid = ::uefi::Guid::from_values( - #time_low, - #time_mid, - #time_high_and_version, - #clock_seq_and_variant, - #node, - ); - } - }); - result.into() -} - /// Attribute macro for marking structs as UEFI protocols. /// /// The macro takes one argument, a GUID string. @@ -243,28 +182,6 @@ fn parse_guid(guid_lit: LitStr) -> Result<(u32, u16, u16, u16, u64), TokenStream )) } -/// Custom derive for the `Protocol` trait -#[proc_macro_derive(Protocol)] -pub fn derive_protocol(item: TokenStream) -> TokenStream { - // Parse the input using Syn - let item = parse_macro_input!(item as DeriveInput); - - // Then implement Protocol - let ident = item.ident.clone(); - let (impl_generics, ty_generics, where_clause) = item.generics.split_for_impl(); - let result = quote! { - // Mark this as a `Protocol` implementation - impl #impl_generics ::uefi::proto::Protocol for #ident #ty_generics #where_clause {} - - // Most UEFI functions expect to be called on the bootstrap processor. - impl #impl_generics !Send for #ident #ty_generics #where_clause {} - - // Most UEFI functions do not support multithreaded access. - impl #impl_generics !Sync for #ident #ty_generics #where_clause {} - }; - result.into() -} - /// Get the name of a function's argument at `arg_index`. fn get_function_arg_name(f: &ItemFn, arg_index: usize, errors: &mut TokenStream2) -> Option { if let Some(FnArg::Typed(arg)) = f.sig.inputs.iter().nth(arg_index) { diff --git a/uefi/src/data_types/guid.rs b/uefi/src/data_types/guid.rs index 95354483e..5694919b3 100644 --- a/uefi/src/data_types/guid.rs +++ b/uefi/src/data_types/guid.rs @@ -133,12 +133,10 @@ pub unsafe trait Identify { const GUID: Guid; } -pub use uefi_macros::unsafe_guid; - #[cfg(test)] mod tests { use super::*; - use uefi::{guid, unsafe_guid}; + use uefi::guid; #[test] fn test_guid_display() { @@ -159,17 +157,6 @@ mod tests { ); } - #[test] - fn test_unsafe_guid_macro() { - #[unsafe_guid("12345678-9abc-def0-1234-56789abcdef0")] - struct X; - - assert_eq!( - X::GUID, - Guid::from_values(0x12345678, 0x9abc, 0xdef0, 0x1234, 0x56789abcdef0) - ); - } - #[test] fn test_to_from_bytes() { #[rustfmt::skip] diff --git a/uefi/src/data_types/mod.rs b/uefi/src/data_types/mod.rs index ad6dd4b30..f3df90227 100644 --- a/uefi/src/data_types/mod.rs +++ b/uefi/src/data_types/mod.rs @@ -121,7 +121,7 @@ pub type VirtualAddress = u64; mod guid; pub use self::guid::Guid; -pub use self::guid::{unsafe_guid, Identify}; +pub use self::guid::Identify; pub mod chars; pub use self::chars::{Char16, Char8}; diff --git a/uefi/src/lib.rs b/uefi/src/lib.rs index 4bc2d7cb6..22e02e1d6 100644 --- a/uefi/src/lib.rs +++ b/uefi/src/lib.rs @@ -85,7 +85,7 @@ extern crate self as uefi; pub mod data_types; #[cfg(feature = "alloc")] pub use self::data_types::CString16; -pub use self::data_types::{unsafe_guid, Identify}; +pub use self::data_types::Identify; pub use self::data_types::{CStr16, CStr8, Char16, Char8, Event, Guid, Handle}; pub use uefi_macros::guid; From d2cf762da6b61a410e189b04c983f53606bb38a6 Mon Sep 17 00:00:00 2001 From: Nicholas Bishop Date: Sun, 11 Dec 2022 04:29:13 -0500 Subject: [PATCH 6/7] Drop use of unstable `negative_impls` feature This is no longer used anywhere. --- uefi-test-runner/src/main.rs | 1 - uefi/src/lib.rs | 1 - 2 files changed, 2 deletions(-) diff --git a/uefi-test-runner/src/main.rs b/uefi-test-runner/src/main.rs index 7562b895f..ea9558066 100644 --- a/uefi-test-runner/src/main.rs +++ b/uefi-test-runner/src/main.rs @@ -1,7 +1,6 @@ #![no_std] #![no_main] #![feature(abi_efiapi)] -#![feature(negative_impls)] #[macro_use] extern crate log; diff --git a/uefi/src/lib.rs b/uefi/src/lib.rs index 22e02e1d6..d411fb8d9 100644 --- a/uefi/src/lib.rs +++ b/uefi/src/lib.rs @@ -60,7 +60,6 @@ #![feature(abi_efiapi)] #![feature(maybe_uninit_slice)] -#![feature(negative_impls)] #![feature(ptr_metadata)] #![cfg_attr(feature = "alloc", feature(vec_into_raw_parts))] #![cfg_attr(feature = "unstable", feature(error_in_core))] From 19e29dc18733f2c602c7bd13e41cc2d7ef0bdc21 Mon Sep 17 00:00:00 2001 From: Nicholas Bishop Date: Sun, 11 Dec 2022 14:38:01 -0500 Subject: [PATCH 7/7] Update changelog --- CHANGELOG.md | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index f4534c666..c89077f16 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,7 @@ ## uefi - [Unreleased] ### Added + - Implementations for the trait `EqStrUntilNul` now allow `?Sized` inputs. This means that you can write `some_cstr16.eq_str_until_nul("test")` instead of `some_cstr16.eq_str_until_nul(&"test")` now. @@ -14,14 +15,22 @@ - Added an `core::error::Error` implementation for `Error` to ease integration with error-handling crates. (requires the **unstable** feature) - Added partial support for the TCG protocols for TPM devices under `uefi::proto::tcg`. +- Added the `unsafe_protocol` macro to provide a slightly nicer way to + implement protocols. ### Changed - `UnalignedSlice` now implements `Clone`, and the `Debug` impl now prints the elements instead of the internal fields. +- The unstable `negative_impls` feature is no longer required to use this library. ### Removed +- The `unsafe_guid` attribute macro and `Protocol` derive macro have + been removed. For implementing protocols, use the `unsafe_protocol` + macro instead. For any other implementations of the `Identify` trait, + implement it directly. + ## uefi-macros - [Unreleased] ## uefi-services - [Unreleased]