Files
RedBear-OS/initfs/src/types.rs
T

127 lines
3.1 KiB
Rust

use core::mem::offset_of;
pub const MAGIC_LEN: usize = 8;
pub const MAGIC: [u8; 8] = *b"RedoxFtw";
macro_rules! primitive(
($wrapper:ident, $bits:expr, $primitive:ident) => {
#[repr(transparent)]
#[derive(Clone, Copy, Default)]
pub struct $wrapper([u8; $bits / 8]);
impl $wrapper {
#[inline]
pub const fn get(self) -> $primitive {
<$primitive>::from_le_bytes(self.0)
}
#[inline]
pub const fn new(primitive: $primitive) -> Self {
Self(<$primitive>::to_le_bytes(primitive))
}
}
impl From<$primitive> for $wrapper {
fn from(primitive: $primitive) -> Self {
Self::new(primitive)
}
}
impl From<$wrapper> for $primitive {
fn from(wrapper: $wrapper) -> Self {
wrapper.get()
}
}
impl core::fmt::Debug for $wrapper {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
write!(f, "{:#0width$x}", self.get(), width = 2 * core::mem::size_of::<$primitive>())
}
}
}
);
primitive!(U16, 16, u16);
primitive!(U32, 32, u32);
primitive!(U64, 64, u64);
#[repr(transparent)]
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub struct Magic(pub [u8; MAGIC_LEN]);
#[repr(transparent)]
#[derive(Clone, Copy, Debug)]
pub struct Offset(pub U32);
#[repr(transparent)]
#[derive(Clone, Copy, Debug)]
pub struct Length(pub U32);
#[repr(C, packed)]
#[derive(Clone, Copy, Debug)]
pub struct Timespec {
pub sec: U64,
pub nsec: U32,
}
#[repr(C, packed)]
#[derive(Clone, Copy, Debug)]
pub struct Header {
pub magic: Magic,
pub inode_table_offset: Offset,
pub creation_time: Timespec,
pub inode_count: U16,
pub bootstrap_entry: U64,
pub initfs_size: U64,
pub page_size: U16,
}
const _: () = {
// Ensure the offsets of field used by the bootloader stay stable.
assert!(offset_of!(Header, bootstrap_entry) == 0x1a);
};
#[repr(C, packed)]
#[derive(Clone, Copy, Debug)]
pub struct InodeHeader {
pub type_: U32,
pub length: Length,
pub offset: Offset,
}
#[derive(Clone, Copy, Debug)]
#[repr(u8)]
pub enum InodeType {
RegularFile = 0x0,
ExecutableFile = 0x1,
Dir = 0x2,
Link = 0x3,
// All other bit patterns are reserved... for now.
}
impl TryFrom<u32> for InodeType {
type Error = ();
fn try_from(value: u32) -> Result<Self, ()> {
Ok(if value == InodeType::RegularFile as u32 {
InodeType::RegularFile
} else if value == InodeType::ExecutableFile as u32 {
InodeType::ExecutableFile
} else if value == InodeType::Dir as u32 {
InodeType::Dir
} else if value == InodeType::Link as u32 {
InodeType::Link
} else {
return Err(());
})
}
}
#[repr(C, packed)]
#[derive(Clone, Copy, Debug)]
pub struct DirEntry {
pub inode: U16,
pub name_len: U16,
pub name_offset: Offset,
}
unsafe impl plain::Plain for Header {}
unsafe impl plain::Plain for InodeHeader {}
unsafe impl plain::Plain for DirEntry {}