Skip to main content

bias_loader_uefi/
depex.rs

1use 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}