Skip to content
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

rename crate features #561

Merged
merged 1 commit into from
Nov 19, 2022
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -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`
20 changes: 12 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
@@ -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.
phip1611 marked this conversation as resolved.
Show resolved Hide resolved
- 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`.

1 change: 1 addition & 0 deletions book/src/SUMMARY.md
Original file line number Diff line number Diff line change
@@ -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)
15 changes: 15 additions & 0 deletions book/src/how_to/crate_features.md
Original file line number Diff line number Diff line change
@@ -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.
2 changes: 1 addition & 1 deletion template/Cargo.toml
Original file line number Diff line number Diff line change
@@ -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"
2 changes: 1 addition & 1 deletion uefi-services/Cargo.toml
Original file line number Diff line number Diff line change
@@ -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 }
4 changes: 2 additions & 2 deletions uefi-services/src/lib.rs
Original file line number Diff line number Diff line change
@@ -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")]
2 changes: 1 addition & 1 deletion uefi-test-runner/Cargo.toml
Original file line number Diff line number Diff line change
@@ -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 }
2 changes: 1 addition & 1 deletion uefi/Cargo.toml
Original file line number Diff line number Diff line change
@@ -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).
3 changes: 1 addition & 2 deletions uefi/src/data_types/guid.rs
Original file line number Diff line number Diff line change
@@ -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() {
4 changes: 2 additions & 2 deletions uefi/src/data_types/mod.rs
Original file line number Diff line number Diff line change
@@ -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;
6 changes: 3 additions & 3 deletions uefi/src/data_types/owned_strs.rs
Original file line number Diff line number Diff line change
@@ -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() {
6 changes: 3 additions & 3 deletions uefi/src/data_types/strs.rs
Original file line number Diff line number Diff line change
@@ -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]
10 changes: 5 additions & 5 deletions uefi/src/data_types/unaligned_slice.rs
Original file line number Diff line number Diff line change
@@ -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() {
File renamed without changes.
29 changes: 22 additions & 7 deletions uefi/src/lib.rs
Original file line number Diff line number Diff line change
@@ -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,24 +41,25 @@
#![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
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;
16 changes: 8 additions & 8 deletions uefi/src/proto/device_path/build.rs
Original file line number Diff line number Diff line change
@@ -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,
]);
2 changes: 1 addition & 1 deletion uefi/src/proto/device_path/mod.rs
Original file line number Diff line number Diff line change
@@ -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]) {
2 changes: 1 addition & 1 deletion uefi/src/proto/media/file/info.rs
Original file line number Diff line number Diff line change
@@ -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;
8 changes: 4 additions & 4 deletions uefi/src/proto/media/file/mod.rs
Original file line number Diff line number Diff line change
@@ -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
8 changes: 4 additions & 4 deletions uefi/src/table/boot.rs
Original file line number Diff line number Diff line change
@@ -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>> {
16 changes: 8 additions & 8 deletions uefi/src/table/runtime.rs
Original file line number Diff line number Diff line change
@@ -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,23 +614,23 @@ newtype_enum! {
}

/// Unique key for a variable.
#[cfg(feature = "exts")]
#[cfg(feature = "alloc")]
#[derive(Debug)]
pub struct VariableKey {
name: Vec<u16>,
/// Unique identifier for the vendor.
pub vendor: VariableVendor,
}

#[cfg(feature = "exts")]
#[cfg(feature = "alloc")]
impl VariableKey {
/// Name of the variable.
pub fn name(&self) -> core::result::Result<&CStr16, FromSliceWithNulError> {
CStr16::from_u16_with_nul(&self.name)
}
}

#[cfg(feature = "exts")]
#[cfg(feature = "alloc")]
impl fmt::Display for VariableKey {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "VariableKey {{ name: ")?;
4 changes: 2 additions & 2 deletions uefi/src/table/system.rs
Original file line number Diff line number Diff line change
@@ -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(
12 changes: 6 additions & 6 deletions xtask/src/cargo.rs
Original file line number Diff line number Diff line change
@@ -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"
);
}
}
4 changes: 2 additions & 2 deletions xtask/src/main.rs
Original file line number Diff line number Diff line change
@@ -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],