Skip to main content

efivar_fix/efi/
variable_flags.rs

1//! Definition of the VariableFlags type
2
3use std::{fmt::Display, str::FromStr};
4
5use crate::Error;
6
7bitflags::bitflags! {
8    /// Possible attributes of EFI variables as a bitfield
9    #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
10    pub struct VariableFlags : u32 {
11        const NON_VOLATILE = 0x1;
12        const BOOTSERVICE_ACCESS = 0x2;
13        const RUNTIME_ACCESS = 0x4;
14        const HARDWARE_ERROR_RECORD = 0x8;
15        const AUTHENTICATED_WRITE_ACCESS = 0x10;
16        const TIME_BASED_AUTHENTICATED_WRITE_ACCESS = 0x20;
17        const APPEND_WRITE = 0x40;
18        const ENHANCED_AUTHENTICATED_ACCESS = 0x80;
19    }
20}
21
22impl Default for VariableFlags {
23    fn default() -> Self {
24        VariableFlags::NON_VOLATILE
25            | VariableFlags::BOOTSERVICE_ACCESS
26            | VariableFlags::RUNTIME_ACCESS
27    }
28}
29
30impl FromStr for VariableFlags {
31    type Err = Error;
32
33    fn from_str(s: &str) -> Result<VariableFlags, Self::Err> {
34        match s {
35            "EFI_VARIABLE_NON_VOLATILE" => Ok(VariableFlags::NON_VOLATILE),
36            "EFI_VARIABLE_BOOTSERVICE_ACCESS" => Ok(VariableFlags::BOOTSERVICE_ACCESS),
37            "EFI_VARIABLE_RUNTIME_ACCESS" => Ok(VariableFlags::RUNTIME_ACCESS),
38            "EFI_VARIABLE_HARDWARE_ERROR_RECORD" => Ok(VariableFlags::HARDWARE_ERROR_RECORD),
39            "EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS" => {
40                Ok(VariableFlags::AUTHENTICATED_WRITE_ACCESS)
41            }
42            "EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS" => {
43                Ok(VariableFlags::TIME_BASED_AUTHENTICATED_WRITE_ACCESS)
44            }
45            "EFI_VARIABLE_APPEND_WRITE" => Ok(VariableFlags::APPEND_WRITE),
46            "EFI_VARIABLE_ENHANCED_AUTHENTICATED_ACCESS" => {
47                Ok(VariableFlags::ENHANCED_AUTHENTICATED_ACCESS)
48            }
49            _ => Err(Error::UnknownFlag { flag: s.to_owned() }),
50        }
51    }
52}
53
54impl Display for VariableFlags {
55    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
56        let mut flag_strings = Vec::new();
57
58        if self.contains(VariableFlags::NON_VOLATILE) {
59            flag_strings.push("EFI_VARIABLE_NON_VOLATILE");
60        }
61        if self.contains(VariableFlags::BOOTSERVICE_ACCESS) {
62            flag_strings.push("EFI_VARIABLE_BOOTSERVICE_ACCESS");
63        }
64        if self.contains(VariableFlags::RUNTIME_ACCESS) {
65            flag_strings.push("EFI_VARIABLE_RUNTIME_ACCESS");
66        }
67        if self.contains(VariableFlags::HARDWARE_ERROR_RECORD) {
68            flag_strings.push("EFI_VARIABLE_HARDWARE_ERROR_RECORD");
69        }
70        if self.contains(VariableFlags::AUTHENTICATED_WRITE_ACCESS) {
71            flag_strings.push("EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS");
72        }
73        if self.contains(VariableFlags::TIME_BASED_AUTHENTICATED_WRITE_ACCESS) {
74            flag_strings.push("EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS");
75        }
76        if self.contains(VariableFlags::APPEND_WRITE) {
77            flag_strings.push("EFI_VARIABLE_APPEND_WRITE");
78        }
79        if self.contains(VariableFlags::ENHANCED_AUTHENTICATED_ACCESS) {
80            flag_strings.push("EFI_VARIABLE_ENHANCED_AUTHENTICATED_ACCESS");
81        }
82
83        f.write_str(&flag_strings.join("\n"))
84    }
85}
86
87#[cfg(test)]
88mod tests {
89    use super::*;
90
91    #[test]
92    fn variable_flags_to_string_empty() {
93        assert_eq!(VariableFlags::empty().to_string(), "");
94    }
95
96    #[test]
97    fn variable_flags_to_string_all() {
98        let s = (VariableFlags::NON_VOLATILE
99            | VariableFlags::BOOTSERVICE_ACCESS
100            | VariableFlags::RUNTIME_ACCESS
101            | VariableFlags::HARDWARE_ERROR_RECORD
102            | VariableFlags::AUTHENTICATED_WRITE_ACCESS
103            | VariableFlags::TIME_BASED_AUTHENTICATED_WRITE_ACCESS
104            | VariableFlags::APPEND_WRITE
105            | VariableFlags::ENHANCED_AUTHENTICATED_ACCESS)
106            .to_string();
107
108        assert!(s.contains("NON_VOLATILE"));
109        assert!(s.contains("BOOTSERVICE_ACCESS"));
110        assert!(s.contains("RUNTIME_ACCESS"));
111        assert!(s.contains("HARDWARE_ERROR_RECORD"));
112        assert!(s.contains("AUTHENTICATED_WRITE_ACCESS"));
113        assert!(s.contains("TIME_BASED_AUTHENTICATED_WRITE_ACCESS"));
114        assert!(s.contains("APPEND_WRITE"));
115        assert!(s.contains("ENHANCED_AUTHENTICATED_ACCESS"));
116    }
117
118    #[test]
119    fn variable_flags_from_string_all() {
120        assert_eq!(
121            VariableFlags::from_str("EFI_VARIABLE_NON_VOLATILE").unwrap(),
122            VariableFlags::NON_VOLATILE
123        );
124        assert_eq!(
125            VariableFlags::from_str("EFI_VARIABLE_BOOTSERVICE_ACCESS").unwrap(),
126            VariableFlags::BOOTSERVICE_ACCESS
127        );
128        assert_eq!(
129            VariableFlags::from_str("EFI_VARIABLE_RUNTIME_ACCESS").unwrap(),
130            VariableFlags::RUNTIME_ACCESS
131        );
132        assert_eq!(
133            VariableFlags::from_str("EFI_VARIABLE_HARDWARE_ERROR_RECORD").unwrap(),
134            VariableFlags::HARDWARE_ERROR_RECORD
135        );
136        assert_eq!(
137            VariableFlags::from_str("EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS").unwrap(),
138            VariableFlags::AUTHENTICATED_WRITE_ACCESS
139        );
140        assert_eq!(
141            VariableFlags::from_str("EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS").unwrap(),
142            VariableFlags::TIME_BASED_AUTHENTICATED_WRITE_ACCESS
143        );
144        assert_eq!(
145            VariableFlags::from_str("EFI_VARIABLE_APPEND_WRITE").unwrap(),
146            VariableFlags::APPEND_WRITE
147        );
148        assert_eq!(
149            VariableFlags::from_str("EFI_VARIABLE_ENHANCED_AUTHENTICATED_ACCESS").unwrap(),
150            VariableFlags::ENHANCED_AUTHENTICATED_ACCESS
151        );
152    }
153
154    #[test]
155    fn variable_flags_from_string_invalid() {
156        assert!(matches!(
157            VariableFlags::from_str("UNKNOWN_FLAG").unwrap_err(),
158            Error::UnknownFlag {
159                flag
160            } if flag == "UNKNOWN_FLAG"
161        ));
162    }
163}