aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorbbuerge <b.buerge@pm.me>2026-10-29 08:09:46 +0000
committerbbuerge <b.buerge@pm.me>2026-10-29 08:09:46 +0000
commitc0419c99800b0fb1017c2d750b60137838ac759d (patch)
tree0fd8a0c819202599fd10b4cbdb96de8f1bea9cd2
parent8b5b8875a78dfd18830a558db327100acf10a32b (diff)
downloadkernel-c0419c99800b0fb1017c2d750b60137838ac759d.tar.xz
kernel-c0419c99800b0fb1017c2d750b60137838ac759d.zip
kernel/filesystem: added function to detect fat-type
-rw-r--r--kernel/kernel/filesystems/fat32/filesystem.cpp44
-rw-r--r--kernel/kernel/filesystems/fat32/filesystem.hpp3
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)