2025-10-21 19:12:16 -07:00
|
|
|
use crate::options::parser::{OptionDescription, OptionForm, OptionsRepresentable};
|
2025-11-03 02:04:21 -05:00
|
|
|
use alloc::collections::BTreeMap;
|
|
|
|
|
use alloc::string::{String, ToString};
|
2025-10-21 19:12:16 -07:00
|
|
|
use anyhow::{Context, Result, bail};
|
2025-11-03 02:04:21 -05:00
|
|
|
|
|
|
|
|
/// Acquire arguments from UEFI environment.
|
|
|
|
|
pub mod env;
|
2025-10-21 19:12:16 -07:00
|
|
|
|
2025-10-20 19:42:39 -07:00
|
|
|
/// The Sprout options parser.
|
|
|
|
|
pub mod parser;
|
2025-10-20 18:17:29 -07:00
|
|
|
|
|
|
|
|
/// Default configuration file path.
|
|
|
|
|
const DEFAULT_CONFIG_PATH: &str = "\\sprout.toml";
|
|
|
|
|
|
|
|
|
|
/// The parsed options of sprout.
|
|
|
|
|
#[derive(Debug)]
|
|
|
|
|
pub struct SproutOptions {
|
2025-10-27 02:38:40 -04:00
|
|
|
/// Configures Sprout automatically based on the environment.
|
|
|
|
|
pub autoconfigure: bool,
|
2025-10-20 18:17:29 -07:00
|
|
|
/// Path to a configuration file to load.
|
|
|
|
|
pub config: String,
|
|
|
|
|
/// Entry to boot without showing the boot menu.
|
|
|
|
|
pub boot: Option<String>,
|
2025-10-26 23:59:50 -04:00
|
|
|
/// Force display of the boot menu.
|
|
|
|
|
pub force_menu: bool,
|
|
|
|
|
/// The timeout for the boot menu in seconds.
|
|
|
|
|
pub menu_timeout: Option<u64>,
|
2025-10-20 18:17:29 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// The default Sprout options.
|
|
|
|
|
impl Default for SproutOptions {
|
|
|
|
|
fn default() -> Self {
|
|
|
|
|
Self {
|
2025-10-27 02:38:40 -04:00
|
|
|
autoconfigure: false,
|
2025-10-20 18:17:29 -07:00
|
|
|
config: DEFAULT_CONFIG_PATH.to_string(),
|
|
|
|
|
boot: None,
|
2025-10-26 23:59:50 -04:00
|
|
|
force_menu: false,
|
|
|
|
|
menu_timeout: None,
|
2025-10-20 18:17:29 -07:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2025-10-21 19:12:16 -07:00
|
|
|
|
|
|
|
|
/// The options parser mechanism for Sprout.
|
|
|
|
|
impl OptionsRepresentable for SproutOptions {
|
|
|
|
|
/// Produce the [SproutOptions] structure.
|
|
|
|
|
type Output = Self;
|
|
|
|
|
|
|
|
|
|
/// All the Sprout options that are defined.
|
|
|
|
|
fn options() -> &'static [(&'static str, OptionDescription<'static>)] {
|
|
|
|
|
&[
|
2025-11-01 20:07:32 -04:00
|
|
|
(
|
|
|
|
|
"autoconfigure",
|
|
|
|
|
OptionDescription {
|
|
|
|
|
description: "Enable Sprout Autoconfiguration",
|
|
|
|
|
form: OptionForm::Flag,
|
|
|
|
|
},
|
|
|
|
|
),
|
2025-10-21 19:12:16 -07:00
|
|
|
(
|
|
|
|
|
"config",
|
|
|
|
|
OptionDescription {
|
|
|
|
|
description: "Path to Sprout configuration file",
|
|
|
|
|
form: OptionForm::Value,
|
|
|
|
|
},
|
|
|
|
|
),
|
|
|
|
|
(
|
|
|
|
|
"boot",
|
|
|
|
|
OptionDescription {
|
|
|
|
|
description: "Entry to boot, bypassing the menu",
|
|
|
|
|
form: OptionForm::Value,
|
|
|
|
|
},
|
|
|
|
|
),
|
2025-10-26 23:59:50 -04:00
|
|
|
(
|
|
|
|
|
"force-menu",
|
|
|
|
|
OptionDescription {
|
|
|
|
|
description: "Force showing of the boot menu",
|
|
|
|
|
form: OptionForm::Flag,
|
|
|
|
|
},
|
|
|
|
|
),
|
|
|
|
|
(
|
|
|
|
|
"menu-timeout",
|
|
|
|
|
OptionDescription {
|
|
|
|
|
description: "Boot menu timeout, in seconds",
|
|
|
|
|
form: OptionForm::Value,
|
|
|
|
|
},
|
|
|
|
|
),
|
2025-10-21 19:12:16 -07:00
|
|
|
(
|
|
|
|
|
"help",
|
|
|
|
|
OptionDescription {
|
|
|
|
|
description: "Display Sprout Help",
|
|
|
|
|
form: OptionForm::Help,
|
|
|
|
|
},
|
|
|
|
|
),
|
|
|
|
|
]
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Produces [SproutOptions] from the parsed raw `options` map.
|
|
|
|
|
fn produce(options: BTreeMap<String, Option<String>>) -> Result<Self> {
|
|
|
|
|
// Use the default value of sprout options and have the raw options be parsed into it.
|
|
|
|
|
let mut result = Self::default();
|
|
|
|
|
|
|
|
|
|
for (key, value) in options {
|
|
|
|
|
match key.as_str() {
|
2025-10-27 02:38:40 -04:00
|
|
|
"autoconfigure" => {
|
|
|
|
|
// Enable autoconfiguration.
|
|
|
|
|
result.autoconfigure = true;
|
|
|
|
|
}
|
|
|
|
|
|
2025-10-21 19:12:16 -07:00
|
|
|
"config" => {
|
|
|
|
|
// The configuration file to load.
|
|
|
|
|
result.config = value.context("--config option requires a value")?;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
"boot" => {
|
|
|
|
|
// The entry to boot.
|
|
|
|
|
result.boot = Some(value.context("--boot option requires a value")?);
|
|
|
|
|
}
|
|
|
|
|
|
2025-10-26 23:59:50 -04:00
|
|
|
"force-menu" => {
|
|
|
|
|
// Force showing of the boot menu.
|
|
|
|
|
result.force_menu = true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
"menu-timeout" => {
|
|
|
|
|
// The timeout for the boot menu in seconds.
|
|
|
|
|
let value = value.context("--menu-timeout option requires a value")?;
|
|
|
|
|
let value = value
|
|
|
|
|
.parse::<u64>()
|
|
|
|
|
.context("menu-timeout must be a number")?;
|
|
|
|
|
result.menu_timeout = Some(value);
|
|
|
|
|
}
|
|
|
|
|
|
2025-10-21 19:12:16 -07:00
|
|
|
_ => bail!("unknown option: --{key}"),
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
Ok(result)
|
|
|
|
|
}
|
|
|
|
|
}
|