1- use crate :: options:: parser:: { OptionDescription , OptionForm , OptionsRepresentable } ;
2- use alloc:: collections:: BTreeMap ;
31use alloc:: string:: { String , ToString } ;
42use 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.
1013const 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" ) ?;
0 commit comments