diff --git a/src/actions/splash.rs b/src/actions/splash.rs index 53abf09..7c0426c 100644 --- a/src/actions/splash.rs +++ b/src/actions/splash.rs @@ -20,7 +20,7 @@ pub struct SplashConfiguration { } pub fn default_splash_time() -> u32 { - 5 + 0 } fn setup_graphics() -> Result> { diff --git a/src/config.rs b/src/config.rs index 057b2de..a786a6d 100644 --- a/src/config.rs +++ b/src/config.rs @@ -41,8 +41,12 @@ pub struct EntryDeclaration { #[derive(Serialize, Deserialize, Default, Clone)] pub struct PhasesConfiguration { + #[serde(default)] + pub early: Vec, #[serde(default)] pub startup: Vec, + #[serde(default)] + pub late: Vec, } #[derive(Serialize, Deserialize, Default, Clone)] diff --git a/src/extractors/filesystem_device_match.rs b/src/extractors/filesystem_device_match.rs index 75c64c7..b2e6649 100644 --- a/src/extractors/filesystem_device_match.rs +++ b/src/extractors/filesystem_device_match.rs @@ -1,14 +1,17 @@ use crate::context::SproutContext; use crate::utils; -use anyhow::{Context, Result}; +use anyhow::{Context, Result, anyhow, bail}; use serde::{Deserialize, Serialize}; use std::ops::Deref; use std::rc::Rc; -use uefi::CString16; +use std::str::FromStr; use uefi::fs::{FileSystem, Path}; use uefi::proto::device_path::DevicePath; use uefi::proto::media::file::{File, FileSystemVolumeLabel}; use uefi::proto::media::fs::SimpleFileSystem; +use uefi::proto::media::partition::PartitionInfo; +use uefi::{CString16, Guid}; +use uefi_raw::Status; #[derive(Serialize, Deserialize, Default, Clone)] pub struct FilesystemDeviceMatchExtractor { @@ -16,6 +19,10 @@ pub struct FilesystemDeviceMatchExtractor { pub has_label: Option, #[serde(default, rename = "has-item")] pub has_item: Option, + #[serde(default, rename = "has-partition-uuid")] + pub has_partition_uuid: Option, + #[serde(default)] + pub fallback: Option, } pub fn extract( @@ -25,6 +32,44 @@ pub fn extract( let handles = uefi::boot::find_handles::() .context("failed to find filesystem handles")?; for handle in handles { + let mut has_match = false; + + let partition_uuid = { + let partition_info = uefi::boot::open_protocol_exclusive::(handle); + + match partition_info { + Ok(partition_info) => { + if let Some(gpt) = partition_info.gpt_partition_entry() { + let uuid = gpt.unique_partition_guid; + Some(uuid) + } else { + None + } + } + + Err(error) => { + if error.status() == Status::NOT_FOUND || error.status() == Status::UNSUPPORTED + { + None + } else { + Err(error).context("failed to open filesystem partition info")?; + None + } + } + } + }; + + if let Some(partition_uuid) = partition_uuid + && let Some(ref has_partition_uuid) = extractor.has_partition_uuid + { + let parsed_uuid = Guid::from_str(has_partition_uuid) + .map_err(|e| anyhow!("failed to parse has-uuid: {}", e))?; + if partition_uuid != parsed_uuid { + continue; + } + has_match = true; + } + let mut filesystem = uefi::boot::open_protocol_exclusive::(handle) .context("failed to open filesystem protocol")?; @@ -41,6 +86,7 @@ pub fn extract( if label.volume_label() != want_label { continue; } + has_match = true; } if let Some(ref item) = extractor.has_item { @@ -57,6 +103,11 @@ pub fn extract( if !(metadata.is_directory() || metadata.is_regular_file()) { continue; } + has_match = true; + } + + if !has_match { + continue; } let path = uefi::boot::open_protocol_exclusive::(handle) @@ -64,5 +115,9 @@ pub fn extract( let path = path.deref(); return utils::device_path_root(path).context("failed to get device path root"); } - Ok(String::new()) + + if let Some(fallback) = &extractor.fallback { + return Ok(fallback.clone()); + } + bail!("unable to find matching filesystem") } diff --git a/src/main.rs b/src/main.rs index 61ee1d8..1fa553a 100644 --- a/src/main.rs +++ b/src/main.rs @@ -61,6 +61,8 @@ fn main() -> Result<()> { context.insert(&config.values); let context = context.freeze(); + phase(context.clone(), &config.phases.early).context("failed to execute early phase")?; + drivers::load(context.clone(), &config.drivers).context("failed to load drivers")?; let mut extracted = BTreeMap::new(); @@ -74,7 +76,7 @@ fn main() -> Result<()> { context.insert(&extracted); let context = context.freeze(); - phase(context.clone(), &config.phases.startup)?; + phase(context.clone(), &config.phases.startup).context("failed to execute startup phase")?; let mut all_entries = Vec::new(); @@ -105,6 +107,8 @@ fn main() -> Result<()> { info!(" entry {}: {}", index + 1, title); } + phase(context.clone(), &config.phases.late).context("failed to execute late phase")?; + let index = 1; let (context, entry) = &final_entries[index - 1];