diff options
| -rw-r--r-- | kernel/kernel/filesystems/fat32/filesystem.cpp | 44 | ||||
| -rw-r--r-- | kernel/kernel/filesystems/fat32/filesystem.hpp | 3 |
2 files changed, 47 insertions, 0 deletions
diff --git a/kernel/kernel/filesystems/fat32/filesystem.cpp b/kernel/kernel/filesystems/fat32/filesystem.cpp index 743968fa..22e5c0ef 100644 --- a/kernel/kernel/filesystems/fat32/filesystem.cpp +++ b/kernel/kernel/filesystems/fat32/filesystem.cpp @@ -73,6 +73,46 @@ namespace kernel::filesystems::fat32 kstd::println("[OS:FAT32] boot_signature: {:#06X}", boot_sector.boot_signature); } + enum struct fat_type + { + fat12, + fat16, + fat32 + }; + + //! Derive the fat-type with the variables in the boot-sector. The differentiation is made by number of clusters in + //! the data-region following microsoft specification 1.03. This function doesn't validate the provided boot_sector and + //! necessitates that it's valid. + //! + //! @param bs populated boot_sector + //! @return returns fat12, fat16 or fat32 + auto get_fat_type(boot_sector const & bs) -> fat_type + { + // is zero for FAT32 because root directory is stored in data-sector + auto const root_dir_size_fat16 = std::uint64_t{bs.root_entry_count} * 32; // todo maybe constant + + // ceiling divide + auto const root_dir_sectors_fat16 = (root_dir_size_fat16 + bs.bytes_per_sector - 1) / bs.bytes_per_sector; + + auto const fat_sectors = bs.fat_size_16 != 0 ? std::uint64_t{bs.fat_size_16} : bs.fat_size_32; + auto const total_sectors = bs.total_sectors_16 != 0 ? std::uint64_t{bs.total_sectors_16} : bs.total_sectors_32; + + auto const fat_region_sectors = bs.number_of_fats * fat_sectors; + + auto const data_region_sectors = + total_sectors - (bs.reserved_sector_count + fat_region_sectors + root_dir_sectors_fat16); + + auto const data_region_clusters = data_region_sectors / bs.sectors_per_cluster; + + if (data_region_clusters <= constants::max_clusters_fat12) + return fat_type::fat12; + + if (data_region_clusters <= constants::max_clusters_fat16) + return fat_type::fat16; + + return fat_type::fat32; + } + //! Read the boot sector from a backing inode and check its signature. //! //! @param backing_inode The inode to read the boot sector from. @@ -92,6 +132,10 @@ namespace kernel::filesystems::fat32 return kstd::failure(errc::invalid_boot_signature); } + if (auto fat_type = get_fat_type(boot_sector); fat_type != fat_type::fat32) { + return kstd::failure(errc::invalid_boot_sector); // todo custom error + } + return boot_sector; } diff --git a/kernel/kernel/filesystems/fat32/filesystem.hpp b/kernel/kernel/filesystems/fat32/filesystem.hpp index a392d0fd..8a173e54 100644 --- a/kernel/kernel/filesystems/fat32/filesystem.hpp +++ b/kernel/kernel/filesystems/fat32/filesystem.hpp @@ -26,6 +26,9 @@ namespace kernel::filesystems::fat32 constexpr std::uint16_t inline boot_signature = 0xAA55; constexpr std::uint16_t inline min_bytes_per_sector = 512; constexpr std::uint16_t inline max_bytes_per_sector = 4096; + + constexpr std::uint16_t inline max_clusters_fat12 = 4'084; + constexpr std::uint16_t inline max_clusters_fat16 = 65'524; } // namespace constants //! The File Allocation Table 32 Filesystem (fat32) |
