1use crate::{BlockCount, BlockIdx, ClusterId};
2use byteorder::{ByteOrder, LittleEndian};
34/// Indentifies the supported types of FAT format
5#[cfg_attr(feature = "defmt-log", derive(defmt::Format))]
6#[derive(Debug, Clone, Eq, PartialEq)]
7pub enum FatSpecificInfo {
8/// Fat16 Format
9Fat16(Fat16Info),
10/// Fat32 Format
11Fat32(Fat32Info),
12}
1314/// FAT32 specific data
15#[cfg_attr(feature = "defmt-log", derive(defmt::Format))]
16#[derive(Debug, Clone, Eq, PartialEq)]
17pub struct Fat32Info {
18/// The root directory does not have a reserved area in FAT32. This is the
19 /// cluster it starts in (nominally 2).
20pub(crate) first_root_dir_cluster: ClusterId,
21/// Block idx of the info sector
22pub(crate) info_location: BlockIdx,
23}
2425/// FAT16 specific data
26#[cfg_attr(feature = "defmt-log", derive(defmt::Format))]
27#[derive(Debug, Clone, Eq, PartialEq)]
28pub struct Fat16Info {
29/// The block the root directory starts in. Relative to start of partition
30 /// (so add `self.lba_offset` before passing to volume manager)
31pub(crate) first_root_dir_block: BlockCount,
32/// Number of entries in root directory (it's reserved and not in the FAT)
33pub(crate) root_entries_count: u16,
34}
3536/// File System Information structure is only present on FAT32 partitions. It
37/// may contain a valid number of free clusters and the number of the next
38/// free cluster. The information contained in the structure must be
39/// considered as advisory only. File system driver implementations are not
40/// required to ensure that information within the structure is kept
41/// consistent.
42pub struct InfoSector<'a> {
43 data: &'a [u8; 512],
44}
4546impl<'a> InfoSector<'a> {
47const LEAD_SIG: u32 = 0x4161_5252;
48const STRUC_SIG: u32 = 0x6141_7272;
49const TRAIL_SIG: u32 = 0xAA55_0000;
5051/// Try and create a new Info Sector from a block.
52pub fn create_from_bytes(data: &[u8; 512]) -> Result<InfoSector, &'static str> {
53let info = InfoSector { data };
54if info.lead_sig() != Self::LEAD_SIG {
55return Err("Bad lead signature on InfoSector");
56 }
57if info.struc_sig() != Self::STRUC_SIG {
58return Err("Bad struc signature on InfoSector");
59 }
60if info.trail_sig() != Self::TRAIL_SIG {
61return Err("Bad trail signature on InfoSector");
62 }
63Ok(info)
64 }
6566define_field!(lead_sig, u32, 0);
67define_field!(struc_sig, u32, 484);
68define_field!(free_count, u32, 488);
69define_field!(next_free, u32, 492);
70define_field!(trail_sig, u32, 508);
7172/// Return how many free clusters are left in this volume, if known.
73pub fn free_clusters_count(&self) -> Option<u32> {
74match self.free_count() {
750xFFFF_FFFF => None,
76 n => Some(n),
77 }
78 }
7980/// Return the number of the next free cluster, if known.
81pub fn next_free_cluster(&self) -> Option<ClusterId> {
82match self.next_free() {
83// 0 and 1 are reserved clusters
840xFFFF_FFFF | 0 | 1 => None,
85 n => Some(ClusterId(n)),
86 }
87 }
88}