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 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()?; 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()?; 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 if bpb.ext_sig != 0x29 {
95 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)?; 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)?; 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 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 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 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 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 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 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 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 (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 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 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 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 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 let reserved_sectors: u16 = if fat_type == FatType::Fat32 { 8 } else { 1 };
558
559 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 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 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 let drive_num =
682 options.drive_num.unwrap_or_else(|| if fat_type == FatType::Fat12 { 0 } else { 0x80 });
683
684 let reserved_0 = [0u8; 12];
686
687 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 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 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 sectors_per_fat_32: if is_fat32 { sectors_per_fat } else { 0 },
727 extended_flags: 0, 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 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 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.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 if fat_type != FatType::Fat32 {
777 let boot_code_offset: u8 = 0x36 + 8;
779 boot.bootjmp[1] = boot_code_offset - 2;
780 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 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 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 assert!(determine_fs_geometry(
1021 None, 8227, 512, None,
1022 512, 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 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}