use bitflags::bitflags;
use bytemuck::{Pod, Zeroable, bytes_of};
use crate::{Error, HEADER_SIZE, Result, VERSION_CURRENT, VERSION_MINIMAL};
pub const PKEX_MAGIC: u32 = 0x58454B50;
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum HeaderError {
MagicNumberError(u32),
}
#[repr(C)]
#[derive(Debug, Clone, Copy, Pod, Zeroable)]
pub struct Header {
pub magic: u32,
pub version_current: u32,
pub version_minimal: u32,
_pad1: [u8; 4],
pub min: [u16; 3],
_pad2: [u8; 2],
pub max: [u16; 3],
_pad3: [u8; 2],
pub mode: ExecMode,
_pad4: [u8; 3],
pub sections: u16,
pub entry_sec: u16,
pub entry_off: u32,
pub author: [u8; 32],
pub name: [u8; 32],
pub _reserved: [u8; 20],
}
impl Default for Header {
fn default() -> Self {
Self::new()
}
}
impl Header {
pub fn new() -> Self {
Self {
magic: PKEX_MAGIC,
version_current: VERSION_CURRENT,
version_minimal: VERSION_MINIMAL,
_pad1: [0; 4],
min: [0; 3],
_pad2: [0; 2],
max: [0; 3],
_pad3: [0; 2],
mode: ExecMode::UserApp,
_pad4: [0; 3],
sections: 0,
entry_sec: 0,
entry_off: HEADER_SIZE as u32,
author: [0; 32],
name: [0; 32],
_reserved: [0; 20],
}
}
#[inline]
pub fn validate(&self) -> Result<()> {
if self.magic != PKEX_MAGIC {
return Err(Error::HeaderError(HeaderError::MagicNumberError(
self.magic,
)));
}
Ok(())
}
#[inline]
pub fn to_array(&self) -> [u8; HEADER_SIZE] {
let mut arr = [0u8; HEADER_SIZE];
arr.copy_from_slice(bytes_of(self));
arr
}
}
bitflags! {
#[repr(transparent)]
#[derive(Debug, Clone, Copy, PartialEq, Eq, Pod, Zeroable)]
pub struct ExecMode: u8 {
const UserApp = 0x00;
const CoreDrv = 0x01;
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_header_length() {
assert_eq!(crate::HEADER_SIZE, 128);
assert_eq!(core::mem::size_of::<Header>(), 128)
}
}