1 //! Module for the [`BootPolicy`] helper type.
2 
3 use core::fmt::{Display, Formatter};
4 
5 /// Errors that can happen when working with [`BootPolicy`].
6 #[derive(Debug, Copy, Clone, PartialOrd, PartialEq, Eq, Ord)]
7 pub enum BootPolicyError {
8     /// Only `0` and `1` are valid integers, all other values are undefined.
9     InvalidInteger(u8),
10 }
11 
12 impl Display for BootPolicyError {
fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result13     fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
14         let s = match self {
15             Self::InvalidInteger(_) => {
16                 "Only `0` and `1` are valid integers, all other values are undefined."
17             }
18         };
19         f.write_str(s)
20     }
21 }
22 
23 #[cfg(feature = "unstable")]
24 impl core::error::Error for BootPolicyError {}
25 
26 /// The UEFI boot policy is a property that influences the behaviour of
27 /// various UEFI functions that load files (typically UEFI images).
28 ///
29 /// This type is not ABI compatible. On the ABI level, this is an UEFI
30 /// boolean.
31 #[derive(Copy, Clone, Debug, Default, Eq, Ord, PartialEq, PartialOrd)]
32 pub enum BootPolicy {
33     /// Indicates that the request originates from the boot manager, and that
34     /// the boot manager is attempting to load the provided `file_path` as a
35     /// boot selection.
36     ///
37     /// Boot selection refers to what a user has chosen in the (GUI) boot menu.
38     ///
39     /// This corresponds to the `TRUE` value in the UEFI spec.
40     BootSelection,
41     /// The provided `file_path` must match an exact file to be loaded.
42     ///
43     /// This corresponds to the `FALSE` value in the UEFI spec.
44     #[default]
45     ExactMatch,
46 }
47 
48 impl From<BootPolicy> for bool {
from(value: BootPolicy) -> Self49     fn from(value: BootPolicy) -> Self {
50         match value {
51             BootPolicy::BootSelection => true,
52             BootPolicy::ExactMatch => false,
53         }
54     }
55 }
56 
57 impl From<bool> for BootPolicy {
from(value: bool) -> Self58     fn from(value: bool) -> Self {
59         match value {
60             true => Self::BootSelection,
61             false => Self::ExactMatch,
62         }
63     }
64 }
65 
66 impl From<BootPolicy> for u8 {
from(value: BootPolicy) -> Self67     fn from(value: BootPolicy) -> Self {
68         match value {
69             BootPolicy::BootSelection => 1,
70             BootPolicy::ExactMatch => 0,
71         }
72     }
73 }
74 
75 impl TryFrom<u8> for BootPolicy {
76     type Error = BootPolicyError;
try_from(value: u8) -> Result<Self, Self::Error>77     fn try_from(value: u8) -> Result<Self, Self::Error> {
78         match value {
79             0 => Ok(Self::ExactMatch),
80             1 => Ok(Self::BootSelection),
81             err => Err(Self::Error::InvalidInteger(err)),
82         }
83     }
84 }
85 
86 #[cfg(test)]
87 mod tests {
88     use super::*;
89 
90     #[test]
boot_policy()91     fn boot_policy() {
92         assert_eq!(bool::from(BootPolicy::ExactMatch), false);
93         assert_eq!(bool::from(BootPolicy::BootSelection), true);
94 
95         assert_eq!(BootPolicy::from(false), BootPolicy::ExactMatch);
96         assert_eq!(BootPolicy::from(true), BootPolicy::BootSelection);
97 
98         assert_eq!(u8::from(BootPolicy::ExactMatch), 0);
99         assert_eq!(u8::from(BootPolicy::BootSelection), 1);
100 
101         assert_eq!(BootPolicy::try_from(0), Ok(BootPolicy::ExactMatch));
102         assert_eq!(BootPolicy::try_from(1), Ok(BootPolicy::BootSelection));
103         assert_eq!(
104             BootPolicy::try_from(2),
105             Err(BootPolicyError::InvalidInteger(2))
106         );
107     }
108 }
109