linux_args/
lib.rs

1use std::path::PathBuf;
2
3#[derive(Debug, Default)]
4pub struct KernelArgs {
5    // Args
6    pub root: Option<PathBuf>,
7    pub loglevel: Option<u32>,
8    pub init: Option<PathBuf>,
9    pub mem: Option<usize>,
10    pub vga: Option<u32>,
11
12    // Flags
13    pub single: bool,
14    pub nomodeset: bool,
15    pub debug: bool,
16    pub noapic: bool,
17    pub irqpool: bool,
18    pub nolapic: bool,
19    pub ipv6_disable: bool,
20    pub ro: bool,
21    pub quiet: bool,
22    pub silent: bool,
23    pub splash: bool,
24}
25
26impl KernelArgs {
27    pub fn parse(cmdline: &str) -> Self {
28        let mut args_struct = KernelArgs::default();
29
30        let args: Vec<&str> = cmdline.split_whitespace().collect();
31        for arg in args {
32            if let Some((key, value)) = parse_key_value(arg) {
33                match key.as_str() {
34                    "root" => args_struct.root = Some(PathBuf::from(value)),
35                    "loglevel" => args_struct.loglevel = value.parse().ok(),
36                    "init" => args_struct.init = Some(PathBuf::from(value)),
37                    "mem" => args_struct.mem = value.parse().ok(),
38                    "vga" => args_struct.vga = value.parse().ok(),
39                    "ipv6.disable" => {
40                        if value == "1" {
41                            args_struct.ipv6_disable = true;
42                        }
43                    }
44                    _ => {}
45                }
46            } else if let Some(flag) = parse_flag(arg) {
47                match flag.as_str() {
48                    "quiet" => args_struct.quiet = true,
49                    "silent" => args_struct.silent = true,
50                    "splash" => args_struct.splash = true,
51                    "single" => args_struct.single = true,
52                    "nomodeset" => args_struct.nomodeset = true,
53                    "debug" => args_struct.debug = true,
54                    "noapic" => args_struct.noapic = true,
55                    "irqpool" => args_struct.irqpool = true,
56                    "nolapic" => args_struct.nolapic = true,
57                    "ro" => args_struct.ro = true,
58                    _ => {}
59                }
60            }
61        }
62
63        args_struct
64    }
65}
66
67fn parse_key_value(arg: &str) -> Option<(String, String)> {
68    let mut parts = arg.splitn(2, '=');
69    match (parts.next(), parts.next()) {
70        (Some(key), Some(value)) => Some((key.to_string(), value.to_string())),
71        _ => None,
72    }
73}
74
75fn parse_flag(arg: &str) -> Option<String> {
76    if !arg.contains('=') {
77        Some(arg.to_string())
78    } else {
79        None
80    }
81}
82
83#[cfg(test)]
84mod tests {
85    use super::*;
86
87    #[test]
88    fn test_parse() {
89        let args = KernelArgs::parse("root=/dev/sda1 init=/sbin/init loglevel=3 mem=8192 vga=732 ipv6.disable=1 quiet silent splash single nomodeset debug noapic irqpool nolapic ro");
90
91        assert_eq!(args.root, Some(PathBuf::from("/dev/sda1")));
92        assert_eq!(args.init, Some(PathBuf::from("/sbin/init")));
93        assert_eq!(args.loglevel, Some(3));
94        assert_eq!(args.mem, Some(8192));
95        assert_eq!(args.vga, Some(732));
96        assert_eq!(args.ipv6_disable, true);
97        assert_eq!(args.quiet, true);
98        assert_eq!(args.silent, true);
99        assert_eq!(args.splash, true);
100        assert_eq!(args.single, true);
101        assert_eq!(args.nomodeset, true);
102        assert_eq!(args.debug, true);
103        assert_eq!(args.noapic, true);
104        assert_eq!(args.irqpool, true);
105        assert_eq!(args.nolapic, true);
106        assert_eq!(args.ro, true);
107    }
108}