bias_loader_uefi/
depex.rs1use thiserror::Error;
2
3#[derive(Debug, Error)]
4pub enum DepExError {
5 #[error("incomplete opcode: not enough input")]
6 Incomplete,
7 #[error("invalid opcode {0:x}")]
8 InvalidOpcode(u8),
9}
10
11pub const OP_SIZE: usize = 1;
12
13pub const OP_WITH_GUID_START: usize = 1;
14pub const OP_WITH_GUID_END: usize = 17;
15pub const OP_WITH_GUID_ARG_SIZE: usize = 16;
16
17pub const OP_BEFORE: u8 = 0x00;
18pub const OP_AFTER: u8 = 0x01;
19pub const OP_PUSH: u8 = 0x02;
20pub const OP_AND: u8 = 0x03;
21pub const OP_OR: u8 = 0x04;
22pub const OP_NOT: u8 = 0x05;
23pub const OP_TRUE: u8 = 0x06;
24pub const OP_FALSE: u8 = 0x07;
25pub const OP_END: u8 = 0x08;
26pub const OP_SOR: u8 = 0x09;
27
28#[derive(
29 Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, serde::Serialize, serde::Deserialize,
30)]
31pub enum DepExOpcode {
32 Before([u8; 16]),
33 After([u8; 16]),
34 Push([u8; 16]),
35 And,
36 Or,
37 Not,
38 True,
39 False,
40 End,
41 Sor,
42}
43
44impl DepExOpcode {
45 pub fn guid(&self) -> Option<[u8; 16]> {
46 match self {
47 Self::Before(guid) | Self::After(guid) | Self::Push(guid) => Some(*guid),
48 _ => None,
49 }
50 }
51
52 pub fn file_guid(&self) -> Option<[u8; 16]> {
53 match self {
54 Self::Before(guid) | Self::After(guid) => Some(*guid),
55 _ => None,
56 }
57 }
58
59 pub fn protocol_guid(&self) -> Option<[u8; 16]> {
60 if let Self::Push(guid) = self {
61 Some(*guid)
62 } else {
63 None
64 }
65 }
66}
67
68impl DepExOpcode {
69 #[inline]
70 fn parse_guid(bytes: &[u8]) -> Result<[u8; 16], DepExError> {
71 if bytes.len() >= OP_WITH_GUID_END {
72 let mut guid = [0u8; OP_WITH_GUID_ARG_SIZE];
73 guid.copy_from_slice(&bytes[OP_WITH_GUID_START..OP_WITH_GUID_END]);
74 Ok(guid)
75 } else {
76 Err(DepExError::Incomplete)
77 }
78 }
79
80 #[inline]
81 pub fn parse(bytes: &[u8]) -> Result<(Self, usize), DepExError> {
82 if bytes.is_empty() {
83 return Err(DepExError::Incomplete);
84 }
85
86 match bytes[0] {
87 OP_BEFORE => {
88 let guid = Self::parse_guid(bytes)?;
89 Ok((Self::Before(guid), OP_SIZE + OP_WITH_GUID_ARG_SIZE))
90 }
91 OP_AFTER => {
92 let guid = Self::parse_guid(bytes)?;
93 Ok((Self::After(guid), OP_SIZE + OP_WITH_GUID_ARG_SIZE))
94 }
95 OP_PUSH => {
96 let guid = Self::parse_guid(bytes)?;
97 Ok((Self::Push(guid), OP_SIZE + OP_WITH_GUID_ARG_SIZE))
98 }
99 OP_AND => Ok((Self::And, OP_SIZE)),
100 OP_OR => Ok((Self::Or, OP_SIZE)),
101 OP_NOT => Ok((Self::Not, OP_SIZE)),
102 OP_TRUE => Ok((Self::True, OP_SIZE)),
103 OP_FALSE => Ok((Self::False, OP_SIZE)),
104 OP_END => Ok((Self::End, OP_SIZE)),
105 OP_SOR => Ok((Self::Sor, OP_SIZE)),
106 opcode => Err(DepExError::InvalidOpcode(opcode)),
107 }
108 }
109
110 pub fn parse_all(bytes: &[u8]) -> Result<Vec<Self>, DepExError> {
111 let mut offset = 0;
112 let mut opcodes = Vec::with_capacity(0);
113
114 while offset < bytes.len() {
115 let (opcode, length) = Self::parse(&bytes[offset..])?;
116
117 opcodes.push(opcode);
118 offset += length;
119 }
120
121 Ok(opcodes)
122 }
123}