use crate::StandardFormat;
use binrw::binrw;
pub const BPB_OFFSET: u64 = 0x0B;
#[derive(Debug, Default)]
#[binrw]
#[brw(little)]
pub(crate) struct BiosParameterBlock2 {
pub(crate) bytes_per_sector: u16,
pub(crate) sectors_per_cluster: u8,
pub(crate) reserved_sectors: u16,
pub(crate) number_of_fats: u8,
pub(crate) root_entries: u16,
pub(crate) total_sectors: u16,
pub(crate) media_descriptor: u8,
pub(crate) sectors_per_fat: u16,
}
impl BiosParameterBlock2 {
pub fn is_valid(&self) -> bool {
if self.bytes_per_sector < 128 || self.bytes_per_sector > 4096 {
return false;
}
if self.sectors_per_cluster > 2 {
return false;
}
if self.number_of_fats == 0 || self.number_of_fats > 2 {
return false;
}
if self.root_entries < 0x70 || self.root_entries > 0xF0 {
return false;
}
if self.total_sectors < 320 || self.total_sectors > 5760 {
return false;
}
if self.sectors_per_fat < 1 || self.sectors_per_fat > 9 {
return false;
}
true
}
}
impl TryFrom<&BiosParameterBlock2> for StandardFormat {
type Error = &'static str;
fn try_from(bpb: &BiosParameterBlock2) -> Result<Self, Self::Error> {
let mut best_match = None;
match bpb.total_sectors {
320 => best_match = Some(StandardFormat::PcFloppy160),
360 => best_match = Some(StandardFormat::PcFloppy180),
640 => best_match = Some(StandardFormat::PcFloppy320),
720 => best_match = Some(StandardFormat::PcFloppy360),
1440 => best_match = Some(StandardFormat::PcFloppy720),
1200 => best_match = Some(StandardFormat::PcFloppy1200),
2880 => best_match = Some(StandardFormat::PcFloppy1440),
5760 => best_match = Some(StandardFormat::PcFloppy2880),
_ => {}
};
if let Some(best_match) = best_match {
return Ok(best_match);
}
match bpb.media_descriptor {
0xFE => best_match = Some(StandardFormat::PcFloppy160),
0xFC => best_match = Some(StandardFormat::PcFloppy180),
0xFD => best_match = Some(StandardFormat::PcFloppy360),
0xFF => best_match = Some(StandardFormat::PcFloppy320),
0xF9 => best_match = Some(StandardFormat::PcFloppy1200),
0xF0 => best_match = Some(StandardFormat::PcFloppy1440),
_ => {}
}
if let Some(best_match) = best_match {
return Ok(best_match);
}
Err("Invalid BPB")
}
}
impl From<StandardFormat> for BiosParameterBlock2 {
fn from(format: StandardFormat) -> Self {
match format {
StandardFormat::PcFloppy160 => BiosParameterBlock2 {
bytes_per_sector: 512,
sectors_per_cluster: 2,
reserved_sectors: 1,
number_of_fats: 2,
root_entries: 0x70,
total_sectors: 320,
media_descriptor: 0xFE,
sectors_per_fat: 1,
},
StandardFormat::PcFloppy180 => BiosParameterBlock2 {
bytes_per_sector: 512,
sectors_per_cluster: 2,
reserved_sectors: 1,
number_of_fats: 2,
root_entries: 0x70,
total_sectors: 360,
media_descriptor: 0xFE,
sectors_per_fat: 1,
},
StandardFormat::PcFloppy320 => BiosParameterBlock2 {
bytes_per_sector: 512,
sectors_per_cluster: 2,
reserved_sectors: 1,
number_of_fats: 2,
root_entries: 0x70,
total_sectors: 640,
media_descriptor: 0xFF,
sectors_per_fat: 1,
},
StandardFormat::PcFloppy360 => BiosParameterBlock2 {
bytes_per_sector: 512,
sectors_per_cluster: 2,
reserved_sectors: 1,
number_of_fats: 2,
root_entries: 0x70,
total_sectors: 720,
media_descriptor: 0xFD,
sectors_per_fat: 2,
},
StandardFormat::PcFloppy720 => BiosParameterBlock2 {
bytes_per_sector: 512,
sectors_per_cluster: 2,
reserved_sectors: 1,
number_of_fats: 2,
root_entries: 0x70,
total_sectors: 1440,
media_descriptor: 0xFD,
sectors_per_fat: 3,
},
StandardFormat::PcFloppy1200 => BiosParameterBlock2 {
bytes_per_sector: 512,
sectors_per_cluster: 2,
reserved_sectors: 1,
number_of_fats: 2,
root_entries: 0xE0,
total_sectors: 1200,
media_descriptor: 0xF9,
sectors_per_fat: 7,
},
StandardFormat::PcFloppy1440 => BiosParameterBlock2 {
bytes_per_sector: 512,
sectors_per_cluster: 1,
reserved_sectors: 1,
number_of_fats: 2,
root_entries: 0xE0,
total_sectors: 2880,
media_descriptor: 0xF0,
sectors_per_fat: 9,
},
StandardFormat::PcFloppy2880 => BiosParameterBlock2 {
bytes_per_sector: 512,
sectors_per_cluster: 1,
reserved_sectors: 1,
number_of_fats: 2,
root_entries: 0xF0,
total_sectors: 5760,
media_descriptor: 0xF0,
sectors_per_fat: 9,
},
_ => Default::default(),
}
}
}
#[derive(Debug, Default)]
#[binrw]
#[brw(little)]
pub(crate) struct BiosParameterBlock3 {
pub(crate) sectors_per_track: u16,
pub(crate) number_of_heads: u16,
pub(crate) hidden_sectors: u32,
}
impl From<StandardFormat> for BiosParameterBlock3 {
fn from(format: StandardFormat) -> Self {
match format {
StandardFormat::PcFloppy160 => BiosParameterBlock3 {
sectors_per_track: 8,
number_of_heads: 1,
hidden_sectors: 0,
},
StandardFormat::PcFloppy180 => BiosParameterBlock3 {
sectors_per_track: 9,
number_of_heads: 1,
hidden_sectors: 0,
},
StandardFormat::PcFloppy320 => BiosParameterBlock3 {
sectors_per_track: 8,
number_of_heads: 2,
hidden_sectors: 0,
},
StandardFormat::PcFloppy360 => BiosParameterBlock3 {
sectors_per_track: 9,
number_of_heads: 2,
hidden_sectors: 0,
},
StandardFormat::PcFloppy720 => BiosParameterBlock3 {
sectors_per_track: 9,
number_of_heads: 2,
hidden_sectors: 0,
},
StandardFormat::PcFloppy1200 => BiosParameterBlock3 {
sectors_per_track: 15,
number_of_heads: 2,
hidden_sectors: 0,
},
StandardFormat::PcFloppy1440 => BiosParameterBlock3 {
sectors_per_track: 18,
number_of_heads: 2,
hidden_sectors: 0,
},
StandardFormat::PcFloppy2880 => BiosParameterBlock3 {
sectors_per_track: 36,
number_of_heads: 2,
hidden_sectors: 0,
},
_ => Default::default(),
}
}
}