fatfs/
boot_sector.rs

1use crate::core::cmp;
2use crate::core::u16;
3use crate::core::u8;
4use crate::io;
5use crate::io::prelude::*;
6use crate::io::{Error, ErrorKind};
7
8use crate::byteorder_ext::{ReadBytesExt, WriteBytesExt};
9use byteorder::LittleEndian;
10
11use crate::dir_entry::DIR_ENTRY_SIZE;
12use crate::error::{FatfsError, FatfsNumericError};
13use crate::fs::{FatType, FormatVolumeOptions, FsStatusFlags};
14use crate::table::RESERVED_FAT_ENTRIES;
15
16use std::collections::HashMap;
17
18const BITS_PER_BYTE: u32 = 8;
19const KB: u64 = 1024;
20const MB: u64 = KB * 1024;
21const GB: u64 = MB * 1024;
22
23#[derive(Default, Debug, Clone)]
24pub(crate) struct BiosParameterBlock {
25    pub(crate) bytes_per_sector: u16,
26    pub(crate) sectors_per_cluster: u8,
27    pub(crate) reserved_sectors: u16,
28    pub(crate) fats: u8,
29    pub(crate) root_entries: u16,
30    pub(crate) total_sectors_16: u16,
31    pub(crate) media: u8,
32    pub(crate) sectors_per_fat_16: u16,
33    pub(crate) sectors_per_track: u16,
34    pub(crate) heads: u16,
35    pub(crate) hidden_sectors: u32,
36    pub(crate) total_sectors_32: u32,
37
38    // Extended BIOS Parameter Block
39    pub(crate) sectors_per_fat_32: u32,
40    pub(crate) extended_flags: u16,
41    pub(crate) fs_version: u16,
42    pub(crate) root_dir_first_cluster: u32,
43    pub(crate) fs_info_sector: u16,
44    pub(crate) backup_boot_sector: u16,
45    pub(crate) reserved_0: [u8; 12],
46    pub(crate) drive_num: u8,
47    pub(crate) reserved_1: u8,
48    pub(crate) ext_sig: u8,
49    pub(crate) volume_id: u32,
50    pub(crate) volume_label: [u8; 11],
51    pub(crate) fs_type_label: [u8; 8],
52}
53
54impl BiosParameterBlock {
55    fn deserialize<R: Read>(rdr: &mut R) -> io::Result<BiosParameterBlock> {
56        let mut bpb: BiosParameterBlock = Default::default();
57        bpb.bytes_per_sector = rdr.read_u16::<LittleEndian>()?;
58        bpb.sectors_per_cluster = rdr.read_u8()?;
59        bpb.reserved_sectors = rdr.read_u16::<LittleEndian>()?;
60        bpb.fats = rdr.read_u8()?;
61        bpb.root_entries = rdr.read_u16::<LittleEndian>()?;
62        bpb.total_sectors_16 = rdr.read_u16::<LittleEndian>()?;
63        bpb.media = rdr.read_u8()?;
64        bpb.sectors_per_fat_16 = rdr.read_u16::<LittleEndian>()?;
65        bpb.sectors_per_track = rdr.read_u16::<LittleEndian>()?;
66        bpb.heads = rdr.read_u16::<LittleEndian>()?;
67        bpb.hidden_sectors = rdr.read_u32::<LittleEndian>()?;
68        bpb.total_sectors_32 = rdr.read_u32::<LittleEndian>()?;
69
70        if bpb.is_fat32() {
71            bpb.sectors_per_fat_32 = rdr.read_u32::<LittleEndian>()?;
72            bpb.extended_flags = rdr.read_u16::<LittleEndian>()?;
73            bpb.fs_version = rdr.read_u16::<LittleEndian>()?;
74            bpb.root_dir_first_cluster = rdr.read_u32::<LittleEndian>()?;
75            bpb.fs_info_sector = rdr.read_u16::<LittleEndian>()?;
76            bpb.backup_boot_sector = rdr.read_u16::<LittleEndian>()?;
77            rdr.read_exact(&mut bpb.reserved_0)?;
78            bpb.drive_num = rdr.read_u8()?;
79            bpb.reserved_1 = rdr.read_u8()?;
80            bpb.ext_sig = rdr.read_u8()?; // 0x29
81            bpb.volume_id = rdr.read_u32::<LittleEndian>()?;
82            rdr.read_exact(&mut bpb.volume_label)?;
83            rdr.read_exact(&mut bpb.fs_type_label)?;
84        } else {
85            bpb.drive_num = rdr.read_u8()?;
86            bpb.reserved_1 = rdr.read_u8()?;
87            bpb.ext_sig = rdr.read_u8()?; // 0x29
88            bpb.volume_id = rdr.read_u32::<LittleEndian>()?;
89            rdr.read_exact(&mut bpb.volume_label)?;
90            rdr.read_exact(&mut bpb.fs_type_label)?;
91        }
92
93        // when the extended boot signature is anything other than 0x29, the fields are invalid
94        if bpb.ext_sig != 0x29 {
95            // fields after ext_sig are not used - clean them
96            bpb.volume_id = 0;
97            bpb.volume_label = [0; 11];
98            bpb.fs_type_label = [0; 8];
99        }
100
101        Ok(bpb)
102    }
103
104    fn serialize<W: Write>(&self, mut wrt: W) -> io::Result<()> {
105        wrt.write_u16::<LittleEndian>(self.bytes_per_sector)?;
106        wrt.write_u8(self.sectors_per_cluster)?;
107        wrt.write_u16::<LittleEndian>(self.reserved_sectors)?;
108        wrt.write_u8(self.fats)?;
109        wrt.write_u16::<LittleEndian>(self.root_entries)?;
110        wrt.write_u16::<LittleEndian>(self.total_sectors_16)?;
111        wrt.write_u8(self.media)?;
112        wrt.write_u16::<LittleEndian>(self.sectors_per_fat_16)?;
113        wrt.write_u16::<LittleEndian>(self.sectors_per_track)?;
114        wrt.write_u16::<LittleEndian>(self.heads)?;
115        wrt.write_u32::<LittleEndian>(self.hidden_sectors)?;
116        wrt.write_u32::<LittleEndian>(self.total_sectors_32)?;
117
118        if self.is_fat32() {
119            wrt.write_u32::<LittleEndian>(self.sectors_per_fat_32)?;
120            wrt.write_u16::<LittleEndian>(self.extended_flags)?;
121            wrt.write_u16::<LittleEndian>(self.fs_version)?;
122            wrt.write_u32::<LittleEndian>(self.root_dir_first_cluster)?;
123            wrt.write_u16::<LittleEndian>(self.fs_info_sector)?;
124            wrt.write_u16::<LittleEndian>(self.backup_boot_sector)?;
125            wrt.write_all(&self.reserved_0)?;
126            wrt.write_u8(self.drive_num)?;
127            wrt.write_u8(self.reserved_1)?;
128            wrt.write_u8(self.ext_sig)?; // 0x29
129            wrt.write_u32::<LittleEndian>(self.volume_id)?;
130            wrt.write_all(&self.volume_label)?;
131            wrt.write_all(&self.fs_type_label)?;
132        } else {
133            wrt.write_u8(self.drive_num)?;
134            wrt.write_u8(self.reserved_1)?;
135            wrt.write_u8(self.ext_sig)?; // 0x29
136            wrt.write_u32::<LittleEndian>(self.volume_id)?;
137            wrt.write_all(&self.volume_label)?;
138            wrt.write_all(&self.fs_type_label)?;
139        }
140        Ok(())
141    }
142
143    fn validate(&self) -> io::Result<()> {
144        // sanity checks
145        if self.bytes_per_sector.count_ones() != 1 {
146            return Err(Error::new(
147                ErrorKind::Other,
148                FatfsError::InvalidBytesPerSector(FatfsNumericError::NotPowerOfTwo),
149            ));
150        } else if self.bytes_per_sector < 512 {
151            return Err(Error::new(
152                ErrorKind::Other,
153                FatfsError::InvalidBytesPerSector(FatfsNumericError::TooSmall(512)),
154            ));
155        } else if self.bytes_per_sector > 4096 {
156            return Err(Error::new(
157                ErrorKind::Other,
158                FatfsError::InvalidBytesPerSector(FatfsNumericError::TooLarge(4096)),
159            ));
160        }
161
162        if self.sectors_per_cluster.count_ones() != 1 {
163            return Err(Error::new(
164                ErrorKind::Other,
165                FatfsError::InvalidSectorsPerCluster(FatfsNumericError::NotPowerOfTwo),
166            ));
167        } else if self.sectors_per_cluster < 1 {
168            return Err(Error::new(
169                ErrorKind::Other,
170                FatfsError::InvalidSectorsPerCluster(FatfsNumericError::TooSmall(1)),
171            ));
172        } else if self.sectors_per_cluster > 128 {
173            return Err(Error::new(
174                ErrorKind::Other,
175                FatfsError::InvalidSectorsPerCluster(FatfsNumericError::TooLarge(128)),
176            ));
177        }
178
179        // bytes per sector is u16, sectors per cluster is u8, so guaranteed no overflow in multiplication
180        let bytes_per_cluster = self.bytes_per_sector as u32 * self.sectors_per_cluster as u32;
181        let maximum_compatibility_bytes_per_cluster: u32 = 32 * 1024;
182
183        if bytes_per_cluster > maximum_compatibility_bytes_per_cluster {
184            // 32k is the largest value to maintain greatest compatibility
185            // Many implementations appear to support 64k per cluster, and some may support 128k or larger
186            // However, >32k is not as thoroughly tested...
187            warn!("fs compatibility: bytes_per_cluster value '{}' in BPB exceeds '{}', and thus may be incompatible with some implementations",
188                bytes_per_cluster, maximum_compatibility_bytes_per_cluster);
189        }
190
191        let is_fat32 = self.is_fat32();
192        if self.reserved_sectors < 1 {
193            return Err(Error::new(ErrorKind::Other, FatfsError::InvalidReservedSectors));
194        } else if !is_fat32 && self.reserved_sectors != 1 {
195            // Microsoft document indicates fat12 and fat16 code exists that presume this value is 1
196            warn!(
197                "fs compatibility: reserved_sectors value '{}' in BPB is not '1', and thus is incompatible with some implementations",
198                self.reserved_sectors
199            );
200        }
201
202        if self.fats == 0 {
203            return Err(Error::new(ErrorKind::Other, FatfsError::InvalidFats));
204        } else if self.fats > 2 {
205            // Microsoft document indicates that few implementations support any values other than 1 or 2
206            warn!(
207                "fs compatibility: numbers of FATs '{}' in BPB is greater than '2', and thus is incompatible with some implementations",
208                self.fats
209            );
210        }
211
212        if is_fat32 && self.root_entries != 0 {
213            return Err(Error::new(ErrorKind::Other, FatfsError::NonZeroRootEntries));
214        }
215
216        if !is_fat32 && self.root_entries == 0 {
217            return Err(Error::new(ErrorKind::Other, FatfsError::ZeroRootEntries));
218        }
219
220        if (u32::from(self.root_entries) * DIR_ENTRY_SIZE as u32) % u32::from(self.bytes_per_sector)
221            != 0
222        {
223            warn!("Root entries should fill sectors fully");
224        }
225
226        if is_fat32 && self.total_sectors_16 != 0 {
227            return Err(Error::new(ErrorKind::Other, FatfsError::NonZeroTotalSectors));
228        }
229
230        if (self.total_sectors_16 == 0) == (self.total_sectors_32 == 0) {
231            return Err(Error::new(ErrorKind::Other, FatfsError::ZeroTotalSectors));
232        }
233
234        if is_fat32 && self.sectors_per_fat_32 == 0 {
235            return Err(Error::new(ErrorKind::Other, FatfsError::InvalidSectorsPerFat));
236        }
237
238        if self.sectors_per_fat() >= std::u32::MAX / (self.fats as u32) {
239            return Err(Error::new(ErrorKind::Other, FatfsError::InvalidSectorsPerFat));
240        }
241
242        if self.fs_version != 0 {
243            return Err(Error::new(ErrorKind::Other, FatfsError::UnknownVersion));
244        }
245
246        if self
247            .reserved_sectors()
248            .checked_add(self.sectors_per_all_fats())
249            .and_then(|e| e.checked_add(self.root_dir_sectors()))
250            .is_none()
251        {
252            return Err(Error::new(ErrorKind::Other, FatfsError::TooManyReservedSectors));
253        }
254
255        if self.total_sectors() <= self.first_data_sector() {
256            return Err(Error::new(ErrorKind::Other, FatfsError::TotalSectorsTooSmall));
257        }
258
259        if is_fat32 && self.backup_boot_sector() >= self.reserved_sectors() {
260            return Err(Error::new(ErrorKind::Other, FatfsError::BackupBootSectorInvalid));
261        }
262
263        if is_fat32 && self.fs_info_sector() >= self.reserved_sectors() {
264            return Err(Error::new(ErrorKind::Other, FatfsError::FsInfoInvalid));
265        }
266
267        let total_clusters = self.total_clusters();
268        let fat_type = FatType::from_clusters(total_clusters);
269        if is_fat32 != (fat_type == FatType::Fat32) {
270            return Err(Error::new(ErrorKind::Other, FatfsError::InvalidNumClusters));
271        }
272        if fat_type == FatType::Fat32 && total_clusters > 0x0FFF_FFFF {
273            return Err(Error::new(ErrorKind::Other, FatfsError::TooManyClusters));
274        }
275
276        let bits_per_fat_entry = fat_type.bits_per_fat_entry();
277        let total_fat_entries =
278            ((self.sectors_per_fat() as u64) * (self.bytes_per_sector as u64) * 8
279                / bits_per_fat_entry as u64) as u32;
280        if total_fat_entries < RESERVED_FAT_ENTRIES {
281            return Err(Error::new(ErrorKind::Other, FatfsError::InvalidFatEntries));
282        }
283        if total_fat_entries - RESERVED_FAT_ENTRIES < total_clusters {
284            warn!("FAT is too small compared to total number of clusters");
285        }
286
287        Ok(())
288    }
289
290    pub(crate) fn mirroring_enabled(&self) -> bool {
291        self.extended_flags & 0x80 == 0
292    }
293
294    pub(crate) fn active_fat(&self) -> u16 {
295        // The zero-based number of the active FAT is only valid if mirroring is disabled.
296        if self.mirroring_enabled() {
297            0
298        } else {
299            self.extended_flags & 0x0F
300        }
301    }
302
303    pub(crate) fn status_flags(&self) -> FsStatusFlags {
304        FsStatusFlags::decode(self.reserved_1)
305    }
306
307    pub(crate) fn is_fat32(&self) -> bool {
308        // because this field must be zero on FAT32, and
309        // because it must be non-zero on FAT12/FAT16,
310        // this provides a simple way to detect FAT32
311        self.sectors_per_fat_16 == 0
312    }
313
314    pub(crate) fn sectors_per_fat(&self) -> u32 {
315        if self.is_fat32() {
316            self.sectors_per_fat_32
317        } else {
318            self.sectors_per_fat_16 as u32
319        }
320    }
321
322    pub(crate) fn total_sectors(&self) -> u32 {
323        if self.total_sectors_16 == 0 {
324            self.total_sectors_32
325        } else {
326            self.total_sectors_16 as u32
327        }
328    }
329
330    pub(crate) fn reserved_sectors(&self) -> u32 {
331        self.reserved_sectors as u32
332    }
333
334    pub(crate) fn root_dir_sectors(&self) -> u32 {
335        let root_dir_bytes = self.root_entries as u32 * DIR_ENTRY_SIZE as u32;
336        (root_dir_bytes + self.bytes_per_sector as u32 - 1) / self.bytes_per_sector as u32
337    }
338
339    pub(crate) fn sectors_per_all_fats(&self) -> u32 {
340        self.fats as u32 * self.sectors_per_fat()
341    }
342
343    pub(crate) fn first_data_sector(&self) -> u32 {
344        let root_dir_sectors = self.root_dir_sectors();
345        let fat_sectors = self.sectors_per_all_fats();
346        self.reserved_sectors() + fat_sectors + root_dir_sectors
347    }
348
349    pub(crate) fn total_clusters(&self) -> u32 {
350        let total_sectors = self.total_sectors();
351        let first_data_sector = self.first_data_sector();
352        let data_sectors = total_sectors - first_data_sector;
353        data_sectors / self.sectors_per_cluster as u32
354    }
355
356    pub(crate) fn bytes_from_sectors(&self, sectors: u32) -> u64 {
357        // Note: total number of sectors is a 32 bit number so offsets have to be 64 bit
358        (sectors as u64) * self.bytes_per_sector as u64
359    }
360
361    pub(crate) fn sectors_from_clusters(&self, clusters: u32) -> Result<u32, FatfsError> {
362        // sectors_per_cluster is an 8 bit number. This shouldn't overflow on a valid FAT disk, as
363        // FAT only supports up to a 32 bit sector count. The input to this function is not
364        // necessarily trusted, however, so we need to do a checked multiply.
365        clusters
366            .checked_mul(self.sectors_per_cluster as u32)
367            .ok_or(FatfsError::InvalidClusterNumber)
368    }
369
370    pub(crate) fn cluster_size(&self) -> u32 {
371        self.sectors_per_cluster as u32 * self.bytes_per_sector as u32
372    }
373
374    pub(crate) fn clusters_from_bytes(&self, bytes: u64) -> u32 {
375        let cluster_size = self.cluster_size() as i64;
376        ((bytes as i64 + cluster_size - 1) / cluster_size) as u32
377    }
378
379    pub(crate) fn fs_info_sector(&self) -> u32 {
380        self.fs_info_sector as u32
381    }
382
383    pub(crate) fn backup_boot_sector(&self) -> u32 {
384        self.backup_boot_sector as u32
385    }
386}
387
388pub(crate) struct BootSector {
389    bootjmp: [u8; 3],
390    oem_name: [u8; 8],
391    pub(crate) bpb: BiosParameterBlock,
392    boot_code: [u8; 448],
393    boot_sig: [u8; 2],
394}
395
396impl BootSector {
397    pub(crate) fn deserialize<R: Read>(rdr: &mut R) -> io::Result<BootSector> {
398        let mut boot: BootSector = Default::default();
399        rdr.read_exact(&mut boot.bootjmp)?;
400        rdr.read_exact(&mut boot.oem_name)?;
401        boot.bpb = BiosParameterBlock::deserialize(rdr)?;
402
403        if boot.bpb.is_fat32() {
404            rdr.read_exact(&mut boot.boot_code[0..420])?;
405        } else {
406            rdr.read_exact(&mut boot.boot_code[0..448])?;
407        }
408        rdr.read_exact(&mut boot.boot_sig)?;
409        Ok(boot)
410    }
411
412    pub(crate) fn serialize<W: Write>(&self, wrt: &mut W) -> io::Result<()> {
413        wrt.write_all(&self.bootjmp)?;
414        wrt.write_all(&self.oem_name)?;
415        self.bpb.serialize(&mut *wrt)?;
416
417        if self.bpb.is_fat32() {
418            wrt.write_all(&self.boot_code[0..420])?;
419        } else {
420            wrt.write_all(&self.boot_code[0..448])?;
421        }
422        wrt.write_all(&self.boot_sig)?;
423        Ok(())
424    }
425
426    pub(crate) fn validate(&self) -> io::Result<()> {
427        if self.boot_sig != [0x55, 0xAA] {
428            return Err(Error::new(ErrorKind::Other, FatfsError::InvalidBootSectorSig));
429        }
430        if self.bootjmp[0] != 0xEB && self.bootjmp[0] != 0xE9 {
431            warn!("Unknown opcode {:x} in bootjmp boot sector field", self.bootjmp[0]);
432        }
433        self.bpb.validate()?;
434        Ok(())
435    }
436}
437
438impl Default for BootSector {
439    fn default() -> BootSector {
440        BootSector {
441            bootjmp: Default::default(),
442            oem_name: Default::default(),
443            bpb: Default::default(),
444            boot_code: [0; 448],
445            boot_sig: Default::default(),
446        }
447    }
448}
449
450pub(crate) fn estimate_fat_type(total_bytes: u64) -> FatType {
451    // Used only to select cluster size if FAT type has not been overriden in options
452    if total_bytes < 4 * MB {
453        FatType::Fat12
454    } else if total_bytes < 512 * MB {
455        FatType::Fat16
456    } else {
457        FatType::Fat32
458    }
459}
460
461fn determine_bytes_per_cluster(total_bytes: u64, bytes_per_sector: u16, fat_type: FatType) -> u32 {
462    let bytes_per_cluster = match fat_type {
463        FatType::Fat12 => (total_bytes.next_power_of_two() / MB * 512) as u32,
464        FatType::Fat16 => {
465            if total_bytes <= 16 * MB {
466                1 * KB as u32
467            } else if total_bytes <= 128 * MB {
468                2 * KB as u32
469            } else {
470                (total_bytes.next_power_of_two() / (64 * MB) * KB) as u32
471            }
472        }
473        FatType::Fat32 => {
474            if total_bytes <= 260 * MB {
475                512
476            } else if total_bytes <= 8 * GB {
477                4 * KB as u32
478            } else {
479                (total_bytes.next_power_of_two() / (2 * GB) * KB) as u32
480            }
481        }
482    };
483    const MAX_CLUSTER_SIZE: u32 = 32 * KB as u32;
484    debug_assert!(bytes_per_cluster.is_power_of_two());
485    cmp::min(cmp::max(bytes_per_cluster, bytes_per_sector as u32), MAX_CLUSTER_SIZE)
486}
487
488fn determine_sectors_per_fat(
489    total_sectors: u32,
490    bytes_per_sector: u16,
491    sectors_per_cluster: u8,
492    fat_type: FatType,
493    reserved_sectors: u16,
494    root_dir_sectors: u32,
495    fats: u8,
496) -> u32 {
497    //
498    // FAT size formula transformations:
499    //
500    // Initial basic formula:
501    // size of FAT in bits >= (total number of clusters + 2) * bits per FAT entry
502    //
503    // Note: when computing number of clusters from number of sectors rounding down is used because partial clusters
504    // are not allowed
505    // Note: in those transformations '/' is a floating-point division (not a rounding towards zero division)
506    //
507    // data_sectors = total_sectors - reserved_sectors - fats * sectors_per_fat - root_dir_sectors
508    // total_clusters = floor(data_sectors / sectors_per_cluster)
509    // bits_per_sector = bytes_per_sector * 8
510    // sectors_per_fat * bits_per_sector >= (total_clusters + 2) * bits_per_fat_entry
511    // sectors_per_fat * bits_per_sector >= (floor(data_sectors / sectors_per_cluster) + 2) * bits_per_fat_entry
512    //
513    // Note: omitting the floor function can cause the FAT to be bigger by 1 entry - negligible
514    //
515    // sectors_per_fat * bits_per_sector >= (data_sectors / sectors_per_cluster + 2) * bits_per_fat_entry
516    // t0 = total_sectors - reserved_sectors - root_dir_sectors
517    // sectors_per_fat * bits_per_sector >= ((t0 - fats * sectors_per_fat) / sectors_per_cluster + 2) * bits_per_fat_entry
518    // sectors_per_fat * bits_per_sector / bits_per_fat_entry >= (t0 - fats * sectors_per_fat) / sectors_per_cluster + 2
519    // sectors_per_fat * bits_per_sector / bits_per_fat_entry >= t0 / sectors_per_cluster + 2 - fats * sectors_per_fat / sectors_per_cluster
520    // sectors_per_fat * bits_per_sector / bits_per_fat_entry + fats * sectors_per_fat / sectors_per_cluster >= t0 / sectors_per_cluster + 2
521    // sectors_per_fat * (bits_per_sector / bits_per_fat_entry + fats / sectors_per_cluster) >= t0 / sectors_per_cluster + 2
522    // sectors_per_fat >= (t0 / sectors_per_cluster + 2) / (bits_per_sector / bits_per_fat_entry + fats / sectors_per_cluster)
523    //
524    // Note: MS specification omits the constant 2 in calculations. This library is taking a better approach...
525    //
526    // sectors_per_fat >= ((t0 + 2 * sectors_per_cluster) / sectors_per_cluster) / (bits_per_sector / bits_per_fat_entry + fats / sectors_per_cluster)
527    // sectors_per_fat >= (t0 + 2 * sectors_per_cluster) / (sectors_per_cluster * bits_per_sector / bits_per_fat_entry + fats)
528    //
529    // Note: compared to MS formula this one can suffer from an overflow problem if u32 type is used
530    //
531    // When converting formula to integer types round towards a bigger FAT:
532    // * first division towards infinity
533    // * second division towards zero (it is in a denominator of the first division)
534
535    let t0: u32 = total_sectors - u32::from(reserved_sectors) - root_dir_sectors;
536    let t1: u64 = u64::from(t0) + u64::from(2 * u32::from(sectors_per_cluster));
537    let bits_per_cluster =
538        u32::from(sectors_per_cluster) * u32::from(bytes_per_sector) * BITS_PER_BYTE;
539    let t2 =
540        u64::from(bits_per_cluster / u32::from(fat_type.bits_per_fat_entry()) + u32::from(fats));
541    let sectors_per_fat = (t1 + t2 - 1) / t2;
542    // Note: casting is safe here because number of sectors per FAT cannot be bigger than total sectors number
543    sectors_per_fat as u32
544}
545
546fn try_fs_geometry(
547    total_sectors: u32,
548    bytes_per_sector: u16,
549    sectors_per_cluster: u8,
550    fat_type: FatType,
551    root_dir_sectors: u32,
552    fats: u8,
553) -> io::Result<(u16, u32)> {
554    // Note: most of implementations use 32 reserved sectors for FAT32 but it's wasting of space
555    // This implementation uses only 8. This is enough to fit in two boot sectors (main and backup) with additional
556    // bootstrap code and one FSInfo sector. It also makes FAT alligned to 4096 which is a nice number.
557    let reserved_sectors: u16 = if fat_type == FatType::Fat32 { 8 } else { 1 };
558
559    // Check if volume has enough space to accomodate reserved sectors, FAT, root directory and some data space
560    // Having less than 8 sectors for FAT and data would make a little sense
561    if total_sectors <= u32::from(reserved_sectors) + u32::from(root_dir_sectors) + 8 {
562        return Err(Error::new(ErrorKind::Other, FatfsError::VolumeTooSmall));
563    }
564
565    // calculate File Allocation Table size
566    let sectors_per_fat = determine_sectors_per_fat(
567        total_sectors,
568        bytes_per_sector,
569        sectors_per_cluster,
570        fat_type,
571        reserved_sectors,
572        root_dir_sectors,
573        fats,
574    );
575
576    let data_sectors = total_sectors
577        - u32::from(reserved_sectors)
578        - u32::from(root_dir_sectors)
579        - sectors_per_fat * u32::from(fats);
580    let total_clusters = data_sectors / u32::from(sectors_per_cluster);
581    if fat_type != FatType::from_clusters(total_clusters) {
582        return Err(Error::new(ErrorKind::Other, FatfsError::InvalidFatType));
583    }
584    debug_assert!(total_clusters >= fat_type.min_clusters());
585    if total_clusters > fat_type.max_clusters() {
586        // Note: it can happen for FAT32
587        return Err(Error::new(ErrorKind::Other, FatfsError::TooManyClusters));
588    }
589
590    return Ok((reserved_sectors, sectors_per_fat));
591}
592
593fn determine_root_dir_sectors(
594    root_dir_entries: u16,
595    bytes_per_sector: u16,
596    fat_type: FatType,
597) -> u32 {
598    if fat_type == FatType::Fat32 {
599        0
600    } else {
601        let root_dir_bytes = u32::from(root_dir_entries) * DIR_ENTRY_SIZE as u32;
602        (root_dir_bytes + u32::from(bytes_per_sector) - 1) / u32::from(bytes_per_sector)
603    }
604}
605
606fn determine_fs_geometry(
607    fat_type: Option<FatType>,
608    total_sectors: u32,
609    bytes_per_sector: u16,
610    bytes_per_cluster: Option<u32>,
611    root_dir_entries: u16,
612    fats: u8,
613) -> io::Result<(FatType, u16, u32, u8)> {
614    let mut failures = HashMap::new();
615    let fat_types = match fat_type {
616        Some(t) => vec![t],
617        None => vec![FatType::Fat32, FatType::Fat16, FatType::Fat12],
618    };
619    for fat_type in fat_types {
620        let bytes_per_cluster = bytes_per_cluster.unwrap_or_else(|| {
621            let total_bytes = u64::from(total_sectors) * u64::from(bytes_per_sector);
622            determine_bytes_per_cluster(total_bytes, bytes_per_sector, fat_type)
623        });
624        let sectors_per_cluster = {
625            let sectors_per_cluster = bytes_per_cluster / u32::from(bytes_per_sector);
626            assert!(sectors_per_cluster <= u32::from(u8::MAX));
627            sectors_per_cluster as u8
628        };
629        let root_dir_sectors =
630            determine_root_dir_sectors(root_dir_entries, bytes_per_sector, fat_type);
631        let result = try_fs_geometry(
632            total_sectors,
633            bytes_per_sector,
634            sectors_per_cluster,
635            fat_type,
636            root_dir_sectors,
637            fats,
638        );
639        match result {
640            Ok((reserved_sectors, sectors_per_fat)) => {
641                return Ok((fat_type, reserved_sectors, sectors_per_fat, sectors_per_cluster));
642            }
643            Err(e) => failures.insert(fat_type, e),
644        };
645    }
646    eprintln!("Failed to identify any valid geometry.  Errors:");
647    for (fat_type, err) in failures {
648        eprintln!(
649            "type: {:?} err: {:?} total_sectors: {}, bytes_per_sector: {} bytes_per_cluster: {:?}\
650            root_dir_entries: {} fats: {}",
651            fat_type,
652            err,
653            total_sectors,
654            bytes_per_sector,
655            bytes_per_cluster,
656            root_dir_entries,
657            fats
658        );
659    }
660
661    return Err(Error::new(ErrorKind::Other, FatfsError::BadDiskSize));
662}
663
664fn format_bpb(
665    options: &FormatVolumeOptions,
666    total_sectors: u32,
667    bytes_per_sector: u16,
668) -> io::Result<(BiosParameterBlock, FatType)> {
669    let fats = options.fats.unwrap_or(2u8);
670    let root_dir_entries = options.max_root_dir_entries.unwrap_or(512);
671    let (fat_type, reserved_sectors, sectors_per_fat, sectors_per_cluster) = determine_fs_geometry(
672        options.fat_type,
673        total_sectors,
674        bytes_per_sector,
675        options.bytes_per_cluster,
676        root_dir_entries,
677        fats,
678    )?;
679
680    // drive_num should be 0 for floppy disks and 0x80 for hard disks - determine it using FAT type
681    let drive_num =
682        options.drive_num.unwrap_or_else(|| if fat_type == FatType::Fat12 { 0 } else { 0x80 });
683
684    // reserved_0 is always zero
685    let reserved_0 = [0u8; 12];
686
687    // setup volume label
688    let mut volume_label = [0u8; 11];
689    if let Some(volume_label_from_opts) = options.volume_label {
690        volume_label.copy_from_slice(&volume_label_from_opts);
691    } else {
692        volume_label.copy_from_slice(b"NO NAME    ");
693    }
694
695    // setup fs_type_label field
696    let mut fs_type_label = [0u8; 8];
697    let fs_type_label_str = match fat_type {
698        FatType::Fat12 => b"FAT12   ",
699        FatType::Fat16 => b"FAT16   ",
700        FatType::Fat32 => b"FAT32   ",
701    };
702    fs_type_label.copy_from_slice(fs_type_label_str);
703
704    // create Bios Parameter Block struct
705    let is_fat32 = fat_type == FatType::Fat32;
706    let sectors_per_fat_16 = if is_fat32 {
707        0
708    } else {
709        debug_assert!(sectors_per_fat <= u32::from(u16::MAX));
710        sectors_per_fat as u16
711    };
712    let bpb = BiosParameterBlock {
713        bytes_per_sector,
714        sectors_per_cluster,
715        reserved_sectors,
716        fats,
717        root_entries: if is_fat32 { 0 } else { root_dir_entries },
718        total_sectors_16: if total_sectors < 0x10000 { total_sectors as u16 } else { 0 },
719        media: options.media.unwrap_or(0xF8),
720        sectors_per_fat_16,
721        sectors_per_track: options.sectors_per_track.unwrap_or(0x20),
722        heads: options.heads.unwrap_or(0x40),
723        hidden_sectors: 0,
724        total_sectors_32: if total_sectors >= 0x10000 { total_sectors } else { 0 },
725        // FAT32 fields start
726        sectors_per_fat_32: if is_fat32 { sectors_per_fat } else { 0 },
727        extended_flags: 0, // mirroring enabled
728        fs_version: 0,
729        root_dir_first_cluster: if is_fat32 { 2 } else { 0 },
730        fs_info_sector: if is_fat32 { 1 } else { 0 },
731        backup_boot_sector: if is_fat32 { 6 } else { 0 },
732        reserved_0,
733        // FAT32 fields end
734        drive_num,
735        reserved_1: 0,
736        ext_sig: 0x29,
737        volume_id: options.volume_id.unwrap_or(0x12345678),
738        volume_label,
739        fs_type_label,
740    };
741
742    // Check if number of clusters is proper for used FAT type
743    if FatType::from_clusters(bpb.total_clusters()) != fat_type {
744        return Err(Error::new(ErrorKind::Other, FatfsError::ClusterFatMismatch));
745    }
746
747    Ok((bpb, fat_type))
748}
749
750pub(crate) fn format_boot_sector(
751    options: &FormatVolumeOptions,
752    total_sectors: u32,
753    bytes_per_sector: u16,
754) -> io::Result<(BootSector, FatType)> {
755    let mut boot: BootSector = Default::default();
756    let (bpb, fat_type) = format_bpb(options, total_sectors, bytes_per_sector)?;
757    boot.bpb = bpb;
758    boot.oem_name.copy_from_slice(b"MSWIN4.1");
759    // Boot code copied from FAT32 boot sector initialized by mkfs.fat
760    boot.bootjmp = [0xEB, 0x58, 0x90];
761    let boot_code: [u8; 129] = [
762        0x0E, 0x1F, 0xBE, 0x77, 0x7C, 0xAC, 0x22, 0xC0, 0x74, 0x0B, 0x56, 0xB4, 0x0E, 0xBB, 0x07,
763        0x00, 0xCD, 0x10, 0x5E, 0xEB, 0xF0, 0x32, 0xE4, 0xCD, 0x16, 0xCD, 0x19, 0xEB, 0xFE, 0x54,
764        0x68, 0x69, 0x73, 0x20, 0x69, 0x73, 0x20, 0x6E, 0x6F, 0x74, 0x20, 0x61, 0x20, 0x62, 0x6F,
765        0x6F, 0x74, 0x61, 0x62, 0x6C, 0x65, 0x20, 0x64, 0x69, 0x73, 0x6B, 0x2E, 0x20, 0x20, 0x50,
766        0x6C, 0x65, 0x61, 0x73, 0x65, 0x20, 0x69, 0x6E, 0x73, 0x65, 0x72, 0x74, 0x20, 0x61, 0x20,
767        0x62, 0x6F, 0x6F, 0x74, 0x61, 0x62, 0x6C, 0x65, 0x20, 0x66, 0x6C, 0x6F, 0x70, 0x70, 0x79,
768        0x20, 0x61, 0x6E, 0x64, 0x0D, 0x0A, 0x70, 0x72, 0x65, 0x73, 0x73, 0x20, 0x61, 0x6E, 0x79,
769        0x20, 0x6B, 0x65, 0x79, 0x20, 0x74, 0x6F, 0x20, 0x74, 0x72, 0x79, 0x20, 0x61, 0x67, 0x61,
770        0x69, 0x6E, 0x20, 0x2E, 0x2E, 0x2E, 0x20, 0x0D, 0x0A,
771    ];
772    boot.boot_code[..boot_code.len()].copy_from_slice(&boot_code);
773    boot.boot_sig = [0x55, 0xAA];
774
775    // fix offsets in bootjmp and boot code for non-FAT32 filesystems (bootcode is on a different offset)
776    if fat_type != FatType::Fat32 {
777        // offset of boot code
778        let boot_code_offset: u8 = 0x36 + 8;
779        boot.bootjmp[1] = boot_code_offset - 2;
780        // offset of message
781        const MESSAGE_OFFSET: u16 = 29;
782        let message_offset_in_sector = u16::from(boot_code_offset) + MESSAGE_OFFSET + 0x7c00;
783        boot.boot_code[3] = (message_offset_in_sector & 0xff) as u8;
784        boot.boot_code[4] = (message_offset_in_sector >> 8) as u8;
785    }
786
787    Ok((boot, fat_type))
788}
789
790#[cfg(test)]
791mod tests {
792    use super::*;
793    extern crate env_logger;
794    use crate::core::u32;
795
796    fn init() {
797        let _ = env_logger::builder().is_test(true).try_init();
798    }
799
800    #[test]
801    fn test_estimate_fat_type() {
802        assert_eq!(estimate_fat_type(3 * MB), FatType::Fat12);
803        assert_eq!(estimate_fat_type(4 * MB), FatType::Fat16);
804        assert_eq!(estimate_fat_type(511 * MB), FatType::Fat16);
805        assert_eq!(estimate_fat_type(512 * MB), FatType::Fat32);
806    }
807
808    #[test]
809    fn test_determine_bytes_per_cluster_fat12() {
810        assert_eq!(determine_bytes_per_cluster(1 * MB + 0, 512, FatType::Fat12), 512);
811        assert_eq!(determine_bytes_per_cluster(1 * MB + 1, 512, FatType::Fat12), 1024);
812        assert_eq!(determine_bytes_per_cluster(1 * MB, 4096, FatType::Fat12), 4096);
813    }
814
815    #[test]
816    fn test_determine_bytes_per_cluster_fat16() {
817        assert_eq!(determine_bytes_per_cluster(1 * MB, 512, Some(FatType::Fat16)), 1 * KB as u32);
818        assert_eq!(
819            determine_bytes_per_cluster(1 * MB, 4 * KB as u16, Some(FatType::Fat16)),
820            4 * KB as u32
821        );
822        assert_eq!(
823            determine_bytes_per_cluster(16 * MB + 0, 512, Some(FatType::Fat16)),
824            1 * KB as u32
825        );
826        assert_eq!(
827            determine_bytes_per_cluster(16 * MB + 1, 512, Some(FatType::Fat16)),
828            2 * KB as u32
829        );
830        assert_eq!(
831            determine_bytes_per_cluster(128 * MB + 0, 512, Some(FatType::Fat16)),
832            2 * KB as u32
833        );
834        assert_eq!(
835            determine_bytes_per_cluster(128 * MB + 1, 512, Some(FatType::Fat16)),
836            4 * KB as u32
837        );
838        assert_eq!(
839            determine_bytes_per_cluster(256 * MB + 0, 512, Some(FatType::Fat16)),
840            4 * KB as u32
841        );
842        assert_eq!(
843            determine_bytes_per_cluster(256 * MB + 1, 512, Some(FatType::Fat16)),
844            8 * KB as u32
845        );
846        assert_eq!(
847            determine_bytes_per_cluster(512 * MB + 0, 512, Some(FatType::Fat16)),
848            8 * KB as u32
849        );
850        assert_eq!(
851            determine_bytes_per_cluster(512 * MB + 1, 512, Some(FatType::Fat16)),
852            16 * KB as u32
853        );
854        assert_eq!(
855            determine_bytes_per_cluster(1024 * MB + 0, 512, Some(FatType::Fat16)),
856            16 * KB as u32
857        );
858        assert_eq!(
859            determine_bytes_per_cluster(1024 * MB + 1, 512, Some(FatType::Fat16)),
860            32 * KB as u32
861        );
862        assert_eq!(
863            determine_bytes_per_cluster(99999 * MB, 512, Some(FatType::Fat16)),
864            32 * KB as u32
865        );
866    }
867
868    #[test]
869    fn test_determine_bytes_per_cluster_fat32() {
870        assert_eq!(determine_bytes_per_cluster(260 * MB as u64, 512, Some(FatType::Fat32)), 512);
871        assert_eq!(
872            determine_bytes_per_cluster(260 * MB as u64, 4 * KB as u16, Some(FatType::Fat32)),
873            4 * KB as u32
874        );
875        assert_eq!(
876            determine_bytes_per_cluster(260 * MB as u64 + 1, 512, Some(FatType::Fat32)),
877            4 * KB as u32
878        );
879        assert_eq!(
880            determine_bytes_per_cluster(8 * GB as u64, 512, Some(FatType::Fat32)),
881            4 * KB as u32
882        );
883        assert_eq!(
884            determine_bytes_per_cluster(8 * GB as u64 + 1, 512, Some(FatType::Fat32)),
885            8 * KB as u32
886        );
887        assert_eq!(
888            determine_bytes_per_cluster(16 * GB as u64 + 0, 512, Some(FatType::Fat32)),
889            8 * KB as u32
890        );
891        assert_eq!(
892            determine_bytes_per_cluster(16 * GB as u64 + 1, 512, Some(FatType::Fat32)),
893            16 * KB as u32
894        );
895        assert_eq!(
896            determine_bytes_per_cluster(32 * GB as u64, 512, Some(FatType::Fat32)),
897            16 * KB as u32
898        );
899        assert_eq!(
900            determine_bytes_per_cluster(32 * GB as u64 + 1, 512, Some(FatType::Fat32)),
901            32 * KB as u32
902        );
903        assert_eq!(
904            determine_bytes_per_cluster(999 * GB as u64, 512, Some(FatType::Fat32)),
905            32 * KB as u32
906        );
907    }
908
909    fn test_determine_sectors_per_fat_single(
910        total_bytes: u64,
911        bytes_per_sector: u16,
912        bytes_per_cluster: u32,
913        fat_type: FatType,
914        reserved_sectors: u16,
915        fats: u8,
916        root_dir_entries: u32,
917    ) {
918        let total_sectors = total_bytes / u64::from(bytes_per_sector);
919        debug_assert!(total_sectors <= u64::from(u32::MAX), "{:x}", total_sectors);
920        let total_sectors = total_sectors as u32;
921
922        let sectors_per_cluster = (bytes_per_cluster / u32::from(bytes_per_sector)) as u8;
923        let root_dir_size = root_dir_entries * DIR_ENTRY_SIZE as u32;
924        let root_dir_sectors =
925            (root_dir_size + u32::from(bytes_per_sector) - 1) / u32::from(bytes_per_sector);
926        let sectors_per_fat = determine_sectors_per_fat(
927            total_sectors,
928            bytes_per_sector,
929            sectors_per_cluster,
930            fat_type,
931            reserved_sectors,
932            root_dir_sectors,
933            fats,
934        );
935
936        let sectors_per_all_fats = u32::from(fats) * sectors_per_fat;
937        let total_data_sectors =
938            total_sectors - u32::from(reserved_sectors) - sectors_per_all_fats - root_dir_sectors;
939        let total_clusters = total_data_sectors / u32::from(sectors_per_cluster);
940        if FatType::from_clusters(total_clusters) != fat_type {
941            // Skip impossible FAT configurations
942            return;
943        }
944        let bits_per_sector = u32::from(bytes_per_sector) * BITS_PER_BYTE;
945        let bits_per_fat = u64::from(sectors_per_fat) * u64::from(bits_per_sector);
946        let total_fat_entries = (bits_per_fat / u64::from(fat_type.bits_per_fat_entry())) as u32;
947        let fat_clusters = total_fat_entries - RESERVED_FAT_ENTRIES;
948        // Note: fat_entries_per_sector is rounded down for FAT12
949        let fat_entries_per_sector = u32::from(bits_per_sector) / fat_type.bits_per_fat_entry();
950        let desc = format!("total_clusters {}, fat_clusters {}, total_sectors {}, bytes/sector {}, sectors/cluster {}, fat_type {:?}, reserved_sectors {}, root_dir_sectors {}, sectors_per_fat {}",
951            total_clusters, fat_clusters, total_sectors, bytes_per_sector, sectors_per_cluster, fat_type, reserved_sectors, root_dir_sectors, sectors_per_fat);
952        assert!(fat_clusters >= total_clusters, "Too small FAT: {}", desc);
953        assert!(
954            fat_clusters <= total_clusters + 2 * fat_entries_per_sector,
955            "Too big FAT: {}",
956            desc
957        );
958    }
959
960    fn test_determine_sectors_per_fat_for_multiple_sizes(
961        bytes_per_sector: u16,
962        fat_type: FatType,
963        reserved_sectors: u16,
964        fats: u8,
965        root_dir_entries: u32,
966    ) {
967        let mut bytes_per_cluster = u32::from(bytes_per_sector);
968        while bytes_per_cluster <= 64 * KB as u32 {
969            let mut size = 1 * MB;
970            while size < 2048 * GB {
971                test_determine_sectors_per_fat_single(
972                    size,
973                    bytes_per_sector,
974                    bytes_per_cluster,
975                    fat_type,
976                    reserved_sectors,
977                    fats,
978                    root_dir_entries,
979                );
980                size = size + size / 7;
981            }
982            size = 2048 * GB - 1;
983            test_determine_sectors_per_fat_single(
984                size,
985                bytes_per_sector,
986                bytes_per_cluster,
987                fat_type,
988                reserved_sectors,
989                fats,
990                root_dir_entries,
991            );
992            bytes_per_cluster *= 2;
993        }
994    }
995
996    #[test]
997    fn test_determine_sectors_per_fat() {
998        init();
999
1000        test_determine_sectors_per_fat_for_multiple_sizes(512, FatType::Fat12, 1, 2, 512);
1001        test_determine_sectors_per_fat_for_multiple_sizes(512, FatType::Fat12, 1, 1, 512);
1002        test_determine_sectors_per_fat_for_multiple_sizes(512, FatType::Fat12, 1, 2, 8192);
1003        test_determine_sectors_per_fat_for_multiple_sizes(4096, FatType::Fat12, 1, 2, 512);
1004
1005        test_determine_sectors_per_fat_for_multiple_sizes(512, FatType::Fat16, 1, 2, 512);
1006        test_determine_sectors_per_fat_for_multiple_sizes(512, FatType::Fat16, 1, 1, 512);
1007        test_determine_sectors_per_fat_for_multiple_sizes(512, FatType::Fat16, 1, 2, 8192);
1008        test_determine_sectors_per_fat_for_multiple_sizes(4096, FatType::Fat16, 1, 2, 512);
1009
1010        test_determine_sectors_per_fat_for_multiple_sizes(512, FatType::Fat32, 32, 2, 0);
1011        test_determine_sectors_per_fat_for_multiple_sizes(512, FatType::Fat32, 32, 1, 0);
1012        test_determine_sectors_per_fat_for_multiple_sizes(4096, FatType::Fat32, 32, 2, 0);
1013    }
1014
1015    #[test]
1016    fn test_determine_fs_geometry() {
1017        init();
1018
1019        // Regression test for a specific case.
1020        assert!(determine_fs_geometry(
1021            None, /*total_sectors=*/ 8227, /*bytes_per_sector=*/ 512, None,
1022            /*root_dir_entries=*/ 512, /*fats=*/ 2
1023        )
1024        .is_ok());
1025    }
1026
1027    #[test]
1028    fn test_format_boot_sector() {
1029        init();
1030
1031        let bytes_per_sector = 512u16;
1032        // test all partition sizes from 1MB to 2TB (u32::MAX sectors is 2TB - 1 for 512 byte sectors)
1033        let mut total_sectors_vec = Vec::new();
1034        let mut size = 1 * MB;
1035        while size < 2048 * GB {
1036            total_sectors_vec.push((size / u64::from(bytes_per_sector)) as u32);
1037            size = size + size / 7;
1038        }
1039        total_sectors_vec.push(u32::MAX);
1040        for total_sectors in total_sectors_vec {
1041            let (boot, _) =
1042                format_boot_sector(&FormatVolumeOptions::new(), total_sectors, bytes_per_sector)
1043                    .expect("format_boot_sector");
1044            boot.validate().expect("validate");
1045        }
1046    }
1047}