use crate::{BlockDevice, SectorId, const_assert_size, error};
use binrw::BinRead;
use binrw::BinReaderExt;
use binrw::io::Cursor;
use log::error;
pub const VALID_BOOTSECTOR_SIGN: [u8; 2] = [0x55, 0xAA];
pub const BOOTABLE_PARTITION_FLAG: u8 = 0x80;
pub const FAT32_PARTITION_ID: [u8; 2] = [0xB, 0xC];
#[derive(Debug, Clone, BinRead)]
pub struct MasterBootRecord {
_mbr_bootstrap: [u8; 436],
pub disk_id: [u8; 10],
pub partitions: [PartitionEntry; 4],
pub valid_bootsector_sign: [u8; 2],
}
const_assert_size!(MasterBootRecord, 512);
impl From<[u8; 512]> for MasterBootRecord {
fn from(input: [u8; 512]) -> Self {
Cursor::new(&input).read_ne().unwrap()
}
}
impl MasterBootRecord {
pub fn load<T: BlockDevice>(mut device: T) -> error::Result<MasterBootRecord> {
let mut buff = [0; 512];
device.read_sector(SectorId(0), &mut buff)?;
Ok(MasterBootRecord::from(buff))
}
pub fn get_vfat_partition(&self, index: usize) -> error::Result<&PartitionEntry> {
let partition = &self.partitions[index];
if !FAT32_PARTITION_ID.contains(&partition.partition_type) {
error!(
"Requested partition index: {}, but partition's type is :{}",
index, partition.partition_type
);
return Err(error::VfatRsError::Mbr {
error: error::MbrError::InvalidPartition { index },
});
}
Ok(partition)
}
}
#[derive(Debug, Default, Clone, Copy, BinRead)]
pub struct PartitionEntry {
pub bootable_indicator_flag: u8,
_starting_header: u8,
_starting_sector: u8,
_starting_cylinder: u8,
pub partition_type: u8,
_ending_header: u8,
_ending_sector: u8,
_ending_cylinder: u8,
pub start_sector: u32,
_total_sectors: u32,
}