From 0b140607db8515090f08b94fc85464f94ccab6a0 Mon Sep 17 00:00:00 2001 From: Arc Riley Date: Mon, 30 Mar 2026 14:45:48 -0700 Subject: [PATCH 1/2] Build cleanups --- .cargo/config.toml | 6 + .gitignore | 1 + Cargo.lock | 376 --------------------------------------------- Cargo.toml | 4 + 4 files changed, 11 insertions(+), 376 deletions(-) create mode 100644 .cargo/config.toml delete mode 100644 Cargo.lock diff --git a/.cargo/config.toml b/.cargo/config.toml new file mode 100644 index 0000000..729fd9d --- /dev/null +++ b/.cargo/config.toml @@ -0,0 +1,6 @@ +[build] +target = "x86_64-unknown-uefi" + +[unstable] +build-std = ["core", "compiler_builtins"] +build-std-features = ["compiler-builtins-mem"] diff --git a/.gitignore b/.gitignore index 3f69aab..9139273 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ +Cargo.lock /target # Infrastructure diff --git a/Cargo.lock b/Cargo.lock deleted file mode 100644 index 7a012f7..0000000 --- a/Cargo.lock +++ /dev/null @@ -1,376 +0,0 @@ -# This file is automatically @generated by Cargo. -# It is not intended for manual editing. -version = 4 - -[[package]] -name = "anyhow" -version = "1.0.101" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f0e0fee31ef5ed1ba1316088939cea399010ed7731dba877ed44aeb407a75ea" - -[[package]] -name = "bit_field" -version = "0.10.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e4b40c7323adcfc0a41c4b88143ed58346ff65a288fc144329c5c45e05d70c6" - -[[package]] -name = "bitflags" -version = "2.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "812e12b5285cc515a9c72a5c1d3b6d46a19dac5acfef5265968c166106e31dd3" - -[[package]] -name = "block-buffer" -version = "0.10.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71" -dependencies = [ - "generic-array", -] - -[[package]] -name = "cfg-if" -version = "1.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801" - -[[package]] -name = "cpufeatures" -version = "0.2.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "59ed5838eebb26a2bb2e58f6d5b5316989ae9d08bab10e0e6d103e656d1b0280" -dependencies = [ - "libc", -] - -[[package]] -name = "crypto-common" -version = "0.1.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "78c8292055d1c1df0cce5d180393dc8cce0abec0a7102adb6c7b1eef6016d60a" -dependencies = [ - "generic-array", - "typenum", -] - -[[package]] -name = "digest" -version = "0.10.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" -dependencies = [ - "block-buffer", - "crypto-common", -] - -[[package]] -name = "edera-sprout-boot" -version = "0.0.28" -dependencies = [ - "anyhow", - "edera-sprout-build", - "edera-sprout-config", - "edera-sprout-eficore", - "hex", - "jaarg", - "log", - "sha2", - "toml", - "uefi", - "uefi-raw", -] - -[[package]] -name = "edera-sprout-build" -version = "0.0.28" - -[[package]] -name = "edera-sprout-config" -version = "0.0.28" -dependencies = [ - "serde", -] - -[[package]] -name = "edera-sprout-eficore" -version = "0.0.28" -dependencies = [ - "anyhow", - "bitflags", - "log", - "shlex", - "spin", - "uefi", - "uefi-raw", -] - -[[package]] -name = "generic-array" -version = "0.14.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" -dependencies = [ - "typenum", - "version_check", -] - -[[package]] -name = "hex" -version = "0.4.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" - -[[package]] -name = "jaarg" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "534d589df1ef528a238f4bc4b1db081a1280f3aedf2695fd8971e9853a7fa4f6" - -[[package]] -name = "libc" -version = "0.2.180" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bcc35a38544a891a5f7c865aca548a982ccb3b8650a5b06d0fd33a10283c56fc" - -[[package]] -name = "lock_api" -version = "0.4.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "224399e74b87b5f3557511d98dff8b14089b3dadafcab6bb93eab67d3aace965" -dependencies = [ - "scopeguard", -] - -[[package]] -name = "log" -version = "0.4.29" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5e5032e24019045c762d3c0f28f5b6b8bbf38563a65908389bf7978758920897" - -[[package]] -name = "proc-macro2" -version = "1.0.106" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8fd00f0bb2e90d81d1044c2b32617f68fcb9fa3bb7640c23e9c748e53fb30934" -dependencies = [ - "unicode-ident", -] - -[[package]] -name = "ptr_meta" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b9a0cf95a1196af61d4f1cbdab967179516d9a4a4312af1f31948f8f6224a79" -dependencies = [ - "ptr_meta_derive", -] - -[[package]] -name = "ptr_meta_derive" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7347867d0a7e1208d93b46767be83e2b8f978c3dad35f775ac8d8847551d6fe1" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "quote" -version = "1.0.44" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "21b2ebcf727b7760c461f091f9f0f539b77b8e87f2fd88131e7f1b433b3cece4" -dependencies = [ - "proc-macro2", -] - -[[package]] -name = "scopeguard" -version = "1.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" - -[[package]] -name = "serde" -version = "1.0.228" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9a8e94ea7f378bd32cbbd37198a4a91436180c5bb472411e48b5ec2e2124ae9e" -dependencies = [ - "serde_core", - "serde_derive", -] - -[[package]] -name = "serde_core" -version = "1.0.228" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "41d385c7d4ca58e59fc732af25c3983b67ac852c1a25000afe1175de458b67ad" -dependencies = [ - "serde_derive", -] - -[[package]] -name = "serde_derive" -version = "1.0.228" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "serde_spanned" -version = "1.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f8bbf91e5a4d6315eee45e704372590b30e260ee83af6639d64557f51b067776" -dependencies = [ - "serde_core", -] - -[[package]] -name = "sha2" -version = "0.10.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a7507d819769d01a365ab707794a4084392c824f54a7a6a7862f8c3d0892b283" -dependencies = [ - "cfg-if", - "cpufeatures", - "digest", -] - -[[package]] -name = "shlex" -version = "1.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" - -[[package]] -name = "spin" -version = "0.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d5fe4ccb98d9c292d56fec89a5e07da7fc4cf0dc11e156b41793132775d3e591" -dependencies = [ - "lock_api", -] - -[[package]] -name = "syn" -version = "2.0.114" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d4d107df263a3013ef9b1879b0df87d706ff80f65a86ea879bd9c31f9b307c2a" -dependencies = [ - "proc-macro2", - "quote", - "unicode-ident", -] - -[[package]] -name = "toml" -version = "0.9.11+spec-1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f3afc9a848309fe1aaffaed6e1546a7a14de1f935dc9d89d32afd9a44bab7c46" -dependencies = [ - "serde_core", - "serde_spanned", - "toml_datetime", - "toml_parser", - "winnow", -] - -[[package]] -name = "toml_datetime" -version = "0.7.5+spec-1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "92e1cfed4a3038bc5a127e35a2d360f145e1f4b971b551a2ba5fd7aedf7e1347" -dependencies = [ - "serde_core", -] - -[[package]] -name = "toml_parser" -version = "1.0.6+spec-1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a3198b4b0a8e11f09dd03e133c0280504d0801269e9afa46362ffde1cbeebf44" -dependencies = [ - "winnow", -] - -[[package]] -name = "typenum" -version = "1.19.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "562d481066bde0658276a35467c4af00bdc6ee726305698a55b86e61d7ad82bb" - -[[package]] -name = "ucs2" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "df79298e11f316400c57ec268f3c2c29ac3c4d4777687955cd3d4f3a35ce7eba" -dependencies = [ - "bit_field", -] - -[[package]] -name = "uefi" -version = "0.36.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "71fe9058b73ee2b6559524af9e33199c13b2485ddbf3ad1181b68051cdc50c17" -dependencies = [ - "bitflags", - "cfg-if", - "log", - "ptr_meta", - "ucs2", - "uefi-macros", - "uefi-raw", - "uguid", -] - -[[package]] -name = "uefi-macros" -version = "0.19.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4687412b5ac74d245d5bfb1733ede50c31be19bf8a4b6a967a29b451bab49e67" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "uefi-raw" -version = "0.13.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f64fe59e11af447d12fd60a403c74106eb104309f34b4c6dbce6e927d97da9d" -dependencies = [ - "bitflags", - "uguid", -] - -[[package]] -name = "uguid" -version = "2.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c8352f8c05e47892e7eaf13b34abd76a7f4aeaf817b716e88789381927f199c" - -[[package]] -name = "unicode-ident" -version = "1.0.23" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "537dd038a89878be9b64dd4bd1b260315c1bb94f4d784956b81e27a088d9a09e" - -[[package]] -name = "version_check" -version = "0.9.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" - -[[package]] -name = "winnow" -version = "0.7.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a5364e9d77fcdeeaa6062ced926ee3381faa2ee02d3eb83a5c27a8825540829" diff --git a/Cargo.toml b/Cargo.toml index 619e6e8..93e07e3 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -62,18 +62,22 @@ features = ["alloc", "global_allocator", "panic_handler"] # which don't handle the UEFI target properly. [profile.dev] opt-level = 2 +panic = "abort" [profile.release] lto = "thin" strip = "symbols" +panic = "abort" [profile.release-debuginfo] inherits = "release" strip = "none" debug = 1 +panic = "abort" [profile.dev-fast] inherits = "dev" strip = "debuginfo" debug = 0 opt-level = 2 +panic = "abort" From 6425600ca733ba2a2d43ae2e6664aca4a0d7769f Mon Sep 17 00:00:00 2001 From: Arc Riley Date: Wed, 1 Apr 2026 23:32:06 -0700 Subject: [PATCH 2/2] Added support for several initrds which are provided to the kernel concatenated into one buffer. Most tools that build initrds (eg Dracut) do this for you but there are some situations where this can be extremely useful. --- crates/boot/src/actions/chainload.rs | 49 ++++++++++++++++---------- crates/boot/src/actions/edera.rs | 20 ++++++----- crates/boot/src/autoconfigure/bls.rs | 2 +- crates/boot/src/autoconfigure/linux.rs | 2 +- crates/config/src/actions/chainload.rs | 40 +++++++++++++++++---- crates/config/src/actions/edera.rs | 10 +++--- crates/parsing/src/lib.rs | 22 +----------- 7 files changed, 85 insertions(+), 60 deletions(-) diff --git a/crates/boot/src/actions/chainload.rs b/crates/boot/src/actions/chainload.rs index 2998ea5..8b4d14b 100644 --- a/crates/boot/src/actions/chainload.rs +++ b/crates/boot/src/actions/chainload.rs @@ -2,9 +2,10 @@ use crate::context::SproutContext; use crate::phases::before_handoff; use alloc::boxed::Box; use alloc::rc::Rc; +use alloc::vec::Vec; use anyhow::{Context, Result, bail}; use edera_sprout_config::actions::chainload::ChainloadConfiguration; -use edera_sprout_parsing::{combine_options, empty_is_none}; +use edera_sprout_parsing::combine_options; use eficore::bootloader_interface::BootloaderInterface; use eficore::loader::source::ImageSource; use eficore::loader::{ImageLoadRequest, ImageLoader}; @@ -62,25 +63,37 @@ pub fn chainload(context: Rc, configuration: &ChainloadConfigurat .set_load_options(options.as_ptr() as *const u8, options.num_bytes() as u32); } - // Stamp the initrd path, if provided. - let initrd = configuration - .linux_initrd - .as_ref() - .map(|item| context.stamp(item)); - // The initrd can be None or empty, so we need to collapse that into a single Option. - let initrd = empty_is_none(initrd); - // If an initrd is provided, register it with the EFI stack. let mut initrd_handle = None; - if let Some(linux_initrd) = initrd { - let content = eficore::path::read_file_contents( - Some(context.root().loaded_image_path()?), - &linux_initrd, - ) - .context("unable to read linux initrd")?; - let handle = - MediaLoaderHandle::register(LINUX_EFI_INITRD_MEDIA_GUID, content.into_boxed_slice()) - .context("unable to register linux initrd")?; + + // Only proceed if the configuration actually contains initrd paths. + if !configuration.initrd.is_empty() { + // Initialize a master buffer to hold the combined bytes of all initrd files. + let mut content = Vec::new(); + + // Iterate through each path provided in the configuration. + for item in &configuration.initrd { + // "Stamp" the path to replace variables (like disk labels) with real values. + let stamped_path = context.stamp(item); + + // Read the file contents from the EFI partition. + let mut segment = eficore::path::read_file_contents( + Some(context.root().loaded_image_path()?), + &stamped_path, + ).context("unable to read linux initrd segment")?; + + // Append this segment's bytes to the end of our master buffer. + // The kernel will see these as a continuous stream of CPIO archives. + content.append(&mut segment); + } + + // Register the full, concatenated buffer with the EFI stack using the Linux-specific GUID. + // This allows the Linux EFI stub to discover the initrd in memory. + let handle = MediaLoaderHandle::register( + LINUX_EFI_INITRD_MEDIA_GUID, + content.into_boxed_slice() + ).context("unable to register initrd")?; + initrd_handle = Some(handle); } diff --git a/crates/boot/src/actions/edera.rs b/crates/boot/src/actions/edera.rs index 363b8a4..9b1f8f6 100644 --- a/crates/boot/src/actions/edera.rs +++ b/crates/boot/src/actions/edera.rs @@ -5,7 +5,7 @@ use alloc::{format, vec}; use anyhow::{Context, Result}; use edera_sprout_config::actions::chainload::ChainloadConfiguration; use edera_sprout_config::actions::edera::EderaConfiguration; -use edera_sprout_parsing::{build_xen_config, combine_options, empty_is_none}; +use edera_sprout_parsing::{build_xen_config, combine_options}; use eficore::media_loader::{ MediaLoaderHandle, constants::xen::{ @@ -74,12 +74,16 @@ pub fn edera(context: Rc, configuration: &EderaConfiguration) -> // Create a vector of media loaders to drop them only after this function completes. let mut media_loaders = vec![config, kernel]; - // Register the initrd if it is provided. - if let Some(initrd) = empty_is_none(configuration.initrd.as_ref()) { - let initrd = - register_media_loader_file(&context, XEN_EFI_RAMDISK_MEDIA_GUID, "initrd", initrd) - .context("unable to register initrd media loader")?; - media_loaders.push(initrd); + // Register each initrd segment, filtering out any empty strings or placeholders. + for initrd_path in configuration.initrd.iter().filter(|s| !s.is_empty()) { + let handle = register_media_loader_file( + &context, + XEN_EFI_RAMDISK_MEDIA_GUID, + "initrd", + initrd_path + ).context("unable to register initrd segment media loader")?; + + media_loaders.push(handle); } // Chainload to the Xen EFI stub. @@ -88,7 +92,7 @@ pub fn edera(context: Rc, configuration: &EderaConfiguration) -> &ChainloadConfiguration { path: configuration.xen.clone(), options: vec![], - linux_initrd: None, + initrd: vec![], }, ) .context("unable to chainload to xen"); diff --git a/crates/boot/src/autoconfigure/bls.rs b/crates/boot/src/autoconfigure/bls.rs index d4ab931..98f63f4 100644 --- a/crates/boot/src/autoconfigure/bls.rs +++ b/crates/boot/src/autoconfigure/bls.rs @@ -86,7 +86,7 @@ pub fn scan( let chainload = ChainloadConfiguration { path: format!("{}\\$chainload", root), options: vec!["$options".to_string()], - linux_initrd: Some(format!("{}\\$initrd", root)), + initrd: alloc::vec![format!("{}\\$initrd", root)], }; // Insert the chainload action into the configuration. diff --git a/crates/boot/src/autoconfigure/linux.rs b/crates/boot/src/autoconfigure/linux.rs index d7ec70c..0eab818 100644 --- a/crates/boot/src/autoconfigure/linux.rs +++ b/crates/boot/src/autoconfigure/linux.rs @@ -231,7 +231,7 @@ pub fn scan( let chainload = ChainloadConfiguration { path: "$kernel".to_string(), options: vec!["$linux-options".to_string()], - linux_initrd: Some("$initrd".to_string()), + initrd: alloc::vec!["$initrd".to_string()], }; // Insert the chainload action into the configuration. diff --git a/crates/config/src/actions/chainload.rs b/crates/config/src/actions/chainload.rs index 55c7f00..e6c0c17 100644 --- a/crates/config/src/actions/chainload.rs +++ b/crates/config/src/actions/chainload.rs @@ -1,6 +1,32 @@ use alloc::string::String; use alloc::vec::Vec; -use serde::{Deserialize, Serialize}; +use serde::{Deserialize, Deserializer, Serialize}; + +// Naming the return type vastly improves readability +type DeResult<'de, D, T> = core::result::Result>::Error>; + +// Type of vector for a list of strings +type StringList = Vec; + +// Helper function to allow "linux-initrd" to be either a single string +// or a list of strings in the TOML file. +fn string_or_vec<'de, D>(deserializer: D) -> DeResult<'de, D, StringList> +where + D: Deserializer<'de>, { + + #[derive(Deserialize)] + #[serde(untagged)] + enum StringOrVec { + String(String), + Vec(Vec), + } + + match StringOrVec::deserialize(deserializer)? { + StringOrVec::String(s) => Ok(alloc::vec![s]), + // Wrap the vector in Ok() to match the return type + StringOrVec::Vec(v) => Ok(v), + } + } /// The configuration of the chainload action. #[derive(Serialize, Deserialize, Debug, Default, Clone)] @@ -8,14 +34,14 @@ pub struct ChainloadConfiguration { /// The path to the image to chainload. /// This can be a Linux EFI stub (vmlinuz usually) or a standard EFI executable. pub path: String, + /// The options to pass to the image. /// The options are concatenated by a space and then passed to the EFI application. #[serde(default)] pub options: Vec, - /// An optional path to a Linux initrd. - /// This uses the `LINUX_EFI_INITRD_MEDIA_GUID` mechanism to load the initrd into the EFI stack. - /// For Linux, you can also use initrd=\path\to\initrd as an option, but this option is - /// generally better and safer as it can support additional load options in the future. - #[serde(default, rename = "linux-initrd")] - pub linux_initrd: Option, + + /// The path(s) to the initrd to use for the image. + /// Supports both a single string or an array of strings. + #[serde(default, rename = "linux-initrd", deserialize_with = "string_or_vec")] + pub initrd: Vec, } diff --git a/crates/config/src/actions/edera.rs b/crates/config/src/actions/edera.rs index 6577610..879fa12 100644 --- a/crates/config/src/actions/edera.rs +++ b/crates/config/src/actions/edera.rs @@ -2,9 +2,11 @@ use alloc::string::String; use alloc::vec::Vec; use serde::{Deserialize, Serialize}; -/// The configuration of the edera action which boots the Edera hypervisor. -/// Edera is based on Xen but modified significantly with a Rust stack. -/// Sprout is a component of the Edera stack and provides the boot functionality of Xen. +type StringList = Vec; + +// The configuration of the edera action which boots the Edera hypervisor. +// Edera is based on Xen but modified significantly with a Rust stack. +// Sprout is a component of the Edera stack and provides the boot functionality of Xen. #[derive(Serialize, Deserialize, Debug, Default, Clone)] pub struct EderaConfiguration { /// The path to the Xen hypervisor EFI image. @@ -13,7 +15,7 @@ pub struct EderaConfiguration { pub kernel: String, /// The path to the initrd to load for dom0. #[serde(default)] - pub initrd: Option, + pub initrd: StringList, /// The options to pass to the kernel. #[serde(default, rename = "kernel-options")] pub kernel_options: Vec, diff --git a/crates/parsing/src/lib.rs b/crates/parsing/src/lib.rs index ba0bb38..9606b85 100644 --- a/crates/parsing/src/lib.rs +++ b/crates/parsing/src/lib.rs @@ -84,8 +84,8 @@ pub fn build_matrix(input: &BTreeMap>) -> Vec>(options: impl Iterator) -> String { options - .flat_map(|item| empty_is_none(Some(item))) .map(|item| item.as_ref().to_string()) + .filter(|item| !item.is_empty()) .collect::>() .join(" ") } @@ -96,11 +96,6 @@ pub fn unique_hash(input: &str) -> String { hex::encode(Sha256::digest(input.as_bytes())) } -/// Filter a string-like Option `input` such that an empty string is [None]. -pub fn empty_is_none>(input: Option) -> Option { - input.filter(|input| !input.as_ref().is_empty()) -} - /// Build a Xen EFI stub configuration file from pre-stamped `xen_options` and `kernel_options`. /// The returned string is in the Xen ini-like config file format. pub fn build_xen_config(xen_options: &str, kernel_options: &str) -> String { @@ -287,21 +282,6 @@ mod tests { assert_eq!(result, ""); } - #[test] - fn empty_is_none_returns_none_for_empty_string() { - assert!(empty_is_none(Some("")).is_none()); - } - - #[test] - fn empty_is_none_returns_some_for_nonempty_string() { - assert_eq!(empty_is_none(Some("x")), Some("x")); - } - - #[test] - fn empty_is_none_passthrough_on_none() { - assert!(empty_is_none(None::<&str>).is_none()); - } - #[test] fn unique_hash_is_deterministic() { assert_eq!(unique_hash("hello"), unique_hash("hello"));