Skip to main content

qemu_command_builder/args/
boot.rs

1use crate::parsers::ARG_BOOT;
2use std::str::FromStr;
3
4use bon::Builder;
5use proptest_derive::Arbitrary;
6use winnow::Result;
7use winnow::ascii::{alphanumeric1, dec_uint};
8use winnow::combinator::opt;
9use winnow::prelude::*;
10use winnow::token::literal;
11
12use crate::common::OnOff;
13use crate::parsers::DELIM_COMMA;
14use crate::shell_string::{ShellString, ShellStringError, shell_string_until_comma};
15use crate::to_command::ToCommand;
16use crate::{pco0, ppo0, qao};
17
18const KEY_ORDER: &str = "order=";
19const KEY_ONCE: &str = "once=";
20const KEY_MENU: &str = "menu=";
21const KEY_SPLASH: &str = "splash=";
22const KEY_SPLASH_TIME: &str = "splash-time=";
23const KEY_REBOOT_TIMEOUT: &str = "reboot-timeout=";
24const KEY_STRICT: &str = "strict=";
25
26/// Specify boot order drives as a string of drive letters. Valid drive
27/// letters depend on the target architecture. The x86 PC uses: a, b
28/// (floppy 1 and 2), c (first hard disk), d (first CD-ROM), n-p
29/// (Etherboot from network adapter 1-4), hard disk boot is the default.
30/// To apply a particular boot order only on the first startup, specify
31/// it via ``once``. Note that the ``order`` or ``once`` parameter
32/// should not be used together with the ``bootindex`` property of
33/// devices, since the firmware implementations normally do not support
34/// both at the same time.
35///
36/// Interactive boot menus/prompts can be enabled via ``menu=on`` as far
37/// as firmware/BIOS supports them. The default is non-interactive boot.
38///
39/// A splash picture could be passed to bios, enabling user to show it
40/// as logo, when option splash=sp\_name is given and menu=on, If
41/// firmware/BIOS supports them. Currently Seabios for X86 system
42/// support it. limitation: The splash file could be a jpeg file or a
43/// BMP file in 24 BPP format(true color). The resolution should be
44/// supported by the SVGA mode, so the recommended is 320x240, 640x480,
45/// 800x640.
46///
47/// A timeout could be passed to bios, guest will pause for rb\_timeout
48/// ms when boot failed, then reboot. If rb\_timeout is '-1', guest will
49/// not reboot, qemu passes '-1' to bios by default. Currently Seabios
50/// for X86 system support it.
51///
52/// Do strict boot via ``strict=on`` as far as firmware/BIOS supports
53/// it. This only effects when boot priority is changed by bootindex
54/// options. The default is non-strict boot.
55#[derive(Debug, Clone, Hash, Ord, PartialOrd, Eq, PartialEq, Builder, Arbitrary)]
56pub struct Boot {
57    order: Option<ShellString>,
58    once: Option<ShellString>,
59    menu: Option<OnOff>,
60    splash: Option<ShellString>,
61    splash_time: Option<usize>,
62    reboot_timeout: Option<usize>,
63    strict: Option<OnOff>,
64}
65
66impl ToCommand for Boot {
67    fn has_args(&self) -> bool {
68        self.order.is_some() || self.once.is_some() || self.menu.is_some() || self.splash.is_some() || self.splash_time.is_some() || self.reboot_timeout.is_some() || self.strict.is_some()
69    }
70
71    fn command(&self) -> String {
72        ARG_BOOT.to_string()
73    }
74    fn to_args(&self) -> Vec<String> {
75        let mut args = vec![];
76
77        if let Some(order) = &self.order {
78            args.push(format!("{}{}", KEY_ORDER, order.as_ref()));
79        }
80        if let Some(once) = &self.once {
81            args.push(format!("{}{}", KEY_ONCE, once.as_ref()));
82        }
83        qao!(&self.menu, args, KEY_MENU);
84        if let Some(splash) = &self.splash {
85            args.push(format!("{}{}", KEY_SPLASH, splash.as_ref()));
86        }
87        qao!(&self.splash_time, args, KEY_SPLASH_TIME);
88        qao!(&self.reboot_timeout, args, KEY_REBOOT_TIMEOUT);
89        qao!(&self.strict, args, KEY_STRICT);
90
91        vec![args.join(DELIM_COMMA)]
92    }
93}
94
95impl FromStr for Boot {
96    type Err = ShellStringError;
97
98    fn from_str(s: &str) -> Result<Self, Self::Err> {
99        boot.parse(s).map_err(|e| ShellStringError::from_parse(e))
100    }
101}
102
103pco0!(order, shell_string_until_comma, ShellString, KEY_ORDER);
104pco0!(once, shell_string_until_comma, ShellString, KEY_ONCE);
105pco0!(menu, alphanumeric1, OnOff, KEY_MENU);
106pco0!(splash, shell_string_until_comma, ShellString, KEY_SPLASH);
107ppo0!(splash_time, dec_uint, usize, KEY_SPLASH_TIME);
108ppo0!(reboot_timeout, dec_uint, usize, KEY_REBOOT_TIMEOUT);
109pco0!(strict, alphanumeric1, OnOff, KEY_STRICT);
110
111pub fn boot(s: &mut &str) -> ModalResult<Boot> {
112    let order = opt(order).parse_next(s)?;
113    let once = opt(once).parse_next(s)?;
114    let menu = opt(menu).parse_next(s)?;
115    let splash = opt(splash).parse_next(s)?;
116    let splash_time = opt(splash_time).parse_next(s)?;
117    let reboot_timeout = opt(reboot_timeout).parse_next(s)?;
118    let strict = opt(strict).parse_next(s)?;
119
120    Ok(Boot {
121        order,
122        once,
123        menu,
124        splash,
125        splash_time,
126        reboot_timeout,
127        strict,
128    })
129}