Skip to content

Commit 0aa7a46

Browse files
authored
Merge pull request #27 from edera-dev/feat/jaarg
feat(options): replace options parser with jaarg
2 parents c21c140 + 8711c54 commit 0aa7a46

File tree

6 files changed

+73
-216
lines changed

6 files changed

+73
-216
lines changed

Cargo.lock

Lines changed: 7 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,11 @@ version = "0.4.3"
2929
default-features = false
3030
features = ["alloc"]
3131

32+
[workspace.dependencies.jaarg]
33+
version = "0.2.1"
34+
default-features = false
35+
features = ["alloc"]
36+
3237
[workspace.dependencies.serde]
3338
version = "1.0.228"
3439
default-features = false

crates/boot/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ anyhow.workspace = true
1212
edera-sprout-config.path = "../config"
1313
edera-sprout-eficore.path = "../eficore"
1414
hex.workspace = true
15+
jaarg.workspace = true
1516
sha2.workspace = true
1617
toml.workspace = true
1718
log.workspace = true

crates/boot/src/main.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@ extern crate alloc;
66
use crate::context::{RootContext, SproutContext};
77
use crate::entries::BootableEntry;
88
use crate::options::SproutOptions;
9-
use crate::options::parser::OptionsRepresentable;
109
use crate::phases::phase;
1110
use alloc::collections::BTreeMap;
1211
use alloc::format;

crates/boot/src/options.rs

Lines changed: 60 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,13 @@
1-
use crate::options::parser::{OptionDescription, OptionForm, OptionsRepresentable};
2-
use alloc::collections::BTreeMap;
31
use alloc::string::{String, ToString};
42
use anyhow::{Context, Result, bail};
5-
6-
/// The Sprout options parser.
7-
pub mod parser;
3+
use core::ptr::null_mut;
4+
use jaarg::alloc::ParseMapResult;
5+
use jaarg::{
6+
ErrorUsageWriter, ErrorUsageWriterContext, HelpWriter, HelpWriterContext, Opt, Opts,
7+
StandardErrorUsageWriter, StandardFullHelpWriter,
8+
};
9+
use log::{error, info};
10+
use uefi_raw::Status;
811

912
/// Default configuration file path.
1013
const DEFAULT_CONFIG_PATH: &str = "\\sprout.toml";
@@ -38,78 +41,74 @@ impl Default for SproutOptions {
3841
}
3942

4043
/// The options parser mechanism for Sprout.
41-
impl OptionsRepresentable for SproutOptions {
42-
/// Produce the [SproutOptions] structure.
43-
type Output = Self;
44+
impl SproutOptions {
45+
/// Produces [SproutOptions] from the arguments provided by the UEFI core.
46+
/// Internally we utilize the `jaarg` argument parser which has excellent no_std support.
47+
pub fn parse() -> Result<Self> {
48+
// All the options for the Sprout executable.
49+
const OPTIONS: Opts<&str> = Opts::new(&[
50+
Opt::help_flag("help", &["--help"]).help_text("Display Sprout Help"),
51+
Opt::flag("autoconfigure", &["--autoconfigure"])
52+
.help_text("Enable Sprout autoconfiguration"),
53+
Opt::value("config", &["--config"], "PATH")
54+
.help_text("Path to Sprout configuration file"),
55+
Opt::value("boot", &["--boot"], "ENTRY").help_text("Entry to boot, bypassing the menu"),
56+
Opt::flag("force-menu", &["--force-menu"]).help_text("Force showing the boot menu"),
57+
Opt::value("menu-timeout", &["--menu-timeout"], "TIMEOUT")
58+
.help_text("Boot menu timeout, in seconds"),
59+
]);
4460

45-
/// All the Sprout options that are defined.
46-
fn options() -> &'static [(&'static str, OptionDescription<'static>)] {
47-
&[
48-
(
49-
"autoconfigure",
50-
OptionDescription {
51-
description: "Enable Sprout Autoconfiguration",
52-
form: OptionForm::Flag,
53-
},
54-
),
55-
(
56-
"config",
57-
OptionDescription {
58-
description: "Path to Sprout configuration file",
59-
form: OptionForm::Value,
60-
},
61-
),
62-
(
63-
"boot",
64-
OptionDescription {
65-
description: "Entry to boot, bypassing the menu",
66-
form: OptionForm::Value,
67-
},
68-
),
69-
(
70-
"force-menu",
71-
OptionDescription {
72-
description: "Force showing of the boot menu",
73-
form: OptionForm::Flag,
74-
},
75-
),
76-
(
77-
"menu-timeout",
78-
OptionDescription {
79-
description: "Boot menu timeout, in seconds",
80-
form: OptionForm::Value,
81-
},
82-
),
83-
(
84-
"help",
85-
OptionDescription {
86-
description: "Display Sprout Help",
87-
form: OptionForm::Help,
88-
},
89-
),
90-
]
91-
}
61+
// Acquire the arguments as determined by the UEFI core.
62+
let args = eficore::env::args()?;
63+
64+
// Parse the OPTIONS into a map using jaarg.
65+
let parsed = match OPTIONS.parse_map(
66+
"sprout",
67+
args.iter(),
68+
|program_name| {
69+
let ctx = HelpWriterContext {
70+
options: &OPTIONS,
71+
program_name,
72+
};
73+
info!("{}", StandardFullHelpWriter::new(ctx));
74+
},
75+
|program_name, error| {
76+
let ctx = ErrorUsageWriterContext {
77+
options: &OPTIONS,
78+
program_name,
79+
error,
80+
};
81+
error!("{}", StandardErrorUsageWriter::new(ctx));
82+
},
83+
) {
84+
ParseMapResult::Map(map) => map,
85+
ParseMapResult::ExitSuccess => unsafe {
86+
uefi::boot::exit(uefi::boot::image_handle(), Status::SUCCESS, 0, null_mut());
87+
},
88+
89+
ParseMapResult::ExitFailure => unsafe {
90+
uefi::boot::exit(uefi::boot::image_handle(), Status::ABORTED, 0, null_mut());
91+
},
92+
};
9293

93-
/// Produces [SproutOptions] from the parsed raw `options` map.
94-
fn produce(options: BTreeMap<String, Option<String>>) -> Result<Self> {
9594
// Use the default value of sprout options and have the raw options be parsed into it.
9695
let mut result = Self::default();
9796

98-
for (key, value) in options {
99-
match key.as_str() {
97+
for (key, value) in parsed {
98+
match key {
10099
"autoconfigure" => {
101100
// Enable autoconfiguration.
102101
result.autoconfigure = true;
103102
}
104103

105104
"config" => {
106105
// The configuration file to load.
107-
result.config = value.context("--config option requires a value")?;
106+
result.config = value;
108107
}
109108

110109
"boot" => {
111110
// The entry to boot.
112-
result.boot = Some(value.context("--boot option requires a value")?);
111+
result.boot = Some(value);
113112
}
114113

115114
"force-menu" => {
@@ -119,7 +118,6 @@ impl OptionsRepresentable for SproutOptions {
119118

120119
"menu-timeout" => {
121120
// The timeout for the boot menu in seconds.
122-
let value = value.context("--menu-timeout option requires a value")?;
123121
let value = value
124122
.parse::<u64>()
125123
.context("menu-timeout must be a number")?;

crates/boot/src/options/parser.rs

Lines changed: 0 additions & 153 deletions
This file was deleted.

0 commit comments

Comments
 (0)