rename crate features

To prevent confusion, this renames the `alloc` crate feature to
`global_allocator` and the `exts` feature to `alloc` to match the
conventions of the ecosystem.
This commit is contained in:
Philipp Schuster 2022-11-12 14:16:37 +01:00 committed by Nicholas Bishop
parent 458b1f98a7
commit 76b5a22981
25 changed files with 108 additions and 72 deletions

View file

@ -30,6 +30,8 @@
### Changed
- Renamed crate feature `alloc` to `global_allocator`.
- Renamed crate feature `exts` to `alloc`.
- Fixed the definition of `AllocateType` so that `MaxAddress` and
`Address` always take a 64-bit value, regardless of target platform.
- The conversion methods on `DevicePathToText` and `DevicePathFromText`

View file

@ -31,17 +31,21 @@ Check out [the UEFI application template](template) for a quick start.
This project contains multiple sub-crates:
- `uefi` (top directory): defines the standard UEFI tables / interfaces.
The objective is to stay unopionated and safely wrap most interfaces.
The objective is to stay unopinionated and safely wrap most interfaces.
Optional features:
- `alloc`: implements a global allocator using UEFI functions.
- This allows you to allocate objects on the heap.
**Optional crate features:**
- `alloc`: Enables functionality requiring the `alloc` crate from the Rust standard library.
- For example, this allows many convenient `uefi-rs` functions to operate on heap data (`Box`).
- It is up to the user to provide a `#[global_allocator]`.
- `global_allocator`: implements a `#[global_allocator]` using UEFI functions.
- This allows you to use all abstractions from the `alloc` crate from the Rust standard library
during runtime. Hence, `Vec`, `Box`, etc. will be able to allocate memory.
**This is optional**, so you can provide a custom `#[global_allocator]` as well.
- There's no guarantee of the efficiency of UEFI's allocator.
- `logger`: logging implementation for the standard [log] crate.
- Prints output to console.
- `logger`: logging implementation for the standard [`log`] crate.
- Prints output to UEFI console.
- No buffering is done: this is not a high-performance logger.
- `exts`: extensions providing utility functions for common patterns.
- Requires the `alloc` crate (either enable the `alloc` optional feature or your own custom allocator).
- `uefi-macros`: procedural macros that are used to derive some traits in `uefi`.

View file

@ -7,6 +7,7 @@
- [Running in a VM](tutorial/vm.md)
- [How-to](how_to/introduction.md)
- [Using Protocols](how_to/protocols.md)
- [Crate Features](how_to/crate_features.md)
- [Concepts](concepts/introduction.md)
- [Boot Stages](concepts/boot_stages.md)
- [Tables](concepts/tables.md)

View file

@ -0,0 +1,15 @@
# Optional Crate Features
There are several optional crate features provided by the `uefi` crate.
- `alloc`: Enables functionality requiring the `alloc` crate from the Rust standard library.
- For example, this allows many convenient `uefi-rs` functions to operate on heap data (`Box`).
- It is up to the user to provide a `#[global allocator]`.
- `global_allocator`: implements a `#[global allocator]` using UEFI functions.
- This allows you to use all abstractions from the `alloc` crate from the Rust standard library
during runtime. Hence, `Vec`, `Box`, etc. will be able to allocate memory.
**This is optional**, so you can provide a custom `#[global allocator]` as well.
- There's no guarantee of the efficiency of UEFI's allocator.
- `logger`: logging implementation for the standard [`log`] crate.
- Prints output to the UEFI boot services standard text output.
- No buffering is done: this is not a high-performance logger.

View file

@ -5,5 +5,5 @@ edition = "2021"
publish = false
[dependencies]
uefi = { version = "0.18.0", features = ["exts"] }
uefi = { version = "0.18.0", features = ["alloc"] }
uefi-services = "0.15.0"

View file

@ -15,7 +15,7 @@ is-it-maintained-issue-resolution = { repository = "rust-osdev/uefi-rs" }
is-it-maintained-open-issues = { repository = "rust-osdev/uefi-rs" }
[dependencies]
uefi = { version = "0.18.0", features = ["alloc"] }
uefi = { version = "0.18.0", features = ["global_allocator"] }
log = { version = "0.4.5", default-features = false }
cfg-if = "1.0.0"
qemu-exit = { version = "3.0.1", optional = true }

View file

@ -83,7 +83,7 @@ pub fn init(st: &mut SystemTable<Boot>) -> Result {
init_logger(st);
let boot_services = st.boot_services();
uefi::alloc::init(boot_services);
uefi::global_allocator::init(boot_services);
// Schedule these tools to be disabled on exit from UEFI boot services
boot_services
@ -181,7 +181,7 @@ unsafe extern "efiapi" fn exit_boot_services(_e: Event, _ctx: Option<NonNull<c_v
logger.disable();
}
uefi::alloc::exit_boot_services();
uefi::global_allocator::exit_boot_services();
}
#[cfg(feature = "panic_handler")]

View file

@ -6,7 +6,7 @@ publish = false
edition = "2021"
[dependencies]
uefi = { path = "../uefi", features = ['exts'] }
uefi = { path = "../uefi", features = ['alloc'] }
uefi-services = { path = "../uefi-services" }
log = { version = "0.4.11", default-features = false }

View file

@ -13,7 +13,7 @@ license = "MPL-2.0"
[features]
default = ["panic-on-logger-errors"]
alloc = []
exts = []
global_allocator = []
logger = []
# Ignore text output errors in logger as a workaround for firmware issues that
# were observed on the VirtualBox UEFI implementation (see uefi-rs#121).

View file

@ -141,9 +141,8 @@ pub use uefi_macros::unsafe_guid;
#[cfg(test)]
mod tests {
use uefi::{guid, unsafe_guid};
extern crate alloc;
use super::*;
use uefi::{guid, unsafe_guid};
#[test]
fn test_guid_display() {

View file

@ -132,9 +132,9 @@ pub use self::strs::{
CStr16, CStr8, EqStrUntilNul, FromSliceWithNulError, FromStrWithBufError, UnalignedCStr16Error,
};
#[cfg(feature = "exts")]
#[cfg(feature = "alloc")]
mod owned_strs;
#[cfg(feature = "exts")]
#[cfg(feature = "alloc")]
pub use self::owned_strs::{CString16, FromStrError};
mod unaligned_slice;

View file

@ -1,6 +1,6 @@
use super::chars::{Char16, NUL_16};
use super::strs::{CStr16, FromSliceWithNulError};
use crate::alloc_api::vec::Vec;
use crate::alloc::vec::Vec;
use crate::data_types::strs::EqStrUntilNul;
use crate::data_types::UnalignedSlice;
use core::fmt;
@ -138,8 +138,8 @@ impl<StrType: AsRef<str>> EqStrUntilNul<StrType> for CString16 {
#[cfg(test)]
mod tests {
use super::*;
use crate::alloc_api::string::String;
use crate::alloc_api::vec;
use crate::alloc::string::String;
use crate::alloc::vec;
#[test]
fn test_cstring16_from_str() {

View file

@ -6,7 +6,7 @@ use core::mem::MaybeUninit;
use core::result::Result;
use core::slice;
#[cfg(feature = "exts")]
#[cfg(feature = "alloc")]
use super::CString16;
/// Errors which can occur during checked `[uN]` -> `CStrN` conversions
@ -397,7 +397,7 @@ impl fmt::Display for CStr16 {
}
}
#[cfg(feature = "exts")]
#[cfg(feature = "alloc")]
impl PartialEq<CString16> for &CStr16 {
fn eq(&self, other: &CString16) -> bool {
PartialEq::eq(*self, other.as_ref())
@ -447,7 +447,7 @@ where
#[cfg(test)]
mod tests {
use super::*;
use crate::alloc_api::string::String;
use crate::alloc::string::String;
use uefi_macros::{cstr16, cstr8};
#[test]

View file

@ -1,8 +1,8 @@
use core::marker::PhantomData;
use core::mem::MaybeUninit;
#[cfg(feature = "exts")]
use crate::alloc_api::vec::Vec;
#[cfg(feature = "alloc")]
use crate::alloc::vec::Vec;
/// Slice backed by a potentially-unaligned pointer.
///
@ -110,7 +110,7 @@ impl<'a, T: Copy> UnalignedSlice<'a, T> {
}
/// Copies `self` into a new `Vec`.
#[cfg(feature = "exts")]
#[cfg(feature = "alloc")]
pub fn to_vec(&self) -> Vec<T> {
let len = self.len();
let mut v = Vec::with_capacity(len);
@ -122,7 +122,7 @@ impl<'a, T: Copy> UnalignedSlice<'a, T> {
}
}
#[cfg(feature = "exts")]
#[cfg(feature = "alloc")]
impl<'a, T: Copy> From<UnalignedSlice<'a, T>> for Vec<T> {
fn from(input: UnalignedSlice<'a, T>) -> Self {
input.to_vec()
@ -185,7 +185,7 @@ impl<'a, T: Copy> Iterator for UnalignedSliceIter<'a, T> {
#[cfg(test)]
mod tests {
use super::*;
use alloc_api::vec::Vec;
use alloc::vec::Vec;
#[test]
fn test_unaligned_slice() {

View file

@ -15,6 +15,20 @@
//! The `proto` module contains the standard UEFI protocols, which are normally provided
//! by the various UEFI drivers and firmware layers.
//!
//! ## Optional crate features:
//!
//! - `alloc`: Enables functionality requiring the `alloc` crate from the Rust standard library.
//! - For example, this allows many convenient `uefi-rs` functions to operate on heap data (`Box`).
//! - It is up to the user to provide a `#[global_allocator]`.
//! - `global_allocator`: implements a `#[global_allocator]` using UEFI functions.
//! - This allows you to use all abstractions from the `alloc` crate from the Rust standard library
//! during runtime. Hence, `Vec`, `Box`, etc. will be able to allocate memory.
//! **This is optional**, so you can provide a custom `#[global_allocator]` as well.
//! - There's no guarantee of the efficiency of UEFI's allocator.
//! - `logger`: logging implementation for the standard [`log`] crate.
//! - Prints output to UEFI console.
//! - No buffering is done: this is not a high-performance logger.
//!
//! ## Adapting to local conditions
//!
//! Unlike system tables, which are present on *all* UEFI implementations,
@ -27,16 +41,17 @@
#![feature(maybe_uninit_slice)]
#![feature(negative_impls)]
#![feature(ptr_metadata)]
#![cfg_attr(feature = "exts", feature(vec_into_raw_parts))]
#![cfg_attr(feature = "alloc", feature(vec_into_raw_parts))]
#![cfg_attr(docsrs, feature(doc_auto_cfg))]
#![no_std]
// Enable some additional warnings and lints.
#![warn(clippy::ptr_as_ptr, missing_docs, unused)]
#![deny(clippy::all)]
// `uefi-exts` requires access to memory allocation APIs.
#[cfg(feature = "exts")]
extern crate alloc as alloc_api;
// Enable once we use vec![] or similar
// #[cfg_attr(feature = "alloc", macro_use)]
#[cfg(feature = "alloc")]
extern crate alloc;
// allow referring to self as ::uefi for macros to work universally (from this crate and from others)
// see https://github.com/rust-lang/rust/issues/54647
@ -44,7 +59,7 @@ extern crate self as uefi;
#[macro_use]
pub mod data_types;
#[cfg(feature = "exts")]
#[cfg(feature = "alloc")]
pub use self::data_types::CString16;
pub use self::data_types::{unsafe_guid, Identify};
pub use self::data_types::{CStr16, CStr8, Char16, Char8, Event, Guid, Handle};
@ -59,8 +74,8 @@ pub mod proto;
pub mod prelude;
#[cfg(feature = "alloc")]
pub mod alloc;
#[cfg(feature = "global_allocator")]
pub mod global_allocator;
#[cfg(feature = "logger")]
pub mod logger;

View file

@ -11,13 +11,13 @@ use crate::proto::device_path::{DevicePath, DevicePathNode};
use core::mem::MaybeUninit;
use core::ptr;
#[cfg(feature = "exts")]
use alloc_api::vec::Vec;
#[cfg(feature = "alloc")]
use alloc::vec::Vec;
/// A builder for [`DevicePaths`].
///
/// The builder can be constructed with either a fixed-length buffer or
/// (if the `exts` feature is enabled) a `Vec`.
/// (if the `alloc` feature is enabled) a `Vec`.
///
/// Nodes are added via the [`push`] method. To construct a node, use one
/// of the structs in these submodules:
@ -82,7 +82,7 @@ impl<'a> DevicePathBuilder<'a> {
}
/// Create a builder backed by a `Vec`.
#[cfg(feature = "exts")]
#[cfg(feature = "alloc")]
pub fn with_vec(v: &'a mut Vec<u8>) -> Self {
Self {
storage: BuilderStorage::Vec(v),
@ -107,7 +107,7 @@ impl<'a> DevicePathBuilder<'a> {
);
*offset += node_size;
}
#[cfg(feature = "exts")]
#[cfg(feature = "alloc")]
BuilderStorage::Vec(vec) => {
let old_size = vec.len();
vec.reserve(node_size);
@ -134,7 +134,7 @@ impl<'a> DevicePathBuilder<'a> {
BuilderStorage::Buf { buf, offset } => unsafe {
MaybeUninit::slice_assume_init_ref(&buf[..*offset])
},
#[cfg(feature = "exts")]
#[cfg(feature = "alloc")]
BuilderStorage::Vec(vec) => vec,
};
@ -149,7 +149,7 @@ enum BuilderStorage<'a> {
offset: usize,
},
#[cfg(feature = "exts")]
#[cfg(feature = "alloc")]
Vec(&'a mut Vec<u8>),
}
@ -450,7 +450,7 @@ mod tests {
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
// Logical unit number
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
// End-entire node
0x7f, 0xff, 0x04, 0x00,
]);

View file

@ -558,7 +558,7 @@ pub enum NodeConversionError {
#[cfg(test)]
mod tests {
use super::*;
use alloc_api::vec::Vec;
use alloc::vec::Vec;
/// Create a node to `path` from raw data.
fn add_node(path: &mut Vec<u8>, device_type: u8, sub_type: u8, node_data: &[u8]) {

View file

@ -375,7 +375,7 @@ impl FileProtocolInfo for FileSystemVolumeLabel {}
#[cfg(test)]
mod tests {
use super::*;
use crate::alloc_api::vec;
use crate::alloc::vec;
use crate::table::runtime::TimeParams;
use crate::table::runtime::{Daylight, Time};
use crate::CString16;

View file

@ -16,10 +16,10 @@ use core::ffi::c_void;
use core::fmt::Debug;
use core::mem;
use core::ptr;
#[cfg(feature = "exts")]
#[cfg(feature = "alloc")]
use {
crate::ResultExt,
alloc_api::{alloc, alloc::Layout, boxed::Box},
::alloc::{alloc, alloc::Layout, boxed::Box},
core::slice,
};
@ -165,7 +165,7 @@ pub trait File: Sized {
(self.imp().flush)(self.imp()).into()
}
#[cfg(feature = "exts")]
#[cfg(feature = "alloc")]
/// Get the dynamically allocated info for a file
fn get_boxed_info<Info: FileProtocolInfo + ?Sized + Debug>(&mut self) -> Result<Box<Info>> {
// Initially try get_info with an empty array, this should always fail
@ -408,7 +408,7 @@ mod tests {
use super::*;
use crate::table::runtime::Time;
use crate::{CString16, Identify};
use alloc_api::vec;
use ::alloc::vec;
// Test `get_boxed_info` by setting up a fake file, which is mostly
// just function pointers. Most of the functions can be empty, only

View file

@ -3,12 +3,12 @@
use super::{Header, Revision};
use crate::data_types::{Align, PhysicalAddress, VirtualAddress};
use crate::proto::device_path::{DevicePath, FfiDevicePath};
#[cfg(feature = "exts")]
#[cfg(feature = "alloc")]
use crate::proto::{loaded_image::LoadedImage, media::fs::SimpleFileSystem};
use crate::proto::{Protocol, ProtocolPointer};
use crate::{Char16, Event, Guid, Handle, Result, Status};
#[cfg(feature = "exts")]
use alloc_api::vec::Vec;
#[cfg(feature = "alloc")]
use ::alloc::vec::Vec;
use bitflags::bitflags;
use core::cell::UnsafeCell;
use core::ffi::c_void;
@ -1265,7 +1265,7 @@ impl BootServices {
}
}
#[cfg(feature = "exts")]
#[cfg(feature = "alloc")]
impl BootServices {
/// Returns all the handles implementing a certain protocol.
pub fn find_handles<P: Protocol>(&self) -> Result<Vec<Handle>> {

View file

@ -1,16 +1,16 @@
//! UEFI services available at runtime, even after the OS boots.
use super::{Header, Revision};
#[cfg(feature = "exts")]
#[cfg(feature = "alloc")]
use crate::data_types::FromSliceWithNulError;
use crate::result::Error;
use crate::table::boot::MemoryDescriptor;
use crate::{guid, CStr16, Char16, Guid, Result, Status};
#[cfg(feature = "exts")]
use alloc_api::{vec, vec::Vec};
#[cfg(feature = "alloc")]
use alloc::{vec, vec::Vec};
use bitflags::bitflags;
use core::fmt::{Debug, Formatter};
#[cfg(feature = "exts")]
#[cfg(feature = "alloc")]
use core::mem;
use core::mem::MaybeUninit;
use core::{fmt, ptr};
@ -157,7 +157,7 @@ impl RuntimeServices {
}
/// Get the names and vendor GUIDs of all currently-set variables.
#[cfg(feature = "exts")]
#[cfg(feature = "alloc")]
pub fn variable_keys(&self) -> Result<Vec<VariableKey>> {
let mut all_variables = Vec::new();
@ -614,7 +614,7 @@ newtype_enum! {
}
/// Unique key for a variable.
#[cfg(feature = "exts")]
#[cfg(feature = "alloc")]
#[derive(Debug)]
pub struct VariableKey {
name: Vec<u16>,
@ -622,7 +622,7 @@ pub struct VariableKey {
pub vendor: VariableVendor,
}
#[cfg(feature = "exts")]
#[cfg(feature = "alloc")]
impl VariableKey {
/// Name of the variable.
pub fn name(&self) -> core::result::Result<&CStr16, FromSliceWithNulError> {
@ -630,7 +630,7 @@ impl VariableKey {
}
}
#[cfg(feature = "exts")]
#[cfg(feature = "alloc")]
impl fmt::Display for VariableKey {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "VariableKey {{ name: ")?;

View file

@ -143,7 +143,7 @@ impl SystemTable<Boot> {
/// Once boot services are exited, the logger and allocator provided by
/// this crate can no longer be used. The logger should be disabled using
/// the [`Logger::disable`] method, and the allocator should be disabled by
/// calling [`alloc::exit_boot_services`]. Note that if the logger and
/// calling [`global_allocator::exit_boot_services`]. Note that if the logger and
/// allocator were initialized with [`uefi_services::init`], they will be
/// disabled automatically when `exit_boot_services` is called.
///
@ -169,7 +169,7 @@ impl SystemTable<Boot> {
/// firmware following exit from boot services, along with a high-level
/// iterator to the UEFI memory map.
///
/// [`alloc::exit_boot_services`]: crate::alloc::exit_boot_services
/// [`global_allocator::exit_boot_services`]: crate::global_allocator::exit_boot_services
/// [`Logger::disable`]: crate::logger::Logger::disable
/// [`uefi_services::init`]: https://docs.rs/uefi-services/latest/uefi_services/fn.init.html
pub fn exit_boot_services(

View file

@ -45,8 +45,8 @@ impl Package {
#[derive(Clone, Copy, Debug)]
pub enum Feature {
GlobalAllocator,
Alloc,
Exts,
Logger,
Ci,
@ -56,8 +56,8 @@ pub enum Feature {
impl Feature {
fn as_str(&self) -> &'static str {
match self {
Self::GlobalAllocator => "global_allocator",
Self::Alloc => "alloc",
Self::Exts => "exts",
Self::Logger => "logger",
Self::Ci => "uefi-test-runner/ci",
@ -67,7 +67,7 @@ impl Feature {
/// Set of features that enables more code in the root uefi crate.
pub fn more_code() -> Vec<Self> {
vec![Self::Alloc, Self::Exts, Self::Logger]
vec![Self::GlobalAllocator, Self::Alloc, Self::Logger]
}
fn comma_separated_string(features: &[Feature]) -> String {
@ -260,7 +260,7 @@ mod tests {
fn test_comma_separated_features() {
assert_eq!(
Feature::comma_separated_string(&Feature::more_code()),
"alloc,exts,logger"
"global_allocator,alloc,logger"
);
}
@ -279,7 +279,7 @@ mod tests {
fn test_cargo_command() {
let cargo = Cargo {
action: CargoAction::Doc { open: true },
features: vec![Feature::Alloc],
features: vec![Feature::GlobalAllocator],
packages: vec![Package::Uefi, Package::Xtask],
release: false,
target: None,
@ -288,7 +288,7 @@ mod tests {
};
assert_eq!(
command_to_string(&cargo.command().unwrap()),
"RUSTDOCFLAGS=-Dwarnings cargo doc --package uefi --package xtask --features alloc --open"
"RUSTDOCFLAGS=-Dwarnings cargo doc --package uefi --package xtask --features global_allocator --open"
);
}
}

View file

@ -74,7 +74,7 @@ fn doc(opt: &DocOpt) -> Result<()> {
fn run_miri() -> Result<()> {
let cargo = Cargo {
action: CargoAction::Miri,
features: [Feature::Exts].into(),
features: [Feature::Alloc].into(),
packages: [Package::Uefi].into(),
release: false,
target: None,
@ -129,7 +129,7 @@ fn run_host_tests() -> Result<()> {
// Run uefi-rs and uefi-macros tests.
let cargo = Cargo {
action: CargoAction::Test,
features: vec![Feature::Exts],
features: vec![Feature::Alloc],
// Don't test uefi-services (or the packages that depend on it)
// as it has lang items that conflict with `std`.
packages: vec![Package::Uefi, Package::UefiMacros],