feat(sprout): introduce no_std sprout which uses stable rust

This commit is contained in:
2025-11-03 02:04:21 -05:00
parent 1c2acdc568
commit 0017d7874d
53 changed files with 312 additions and 182 deletions

View File

@@ -9,7 +9,7 @@ edition.workspace = true
[dependencies.serde]
workspace = true
features = ["derive"]
default-features = false
[lib]
name = "edera_sprout_config"

View File

@@ -1,3 +1,5 @@
use alloc::string::String;
use alloc::vec::Vec;
use serde::{Deserialize, Serialize};
/// The configuration of the chainload action.

View File

@@ -1,3 +1,5 @@
use alloc::string::String;
use alloc::vec::Vec;
use serde::{Deserialize, Serialize};
/// The configuration of the edera action which boots the Edera hypervisor.

View File

@@ -1,3 +1,4 @@
use alloc::string::String;
use serde::{Deserialize, Serialize};
/// The configuration of the print action.

View File

@@ -1,3 +1,4 @@
use alloc::string::String;
use serde::{Deserialize, Serialize};
/// Declares a driver configuration.

View File

@@ -1,5 +1,7 @@
use alloc::collections::BTreeMap;
use alloc::string::String;
use alloc::vec::Vec;
use serde::{Deserialize, Serialize};
use std::collections::BTreeMap;
/// Declares a boot entry to display in the boot menu.
///

View File

@@ -1,3 +1,4 @@
use alloc::string::String;
use serde::{Deserialize, Serialize};
/// The filesystem device match extractor.

View File

@@ -1,4 +1,5 @@
use crate::entries::EntryDeclaration;
use alloc::string::{String, ToString};
use serde::{Deserialize, Serialize};
/// The default path to the BLS directory.

View File

@@ -1,6 +1,8 @@
use crate::entries::EntryDeclaration;
use alloc::collections::BTreeMap;
use alloc::string::String;
use alloc::vec::Vec;
use serde::{Deserialize, Serialize};
use std::collections::BTreeMap;
/// List generator configuration.
/// The list generator produces multiple entries based

View File

@@ -1,6 +1,8 @@
use crate::entries::EntryDeclaration;
use alloc::collections::BTreeMap;
use alloc::string::String;
use alloc::vec::Vec;
use serde::{Deserialize, Serialize};
use std::collections::BTreeMap;
/// Matrix generator configuration.
/// The matrix generator produces multiple entries based

View File

@@ -1,5 +1,7 @@
//! Sprout configuration descriptions.
//! This crate provides all the configuration structures for Sprout.
#![no_std]
extern crate alloc;
use crate::actions::ActionDeclaration;
use crate::drivers::DriverDeclaration;
@@ -7,8 +9,9 @@ use crate::entries::EntryDeclaration;
use crate::extractors::ExtractorDeclaration;
use crate::generators::GeneratorDeclaration;
use crate::phases::PhasesConfiguration;
use alloc::collections::BTreeMap;
use alloc::string::String;
use serde::{Deserialize, Serialize};
use std::collections::BTreeMap;
pub mod actions;
pub mod drivers;

View File

@@ -1,5 +1,7 @@
use alloc::collections::BTreeMap;
use alloc::string::String;
use alloc::vec::Vec;
use serde::{Deserialize, Serialize};
use std::collections::BTreeMap;
/// Configures the various phases of the boot process.
/// This allows hooking various phases to run actions.

View File

@@ -13,12 +13,14 @@ bitflags.workspace = true
edera-sprout-config.path = "../config"
hex.workspace = true
sha2.workspace = true
shlex.workspace = true
spin.workspace = true
toml.workspace = true
log.workspace = true
[dependencies.uefi]
workspace = true
features = ["alloc", "logger"]
features = ["alloc", "global_allocator", "logger", "panic_handler"]
[dependencies.uefi-raw]
workspace = true

View File

@@ -1,6 +1,6 @@
use crate::context::SproutContext;
use alloc::rc::Rc;
use anyhow::{Context, Result, bail};
use std::rc::Rc;
/// EFI chainloader action.
pub mod chainload;

View File

@@ -4,10 +4,11 @@ use crate::integrations::shim::{ShimInput, ShimSupport};
use crate::utils;
use crate::utils::media_loader::MediaLoaderHandle;
use crate::utils::media_loader::constants::linux::LINUX_EFI_INITRD_MEDIA_GUID;
use alloc::boxed::Box;
use alloc::rc::Rc;
use anyhow::{Context, Result, bail};
use edera_sprout_config::actions::chainload::ChainloadConfiguration;
use log::error;
use std::rc::Rc;
use uefi::CString16;
use uefi::proto::loaded_image::LoadedImage;

View File

@@ -1,5 +1,3 @@
use std::rc::Rc;
use crate::{
actions,
context::SproutContext,
@@ -13,6 +11,9 @@ use crate::{
},
},
};
use alloc::rc::Rc;
use alloc::string::{String, ToString};
use alloc::{format, vec};
use anyhow::{Context, Result};
use edera_sprout_config::actions::chainload::ChainloadConfiguration;
use edera_sprout_config::actions::edera::EderaConfiguration;

View File

@@ -1,8 +1,8 @@
use crate::context::SproutContext;
use alloc::rc::Rc;
use anyhow::Result;
use edera_sprout_config::actions::print::PrintConfiguration;
use log::info;
use std::rc::Rc;
/// Executes the print action with the specified `configuration` inside the provided `context`.
pub fn print(context: Rc<SproutContext>, configuration: &PrintConfiguration) -> Result<()> {

View File

@@ -1,4 +1,6 @@
use crate::utils;
use alloc::string::ToString;
use alloc::{format, vec};
use anyhow::{Context, Result};
use edera_sprout_config::RootConfiguration;
use edera_sprout_config::actions::ActionDeclaration;

View File

@@ -1,5 +1,9 @@
use crate::utils;
use crate::utils::vercmp;
use alloc::collections::BTreeMap;
use alloc::string::{String, ToString};
use alloc::vec::Vec;
use alloc::{format, vec};
use anyhow::{Context, Result};
use edera_sprout_config::RootConfiguration;
use edera_sprout_config::actions::ActionDeclaration;
@@ -7,7 +11,6 @@ use edera_sprout_config::actions::chainload::ChainloadConfiguration;
use edera_sprout_config::entries::EntryDeclaration;
use edera_sprout_config::generators::GeneratorDeclaration;
use edera_sprout_config::generators::list::ListConfiguration;
use std::collections::BTreeMap;
use uefi::CString16;
use uefi::fs::{FileSystem, Path, PathBuf};
use uefi::proto::device_path::DevicePath;

View File

@@ -1,4 +1,6 @@
use crate::utils;
use alloc::string::ToString;
use alloc::{format, vec};
use anyhow::{Context, Result};
use edera_sprout_config::RootConfiguration;
use edera_sprout_config::actions::ActionDeclaration;

View File

@@ -1,10 +1,11 @@
use crate::options::SproutOptions;
use crate::platform::tpm::PlatformTpm;
use crate::utils;
use alloc::vec::Vec;
use anyhow::{Context, Result, bail};
use core::ops::Deref;
use edera_sprout_config::{RootConfiguration, latest_version};
use log::info;
use std::ops::Deref;
use toml::Value;
use uefi::proto::device_path::LoadedImageDevicePath;

View File

@@ -1,11 +1,15 @@
use crate::options::SproutOptions;
use crate::platform::timer::PlatformTimer;
use alloc::boxed::Box;
use alloc::collections::{BTreeMap, BTreeSet};
use alloc::format;
use alloc::rc::Rc;
use alloc::string::{String, ToString};
use alloc::vec::Vec;
use anyhow::anyhow;
use anyhow::{Result, bail};
use core::cmp::Reverse;
use edera_sprout_config::actions::ActionDeclaration;
use std::cmp::Reverse;
use std::collections::{BTreeMap, BTreeSet};
use std::rc::Rc;
use uefi::proto::device_path::DevicePath;
/// The maximum number of iterations that can be performed in [SproutContext::finalize].

View File

@@ -1,11 +1,13 @@
use crate::context::SproutContext;
use crate::integrations::shim::{ShimInput, ShimSupport};
use crate::utils;
use alloc::collections::BTreeMap;
use alloc::format;
use alloc::rc::Rc;
use alloc::string::String;
use anyhow::{Context, Result};
pub(crate) use edera_sprout_config::drivers::DriverDeclaration;
use edera_sprout_config::drivers::DriverDeclaration;
use log::info;
use std::collections::BTreeMap;
use std::rc::Rc;
use uefi::boot::SearchType;
/// Loads the driver specified by the `driver` declaration.

View File

@@ -1,6 +1,7 @@
use crate::context::SproutContext;
use alloc::rc::Rc;
use alloc::string::{String, ToString};
use edera_sprout_config::entries::EntryDeclaration;
use std::rc::Rc;
/// Represents an entry that is stamped and ready to be booted.
#[derive(Clone)]

View File

@@ -1,7 +1,8 @@
use crate::context::SproutContext;
use alloc::rc::Rc;
use alloc::string::String;
use anyhow::{Result, bail};
use edera_sprout_config::extractors::ExtractorDeclaration;
use std::rc::Rc;
/// The filesystem device match extractor.
pub mod filesystem_device_match;

View File

@@ -1,10 +1,11 @@
use crate::context::SproutContext;
use crate::utils;
use alloc::rc::Rc;
use alloc::string::String;
use anyhow::{Context, Result, anyhow, bail};
use core::ops::Deref;
use core::str::FromStr;
use edera_sprout_config::extractors::filesystem_device_match::FilesystemDeviceMatchExtractor;
use std::ops::Deref;
use std::rc::Rc;
use std::str::FromStr;
use uefi::fs::{FileSystem, Path};
use uefi::proto::device_path::DevicePath;
use uefi::proto::media::file::{File, FileSystemVolumeLabel};

View File

@@ -1,9 +1,10 @@
use crate::context::SproutContext;
use crate::entries::BootableEntry;
use alloc::rc::Rc;
use alloc::vec::Vec;
use anyhow::Result;
use anyhow::bail;
use edera_sprout_config::generators::GeneratorDeclaration;
use std::rc::Rc;
/// The BLS generator.
pub mod bls;

View File

@@ -3,11 +3,14 @@ use crate::entries::BootableEntry;
use crate::generators::bls::entry::BlsEntry;
use crate::utils;
use crate::utils::vercmp;
use alloc::format;
use alloc::rc::Rc;
use alloc::string::{String, ToString};
use alloc::vec::Vec;
use anyhow::{Context, Result};
use core::cmp::Ordering;
use core::str::FromStr;
use edera_sprout_config::generators::bls::BlsConfiguration;
use std::cmp::Ordering;
use std::rc::Rc;
use std::str::FromStr;
use uefi::cstr16;
use uefi::fs::{FileSystem, PathBuf};
use uefi::proto::device_path::text::{AllowShortcuts, DisplayOnly};

View File

@@ -1,5 +1,6 @@
use alloc::string::{String, ToString};
use anyhow::{Error, Result};
use std::str::FromStr;
use core::str::FromStr;
/// Represents a parsed BLS entry.
/// Fields unrelated to Sprout are not included.

View File

@@ -1,8 +1,10 @@
use crate::context::SproutContext;
use crate::entries::BootableEntry;
use alloc::rc::Rc;
use alloc::string::ToString;
use alloc::vec::Vec;
use anyhow::Result;
use edera_sprout_config::generators::list::ListConfiguration;
use std::rc::Rc;
/// Generates a set of entries using the specified `list` configuration in the `context`.
pub fn generate(

View File

@@ -1,11 +1,14 @@
use crate::context::SproutContext;
use crate::entries::BootableEntry;
use crate::generators::list;
use alloc::collections::BTreeMap;
use alloc::rc::Rc;
use alloc::string::String;
use alloc::vec;
use alloc::vec::Vec;
use anyhow::Result;
use edera_sprout_config::generators::list::ListConfiguration;
use edera_sprout_config::generators::matrix::MatrixConfiguration;
use std::collections::BTreeMap;
use std::rc::Rc;
/// Builds out multiple generations of `input` based on a matrix style.
/// For example, if input is: {"x": ["a", "b"], "y": ["c", "d"]}

View File

@@ -2,6 +2,9 @@ use crate::integrations::bootloader_interface::bitflags::LoaderFeatures;
use crate::platform::timer::PlatformTimer;
use crate::utils::device_path_subpath;
use crate::utils::variables::{VariableClass, VariableController};
use alloc::format;
use alloc::string::{String, ToString};
use alloc::vec::Vec;
use anyhow::{Context, Result};
use uefi::proto::device_path::DevicePath;
use uefi::{Guid, guid};

View File

@@ -3,10 +3,13 @@ use crate::secure::SecureBoot;
use crate::utils;
use crate::utils::ResolvedPath;
use crate::utils::variables::{VariableClass, VariableController};
use alloc::boxed::Box;
use alloc::string::ToString;
use alloc::vec::Vec;
use anyhow::{Context, Result, anyhow, bail};
use core::ffi::c_void;
use core::pin::Pin;
use log::warn;
use std::ffi::c_void;
use std::pin::Pin;
use uefi::Handle;
use uefi::boot::LoadImageSource;
use uefi::proto::device_path::text::{AllowShortcuts, DisplayOnly};

View File

@@ -1,8 +1,9 @@
use crate::integrations::shim::{ShimInput, ShimSupport, ShimVerificationOutput};
use crate::utils;
use anyhow::{Context, Result, bail};
use anyhow::{Context, Result};
use core::slice;
use log::warn;
use std::sync::{LazyLock, Mutex};
use spin::{Lazy, Mutex};
use uefi::proto::device_path::FfiDevicePath;
use uefi::proto::unsafe_protocol;
use uefi::{Guid, guid};
@@ -45,8 +46,7 @@ struct SecurityHookState {
/// Global state for the security hook.
/// This is messy, but it is safe given the mutex.
static GLOBAL_HOOK_STATE: LazyLock<Mutex<Option<SecurityHookState>>> =
LazyLock::new(|| Mutex::new(None));
static GLOBAL_HOOK_STATE: Lazy<Mutex<Option<SecurityHookState>>> = Lazy::new(|| Mutex::new(None));
/// Security hook helper.
pub struct SecurityHook;
@@ -110,24 +110,13 @@ impl SecurityHook {
// Verify the input, if it fails, call the original hook.
if !Self::verify(input) {
// Acquire the global hook state to grab the original hook.
let function = match GLOBAL_HOOK_STATE.lock() {
// We have acquired the lock, so we can find the original hook.
Ok(state) => match state.as_ref() {
// The hook state is available, so we can acquire the original hook.
Some(state) => state.original_hook.file_authentication_state,
let function = match GLOBAL_HOOK_STATE.lock().as_ref() {
// The hook state is available, so we can acquire the original hook.
Some(state) => state.original_hook.file_authentication_state,
// The hook state is not available, so we can't call the original hook.
None => {
warn!("global hook state is not available, unable to call original hook");
return Status::LOAD_ERROR;
}
},
Err(error) => {
warn!(
"unable to acquire global hook state lock to call original hook: {}",
error,
);
// The hook state is not available, so we can't call the original hook.
None => {
warn!("global hook state is not available, unable to call original hook");
return Status::LOAD_ERROR;
}
};
@@ -161,7 +150,7 @@ impl SecurityHook {
}
// Construct a slice out of the file buffer and size.
let buffer = unsafe { std::slice::from_raw_parts(file_buffer, file_size) };
let buffer = unsafe { slice::from_raw_parts(file_buffer, file_size) };
// Construct a shim input from the path.
let input = ShimInput::SecurityHookBuffer(Some(path), buffer);
@@ -169,24 +158,13 @@ impl SecurityHook {
// Verify the input, if it fails, call the original hook.
if !Self::verify(input) {
// Acquire the global hook state to grab the original hook.
let function = match GLOBAL_HOOK_STATE.lock() {
// We have acquired the lock, so we can find the original hook.
Ok(state) => match state.as_ref() {
// The hook state is available, so we can acquire the original hook.
Some(state) => state.original_hook2.file_authentication,
let function = match GLOBAL_HOOK_STATE.lock().as_ref() {
// The hook state is available, so we can acquire the original hook.
Some(state) => state.original_hook2.file_authentication,
// The hook state is not available, so we can't call the original hook.
None => {
warn!("global hook state is not available, unable to call original hook");
return Status::LOAD_ERROR;
}
},
Err(error) => {
warn!(
"unable to acquire global hook state lock to call original hook: {}",
error
);
// The hook state is not available, so we can't call the original hook.
None => {
warn!("global hook state is not available, unable to call original hook");
return Status::LOAD_ERROR;
}
};
@@ -237,9 +215,7 @@ impl SecurityHook {
};
// Acquire the lock to the global state and replace it.
let Ok(mut global_state) = GLOBAL_HOOK_STATE.lock() else {
bail!("unable to acquire global hook state lock");
};
let mut global_state = GLOBAL_HOOK_STATE.lock();
global_state.replace(state);
// Install the hooks into the UEFI stack.
@@ -276,9 +252,7 @@ impl SecurityHook {
.context("unable to open security arch2 protocol")?;
// Acquire the lock to the global state.
let Ok(mut global_state) = GLOBAL_HOOK_STATE.lock() else {
bail!("unable to acquire global hook state lock");
};
let mut global_state = GLOBAL_HOOK_STATE.lock();
// Take the state and replace the original functions.
let Some(state) = global_state.take() else {

View File

@@ -1,8 +1,8 @@
#![doc = include_str!("../README.md")]
#![feature(uefi_std)]
#![no_std]
#![no_main]
/// The delay to wait for when an error occurs in Sprout.
const DELAY_ON_ERROR: Duration = Duration::from_secs(10);
extern crate alloc;
use crate::context::{RootContext, SproutContext};
use crate::entries::BootableEntry;
@@ -14,13 +14,18 @@ use crate::platform::timer::PlatformTimer;
use crate::platform::tpm::PlatformTpm;
use crate::secure::SecureBoot;
use crate::utils::PartitionGuidForm;
use alloc::collections::BTreeMap;
use alloc::format;
use alloc::string::ToString;
use alloc::vec::Vec;
use anyhow::{Context, Result, bail};
use core::ops::Deref;
use core::time::Duration;
use edera_sprout_config::RootConfiguration;
use log::{error, info, warn};
use std::collections::BTreeMap;
use std::ops::Deref;
use std::time::Duration;
use uefi::entry;
use uefi::proto::device_path::LoadedImageDevicePath;
use uefi_raw::Status;
/// actions: Code that can be configured and executed by Sprout.
pub mod actions;
@@ -73,6 +78,9 @@ pub mod options;
/// utils: Utility functions that are used by other parts of Sprout.
pub mod utils;
/// The delay to wait for when an error occurs in Sprout.
const DELAY_ON_ERROR: Duration = Duration::from_secs(10);
/// Run Sprout, returning an error if one occurs.
fn run() -> Result<()> {
// For safety reasons, we will note that Secure Boot is in beta on Sprout.
@@ -373,9 +381,14 @@ fn run() -> Result<()> {
/// The main entrypoint of sprout.
/// It is possible this function will not return if actions that are executed
/// exit boot services or do not return control to sprout.
fn main() -> Result<()> {
#[entry]
fn efi_main() -> Status {
// Initialize the basic UEFI environment.
setup::init()?;
// If initialization fails, we will return ABORTED.
if let Err(error) = setup::init() {
error!("unable to initialize environment: {}", error);
return Status::ABORTED;
}
// Run Sprout, then handle the error.
let result = run();
@@ -387,9 +400,10 @@ fn main() -> Result<()> {
}
// Sleep to allow the user to read the error.
uefi::boot::stall(DELAY_ON_ERROR);
return Status::ABORTED;
}
// Sprout doesn't necessarily guarantee anything was booted.
// If we reach here, we will exit back to whoever called us.
Ok(())
Status::SUCCESS
}

View File

@@ -1,9 +1,10 @@
use crate::entries::BootableEntry;
use crate::integrations::bootloader_interface::BootloaderInterface;
use crate::platform::timer::PlatformTimer;
use alloc::vec;
use anyhow::{Context, Result, bail};
use core::time::Duration;
use log::{info, warn};
use std::time::Duration;
use uefi::ResultExt;
use uefi::boot::TimerTrigger;
use uefi::proto::console::text::{Input, Key, ScanCode};

View File

@@ -1,6 +1,10 @@
use crate::options::parser::{OptionDescription, OptionForm, OptionsRepresentable};
use alloc::collections::BTreeMap;
use alloc::string::{String, ToString};
use anyhow::{Context, Result, bail};
use std::collections::BTreeMap;
/// Acquire arguments from UEFI environment.
pub mod env;
/// The Sprout options parser.
pub mod parser;

View File

@@ -0,0 +1,77 @@
use alloc::string::{String, ToString};
use alloc::vec::Vec;
use anyhow::{Context, Result, bail};
use uefi::proto::loaded_image::{LoadOptionsError, LoadedImage};
/// Loads the command-line arguments passed to Sprout.
pub fn args() -> Result<Vec<String>> {
// Acquire the image handle of Sprout.
let handle = uefi::boot::image_handle();
// Open the LoadedImage protocol for Sprout.
let loaded_image = uefi::boot::open_protocol_exclusive::<LoadedImage>(handle)
.context("unable to open loaded image protocol for sprout")?;
// Load the command-line argument string.
let options = match loaded_image.load_options_as_cstr16() {
// Load options were passed. We will return them for processing.
Ok(options) => options,
// No load options were passed. We will return an empty vector.
Err(LoadOptionsError::NotSet) => {
return Ok(Vec::new());
}
Err(LoadOptionsError::NotAligned) => {
bail!("load options are not properly aligned");
}
Err(LoadOptionsError::InvalidString(error)) => {
bail!("load options are not a valid string: {}", error);
}
};
// Convert the options to a string.
let options = options.to_string();
// Use shlex to parse the options.
// If shlex fails, we will fall back to a simple whitespace split.
let mut args = shlex::split(&options).unwrap_or_else(|| {
options
.split_ascii_whitespace()
.map(|string| string.to_string())
.collect::<Vec<_>>()
});
// If there is a first argument, check if it is not an option.
// If it is not, we will assume it is the path to the executable and remove it.
if let Some(arg) = args.first()
&& !arg.starts_with('-')
{
args.remove(0);
}
// Correct firmware that may add invalid arguments at the start.
// Witnessed this on a Dell Precision 5690 when direct booting.
loop {
// Grab the first argument or break.
let Some(arg) = args.first() else {
break;
};
// Check if the argument is a valid character.
// If it is not, remove it and continue.
let Some(first_character) = arg.chars().next() else {
break;
};
// If the character is not a printable character or a backtick, remove it and continue.
if first_character < 0x1f as char || first_character == '`' {
args.remove(0);
continue;
}
break;
}
Ok(args)
}

View File

@@ -1,6 +1,10 @@
use crate::options::env;
use alloc::collections::BTreeMap;
use alloc::string::{String, ToString};
use anyhow::{Context, Result, bail};
use core::ptr::null_mut;
use log::info;
use std::collections::BTreeMap;
use uefi_raw::Status;
/// The type of option. This disambiguates different behavior
/// of how options are handled.
@@ -47,23 +51,7 @@ pub trait OptionsRepresentable {
// Collect all the arguments to Sprout.
// Skip the first argument, which is the path to our executable.
let mut args = std::env::args().skip(1).collect::<Vec<_>>();
// Correct firmware that may add invalid arguments at the start.
// Witnessed this on a Dell Precision 5690 when direct booting.
loop {
// Grab the first argument or break.
let Some(arg) = args.first() else {
break;
};
// If the argument starts with a tilde, remove it.
if arg.starts_with("`") {
args.remove(0);
continue;
}
break;
}
let args = env::args()?;
// Represent options as key-value pairs.
let mut options = BTreeMap::new();
@@ -77,7 +65,7 @@ pub trait OptionsRepresentable {
break;
};
// If the doesn't start with --, that is invalid.
// If the option doesn't start with --, that is invalid.
if !option.starts_with("--") {
bail!("invalid option: {option}");
}
@@ -144,7 +132,9 @@ pub trait OptionsRepresentable {
);
}
// Exit because the help has been displayed.
std::process::exit(0);
unsafe {
uefi::boot::exit(uefi::boot::image_handle(), Status::SUCCESS, 0, null_mut());
};
}
// Insert the option and the value into the map.

View File

@@ -1,8 +1,9 @@
use crate::actions;
use crate::context::SproutContext;
use alloc::format;
use alloc::rc::Rc;
use anyhow::{Context, Result};
use edera_sprout_config::phases::PhaseConfiguration;
use std::rc::Rc;
/// Executes the specified [phase] of the boot process.
/// The value [phase] should be a reference of a specific phase in the [PhasesConfiguration].

View File

@@ -1,7 +1,7 @@
// Referenced https://github.com/sheroz/tick_counter (MIT license) as a baseline.
// Architecturally modified to support UEFI and remove x86 (32-bit) support.
use std::time::Duration;
use core::time::Duration;
/// Support for aarch64 timers.
#[cfg(target_arch = "aarch64")]

View File

@@ -1,5 +1,5 @@
use crate::platform::timer::TickFrequency;
use std::arch::asm;
use core::arch::asm;
/// Reads the cntvct_el0 counter and returns the value.
pub fn ticks() -> u64 {

View File

@@ -1,6 +1,6 @@
use crate::platform::timer::TickFrequency;
use core::arch::asm;
use std::time::Duration;
use core::time::Duration;
/// We will measure the frequency of the timer based on 1000 microseconds.
/// This will result in a call to BS->Stall(1000) in the end.

View File

@@ -1,27 +1,8 @@
use anyhow::{Context, Result};
use std::os::uefi as uefi_std;
/// Initializes the UEFI environment.
///
/// This fetches the system table and current image handle from uefi_std and injects
/// them into the uefi crate.
pub fn init() -> Result<()> {
// Acquire the system table and image handle from the uefi_std environment.
let system_table = uefi_std::env::system_table();
let image_handle = uefi_std::env::image_handle();
// SAFETY: The UEFI variables above come from the Rust std.
// These variables are not-null and calling the uefi crates with these values is validated
// to be corrected by hand.
unsafe {
// Set the system table and image handle.
uefi::table::set_system_table(system_table.as_ptr().cast());
let handle = uefi::Handle::from_ptr(image_handle.as_ptr().cast())
.context("unable to resolve image handle")?;
uefi::boot::set_image_handle(handle);
}
// Initialize the uefi logger mechanism and other helpers.
// Initialize the uefi internals.
uefi::helpers::init().context("unable to initialize uefi")?;
Ok(())
}

View File

@@ -1,6 +1,10 @@
use alloc::borrow::ToOwned;
use alloc::boxed::Box;
use alloc::string::{String, ToString};
use alloc::vec::Vec;
use anyhow::{Context, Result, bail};
use core::ops::Deref;
use sha2::{Digest, Sha256};
use std::ops::Deref;
use uefi::boot::SearchType;
use uefi::fs::{FileSystem, Path};
use uefi::proto::device_path::text::{AllowShortcuts, DevicePathFromText, DisplayOnly};

View File

@@ -1,3 +1,5 @@
use alloc::vec;
use alloc::vec::Vec;
use anyhow::{Context, Result};
use uefi::proto::console::gop::{BltOp, BltPixel, BltRegion, GraphicsOutput};

View File

@@ -1,5 +1,8 @@
use alloc::boxed::Box;
use alloc::vec::Vec;
use anyhow::{Context, Result, bail};
use std::ffi::c_void;
use core::ffi::c_void;
use core::ptr;
use uefi::proto::device_path::DevicePath;
use uefi::proto::device_path::build::DevicePathBuilder;
use uefi::proto::device_path::build::media::Vendor;
@@ -261,8 +264,7 @@ impl MediaLoaderHandle {
let protocol = Box::from_raw(self.protocol);
// Retrieve a box for the data we passed in.
let slice =
std::ptr::slice_from_raw_parts_mut(protocol.address as *mut u8, protocol.length);
let slice = ptr::slice_from_raw_parts_mut(protocol.address as *mut u8, protocol.length);
let data = Box::from_raw(slice);
// Drop all the allocations explicitly, as we don't want to leak them.

View File

@@ -1,4 +1,7 @@
use crate::utils;
use alloc::format;
use alloc::string::{String, ToString};
use alloc::vec::Vec;
use anyhow::{Context, Result};
use log::warn;
use uefi::{CString16, guid};

View File

@@ -1,5 +1,5 @@
use std::cmp::Ordering;
use std::iter::Peekable;
use core::cmp::Ordering;
use core::iter::Peekable;
/// Handles single character advancement and comparison.
macro_rules! handle_single_char {