mirror of
https://github.com/edera-dev/sprout.git
synced 2025-12-20 00:40:18 +00:00
chore(code): move crates/sprout to crates/boot and name it edera-sprout-boot
This commit is contained in:
138
crates/boot/src/actions/edera.rs
Normal file
138
crates/boot/src/actions/edera.rs
Normal file
@@ -0,0 +1,138 @@
|
||||
use crate::{
|
||||
actions,
|
||||
context::SproutContext,
|
||||
utils::{self},
|
||||
};
|
||||
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;
|
||||
use eficore::media_loader::{
|
||||
MediaLoaderHandle,
|
||||
constants::xen::{
|
||||
XEN_EFI_CONFIG_MEDIA_GUID, XEN_EFI_KERNEL_MEDIA_GUID, XEN_EFI_RAMDISK_MEDIA_GUID,
|
||||
},
|
||||
};
|
||||
use log::error;
|
||||
use uefi::Guid;
|
||||
|
||||
/// Builds a configuration string for the Xen EFI stub using the specified `configuration`.
|
||||
fn build_xen_config(context: Rc<SproutContext>, configuration: &EderaConfiguration) -> String {
|
||||
// Stamp xen options and combine them.
|
||||
let xen_options = utils::combine_options(
|
||||
configuration
|
||||
.xen_options
|
||||
.iter()
|
||||
.map(|item| context.stamp(item)),
|
||||
);
|
||||
|
||||
// Stamp kernel options and combine them.
|
||||
let kernel_options = utils::combine_options(
|
||||
configuration
|
||||
.kernel_options
|
||||
.iter()
|
||||
.map(|item| context.stamp(item)),
|
||||
);
|
||||
|
||||
// xen config file format is ini-like
|
||||
[
|
||||
// global section
|
||||
"[global]".to_string(),
|
||||
// default configuration section
|
||||
"default=sprout".to_string(),
|
||||
// configuration section for sprout
|
||||
"[sprout]".to_string(),
|
||||
// xen options
|
||||
format!("options={}", xen_options),
|
||||
// kernel options, stub replaces the kernel path
|
||||
// the kernel is provided via media loader
|
||||
format!("kernel=stub {}", kernel_options),
|
||||
// required or else the last line will be ignored
|
||||
"".to_string(),
|
||||
]
|
||||
.join("\n")
|
||||
}
|
||||
|
||||
/// Register a media loader for some `text` with the vendor `guid`.
|
||||
/// `what` should indicate some identifying value for error messages
|
||||
/// like `config` or `kernel`.
|
||||
/// Provides a [MediaLoaderHandle] that can be used to unregister the media loader.
|
||||
fn register_media_loader_text(guid: Guid, what: &str, text: String) -> Result<MediaLoaderHandle> {
|
||||
MediaLoaderHandle::register(guid, text.as_bytes().to_vec().into_boxed_slice())
|
||||
.context(format!("unable to register {} media loader", what)) /* */
|
||||
}
|
||||
|
||||
/// Register a media loader for the file `path` with the vendor `guid`.
|
||||
/// `what` should indicate some identifying value for error messages
|
||||
/// like `config` or `kernel`.
|
||||
/// Provides a [MediaLoaderHandle] that can be used to unregister the media loader.
|
||||
fn register_media_loader_file(
|
||||
context: &Rc<SproutContext>,
|
||||
guid: Guid,
|
||||
what: &str,
|
||||
path: &str,
|
||||
) -> Result<MediaLoaderHandle> {
|
||||
// Stamp the path to the file.
|
||||
let path = context.stamp(path);
|
||||
// Read the file contents.
|
||||
let content =
|
||||
eficore::path::read_file_contents(Some(context.root().loaded_image_path()?), &path)
|
||||
.context(format!("unable to read {} file", what))?;
|
||||
// Register the media loader.
|
||||
let handle = MediaLoaderHandle::register(guid, content.into_boxed_slice())
|
||||
.context(format!("unable to register {} media loader", what))?;
|
||||
Ok(handle)
|
||||
}
|
||||
|
||||
/// Executes the edera action which will boot the Edera hypervisor with the specified
|
||||
/// `configuration` and `context`. This action uses Edera-specific Xen EFI stub functionality.
|
||||
pub fn edera(context: Rc<SproutContext>, configuration: &EderaConfiguration) -> Result<()> {
|
||||
// Build the Xen config file content for this configuration.
|
||||
let config = build_xen_config(context.clone(), configuration);
|
||||
|
||||
// Register the media loader for the config.
|
||||
let config = register_media_loader_text(XEN_EFI_CONFIG_MEDIA_GUID, "config", config)
|
||||
.context("unable to register config media loader")?;
|
||||
|
||||
// Register the media loaders for the kernel.
|
||||
let kernel = register_media_loader_file(
|
||||
&context,
|
||||
XEN_EFI_KERNEL_MEDIA_GUID,
|
||||
"kernel",
|
||||
&configuration.kernel,
|
||||
)
|
||||
.context("unable to register kernel media loader")?;
|
||||
|
||||
// Create a vector of media loaders to unregister on error.
|
||||
let mut media_loaders = vec![config, kernel];
|
||||
|
||||
// Register the initrd if it is provided.
|
||||
if let Some(initrd) = utils::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);
|
||||
}
|
||||
|
||||
// Chainload to the Xen EFI stub.
|
||||
let result = actions::chainload::chainload(
|
||||
context.clone(),
|
||||
&ChainloadConfiguration {
|
||||
path: configuration.xen.clone(),
|
||||
options: vec![],
|
||||
linux_initrd: None,
|
||||
},
|
||||
)
|
||||
.context("unable to chainload to xen");
|
||||
|
||||
// Unregister the media loaders when an error happens.
|
||||
for media_loader in media_loaders {
|
||||
if let Err(error) = media_loader.unregister() {
|
||||
error!("unable to unregister media loader: {}", error);
|
||||
}
|
||||
}
|
||||
|
||||
result
|
||||
}
|
||||
Reference in New Issue
Block a user