diff --git a/src/autoconfigure.rs b/src/autoconfigure.rs index 3f90e53..ea872b1 100644 --- a/src/autoconfigure.rs +++ b/src/autoconfigure.rs @@ -1,101 +1,11 @@ -use crate::actions::ActionDeclaration; -use crate::actions::chainload::ChainloadConfiguration; use crate::config::RootConfiguration; -use crate::entries::EntryDeclaration; -use crate::generators::GeneratorDeclaration; -use crate::generators::bls::BlsConfiguration; use anyhow::{Context, Result}; -use uefi::cstr16; -use uefi::fs::{FileSystem, Path}; +use uefi::fs::FileSystem; use uefi::proto::device_path::DevicePath; -use uefi::proto::device_path::text::{AllowShortcuts, DisplayOnly}; use uefi::proto::media::fs::SimpleFileSystem; -/// The name prefix of the BLS chainload action that will be used -/// by the BLS generator to chainload entries. -const BLS_CHAINLOAD_ACTION_PREFIX: &str = "bls-chainload-"; - -/// Scan the specified `filesystem` for BLS configurations. -fn scan_for_bls( - filesystem: &mut FileSystem, - root: &DevicePath, - config: &mut RootConfiguration, -) -> Result { - // BLS has a loader.conf file that can specify its own auto-entries mechanism. - let bls_loader_conf_path = Path::new(cstr16!("\\loader\\loader.conf")); - // BLS also has an entries directory that can specify explicit entries. - let bls_entries_path = Path::new(cstr16!("\\loader\\entries")); - - // Convert the device path root to a string we can use in the configuration. - let mut root = root - .to_string(DisplayOnly(false), AllowShortcuts(false)) - .context("unable to convert device root to string")? - .to_string(); - // Add a trailing slash to the root to ensure the path is valid. - root.push('/'); - - // Whether we have a loader.conf file. - let has_loader_conf = filesystem - .try_exists(bls_loader_conf_path) - .context("unable to check for BLS loader.conf file")?; - - // Whether we have an entries directory. - // We actually iterate the entries to see if there are any. - let has_entries_dir = filesystem - .read_dir(bls_entries_path) - .ok() - .and_then(|mut iterator| iterator.next()) - .map(|entry| entry.is_ok()) - .unwrap_or(false); - - // Detect if a BLS supported configuration is on this filesystem. - // We check both loader.conf and entries directory as only one of them is required. - if !(has_loader_conf || has_entries_dir) { - return Ok(false); - } - - // Generate a unique name for the BLS chainload action. - let chainload_action_name = format!("{}{}", BLS_CHAINLOAD_ACTION_PREFIX, root); - - // BLS is now detected, generate a configuration for it. - let generator = BlsConfiguration { - entry: EntryDeclaration { - title: "$title".to_string(), - actions: vec![chainload_action_name.clone()], - ..Default::default() - }, - path: format!("{}\\loader", root), - }; - - // Generate a unique name for the BLS generator and insert the generator into the configuration. - config.generators.insert( - format!("autoconfigure-bls-{}", root), - GeneratorDeclaration { - bls: Some(generator), - ..Default::default() - }, - ); - - // Generate a chainload configuration for BLS. - // BLS will provide these values to us. - let chainload = ChainloadConfiguration { - path: format!("{}\\$chainload", root), - options: vec!["$options".to_string()], - linux_initrd: Some(format!("{}\\$initrd", root)), - }; - - // Insert the chainload action into the configuration. - config.actions.insert( - chainload_action_name, - ActionDeclaration { - chainload: Some(chainload), - ..Default::default() - }, - ); - - // We had a BLS supported configuration, so return true. - Ok(true) -} +/// bls: autodetect and configure BLS-enabled systems. +pub mod bls; /// Generate a [RootConfiguration] based on the environment. /// Intakes a `config` to use as the basis of the autoconfiguration. @@ -121,8 +31,8 @@ pub fn autoconfigure(config: &mut RootConfiguration) -> Result<()> { let mut filesystem = FileSystem::new(filesystem); // Scan the filesystem for BLS supported configurations. - // If we find any, we will add a BLS generator to the configuration. - scan_for_bls(&mut filesystem, &root, config).context("unable to scan filesystem")?; + bls::scan(&mut filesystem, &root, config) + .context("unable to scan for bls configurations")?; } Ok(()) diff --git a/src/autoconfigure/bls.rs b/src/autoconfigure/bls.rs new file mode 100644 index 0000000..a21c904 --- /dev/null +++ b/src/autoconfigure/bls.rs @@ -0,0 +1,97 @@ +use crate::actions::ActionDeclaration; +use crate::actions::chainload::ChainloadConfiguration; +use crate::config::RootConfiguration; +use crate::entries::EntryDeclaration; +use crate::generators::GeneratorDeclaration; +use crate::generators::bls::BlsConfiguration; +use anyhow::Context; +use uefi::cstr16; +use uefi::fs::{FileSystem, Path}; +use uefi::proto::device_path::DevicePath; +use uefi::proto::device_path::text::{AllowShortcuts, DisplayOnly}; + +/// The name prefix of the BLS chainload action that will be used +/// by the BLS generator to chainload entries. +const BLS_CHAINLOAD_ACTION_PREFIX: &str = "bls-chainload-"; + +/// Scan the specified `filesystem` for BLS configurations. +pub fn scan( + filesystem: &mut FileSystem, + root: &DevicePath, + config: &mut RootConfiguration, +) -> anyhow::Result { + // BLS has a loader.conf file that can specify its own auto-entries mechanism. + let bls_loader_conf_path = Path::new(cstr16!("\\loader\\loader.conf")); + // BLS also has an entries directory that can specify explicit entries. + let bls_entries_path = Path::new(cstr16!("\\loader\\entries")); + + // Convert the device path root to a string we can use in the configuration. + let mut root = root + .to_string(DisplayOnly(false), AllowShortcuts(false)) + .context("unable to convert device root to string")? + .to_string(); + // Add a trailing slash to the root to ensure the path is valid. + root.push('/'); + + // Whether we have a loader.conf file. + let has_loader_conf = filesystem + .try_exists(bls_loader_conf_path) + .context("unable to check for BLS loader.conf file")?; + + // Whether we have an entries directory. + // We actually iterate the entries to see if there are any. + let has_entries_dir = filesystem + .read_dir(bls_entries_path) + .ok() + .and_then(|mut iterator| iterator.next()) + .map(|entry| entry.is_ok()) + .unwrap_or(false); + + // Detect if a BLS supported configuration is on this filesystem. + // We check both loader.conf and entries directory as only one of them is required. + if !(has_loader_conf || has_entries_dir) { + return Ok(false); + } + + // Generate a unique name for the BLS chainload action. + let chainload_action_name = format!("{}{}", BLS_CHAINLOAD_ACTION_PREFIX, root); + + // BLS is now detected, generate a configuration for it. + let generator = BlsConfiguration { + entry: EntryDeclaration { + title: "$title".to_string(), + actions: vec![chainload_action_name.clone()], + ..Default::default() + }, + path: format!("{}\\loader", root), + }; + + // Generate a unique name for the BLS generator and insert the generator into the configuration. + config.generators.insert( + format!("autoconfigure-bls-{}", root), + GeneratorDeclaration { + bls: Some(generator), + ..Default::default() + }, + ); + + // Generate a chainload configuration for BLS. + // BLS will provide these values to us. + let chainload = ChainloadConfiguration { + path: format!("{}\\$chainload", root), + options: vec!["$options".to_string()], + linux_initrd: Some(format!("{}\\$initrd", root)), + }; + + // Insert the chainload action into the configuration. + config.actions.insert( + chainload_action_name, + ActionDeclaration { + chainload: Some(chainload), + ..Default::default() + }, + ); + + // We had a BLS supported configuration, so return true. + Ok(true) +}