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