embedded_sdmmc/fat/
bpb.rs1use crate::{
4 blockdevice::BlockCount,
5 fat::{FatType, OnDiskDirEntry},
6};
7use byteorder::{ByteOrder, LittleEndian};
8
9pub struct Bpb<'a> {
14 data: &'a [u8; 512],
15 pub(crate) fat_type: FatType,
16 cluster_count: u32,
17}
18
19impl<'a> Bpb<'a> {
20 pub(crate) const FOOTER_VALUE: u16 = 0xAA55;
21
22 pub fn create_from_bytes(data: &[u8; 512]) -> Result<Bpb, &'static str> {
24 let mut bpb = Bpb {
25 data,
26 fat_type: FatType::Fat16,
27 cluster_count: 0,
28 };
29 if bpb.footer() != Self::FOOTER_VALUE {
30 return Err("Bad BPB footer");
31 }
32
33 let root_dir_blocks =
34 BlockCount::from_bytes(u32::from(bpb.root_entries_count()) * OnDiskDirEntry::LEN_U32).0;
35 let non_data_blocks = u32::from(bpb.reserved_block_count())
36 + (u32::from(bpb.num_fats()) * bpb.fat_size())
37 + root_dir_blocks;
38 let data_blocks = bpb.total_blocks() - non_data_blocks;
39 bpb.cluster_count = data_blocks / u32::from(bpb.blocks_per_cluster());
40 if bpb.cluster_count < 4085 {
41 return Err("FAT12 is unsupported");
42 } else if bpb.cluster_count < 65525 {
43 bpb.fat_type = FatType::Fat16;
44 } else {
45 bpb.fat_type = FatType::Fat32;
46 }
47
48 match bpb.fat_type {
49 FatType::Fat16 => Ok(bpb),
50 FatType::Fat32 if bpb.fs_ver() == 0 => {
51 Ok(bpb)
53 }
54 _ => Err("Invalid FAT format"),
55 }
56 }
57
58 define_field!(bytes_per_block, u16, 11);
60 define_field!(blocks_per_cluster, u8, 13);
61 define_field!(reserved_block_count, u16, 14);
62 define_field!(num_fats, u8, 16);
63 define_field!(root_entries_count, u16, 17);
64 define_field!(total_blocks16, u16, 19);
65 define_field!(media, u8, 21);
66 define_field!(fat_size16, u16, 22);
67 define_field!(blocks_per_track, u16, 24);
68 define_field!(num_heads, u16, 26);
69 define_field!(hidden_blocks, u32, 28);
70 define_field!(total_blocks32, u32, 32);
71 define_field!(footer, u16, 510);
72
73 define_field!(fat_size32, u32, 36);
75 define_field!(fs_ver, u16, 42);
76 define_field!(first_root_dir_cluster, u32, 44);
77 define_field!(fs_info, u16, 48);
78 define_field!(backup_boot_block, u16, 50);
79
80 pub fn oem_name(&self) -> &[u8] {
82 &self.data[3..11]
83 }
84
85 pub fn volume_label(&self) -> &[u8] {
89 if self.fat_type != FatType::Fat32 {
90 &self.data[43..=53]
91 } else {
92 &self.data[71..=81]
93 }
94 }
95
96 pub fn fs_info_block(&self) -> Option<BlockCount> {
101 if self.fat_type != FatType::Fat32 {
102 None
103 } else {
104 Some(BlockCount(u32::from(self.fs_info())))
105 }
106 }
107
108 pub fn fat_size(&self) -> u32 {
112 let result = u32::from(self.fat_size16());
113 if result != 0 {
114 result
115 } else {
116 self.fat_size32()
117 }
118 }
119
120 pub fn total_blocks(&self) -> u32 {
122 let result = u32::from(self.total_blocks16());
123 if result != 0 {
124 result
125 } else {
126 self.total_blocks32()
127 }
128 }
129
130 pub fn total_clusters(&self) -> u32 {
132 self.cluster_count
133 }
134}
135
136