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}