Skip to content

Commit f44392b

Browse files
committed
EFI type updates
* Define EfiGuidError * Define EfiVariable * Upate EfiVariableAttribute definition
1 parent 60474b1 commit f44392b

File tree

7 files changed

+280
-80
lines changed

7 files changed

+280
-80
lines changed

src/lib/efivar/mod.rs

Lines changed: 17 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,30 +1,29 @@
11
pub mod types;
22

3-
43
pub mod attributes {
5-
use types::EfivarAttribute;
4+
use types::EfiVariableAttribute;
65

7-
pub static NON_VOLATILE:EfivarAttribute
8-
= EfivarAttribute::init("Non Volatile", 0x1);
6+
pub static NON_VOLATILE:EfiVariableAttribute
7+
= EfiVariableAttribute::init("Non Volatile", 0x1);
98

10-
pub static BOOTSERVICE_ACCESS:EfivarAttribute
11-
= EfivarAttribute::init("Bootservice Access", 0x2);
9+
pub static BOOTSERVICE_ACCESS:EfiVariableAttribute
10+
= EfiVariableAttribute::init("Bootservice Access", 0x2);
1211

13-
pub static RUNTIME_ACCESS:EfivarAttribute
14-
= EfivarAttribute::init("Runtime Access", 0x4);
12+
pub static RUNTIME_ACCESS:EfiVariableAttribute
13+
= EfiVariableAttribute::init("Runtime Access", 0x4);
1514

16-
pub static HARDWARE_ERROR_RECORD:EfivarAttribute
17-
= EfivarAttribute::init("Hardware Error Record", 0x8);
15+
pub static HARDWARE_ERROR_RECORD:EfiVariableAttribute
16+
= EfiVariableAttribute::init("Hardware Error Record", 0x8);
1817

19-
pub static AUTHENTICATED_WRITE_ACCESS:EfivarAttribute
20-
= EfivarAttribute::init("Authenticated Write Access", 0x10);
18+
pub static AUTHENTICATED_WRITE_ACCESS:EfiVariableAttribute
19+
= EfiVariableAttribute::init("Authenticated Write Access", 0x10);
2120

22-
pub static TIME_BASED_AUTHENTICATED_WRITE_ACCESS:EfivarAttribute
23-
= EfivarAttribute::init("Time-Based Authenticated Write Access", 0x20);
21+
pub static TIME_BASED_AUTHENTICATED_WRITE_ACCESS:EfiVariableAttribute
22+
= EfiVariableAttribute::init("Time-Based Authenticated Write Access", 0x20);
2423

25-
pub static APPEND_WRITE:EfivarAttribute
26-
= EfivarAttribute::init("Append Write", 0x40);
24+
pub static APPEND_WRITE:EfiVariableAttribute
25+
= EfiVariableAttribute::init("Append Write", 0x40);
2726

28-
pub static ENHANCED_AUTHENTICATED_ACCESS:EfivarAttribute
29-
= EfivarAttribute::init("Enhanced Authenticated Access", 0x80);
27+
pub static ENHANCED_AUTHENTICATED_ACCESS:EfiVariableAttribute
28+
= EfiVariableAttribute::init("Enhanced Authenticated Access", 0x80);
3029
}

src/lib/efivar/types/efi_guid.rs

Lines changed: 120 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,11 @@
1+
use std::convert::TryFrom;
12
use std::fmt;
3+
use std::iter;
4+
use std::str::FromStr;
5+
use super::EfiGuidError;
6+
use types::efi_guid_error;
27

8+
#[derive(Debug, Clone, PartialEq, Eq, Copy)]
39
pub struct EfiGuid {
410
a: u32,
511
b: u16,
@@ -15,8 +21,119 @@ impl fmt::Display for EfiGuid {
1521
}
1622
}
1723

18-
impl EfiGuid {
19-
pub fn from_zero() -> Self {
20-
return Self { a: 0, b: 0, c: 0, d: [0; 8] };
24+
macro_rules! from_byte_array {
25+
($type:ty) => {
26+
impl From<$type> for EfiGuid {
27+
fn from(value: $type) -> Self {
28+
return Self {
29+
a: (u32::from(value[3] as u8) << 24) | (u32::from(value[2] as u8) << 16) |
30+
(u32::from(value[1] as u8) << 8) | (u32::from(value[0] as u8)),
31+
b: (u16::from(value[5] as u8) << 8) | (u16::from(value[4] as u8)),
32+
c: (u16::from(value[7] as u8) << 8) | (u16::from(value[6] as u8)),
33+
d: [
34+
(value[8] as u8), (value[9] as u8), (value[10] as u8), (value[11] as u8),
35+
(value[12] as u8), (value[13] as u8), (value[14] as u8), (value[15] as u8),
36+
]
37+
};
38+
}
2139
}
40+
}
41+
}
42+
43+
macro_rules! from_byte_arrays {
44+
($type:ty) => {
45+
from_byte_array!(& [$type;16]);
46+
from_byte_array!(&mut [$type;16]);
47+
}
48+
}
49+
50+
macro_rules! try_from_byte_slice {
51+
($type:ty) => {
52+
impl TryFrom<&[$type]> for EfiGuid {
53+
type Error = EfiGuidError;
54+
55+
fn try_from(value: &[$type]) -> Result<Self, EfiGuidError> {
56+
let len = value.len();
57+
58+
return match <&[$type;16]>::try_from(value) {
59+
Ok(o) => Ok(Self::from(o)),
60+
Err(_) => if len < 16 { Err(efi_guid_error::SRC_SLICE_LENGTH_TOO_SHORT)}
61+
else { Err(efi_guid_error::SRC_SLICE_LENGTH_TOO_LONG) }
62+
}
63+
}
64+
}
65+
}
66+
}
67+
68+
69+
macro_rules! try_from_byte_vec {
70+
($type:ty) => {
71+
impl TryFrom<Vec<$type>> for EfiGuid {
72+
type Error = EfiGuidError;
73+
74+
fn try_from(value: Vec<$type>) -> Result<Self, EfiGuidError> {
75+
let vec_len = value.len();
76+
match <[$type;16]>::try_from(value) {
77+
Ok(a) => Ok(EfiGuid::from(&a)),
78+
Err(_o) => if vec_len < 16 {
79+
Err(efi_guid_error::SRC_VEC_LENGTH_TOO_SHORT)
80+
} else {
81+
Err(efi_guid_error::SRC_VEC_LENGTH_TOO_LONG)
82+
}
83+
}
84+
}
85+
}
86+
}
87+
}
88+
89+
macro_rules! from_bytes {
90+
($type:ty) => {
91+
from_byte_arrays!($type);
92+
try_from_byte_slice!($type);
93+
try_from_byte_vec!($type);
94+
};
95+
($type:ty, $($types:ty),+) => {
96+
from_bytes!($type);
97+
from_bytes!($($types),+);
98+
}
99+
}
100+
101+
from_bytes!(i8, u8);
102+
103+
104+
impl FromStr for EfiGuid {
105+
type Err = EfiGuidError;
106+
107+
fn from_str(value: &str) -> Result<Self, EfiGuidError> {
108+
let chars:Vec<char> = value.chars().into_iter().collect();
109+
if chars.len() != 36 {
110+
return Err(efi_guid_error::BAD_FORMAT);
111+
}
112+
let digits = chars.into_iter().enumerate().filter_map(|(i, c)| {
113+
if i == 8 || i == 13 || i == 18 || i == 23 {
114+
if c != '-' {
115+
return Some(Err(efi_guid_error::BAD_FORMAT));
116+
}
117+
return None;
118+
}
119+
return match c.to_digit(16) {
120+
Some(d) => Some(Ok(d as u8)),
121+
None => Some(Err(efi_guid_error::BAD_FORMAT)),
122+
}
123+
})
124+
.collect::<Result<Vec<u8>, _>>()?;
125+
126+
return Ok(Self {
127+
a: digits[0..8].iter().fold(0u32, |sum, d| (sum << 4) + u32::from(*d)),
128+
b: digits[8..12].iter().fold(0u16, |sum, d| (sum << 4) + u16::from(*d)),
129+
c: digits[12..16].iter().fold(0u16, |sum, d| (sum << 4) + u16::from(*d)),
130+
d: match <[u8; 8]>::try_from(iter::zip(
131+
digits[16..].into_iter().step_by(2),
132+
digits[16..].into_iter().skip(1).step_by(2)
133+
).map(|(h, l)| (h << 4) + l).collect::<Vec<u8>>()) {
134+
Ok(o) => Ok(o),
135+
Err(_) => Err(efi_guid_error::BAD_FORMAT),
136+
}.unwrap()
137+
});
138+
}
22139
}
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
use std::error::Error;
2+
use std::fmt;
3+
4+
#[derive(Debug, Clone, PartialEq, Eq, Copy)]
5+
pub enum EfiGuidErrorKind {
6+
BadFormat,
7+
SliceLengthTooLong,
8+
SliceLengthTooShort,
9+
VecLengthTooLong,
10+
VecLengthTooShort,
11+
}
12+
13+
#[derive(Debug, Clone, PartialEq, Eq, Copy)]
14+
pub struct EfiGuidError(EfiGuidErrorKind);
15+
16+
impl Error for EfiGuidError {}
17+
18+
impl fmt::Display for EfiGuidError {
19+
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
20+
match self.0 {
21+
EfiGuidErrorKind::BadFormat => write!(f,
22+
"bad format. Correct format is xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"),
23+
EfiGuidErrorKind::SliceLengthTooLong => write!(f,
24+
"source slice too long. Slice must have a size of 16"),
25+
EfiGuidErrorKind::SliceLengthTooShort => write!(f,
26+
"source slice too short. Slice must have a size of 16"),
27+
EfiGuidErrorKind::VecLengthTooLong => write!(f,
28+
"source vector too long. Vector must have a size of 16"),
29+
EfiGuidErrorKind::VecLengthTooShort => write!(f,
30+
"source vector too short. Vector must have a size of 16"),
31+
}
32+
}
33+
}
34+
35+
pub const BAD_FORMAT: EfiGuidError =
36+
EfiGuidError(EfiGuidErrorKind::BadFormat);
37+
38+
pub const SRC_SLICE_LENGTH_TOO_LONG: EfiGuidError =
39+
EfiGuidError(EfiGuidErrorKind::SliceLengthTooLong);
40+
41+
pub const SRC_SLICE_LENGTH_TOO_SHORT: EfiGuidError =
42+
EfiGuidError(EfiGuidErrorKind::SliceLengthTooShort);
43+
44+
pub const SRC_VEC_LENGTH_TOO_LONG: EfiGuidError =
45+
EfiGuidError(EfiGuidErrorKind::VecLengthTooLong);
46+
47+
pub const SRC_VEC_LENGTH_TOO_SHORT: EfiGuidError =
48+
EfiGuidError(EfiGuidErrorKind::VecLengthTooShort);
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
use std::fmt;
2+
3+
pub use super::efi_guid::EfiGuid;
4+
pub use super::efi_variable_attribute::EfiVariableAttribute;
5+
6+
pub struct EfiVariable<'a> {
7+
pub attributes: Vec<&'a EfiVariableAttribute>,
8+
pub guid: EfiGuid,
9+
pub name: &'a str,
10+
pub data: Vec<u8>,
11+
}
12+
13+
impl fmt::Display for EfiVariable<'_> {
14+
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
15+
f.write_str(&format!("EfiVariable {{ attributes: ["))?;
16+
for a in self.attributes.iter() {
17+
f.write_str(&format!("{}", *a)[..])?;
18+
}
19+
f.write_str(&format!("], guid: \"{}\", name: \"{}\", data: [", self.guid, self.name)[..])?;
20+
if self.data.len() > 0 {
21+
f.write_str(&format!("{:02x}", self.data[0])[..])?;
22+
}
23+
if self.data.len() > 1 {
24+
for b in self.data[1..].iter() {
25+
f.write_str(&format!(" {:02x}", *b)[..])?;
26+
};
27+
}
28+
f.write_str("] }}")?;
29+
30+
return Ok(());
31+
}
32+
}
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
use std::fmt;
2+
3+
macro_rules! EfiVariableAttribute_field_value_maps {
4+
($type:ident) => {
5+
impl From<EfiVariableAttribute> for $type {
6+
fn from(attr: EfiVariableAttribute) -> $type {
7+
return attr.value as $type;
8+
}
9+
}
10+
11+
impl From<&EfiVariableAttribute> for $type {
12+
fn from(attr: &EfiVariableAttribute) -> $type {
13+
return (*attr).value as $type;
14+
}
15+
}
16+
};
17+
($type:ident, $($types:ident),+) => {
18+
EfiVariableAttribute_field_value_maps!($type);
19+
EfiVariableAttribute_field_value_maps!($($types),+);
20+
}
21+
}
22+
23+
#[derive(Clone, Copy, PartialEq, Eq)]
24+
pub struct EfiVariableAttribute {
25+
name: &'static str,
26+
value: u64,
27+
}
28+
29+
impl fmt::Display for EfiVariableAttribute {
30+
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
31+
return write!(f, "EfiVariableAttribute {{name: \"{}\", value: {:#016x}}}", self.name, self.value);
32+
}
33+
}
34+
35+
EfiVariableAttribute_field_value_maps!(u128, u64, u32, u16, i128, i64, i32);
36+
37+
impl From<EfiVariableAttribute> for String {
38+
fn from(attr: EfiVariableAttribute) -> String {
39+
return String::from(attr.name);
40+
}
41+
}
42+
43+
impl From<&EfiVariableAttribute> for String {
44+
fn from(attr: &EfiVariableAttribute) -> String {
45+
return String::from((*attr).name);
46+
}
47+
}
48+
49+
impl EfiVariableAttribute {
50+
pub(crate) const fn init(name: &'static str, value: u64) -> Self {
51+
return Self {name, value};
52+
}
53+
54+
pub fn name(&self) -> &'static str {
55+
return self.name;
56+
}
57+
}

src/lib/efivar/types/efivar_attribute.rs

Lines changed: 0 additions & 57 deletions
This file was deleted.

src/lib/efivar/types/mod.rs

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
11
mod efi_guid;
2-
mod efivar_attribute;
2+
mod efi_guid_error;
3+
mod efi_variable;
4+
mod efi_variable_attribute;
35

46
pub use self::efi_guid::EfiGuid;
5-
pub use self::efivar_attribute::EfivarAttribute;
7+
pub use self::efi_guid_error::EfiGuidError;
8+
pub use self::efi_variable_attribute::EfiVariableAttribute;
9+
pub use self::efi_variable::EfiVariable;

0 commit comments

Comments
 (0)