openhcl_boot/
cmdline.rs

1// Copyright (c) Microsoft Corporation.
2// Licensed under the MIT License.
3
4//! Command line arguments and parsing for openhcl_boot.
5
6use underhill_confidentiality::OPENHCL_CONFIDENTIAL_DEBUG_ENV_VAR_NAME;
7
8/// Enable the private VTL2 GPA pool for page allocations. This is only enabled
9/// via the command line, because in order to support the VTL2 GPA pool
10/// generically, the boot shim must read serialized data from the previous
11/// OpenHCL instance on a servicing boot in order to guarantee the same memory
12/// layout is presented.
13///
14/// The value specified is the number of 4K pages to reserve for the pool.
15///
16/// TODO: Remove this commandline once support for reading saved state is
17/// supported in openhcl_boot.
18const ENABLE_VTL2_GPA_POOL: &str = "OPENHCL_ENABLE_VTL2_GPA_POOL=";
19
20/// Options controlling sidecar.
21///
22/// * `off`: Disable sidecar support.
23/// * `on`: Enable sidecar support. Sidecar will still only be started if
24///   sidecar is present in the binary and supported on the platform. This
25///   is the default.
26/// * `log`: Enable sidecar logging.
27const SIDECAR: &str = "OPENHCL_SIDECAR=";
28
29/// Disable NVME keep alive regardless if the host supports it.
30const DISABLE_NVME_KEEP_ALIVE: &str = "OPENHCL_DISABLE_NVME_KEEP_ALIVE=";
31
32#[derive(Debug, PartialEq)]
33pub struct BootCommandLineOptions {
34    pub confidential_debug: bool,
35    pub enable_vtl2_gpa_pool: Option<u64>,
36    pub sidecar: bool,
37    pub sidecar_logging: bool,
38    pub disable_nvme_keep_alive: bool,
39}
40
41impl BootCommandLineOptions {
42    pub const fn new() -> Self {
43        BootCommandLineOptions {
44            confidential_debug: false,
45            enable_vtl2_gpa_pool: None,
46            sidecar: true, // sidecar is enabled by default
47            sidecar_logging: false,
48            disable_nvme_keep_alive: false,
49        }
50    }
51}
52
53impl BootCommandLineOptions {
54    /// Parse arguments from a command line.
55    pub fn parse(&mut self, cmdline: &str) {
56        for arg in cmdline.split_whitespace() {
57            if arg.starts_with(OPENHCL_CONFIDENTIAL_DEBUG_ENV_VAR_NAME) {
58                let arg = arg.split_once('=').map(|(_, arg)| arg);
59                if arg.is_some_and(|a| a != "0") {
60                    self.confidential_debug = true;
61                }
62            } else if arg.starts_with(ENABLE_VTL2_GPA_POOL) {
63                self.enable_vtl2_gpa_pool = arg.split_once('=').and_then(|(_, arg)| {
64                    let num = arg.parse::<u64>().unwrap_or(0);
65                    // A size of 0 or failure to parse is treated as disabling
66                    // the pool.
67                    if num == 0 { None } else { Some(num) }
68                });
69            } else if arg.starts_with(SIDECAR) {
70                if let Some((_, arg)) = arg.split_once('=') {
71                    for arg in arg.split(',') {
72                        match arg {
73                            "off" => self.sidecar = false,
74                            "on" => self.sidecar = true,
75                            "log" => self.sidecar_logging = true,
76                            _ => {}
77                        }
78                    }
79                }
80            } else if arg.starts_with(DISABLE_NVME_KEEP_ALIVE) {
81                let arg = arg.split_once('=').map(|(_, arg)| arg);
82                if arg.is_some_and(|a| a != "0") {
83                    self.disable_nvme_keep_alive = true;
84                }
85            }
86        }
87    }
88}
89
90#[cfg(test)]
91mod tests {
92    use super::*;
93
94    fn parse_boot_command_line(cmdline: &str) -> BootCommandLineOptions {
95        let mut options = BootCommandLineOptions::new();
96        options.parse(cmdline);
97        options
98    }
99
100    #[test]
101    fn test_vtl2_gpa_pool_parsing() {
102        assert_eq!(
103            parse_boot_command_line("OPENHCL_ENABLE_VTL2_GPA_POOL=1"),
104            BootCommandLineOptions {
105                enable_vtl2_gpa_pool: Some(1),
106                ..BootCommandLineOptions::new()
107            }
108        );
109        assert_eq!(
110            parse_boot_command_line("OPENHCL_ENABLE_VTL2_GPA_POOL=0"),
111            BootCommandLineOptions {
112                enable_vtl2_gpa_pool: None,
113                ..BootCommandLineOptions::new()
114            }
115        );
116        assert_eq!(
117            parse_boot_command_line("OPENHCL_ENABLE_VTL2_GPA_POOL=asdf"),
118            BootCommandLineOptions {
119                enable_vtl2_gpa_pool: None,
120                ..BootCommandLineOptions::new()
121            }
122        );
123        assert_eq!(
124            parse_boot_command_line("OPENHCL_ENABLE_VTL2_GPA_POOL=512"),
125            BootCommandLineOptions {
126                enable_vtl2_gpa_pool: Some(512),
127                ..BootCommandLineOptions::new()
128            }
129        );
130    }
131
132    #[test]
133    fn test_sidecar_parsing() {
134        assert_eq!(
135            parse_boot_command_line("OPENHCL_SIDECAR=on"),
136            BootCommandLineOptions {
137                sidecar: true,
138                ..BootCommandLineOptions::new()
139            }
140        );
141        assert_eq!(
142            parse_boot_command_line("OPENHCL_SIDECAR=off"),
143            BootCommandLineOptions {
144                sidecar: false,
145                ..BootCommandLineOptions::new()
146            }
147        );
148        assert_eq!(
149            parse_boot_command_line("OPENHCL_SIDECAR=on,off"),
150            BootCommandLineOptions {
151                sidecar: false,
152                ..BootCommandLineOptions::new()
153            }
154        );
155        assert_eq!(
156            parse_boot_command_line("OPENHCL_SIDECAR=on,log"),
157            BootCommandLineOptions {
158                sidecar: true,
159                sidecar_logging: true,
160                ..BootCommandLineOptions::new()
161            }
162        );
163        assert_eq!(
164            parse_boot_command_line("OPENHCL_SIDECAR=log"),
165            BootCommandLineOptions {
166                sidecar: true,
167                sidecar_logging: true,
168                ..BootCommandLineOptions::new()
169            }
170        );
171    }
172}