Skip to main content

efivar_fix/
error.rs

1use std::io;
2
3use crate::efi::Variable;
4
5/// Describes an error returned by EFI variable operations
6#[derive(Debug, thiserror::Error)]
7pub enum Error {
8    #[error("failed to parse variable name: {}", name)]
9    InvalidVarName { name: String },
10    #[error("variable not found: {}", var)]
11    VarNotFound { var: Variable },
12    #[error("permission denied for variable: {}", var)]
13    PermissionDenied { var: Variable },
14    #[error("unknown i/o error for variable: {}", var)]
15    VarUnknownError { var: Variable, error: io::Error },
16    #[error("base64 decoding error: {}", error)]
17    #[cfg(feature = "store")]
18    Base64DecodeError { error: base64::DecodeError },
19    #[error("base64 decoding error: {}", error)]
20    #[cfg(feature = "store")]
21    Base64DecodeSliceError { error: base64::DecodeSliceError },
22    #[error("unknown i/o error: {}", .0)]
23    UnknownIoError(std::io::Error),
24    #[error("unknown EFI variable flag: '{}'", flag)]
25    UnknownFlag { flag: String },
26    #[error("failed to decode name as valid UTF-8")]
27    InvalidUTF8,
28    #[error("failed to decode uuid: {}", error)]
29    UuidError { error: uuid::Error },
30    #[error("failed to parse variable content (invalid content)")]
31    VarParseError,
32    #[error("failed to parse string: {}", 0)]
33    StringParseError(crate::utils::StringParseError),
34}
35
36#[cfg(not(target_os = "windows"))]
37fn is_variable_not_found_error(err: &io::Error) -> bool {
38    err.kind() == io::ErrorKind::NotFound
39}
40
41#[cfg(target_os = "windows")]
42fn is_variable_not_found_error(err: &io::Error) -> bool {
43    err.raw_os_error() == Some(203)
44}
45
46#[cfg(not(target_os = "windows"))]
47fn is_permission_denied_error(err: &io::Error) -> bool {
48    err.kind() == io::ErrorKind::PermissionDenied
49}
50
51#[cfg(target_os = "windows")]
52fn is_permission_denied_error(err: &io::Error) -> bool {
53    err.raw_os_error() == Some(1314)
54}
55
56impl Error {
57    pub fn for_variable(error: io::Error, var: &Variable) -> Self {
58        let var = var.clone();
59
60        if is_variable_not_found_error(&error) {
61            return Error::VarNotFound { var };
62        }
63
64        if is_permission_denied_error(&error) {
65            return Error::PermissionDenied { var };
66        }
67
68        Error::VarUnknownError { var, error }
69    }
70
71    #[cfg(target_os = "windows")]
72    pub fn for_variable_os(var: &Variable) -> Self {
73        Error::for_variable(io::Error::last_os_error(), var)
74    }
75}
76
77#[cfg(feature = "store")]
78impl From<base64::DecodeError> for Error {
79    fn from(error: base64::DecodeError) -> Self {
80        Error::Base64DecodeError { error }
81    }
82}
83
84#[cfg(feature = "store")]
85impl From<base64::DecodeSliceError> for Error {
86    fn from(error: base64::DecodeSliceError) -> Self {
87        Error::Base64DecodeSliceError { error }
88    }
89}