use crate::partition::PartitionEntry;
use crate::Error;
pub const SECTOR_SIZE: usize = 512;
pub const BOOT_CODE_LEN: usize = 446;
const DISK_SERIAL_OFFSET: usize = 440;
const RESERVED_OFFSET: usize = 444;
const PT_OFFSET: usize = 446;
const SIGNATURE_OFFSET: usize = 510;
const BOOT_SIG: [u8; 2] = [0x55, 0xAA];
#[derive(Debug, Clone)]
pub struct MbrSector {
pub boot_code: [u8; BOOT_CODE_LEN],
pub disk_serial: u32,
pub reserved: [u8; 2],
pub entries: [PartitionEntry; 4],
pub signature: [u8; 2],
}
pub fn parse_mbr_sector(sector: &[u8]) -> Result<MbrSector, Error> {
if sector.len() < SECTOR_SIZE {
return Err(Error::TooShort(sector.len()));
}
let sig = [sector[SIGNATURE_OFFSET], sector[SIGNATURE_OFFSET + 1]];
if sig != BOOT_SIG {
let val = u16::from_be_bytes(sig);
return Err(Error::BadSignature(val));
}
let mut boot_code = [0u8; BOOT_CODE_LEN];
boot_code.copy_from_slice(§or[..BOOT_CODE_LEN]);
let disk_serial = u32::from_le_bytes([
sector[DISK_SERIAL_OFFSET],
sector[DISK_SERIAL_OFFSET + 1],
sector[DISK_SERIAL_OFFSET + 2],
sector[DISK_SERIAL_OFFSET + 3],
]);
let reserved = [sector[RESERVED_OFFSET], sector[RESERVED_OFFSET + 1]];
let entries = std::array::from_fn(|i| {
let off = PT_OFFSET + i * 16;
let buf: &[u8; 16] = sector[off..off + 16].try_into().unwrap();
PartitionEntry::from_bytes(buf)
});
Ok(MbrSector {
boot_code,
disk_serial,
reserved,
entries,
signature: sig,
})
}