From bb5fcc3da724b23a49d8046056804e55e358deeb Mon Sep 17 00:00:00 2001 From: Philipp Schuster Date: Sat, 12 Nov 2022 14:16:37 +0100 Subject: [PATCH] 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. --- CHANGELOG.md | 2 ++ README.md | 20 +++++++++------ book/src/SUMMARY.md | 1 + book/src/how_to/crate_features.md | 15 +++++++++++ template/Cargo.toml | 2 +- uefi-services/Cargo.toml | 2 +- uefi-services/src/lib.rs | 4 +-- uefi-test-runner/Cargo.toml | 2 +- uefi/Cargo.toml | 2 +- uefi/src/data_types/guid.rs | 3 +-- uefi/src/data_types/mod.rs | 4 +-- uefi/src/data_types/owned_strs.rs | 6 ++--- uefi/src/data_types/strs.rs | 6 ++--- uefi/src/data_types/unaligned_slice.rs | 10 ++++---- uefi/src/{alloc.rs => global_allocator.rs} | 0 uefi/src/lib.rs | 29 ++++++++++++++++------ uefi/src/proto/device_path/build.rs | 16 ++++++------ uefi/src/proto/device_path/mod.rs | 2 +- uefi/src/proto/media/file/info.rs | 2 +- uefi/src/proto/media/file/mod.rs | 8 +++--- uefi/src/table/boot.rs | 8 +++--- uefi/src/table/runtime.rs | 16 ++++++------ uefi/src/table/system.rs | 4 +-- xtask/src/cargo.rs | 12 ++++----- xtask/src/main.rs | 4 +-- 25 files changed, 108 insertions(+), 72 deletions(-) create mode 100644 book/src/how_to/crate_features.md rename uefi/src/{alloc.rs => global_allocator.rs} (100%) diff --git a/CHANGELOG.md b/CHANGELOG.md index 065e60491..f3733591c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -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` diff --git a/README.md b/README.md index e676afbb6..7d0b13bfb 100644 --- a/README.md +++ b/README.md @@ -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`. diff --git a/book/src/SUMMARY.md b/book/src/SUMMARY.md index be7eb70c6..7d08184e2 100644 --- a/book/src/SUMMARY.md +++ b/book/src/SUMMARY.md @@ -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) diff --git a/book/src/how_to/crate_features.md b/book/src/how_to/crate_features.md new file mode 100644 index 000000000..47acdd799 --- /dev/null +++ b/book/src/how_to/crate_features.md @@ -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. diff --git a/template/Cargo.toml b/template/Cargo.toml index 366bc2723..4b9eb9e25 100644 --- a/template/Cargo.toml +++ b/template/Cargo.toml @@ -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" diff --git a/uefi-services/Cargo.toml b/uefi-services/Cargo.toml index ad7d680c0..a13c08a66 100644 --- a/uefi-services/Cargo.toml +++ b/uefi-services/Cargo.toml @@ -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 } diff --git a/uefi-services/src/lib.rs b/uefi-services/src/lib.rs index 40a1e35a4..3fed88b7e 100644 --- a/uefi-services/src/lib.rs +++ b/uefi-services/src/lib.rs @@ -83,7 +83,7 @@ pub fn init(st: &mut SystemTable) -> 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> EqStrUntilNul 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() { diff --git a/uefi/src/data_types/strs.rs b/uefi/src/data_types/strs.rs index 3aee20c73..1df8c6935 100644 --- a/uefi/src/data_types/strs.rs +++ b/uefi/src/data_types/strs.rs @@ -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 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] diff --git a/uefi/src/data_types/unaligned_slice.rs b/uefi/src/data_types/unaligned_slice.rs index 757a1c8ca..bd1ee9774 100644 --- a/uefi/src/data_types/unaligned_slice.rs +++ b/uefi/src/data_types/unaligned_slice.rs @@ -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 { 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> for Vec { 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() { diff --git a/uefi/src/alloc.rs b/uefi/src/global_allocator.rs similarity index 100% rename from uefi/src/alloc.rs rename to uefi/src/global_allocator.rs diff --git a/uefi/src/lib.rs b/uefi/src/lib.rs index e00713262..8d2f53087 100644 --- a/uefi/src/lib.rs +++ b/uefi/src/lib.rs @@ -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; diff --git a/uefi/src/proto/device_path/build.rs b/uefi/src/proto/device_path/build.rs index 95e6c257c..d838f3a2e 100644 --- a/uefi/src/proto/device_path/build.rs +++ b/uefi/src/proto/device_path/build.rs @@ -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) -> 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), } @@ -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, ]); diff --git a/uefi/src/proto/device_path/mod.rs b/uefi/src/proto/device_path/mod.rs index 0ccaebb76..36a04001c 100644 --- a/uefi/src/proto/device_path/mod.rs +++ b/uefi/src/proto/device_path/mod.rs @@ -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, device_type: u8, sub_type: u8, node_data: &[u8]) { diff --git a/uefi/src/proto/media/file/info.rs b/uefi/src/proto/media/file/info.rs index 327487dc8..49c7cb9eb 100644 --- a/uefi/src/proto/media/file/info.rs +++ b/uefi/src/proto/media/file/info.rs @@ -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; diff --git a/uefi/src/proto/media/file/mod.rs b/uefi/src/proto/media/file/mod.rs index 1b58eb956..768fb07ce 100644 --- a/uefi/src/proto/media/file/mod.rs +++ b/uefi/src/proto/media/file/mod.rs @@ -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(&mut self) -> Result> { // 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 diff --git a/uefi/src/table/boot.rs b/uefi/src/table/boot.rs index 90c08c5cf..b30cd6402 100644 --- a/uefi/src/table/boot.rs +++ b/uefi/src/table/boot.rs @@ -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(&self) -> Result> { diff --git a/uefi/src/table/runtime.rs b/uefi/src/table/runtime.rs index 58eefb424..b498d4884 100644 --- a/uefi/src/table/runtime.rs +++ b/uefi/src/table/runtime.rs @@ -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> { 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, @@ -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: ")?; diff --git a/uefi/src/table/system.rs b/uefi/src/table/system.rs index d1bca70ed..87cd64661 100644 --- a/uefi/src/table/system.rs +++ b/uefi/src/table/system.rs @@ -143,7 +143,7 @@ impl SystemTable { /// 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 { /// 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( diff --git a/xtask/src/cargo.rs b/xtask/src/cargo.rs index c28731602..82691fb95 100644 --- a/xtask/src/cargo.rs +++ b/xtask/src/cargo.rs @@ -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 { - 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" ); } } diff --git a/xtask/src/main.rs b/xtask/src/main.rs index c6f73c2c1..92255ef23 100644 --- a/xtask/src/main.rs +++ b/xtask/src/main.rs @@ -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],