improve filesystem device match to support uuids and add early splash

This commit is contained in:
2025-10-13 16:23:08 -07:00
parent c6f7412df0
commit 4a5dc39c49
4 changed files with 68 additions and 5 deletions

View File

@@ -20,7 +20,7 @@ pub struct SplashConfiguration {
} }
pub fn default_splash_time() -> u32 { pub fn default_splash_time() -> u32 {
5 0
} }
fn setup_graphics() -> Result<ScopedProtocol<GraphicsOutput>> { fn setup_graphics() -> Result<ScopedProtocol<GraphicsOutput>> {

View File

@@ -41,8 +41,12 @@ pub struct EntryDeclaration {
#[derive(Serialize, Deserialize, Default, Clone)] #[derive(Serialize, Deserialize, Default, Clone)]
pub struct PhasesConfiguration { pub struct PhasesConfiguration {
#[serde(default)]
pub early: Vec<PhaseConfiguration>,
#[serde(default)] #[serde(default)]
pub startup: Vec<PhaseConfiguration>, pub startup: Vec<PhaseConfiguration>,
#[serde(default)]
pub late: Vec<PhaseConfiguration>,
} }
#[derive(Serialize, Deserialize, Default, Clone)] #[derive(Serialize, Deserialize, Default, Clone)]

View File

@@ -1,14 +1,17 @@
use crate::context::SproutContext; use crate::context::SproutContext;
use crate::utils; use crate::utils;
use anyhow::{Context, Result}; use anyhow::{Context, Result, anyhow, bail};
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use std::ops::Deref; use std::ops::Deref;
use std::rc::Rc; use std::rc::Rc;
use uefi::CString16; use std::str::FromStr;
use uefi::fs::{FileSystem, Path}; use uefi::fs::{FileSystem, Path};
use uefi::proto::device_path::DevicePath; use uefi::proto::device_path::DevicePath;
use uefi::proto::media::file::{File, FileSystemVolumeLabel}; use uefi::proto::media::file::{File, FileSystemVolumeLabel};
use uefi::proto::media::fs::SimpleFileSystem; 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)] #[derive(Serialize, Deserialize, Default, Clone)]
pub struct FilesystemDeviceMatchExtractor { pub struct FilesystemDeviceMatchExtractor {
@@ -16,6 +19,10 @@ pub struct FilesystemDeviceMatchExtractor {
pub has_label: Option<String>, pub has_label: Option<String>,
#[serde(default, rename = "has-item")] #[serde(default, rename = "has-item")]
pub has_item: Option<String>, pub has_item: Option<String>,
#[serde(default, rename = "has-partition-uuid")]
pub has_partition_uuid: Option<String>,
#[serde(default)]
pub fallback: Option<String>,
} }
pub fn extract( pub fn extract(
@@ -25,6 +32,44 @@ pub fn extract(
let handles = uefi::boot::find_handles::<SimpleFileSystem>() let handles = uefi::boot::find_handles::<SimpleFileSystem>()
.context("failed to find filesystem handles")?; .context("failed to find filesystem handles")?;
for handle in handles { for handle in handles {
let mut has_match = false;
let partition_uuid = {
let partition_info = uefi::boot::open_protocol_exclusive::<PartitionInfo>(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::<SimpleFileSystem>(handle) let mut filesystem = uefi::boot::open_protocol_exclusive::<SimpleFileSystem>(handle)
.context("failed to open filesystem protocol")?; .context("failed to open filesystem protocol")?;
@@ -41,6 +86,7 @@ pub fn extract(
if label.volume_label() != want_label { if label.volume_label() != want_label {
continue; continue;
} }
has_match = true;
} }
if let Some(ref item) = extractor.has_item { if let Some(ref item) = extractor.has_item {
@@ -57,6 +103,11 @@ pub fn extract(
if !(metadata.is_directory() || metadata.is_regular_file()) { if !(metadata.is_directory() || metadata.is_regular_file()) {
continue; continue;
} }
has_match = true;
}
if !has_match {
continue;
} }
let path = uefi::boot::open_protocol_exclusive::<DevicePath>(handle) let path = uefi::boot::open_protocol_exclusive::<DevicePath>(handle)
@@ -64,5 +115,9 @@ pub fn extract(
let path = path.deref(); let path = path.deref();
return utils::device_path_root(path).context("failed to get device path root"); 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")
} }

View File

@@ -61,6 +61,8 @@ fn main() -> Result<()> {
context.insert(&config.values); context.insert(&config.values);
let context = context.freeze(); 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")?; drivers::load(context.clone(), &config.drivers).context("failed to load drivers")?;
let mut extracted = BTreeMap::new(); let mut extracted = BTreeMap::new();
@@ -74,7 +76,7 @@ fn main() -> Result<()> {
context.insert(&extracted); context.insert(&extracted);
let context = context.freeze(); 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(); let mut all_entries = Vec::new();
@@ -105,6 +107,8 @@ fn main() -> Result<()> {
info!(" entry {}: {}", index + 1, title); info!(" entry {}: {}", index + 1, title);
} }
phase(context.clone(), &config.phases.late).context("failed to execute late phase")?;
let index = 1; let index = 1;
let (context, entry) = &final_entries[index - 1]; let (context, entry) = &final_entries[index - 1];