1use std::path::PathBuf;
2
3#[derive(Debug, Default)]
4pub struct KernelArgs {
5 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 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}