Skip to main content

proka_exec/
header.rs

1//! The header definitions.
2use crate::{Error, HEADER_SIZE, Result};
3
4/// The magic number, fixed to 'PKEX'
5pub const PKEX_MAGIC: u32 = 0x58454B50;
6
7/// Error types in header.
8#[derive(Debug, Clone, Copy, PartialEq, Eq)]
9pub enum HeaderError {
10    /// Magic number error.
11    /// 
12    /// Contains the incorrect magic number.
13    MagicNumberError(u32),
14}
15
16/// The main header struct, which contains the metadata of the PKE file.
17#[repr(C, packed)]
18#[derive(Debug, Clone, Copy)]
19pub struct Header {
20    /// The magic number, fixed to 'PKEX'
21    pub magic: u32,
22
23    /// The minimal kernel version supported.
24    ///
25    /// # Note
26    /// As the `proka-bootloader`'s definitions, its format is similar
27    /// like `[major, minor, fix]`. See `proka-bootloader` crate for more informations.
28    pub min: [u16; 3],
29
30    /// The maximum kernel supported.
31    ///
32    /// For notes, see above.
33    pub max: [u16; 3],
34
35    /// Signifies is this executable run as `userapp` or `coredrv`.
36    pub mode: ExecMode,
37
38    /// The section table count.
39    pub sections: u16,
40
41    /// The section which contains the entry point.
42    pub entry_sec: u16,
43
44    /// The entry offset of the section.
45    pub entry_off: u32,
46
47    /// The author name (max length is 32 bytes).
48    pub author: [u8; 32],
49
50    /// The executable/project name.
51    pub name: [u8; 32],
52
53    /// Extended bits for different mode parsing (reserved).
54    pub extended: [u8; 36],
55}
56
57impl Default for Header {
58    fn default() -> Self {
59        Self::new()
60    }
61}
62
63impl Header {
64    /// Create a header object.
65    pub fn new() -> Self {
66        Self {
67            magic: PKEX_MAGIC,
68            min: [0; 3],
69            max: [0; 3],
70            mode: ExecMode::UserApp,
71            sections: 0,
72            entry_sec: 0,
73            entry_off: HEADER_SIZE as u32,
74            author: [0; 32],
75            name: [0; 32],
76            extended: [0u8; 36],
77        }
78    }
79
80    /// Validate is this a valid proka executable.
81    #[inline]
82    pub fn validate(&self) -> Result<()> {
83        if self.magic != PKEX_MAGIC {
84            return Err(Error::HeaderError(HeaderError::MagicNumberError(self.magic)));
85        }
86        Ok(())
87    }
88
89    /// Convert this header to array
90    #[inline]
91    pub const fn to_array(&self) -> [u8; HEADER_SIZE] {
92        // SAFETY: used `#[repr(C)]`
93        unsafe { core::ptr::read(self as *const Self as *const [u8; HEADER_SIZE]) }
94    }
95}
96
97/// The executable mode.
98#[repr(u32)]
99#[derive(Default, Debug, Clone, Copy, PartialEq, Eq)]
100pub enum ExecMode {
101    /// Run in `userapp` mode (Ring 3).
102    #[default]
103    UserApp,
104
105    /// Run in `coredrv` mode (Ring 0).
106    CoreDrv,
107}
108
109// Tests
110#[cfg(test)]
111mod tests {
112    use super::*;
113
114    #[test]
115    fn test_header_length() {
116        assert_eq!(crate::HEADER_SIZE, 128);
117        assert_eq!(core::mem::size_of::<Header>(), 128)
118    }
119}