pub const PROTECTIVE_TYPE: u8 = 0xEE;
const PARTITION_TABLE_OFFSET: usize = 446;
const ENTRY_SIZE: usize = 16;
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[cfg_attr(feature = "serde", derive(serde::Serialize))]
pub struct MbrPartitionRecord {
pub index: usize,
pub status: u8,
pub type_code: u8,
pub lba_start: u32,
pub lba_count: u32,
}
impl MbrPartitionRecord {
#[must_use]
pub fn is_empty(&self) -> bool {
self.type_code == 0x00 && self.lba_start == 0 && self.lba_count == 0
}
#[must_use]
pub fn is_protective(&self) -> bool {
self.type_code == PROTECTIVE_TYPE
}
#[must_use]
pub fn lba_end(&self) -> u64 {
u64::from(self.lba_start)
.saturating_add(u64::from(self.lba_count))
.saturating_sub(1)
}
}
#[must_use]
pub fn parse_mbr_entries(sector: &[u8]) -> [MbrPartitionRecord; 4] {
core::array::from_fn(|index| {
let off = PARTITION_TABLE_OFFSET + index * ENTRY_SIZE;
match sector.get(off..off + ENTRY_SIZE) {
Some(b) => MbrPartitionRecord {
index,
status: b[0],
type_code: b[4],
lba_start: u32::from_le_bytes([b[8], b[9], b[10], b[11]]),
lba_count: u32::from_le_bytes([b[12], b[13], b[14], b[15]]),
},
None => MbrPartitionRecord {
index,
status: 0,
type_code: 0,
lba_start: 0,
lba_count: 0,
},
}
})
}