Skip to content

uefi: change Fn closure to FnMut #1662

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 14 commits into from
9 changes: 7 additions & 2 deletions uefi/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,8 +1,13 @@
# uefi - [Unreleased]

## Added
- Added `ConfigTableEntry::MEMORY_ATTRIBUTES_GUID` and `ConfigTableEntry::IMAGE_SECURITY_DATABASE_GUID`.

## Changed
- **Breaking:** `boot::stall` now take `Duration` instead of
`usize`.
- **Breaking:** `boot::stall` now take `core::time::Duration` instead of `usize`.
- `table::cfg::*_GUID` constants now deprecated. Use `ConfigTableEntry::*_GUID` instead.
- `system::with_config_table`, `system::with_stdin`, `system::with_stdout` and `system::with_stderr`
now take mutably closure.


# uefi - 0.35.0 (2025-05-04)
Expand Down
57 changes: 49 additions & 8 deletions uefi/src/system.rs
Original file line number Diff line number Diff line change
Expand Up @@ -51,9 +51,26 @@ pub fn uefi_revision() -> Revision {

/// Call `f` with a slice of [`ConfigTableEntry`]. Each entry provides access to
/// a vendor-specific table.
pub fn with_config_table<F, R>(f: F) -> R
///
/// # Example
///
/// ```rust,no_run
/// use uefi::system::with_config_table;
/// use uefi::table::cfg::ConfigTableEntry;
///
/// with_config_table(|slice| {
/// for i in slice {
/// match i.guid {
/// ConfigTableEntry::ACPI_GUID => println!("Found ACPI1"),
/// ConfigTableEntry::ACPI2_GUID => println!("Found ACPI2"),
/// guid => println!("Found {}", guid),
/// }
/// }
/// });
/// ```
pub fn with_config_table<F, R>(mut f: F) -> R
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please document these changes in the changelog

where
F: Fn(&[ConfigTableEntry]) -> R,
F: FnMut(&[ConfigTableEntry]) -> R,
{
let st = table::system_table_raw_panicking();
// SAFETY: valid per requirements of `set_system_table`.
Expand All @@ -75,9 +92,9 @@ where
///
/// This function will panic if called after exiting boot services, or if stdin
/// is not available.
pub fn with_stdin<F, R>(f: F) -> R
pub fn with_stdin<F, R>(mut f: F) -> R
where
F: Fn(&mut Input) -> R,
F: FnMut(&mut Input) -> R,
{
let st = table::system_table_raw_panicking();
// SAFETY: valid per requirements of `set_system_table`.
Expand All @@ -101,9 +118,9 @@ where
///
/// This function will panic if called after exiting boot services, or if stdout
/// is not available.
pub fn with_stdout<F, R>(f: F) -> R
pub fn with_stdout<F, R>(mut f: F) -> R
where
F: Fn(&mut Output) -> R,
F: FnMut(&mut Output) -> R,
{
let st = table::system_table_raw_panicking();
// SAFETY: valid per requirements of `set_system_table`.
Expand All @@ -127,9 +144,9 @@ where
///
/// This function will panic if called after exiting boot services, or if stderr
/// is not available.
pub fn with_stderr<F, R>(f: F) -> R
pub fn with_stderr<F, R>(mut f: F) -> R
where
F: Fn(&mut Output) -> R,
F: FnMut(&mut Output) -> R,
{
let st = table::system_table_raw_panicking();
// SAFETY: valid per requirements of `set_system_table`.
Expand All @@ -146,3 +163,27 @@ where

f(stderr)
}

#[cfg(test)]
mod tests {
use super::*;
use crate::table::cfg::ACPI2_GUID;

#[allow(dead_code)]
#[allow(clippy::assertions_on_constants)]
fn with_config_table_compile_test() {
assert!(false, "compile test only");
let mut acpi2_address = None;
with_config_table(|slice| {
for i in slice {
match i.guid {
ACPI2_GUID => {
acpi2_address = Some(i.address);
break;
}
_ => {}
}
}
});
}
}
143 changes: 127 additions & 16 deletions uefi/src/table/cfg.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@
//!
//! This module contains the actual entries of the configuration table,
//! as well as GUIDs for many known vendor tables.
//!
//! See <https://uefi.org/specs/UEFI/2.10/04_EFI_System_Table.html#efi-configuration-table-properties-table>.

use crate::{guid, Guid};
use bitflags::bitflags;
Expand All @@ -16,6 +18,8 @@ use core::ffi::c_void;
/// Contains a set of GUID / pointer for a vendor-specific table.
///
/// The UEFI standard guarantees each entry is unique.
///
/// See <https://uefi.org/specs/UEFI/2.10/04_EFI_System_Table.html#efi-configuration-table>.
#[derive(Clone, Debug, Eq, PartialEq, Ord, PartialOrd, Hash)]
#[repr(C)]
pub struct ConfigTableEntry {
Expand All @@ -26,26 +30,106 @@ pub struct ConfigTableEntry {
/// Whether this is a physical or virtual address depends on the table.
pub address: *const c_void,
}
/// Entry pointing to the old ACPI 1 RSDP.
pub const ACPI_GUID: Guid = guid!("eb9d2d30-2d88-11d3-9a16-0090273fc14d");

///Entry pointing to the ACPI 2 RSDP.
pub const ACPI2_GUID: Guid = guid!("8868e871-e4f1-11d3-bc22-0080c73c8881");
impl ConfigTableEntry {
/// Entry pointing to the old ACPI 1 RSDP.
pub const ACPI_GUID: Guid = guid!("eb9d2d30-2d88-11d3-9a16-0090273fc14d");

/// Entry pointing to the ACPI 2 RSDP.
pub const ACPI2_GUID: Guid = guid!("8868e871-e4f1-11d3-bc22-0080c73c8881");

/// Entry pointing to the SMBIOS 1.0 table.
pub const SMBIOS_GUID: Guid = guid!("eb9d2d31-2d88-11d3-9a16-0090273fc14d");

/// Entry pointing to the SMBIOS 3.0 table.
pub const SMBIOS3_GUID: Guid = guid!("f2fd1544-9794-4a2c-992e-e5bbcf20e394");

/// Entry pointing to the EFI System Resource table (ESRT).
pub const ESRT_GUID: Guid = guid!("b122a263-3661-4f68-9929-78f8b0d62180");

/// Hand-off Blocks are used to pass data from the early pre-UEFI environment to the UEFI drivers.
///
/// Most OS loaders or applications should not mess with this.
pub const HAND_OFF_BLOCK_LIST_GUID: Guid = guid!("7739f24c-93d7-11d4-9a3a-0090273fc14d");

/// Table used in the early boot environment to record memory ranges.
pub const MEMORY_TYPE_INFORMATION_GUID: Guid = guid!("4c19049f-4137-4dd3-9c10-8b97a83ffdfa");

/// Used to identify Hand-off Blocks which store
/// status codes reported during the pre-UEFI environment.
pub const MEMORY_STATUS_CODE_RECORD_GUID: Guid = guid!("060cc026-4c0d-4dda-8f41-595fef00a502");

/// Provides additional information about regions within the run-time memory blocks.
/// See <https://uefi.org/specs/UEFI/2.10/04_EFI_System_Table.html#efi-memory-attributes-table>.
pub const MEMORY_ATTRIBUTES_GUID: Guid = guid!("dcfa911d-26eb-469f-a220-38b7dc461220");

/// Constants used for UEFI signature database variable access.
/// See <https://uefi.org/specs/UEFI/2.11/32_Secure_Boot_and_Driver_Signing.html#uefi-image-variable-guid-variable-name>.
pub const IMAGE_SECURITY_DATABASE_GUID: Guid = guid!("d719b2cb-3d3a-4596-a3bc-dad00e67656f");

/// Table which provides Driver eXecution Environment services.
pub const DXE_SERVICES_GUID: Guid = guid!("05ad34ba-6f02-4214-952e-4da0398e2bb9");

/// LZMA-compressed filesystem.
pub const LZMA_COMPRESS_GUID: Guid = guid!("ee4e5898-3914-4259-9d6e-dc7bd79403cf");

/// A custom compressed filesystem used by the Tiano UEFI implementation.
pub const TIANO_COMPRESS_GUID: Guid = guid!("a31280ad-481e-41b6-95e8-127f4c984779");

/// Pointer to the debug image info table.
pub const DEBUG_IMAGE_INFO_GUID: Guid = guid!("49152e77-1ada-4764-b7a2-7afefed95e8b");

/// GUID of the UEFI properties table.
///
/// The properties table is used to provide additional info
/// about the UEFI implementation.
pub const PROPERTIES_TABLE_GUID: Guid = guid!("880aaca3-4adc-4a04-9079-b747340825e5");
}

/// Entry pointing to the old ACPI 1 RSDP.
#[deprecated(
since = "0.35.1",
note = "please use `ConfigTableEntry::ACPI_GUID` instead"
)]
pub const ACPI_GUID: Guid = ConfigTableEntry::ACPI_GUID;

/// Entry pointing to the ACPI 2 RSDP.
#[deprecated(
since = "0.35.1",
note = "please use `ConfigTableEntry::ACPI2_GUID` instead"
)]
pub const ACPI2_GUID: Guid = ConfigTableEntry::ACPI2_GUID;

/// Entry pointing to the SMBIOS 1.0 table.
pub const SMBIOS_GUID: Guid = guid!("eb9d2d31-2d88-11d3-9a16-0090273fc14d");
#[deprecated(
since = "0.35.1",
note = "please use `ConfigTableEntry::SMBIOS_GUID` instead"
)]
pub const SMBIOS_GUID: Guid = ConfigTableEntry::SMBIOS_GUID;

/// Entry pointing to the SMBIOS 3.0 table.
pub const SMBIOS3_GUID: Guid = guid!("f2fd1544-9794-4a2c-992e-e5bbcf20e394");
#[deprecated(
since = "0.35.1",
note = "please use `ConfigTableEntry::SMBIOS3_GUID` instead"
)]
pub const SMBIOS3_GUID: Guid = ConfigTableEntry::SMBIOS3_GUID;

/// Entry pointing to the EFI System Resource table (ESRT).
pub const ESRT_GUID: Guid = guid!("b122a263-3661-4f68-9929-78f8b0d62180");
#[deprecated(
since = "0.35.1",
note = "please use `ConfigTableEntry::ESRT_GUID` instead"
)]
pub const ESRT_GUID: Guid = ConfigTableEntry::ESRT_GUID;

/// GUID of the UEFI properties table.
///
/// The properties table is used to provide additional info
/// about the UEFI implementation.
pub const PROPERTIES_TABLE_GUID: Guid = guid!("880aaca3-4adc-4a04-9079-b747340825e5");
#[deprecated(
since = "0.35.1",
note = "please use `ConfigTableEntry::PROPERTIES_TABLE_GUID` instead"
)]
pub const PROPERTIES_TABLE_GUID: Guid = ConfigTableEntry::PROPERTIES_TABLE_GUID;

/// This table contains additional information about the UEFI implementation.
#[repr(C)]
Expand Down Expand Up @@ -77,23 +161,50 @@ bitflags! {
/// Hand-off Blocks are used to pass data from the early pre-UEFI environment to the UEFI drivers.
///
/// Most OS loaders or applications should not mess with this.
pub const HAND_OFF_BLOCK_LIST_GUID: Guid = guid!("7739f24c-93d7-11d4-9a3a-0090273fc14d");
#[deprecated(
since = "0.35.1",
note = "please use `ConfigTableEntry::HAND_OFF_BLOCK_LIST_GUID` instead"
)]
pub const HAND_OFF_BLOCK_LIST_GUID: Guid = ConfigTableEntry::HAND_OFF_BLOCK_LIST_GUID;

/// Table used in the early boot environment to record memory ranges.
pub const MEMORY_TYPE_INFORMATION_GUID: Guid = guid!("4c19049f-4137-4dd3-9c10-8b97a83ffdfa");
#[deprecated(
since = "0.35.1",
note = "please use `ConfigTableEntry::MEMORY_TYPE_INFORMATION_GUID` instead"
)]
pub const MEMORY_TYPE_INFORMATION_GUID: Guid = ConfigTableEntry::MEMORY_TYPE_INFORMATION_GUID;

/// Used to identify Hand-off Blocks which store
/// status codes reported during the pre-UEFI environment.
pub const MEMORY_STATUS_CODE_RECORD_GUID: Guid = guid!("060cc026-4c0d-4dda-8f41-595fef00a502");
#[deprecated(
since = "0.35.1",
note = "please use `ConfigTableEntry::MEMORY_STATUS_CODE_RECORD_GUID` instead"
)]
pub const MEMORY_STATUS_CODE_RECORD_GUID: Guid = ConfigTableEntry::MEMORY_STATUS_CODE_RECORD_GUID;

/// Table which provides Driver eXecution Environment services.
pub const DXE_SERVICES_GUID: Guid = guid!("05ad34ba-6f02-4214-952e-4da0398e2bb9");
#[deprecated(
since = "0.35.1",
note = "please use `ConfigTableEntry::DXE_SERVICES_GUID` instead"
)]
pub const DXE_SERVICES_GUID: Guid = ConfigTableEntry::DXE_SERVICES_GUID;

/// LZMA-compressed filesystem.
pub const LZMA_COMPRESS_GUID: Guid = guid!("ee4e5898-3914-4259-9d6e-dc7bd79403cf");
#[deprecated(
since = "0.35.1",
note = "please use `ConfigTableEntry::LZMA_COMPRESS_GUID` instead"
)]
pub const LZMA_COMPRESS_GUID: Guid = ConfigTableEntry::LZMA_COMPRESS_GUID;

/// A custom compressed filesystem used by the Tiano UEFI implementation.
pub const TIANO_COMPRESS_GUID: Guid = guid!("a31280ad-481e-41b6-95e8-127f4c984779");

#[deprecated(
since = "0.35.1",
note = "please use `ConfigTableEntry::TIANO_COMPRESS_GUID` instead"
)]
pub const TIANO_COMPRESS_GUID: Guid = ConfigTableEntry::TIANO_COMPRESS_GUID;
/// Pointer to the debug image info table.
pub const DEBUG_IMAGE_INFO_GUID: Guid = guid!("49152e77-1ada-4764-b7a2-7afefed95e8b");
#[deprecated(
since = "0.35.1",
note = "please use `ConfigTableEntry::DEBUG_IMAGE_INFO_GUID` instead"
)]
pub const DEBUG_IMAGE_INFO_GUID: Guid = ConfigTableEntry::DEBUG_IMAGE_INFO_GUID;
43 changes: 38 additions & 5 deletions xtask/src/check_raw.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,12 +23,28 @@ use syn::{
};
use walkdir::WalkDir;

/// Type of an `Item`.
#[derive(Debug, Eq, PartialEq)]
enum ItemKind {
Enum,
Other,
}

impl From<&Item> for ItemKind {
fn from(item: &Item) -> Self {
match item {
Item::Enum(_) => Self::Enum,
_ => Self::Other,
}
}
}

/// All possible validation error kinds.
#[derive(Debug, Eq, PartialEq)]
enum ErrorKind {
ForbiddenAbi,
ForbiddenAttr,
ForbiddenItemKind,
ForbiddenItemKind(ItemKind),
ForbiddenRepr,
ForbiddenType,
MalformedAttrs,
Expand All @@ -47,7 +63,9 @@ impl Display for ErrorKind {
match self {
Self::ForbiddenAbi => "forbidden ABI",
Self::ForbiddenAttr => "forbidden attribute",
Self::ForbiddenItemKind => "forbidden type of item",
Self::ForbiddenItemKind(ItemKind::Enum) =>
"forbidden use of enum; use the `newtype_enum!` macro instead",
Self::ForbiddenItemKind(_) => "forbidden type of item",
Self::ForbiddenRepr => "forbidden repr",
Self::ForbiddenType => "forbidden type",
Self::MalformedAttrs => "malformed attribute contents",
Expand Down Expand Up @@ -364,7 +382,11 @@ fn check_item(item: &Item, src: &Path) -> Result<(), Error> {
// Allow.
}
item => {
return Err(Error::new(ErrorKind::ForbiddenItemKind, src, item));
return Err(Error::new(
ErrorKind::ForbiddenItemKind(item.into()),
src,
item,
));
}
}

Expand Down Expand Up @@ -424,15 +446,26 @@ mod tests {
}

#[test]
fn test_invalid_item() {
fn test_invalid_item_enum() {
// Rust enums are not allowed.
check_item_err(
parse_quote! {
pub enum E {
A
}
},
ErrorKind::ForbiddenItemKind,
ErrorKind::ForbiddenItemKind(ItemKind::Enum),
);
}

#[test]
fn test_invalid_item_other() {
// Top-level functions are not allowed.
check_item_err(
parse_quote! {
pub fn x() {}
},
ErrorKind::ForbiddenItemKind(ItemKind::Other),
);
}

Expand Down