#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum ImageArch {
Riscv {
is_be: bool,
},
Arm64 {
is_be: bool,
page_size: PageSize,
phys_placement_48bit: bool,
},
}
#[allow(unused)]
#[derive(Debug, Clone)]
pub struct Header {
pub text_offset: u64,
pub image_size: u64,
pub arch: ImageArch,
}
#[allow(unused)]
impl Header {
pub fn parse(image: &[u8]) -> Option<Self> {
if let Some(hdr) = ARM64Header::parse(image) {
return Some(Self {
text_offset: hdr.text_offset,
image_size: hdr.image_size,
arch: ImageArch::Arm64 {
is_be: hdr.kernel_is_be(),
page_size: hdr.page_size(),
phys_placement_48bit: hdr.phys_placement_48bit(),
},
});
}
if let Some(hdr) = RiscvHeader::parse(image) {
return Some(Self {
text_offset: hdr.text_offset,
image_size: hdr.image_size,
arch: ImageArch::Riscv {
is_be: hdr.kernel_is_be(),
},
});
}
None
}
pub fn hdr_size() -> usize {
size_of::<ARM64Header>()
}
}
#[allow(unused)]
#[repr(C)]
struct ARM64Header {
code0: u32,
code1: u32,
text_offset: u64,
image_size: u64,
flags: u64,
res2: u64,
res3: u64,
res4: u64,
magic: u32,
res5: u32,
}
impl ARM64Header {
const MAGIC: u32 = 0x644d5241;
fn parse(buffer: &[u8]) -> Option<Self> {
if buffer.len() < core::mem::size_of::<Self>() {
return None;
}
let hdr: Self = unsafe { core::ptr::read_unaligned(buffer.as_ptr() as *const _) };
if hdr.magic != Self::MAGIC {
return None;
}
Some(hdr)
}
fn kernel_is_be(&self) -> bool {
(self.flags & 0x1) != 0
}
fn page_size(&self) -> PageSize {
match (self.flags >> 1) & 0x3 {
0 => PageSize::Unspecified,
1 => PageSize::Size4K,
2 => PageSize::Size16K,
3 => PageSize::Size64K,
_ => PageSize::Unspecified,
}
}
fn phys_placement_48bit(&self) -> bool {
((self.flags >> 3) & 0x1) != 0
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum PageSize {
Unspecified,
Size4K,
Size16K,
Size64K,
}
#[allow(unused)]
struct RiscvHeader {
code0: u32,
code1: u32,
text_offset: u64,
image_size: u64,
flags: u64,
version: u32,
res1: u32,
res2: u64,
magic: u64,
magic2: u32,
res4: u32,
}
impl RiscvHeader {
const MAGIC: u64 = 0x5643534952; const MAGIC2: u32 = 0x56534905;
fn parse(buffer: &[u8]) -> Option<Self> {
if buffer.len() < core::mem::size_of::<Self>() {
return None;
}
let hdr: Self = unsafe { core::ptr::read_unaligned(buffer.as_ptr() as *const _) };
if hdr.magic != Self::MAGIC || hdr.magic2 != Self::MAGIC2 {
return None;
}
Some(hdr)
}
fn kernel_is_be(&self) -> bool {
(self.flags & 0x1) != 0
}
}