xref: /DADK/dadk-config/src/boot/metadata.rs (revision eaa67f3cf8881c221a744937c6318444b068a801)
1 use serde::Deserialize;
2 
3 use super::hypervisor::hyp_type::HypervisorType;
4 
5 #[derive(Debug, Clone, Deserialize)]
6 pub struct BootMetadata {
7     /// The boot protocol used during startup
8     #[serde(rename = "boot-protocol")]
9     pub boot_protocol: BootProtocol,
10     /// The mode of booting
11     #[serde(rename = "boot-mode")]
12     pub boot_mode: BootMode,
13     /// The hypervisor used during startup
14     pub hypervisor: HypervisorType,
15 
16     /// Kernel command-line arguments
17     #[serde(rename = "kcmd-args", default = "default_empty_vec")]
18     pub kcmd_args: Vec<String>,
19     /// Arguments passed to the init process
20     #[serde(rename = "init-args", default = "default_empty_vec")]
21     pub init_args: Vec<String>,
22 }
23 
24 fn default_empty_vec() -> Vec<String> {
25     vec![]
26 }
27 
28 #[derive(Debug, Clone, Deserialize, PartialEq, Eq)]
29 pub enum BootProtocol {
30     /// BIOS Bootloader
31     #[serde(rename = "grub-legacy")]
32     GrubLegacy,
33     /// UEFI Bootloader (Grub)
34     #[serde(rename = "grub-efi")]
35     GrubEFI,
36     /// Direct Linux Boot (with `-kernel` options)
37     #[serde(rename = "direct")]
38     Direct,
39     /// Dragon Stub Bootloader (riscv only)
40     #[serde(rename = "dragon-stub")]
41     DragonStub,
42 }
43 
44 /// The mode of booting
45 #[derive(Debug, Clone, Deserialize, PartialEq, Eq)]
46 pub enum BootMode {
47     /// Graphic mode
48     #[serde(rename = "graphic")]
49     Graphic,
50     /// Graphic mode with VNC
51     #[serde(rename = "graphic-vnc")]
52     GraphicVnc,
53     /// No graphic mode
54     #[serde(rename = "no-graphic")]
55     NoGraphic,
56 }
57 
58 #[cfg(test)]
59 mod tests {
60     use super::*;
61 
62     // Helper function to parse TOML string into BootMetadata
63     fn parse_boot_metadata(toml_str: &str) -> Result<BootMetadata, toml::de::Error> {
64         toml::from_str(toml_str)
65     }
66 
67     fn assert_missing_field(err_str: &str, field: &str) {
68         assert!(err_str.contains(&format!("missing field `{field}`")));
69     }
70 
71     fn assert_unknown_variant(err_str: &str, variant: &str) {
72         assert!(err_str.contains(&format!("unknown variant `{variant}`")));
73     }
74 
75     #[test]
76     fn test_parse_grub_legacy_graphic() {
77         let toml_str = r#"
78         boot-protocol = "grub-legacy"
79         boot-mode = "graphic"
80         hypervisor = "qemu"
81         "#;
82 
83         let result = parse_boot_metadata(toml_str).unwrap();
84         assert_eq!(result.boot_protocol, BootProtocol::GrubLegacy);
85         assert_eq!(result.boot_mode, BootMode::Graphic);
86     }
87 
88     #[test]
89     fn test_parse_grub_efi_graphic_vnc() {
90         let toml_str = r#"
91         boot-protocol = "grub-efi"
92         boot-mode = "graphic-vnc"
93         hypervisor = "qemu"
94         "#;
95 
96         let result = parse_boot_metadata(toml_str).unwrap();
97         assert_eq!(result.boot_protocol, BootProtocol::GrubEFI);
98         assert_eq!(result.boot_mode, BootMode::GraphicVnc);
99     }
100 
101     #[test]
102     fn test_parse_direct_no_graphic() {
103         let toml_str = r#"
104         boot-protocol = "direct"
105         boot-mode = "no-graphic"
106         hypervisor = "qemu"
107         "#;
108 
109         let result = parse_boot_metadata(toml_str).unwrap();
110         assert_eq!(result.boot_protocol, BootProtocol::Direct);
111         assert_eq!(result.boot_mode, BootMode::NoGraphic);
112     }
113 
114     #[test]
115     fn test_parse_dragon_stub_graphic() {
116         let toml_str = r#"
117         boot-protocol = "dragon-stub"
118         boot-mode = "graphic"
119         hypervisor = "qemu"
120         "#;
121 
122         let result = parse_boot_metadata(toml_str).unwrap();
123         assert_eq!(result.boot_protocol, BootProtocol::DragonStub);
124         assert_eq!(result.boot_mode, BootMode::Graphic);
125     }
126 
127     #[test]
128     fn test_parse_missing_boot_protocol() {
129         let toml_str = r#"
130         boot-mode = "graphic"
131         "#;
132 
133         let r = parse_boot_metadata(toml_str);
134         assert!(r.is_err());
135         let r = r.unwrap_err();
136         assert_missing_field(&r.to_string(), "boot-protocol");
137     }
138 
139     #[test]
140     fn test_parse_missing_boot_mode() {
141         let toml_str = r#"
142         boot-protocol = "grub-legacy"
143         hypervisor = "qemu"
144         "#;
145 
146         let r = parse_boot_metadata(toml_str);
147         assert!(r.is_err());
148         let r = r.unwrap_err();
149         assert_missing_field(&r.to_string(), "boot-mode");
150     }
151 
152     #[test]
153     fn test_parse_invalid_boot_protocol() {
154         let toml_str = r#"
155         boot-protocol = "invalid-protocol"
156         boot-mode = "graphic"
157         "#;
158         let r = parse_boot_metadata(toml_str);
159         assert!(r.is_err());
160         let r = r.unwrap_err();
161         assert_unknown_variant(&r.to_string(), "invalid-protocol");
162     }
163 
164     #[test]
165     fn test_parse_invalid_boot_mode() {
166         let toml_str = r#"
167         boot-protocol = "grub-legacy"
168         boot-mode = "invalid-mode"
169         "#;
170 
171         let r = parse_boot_metadata(toml_str);
172         assert!(r.is_err());
173         let r = r.unwrap_err();
174         assert_unknown_variant(&r.to_string(), "invalid-mode");
175     }
176 
177     #[test]
178     fn test_parse_empty_fields() {
179         let toml_str = r#"
180         boot-protocol = ""
181         boot-mode = ""
182         "#;
183 
184         assert!(parse_boot_metadata(toml_str).is_err());
185     }
186 }
187