embedded_fat/fat/
info.rs

1use crate::{BlockCount, BlockIdx, ClusterId};
2use byteorder::{ByteOrder, LittleEndian};
3
4/// 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
9    Fat16(Fat16Info),
10    /// Fat32 Format
11    Fat32(Fat32Info),
12}
13
14/// 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).
20    pub(crate) first_root_dir_cluster: ClusterId,
21    /// Block idx of the info sector
22    pub(crate) info_location: BlockIdx,
23}
24
25/// 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)
31    pub(crate) first_root_dir_block: BlockCount,
32    /// Number of entries in root directory (it's reserved and not in the FAT)
33    pub(crate) root_entries_count: u16,
34}
35
36/// 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}
45
46impl<'a> InfoSector<'a> {
47    const LEAD_SIG: u32 = 0x4161_5252;
48    const STRUC_SIG: u32 = 0x6141_7272;
49    const TRAIL_SIG: u32 = 0xAA55_0000;
50
51    /// Try and create a new Info Sector from a block.
52    pub fn create_from_bytes(data: &[u8; 512]) -> Result<InfoSector, &'static str> {
53        let info = InfoSector { data };
54        if info.lead_sig() != Self::LEAD_SIG {
55            return Err("Bad lead signature on InfoSector");
56        }
57        if info.struc_sig() != Self::STRUC_SIG {
58            return Err("Bad struc signature on InfoSector");
59        }
60        if info.trail_sig() != Self::TRAIL_SIG {
61            return Err("Bad trail signature on InfoSector");
62        }
63        Ok(info)
64    }
65
66    define_field!(lead_sig, u32, 0);
67    define_field!(struc_sig, u32, 484);
68    define_field!(free_count, u32, 488);
69    define_field!(next_free, u32, 492);
70    define_field!(trail_sig, u32, 508);
71
72    /// Return how many free clusters are left in this volume, if known.
73    pub fn free_clusters_count(&self) -> Option<u32> {
74        match self.free_count() {
75            0xFFFF_FFFF => None,
76            n => Some(n),
77        }
78    }
79
80    /// Return the number of the next free cluster, if known.
81    pub fn next_free_cluster(&self) -> Option<ClusterId> {
82        match self.next_free() {
83            // 0 and 1 are reserved clusters
84            0xFFFF_FFFF | 0 | 1 => None,
85            n => Some(ClusterId(n)),
86        }
87    }
88}