diff options
Diffstat (limited to 'kernel')
| -rw-r--r-- | kernel/CMakeLists.txt | 1 | ||||
| -rw-r--r-- | kernel/kernel/filesystems/fat32/driver_state.hpp | 15 | ||||
| -rw-r--r-- | kernel/kernel/filesystems/fat32/error.cpp | 9 | ||||
| -rw-r--r-- | kernel/kernel/filesystems/fat32/error.hpp | 5 | ||||
| -rw-r--r-- | kernel/kernel/filesystems/fat32/file_allocation_table.cpp | 113 | ||||
| -rw-r--r-- | kernel/kernel/filesystems/fat32/file_allocation_table.hpp | 79 | ||||
| -rw-r--r-- | kernel/kernel/filesystems/fat32/filesystem.cpp | 115 | ||||
| -rw-r--r-- | kernel/kernel/filesystems/fat32/filesystem.hpp | 2 | ||||
| -rw-r--r-- | kernel/kernel/filesystems/fat32/inode.cpp | 13 | ||||
| -rw-r--r-- | kernel/kernel/filesystems/fat32/inode.hpp | 22 | ||||
| -rw-r--r-- | kernel/kernel/main.cpp | 63 |
11 files changed, 415 insertions, 22 deletions
diff --git a/kernel/CMakeLists.txt b/kernel/CMakeLists.txt index aacb5d97..4b2d96da 100644 --- a/kernel/CMakeLists.txt +++ b/kernel/CMakeLists.txt @@ -87,6 +87,7 @@ target_sources("kernel_lib" PRIVATE # fat32 Filesystem "kernel/filesystems/fat32/error.cpp" + "kernel/filesystems/fat32/file_allocation_table.cpp" "kernel/filesystems/fat32/filesystem.cpp" "kernel/filesystems/fat32/inode.cpp" "kernel/filesystems/fat32/module.cpp" diff --git a/kernel/kernel/filesystems/fat32/driver_state.hpp b/kernel/kernel/filesystems/fat32/driver_state.hpp index 55b90724..09e2fed2 100644 --- a/kernel/kernel/filesystems/fat32/driver_state.hpp +++ b/kernel/kernel/filesystems/fat32/driver_state.hpp @@ -8,7 +8,9 @@ #include <kapi/tracked_mutex.hpp> #include <kstd/memory.hpp> -#include <kstd/vector.hpp> +#include <kstd/units.hpp> + +#include <cstdint> namespace kernel::filesystems::fat32 { @@ -16,8 +18,17 @@ namespace kernel::filesystems::fat32 struct driver_state : vfs::driver_state { struct boot_sector boot_sector{}; + kstd::shared_ptr<kernel::vfs::inode> backing_inode{}; + + kstd::bytes sector_size{}; + kstd::bytes cluster_size{}; + std::uint32_t fat_start_sector{}; + std::uint32_t data_start_sector{}; + std::uint32_t cluster_count{}; + + mutable kapi::tracked_mutex lock{}; }; } // namespace kernel::filesystems::fat32 -#endif
\ No newline at end of file +#endif diff --git a/kernel/kernel/filesystems/fat32/error.cpp b/kernel/kernel/filesystems/fat32/error.cpp index 4a18eb9e..e8e72fb7 100644 --- a/kernel/kernel/filesystems/fat32/error.cpp +++ b/kernel/kernel/filesystems/fat32/error.cpp @@ -24,6 +24,12 @@ namespace kernel::filesystems::fat32 { case errc::invalid_boot_signature: return "invalid boot signature"; + case errc::invalid_boot_sector: + return "invalid boot sector"; + case errc::invalid_cluster: + return "invalid cluster"; + case errc::corrupted_cluster_chain: + return "corrupted cluster chain"; default: return "unknown fat32 error"; }; @@ -35,6 +41,9 @@ namespace kernel::filesystems::fat32 switch (static_cast<errc>(code)) { case errc::invalid_boot_signature: + case errc::invalid_boot_sector: + case errc::invalid_cluster: + case errc::corrupted_cluster_chain: if (condition.category() == kernel::vfs::category()) { return condition.value() == static_cast<int>(kernel::vfs::errc::invalid_filesystem); diff --git a/kernel/kernel/filesystems/fat32/error.hpp b/kernel/kernel/filesystems/fat32/error.hpp index 6955be3f..0b06c503 100644 --- a/kernel/kernel/filesystems/fat32/error.hpp +++ b/kernel/kernel/filesystems/fat32/error.hpp @@ -11,7 +11,10 @@ namespace kernel::filesystems::fat32 { enum struct errc : int { - invalid_boot_signature = 1 + invalid_boot_signature = 1, + invalid_boot_sector, + invalid_cluster, + corrupted_cluster_chain, }; [[nodiscard]] auto category() noexcept -> kstd::error_category const &; diff --git a/kernel/kernel/filesystems/fat32/file_allocation_table.cpp b/kernel/kernel/filesystems/fat32/file_allocation_table.cpp new file mode 100644 index 00000000..02410ac8 --- /dev/null +++ b/kernel/kernel/filesystems/fat32/file_allocation_table.cpp @@ -0,0 +1,113 @@ +#include <kernel/filesystems/fat32/file_allocation_table.hpp> + +#include <kernel/filesystems/fat32/driver_state.hpp> +#include <kernel/filesystems/fat32/error.hpp> + +#include <kstd/result.hpp> +#include <kstd/span.hpp> +#include <kstd/units.hpp> +#include <kstd/vector.hpp> + +#include <cstdint> +#include <optional> + +namespace kernel::filesystems::fat32 +{ + auto is_valid_cluster(std::uint32_t cluster, driver_state const & state) -> bool + { + return cluster >= constants::first_data_cluster && cluster - constants::first_data_cluster < state.cluster_count; + } + + auto cluster_offset(std::uint32_t cluster, driver_state const & state) -> kstd::bytes + { + auto const cluster_index = cluster - constants::first_data_cluster; + return state.data_start_sector * state.sector_size + cluster_index * state.cluster_size; + } + + auto read_fat_entry(std::uint32_t cluster, driver_state const & state) -> kstd::result<fat_entry> + { + if (!is_valid_cluster(cluster, state)) + { + return kstd::failure(errc::invalid_cluster); + } + + auto const entry_offset = state.fat_start_sector * state.sector_size + cluster * constants::fat_entry_size; + auto raw_entry = std::uint32_t{}; + if (auto read_result = state.backing_inode->read(kstd::raw_bytes(raw_entry), entry_offset); !read_result) + { + return kstd::failure(read_result.error()); + } + + auto const value = raw_entry & constants::cluster_mask; + + if (value == constants::free_cluster) + { + return fat_entry{fat_entry_type::free, value}; + } + + if (value == constants::reserved_cluster) + { + return fat_entry{fat_entry_type::reserved, value}; + } + + if (value == constants::bad_cluster) + { + return fat_entry{fat_entry_type::bad_cluster, value}; + } + + if (value >= constants::end_of_chain) + { + return fat_entry{fat_entry_type::end_of_chain, value}; + } + + return fat_entry{fat_entry_type::allocated, value}; + } + + auto next_cluster(std::uint32_t cluster, driver_state const & state) -> kstd::result<std::optional<std::uint32_t>> + { + auto const entry = read_fat_entry(cluster, state); + if (!entry) + { + return kstd::failure(entry.error()); + } + + if (entry->type == fat_entry_type::end_of_chain) + { + return std::nullopt; + } + + if (entry->type != fat_entry_type::allocated || !is_valid_cluster(entry->value, state)) + { + return kstd::failure(errc::corrupted_cluster_chain); + } + + return entry->value; + } + + auto cluster_chain(std::uint32_t first_cluster, driver_state const & state) + -> kstd::result<kstd::vector<std::uint32_t>> + { + auto chain = kstd::vector<std::uint32_t>{}; + auto current = std::optional{first_cluster}; + + while (current) + { + if (chain.size() >= state.cluster_count) + { + return kstd::failure(errc::corrupted_cluster_chain); + } + + chain.push_back(*current); + + auto const next = next_cluster(*current, state); + if (!next) + { + return kstd::failure(next.error()); + } + + current = *next; + } + + return chain; + } +} // namespace kernel::filesystems::fat32 diff --git a/kernel/kernel/filesystems/fat32/file_allocation_table.hpp b/kernel/kernel/filesystems/fat32/file_allocation_table.hpp new file mode 100644 index 00000000..df5c723d --- /dev/null +++ b/kernel/kernel/filesystems/fat32/file_allocation_table.hpp @@ -0,0 +1,79 @@ +#ifndef TEACHOS_KERNEL_FILESYSTEMS_FAT32_FILE_ALLOCATION_TABLE_HPP +#define TEACHOS_KERNEL_FILESYSTEMS_FAT32_FILE_ALLOCATION_TABLE_HPP + +#include <kernel/filesystems/fat32/driver_state.hpp> + +#include <kstd/result.hpp> +#include <kstd/units.hpp> +#include <kstd/vector.hpp> + +#include <cstdint> +#include <optional> + +namespace kernel::filesystems::fat32 +{ + namespace constants + { + constexpr std::uint32_t inline first_data_cluster = 2; + constexpr std::uint32_t inline cluster_mask = 0x0FFF'FFFF; + constexpr std::uint32_t inline free_cluster = 0x0000'0000; + constexpr std::uint32_t inline reserved_cluster = 0x0000'0001; + constexpr std::uint32_t inline bad_cluster = 0x0FFF'FFF7; + constexpr std::uint32_t inline end_of_chain = 0x0FFF'FFF8; + constexpr kstd::bytes inline fat_entry_size = kstd::bytes{sizeof(std::uint32_t)}; + } // namespace constants + + enum struct fat_entry_type : std::uint8_t + { + free, + reserved, + allocated, + bad_cluster, + end_of_chain, + }; + + struct fat_entry + { + fat_entry_type type; + std::uint32_t value; + }; + + //! Check if a cluster number refers to a cluster inside the data region. + //! + //! @param cluster The cluster number to check. + //! @param state The driver state to operate on. + //! @return @c true iff. the cluster lies within the data region, @c false otherwise. + [[nodiscard]] auto is_valid_cluster(std::uint32_t cluster, driver_state const & state) -> bool; + + //! Get the offset of a cluster's data on the backing inode. + //! + //! @param cluster The cluster number, which must be valid. + //! @param state The driver state to operate on. + //! @return The byte offset of the first byte of the cluster. + [[nodiscard]] auto cluster_offset(std::uint32_t cluster, driver_state const & state) -> kstd::bytes; + + //! Read and classify the file allocation table entry of a cluster. + //! + //! @param cluster The cluster whose entry to read. + //! @param state The driver state to operate on. + //! @return The classified entry on success, an error otherwise. + [[nodiscard]] auto read_fat_entry(std::uint32_t cluster, driver_state const & state) -> kstd::result<fat_entry>; + + //! Look up the successor of a cluster in the file allocation table. + //! + //! @param cluster The cluster whose successor to look up. + //! @param state The driver state to operate on. + //! @return The next cluster in the chain, @c std::nullopt if @p cluster is the last one, an error otherwise. + [[nodiscard]] auto next_cluster(std::uint32_t cluster, driver_state const & state) + -> kstd::result<std::optional<std::uint32_t>>; + + //! Collect all clusters of the chain starting at a given cluster. + //! + //! @param first_cluster The first cluster of the chain. + //! @param state The driver state to operate on. + //! @return The clusters of the chain in order on success, an error otherwise. + [[nodiscard]] auto cluster_chain(std::uint32_t first_cluster, driver_state const & state) + -> kstd::result<kstd::vector<std::uint32_t>>; +} // namespace kernel::filesystems::fat32 + +#endif diff --git a/kernel/kernel/filesystems/fat32/filesystem.cpp b/kernel/kernel/filesystems/fat32/filesystem.cpp index 30f1b286..743968fa 100644 --- a/kernel/kernel/filesystems/fat32/filesystem.cpp +++ b/kernel/kernel/filesystems/fat32/filesystem.cpp @@ -1,7 +1,9 @@ #include <kernel/filesystems/fat32/filesystem.hpp> #include <kernel/filesystems/fat32/boot_sector.hpp> +#include <kernel/filesystems/fat32/driver_state.hpp> #include <kernel/filesystems/fat32/error.hpp> +#include <kernel/filesystems/fat32/file_allocation_table.hpp> #include <kernel/filesystems/fat32/inode.hpp> #include <kernel/vfs/error.hpp> #include <kernel/vfs/filesystem.hpp> @@ -16,6 +18,7 @@ #include <kstd/units.hpp> #include <array> +#include <bit> #include <cstddef> #include <cstdint> #include <optional> @@ -38,9 +41,7 @@ namespace kernel::filesystems::fat32 return {array.data(), array.size()}; } - //! Print all fields of a boot sector. - //! - //! @param boot_sector The boot sector to print. + // TODO: Remove later, just for demo auto print_boot_sector(boot_sector const & boot_sector) -> void { kstd::println("[OS:FAT32] jump_boot: {:#04X} {:#04X} {:#04X}", boot_sector.jump_boot[0], boot_sector.jump_boot[1], @@ -71,33 +72,113 @@ namespace kernel::filesystems::fat32 kstd::println("[OS:FAT32] filesystem_type: '{}'", to_string_view(boot_sector.filesystem_type)); kstd::println("[OS:FAT32] boot_signature: {:#06X}", boot_sector.boot_signature); } - } // namespace - auto filesystem::probe(inode_ptr const & inode) const -> kstd::result<std::uint32_t> - { - auto boot_sector = fat32::boot_sector{}; - auto const bytes = kstd::raw_bytes(boot_sector); - auto const read_result = inode->read(bytes, constants::boot_sector_offset); + //! Read the boot sector from a backing inode and check its signature. + //! + //! @param backing_inode The inode to read the boot sector from. + //! @return The boot sector on success, an error otherwise. + [[nodiscard]] auto read_boot_sector(kernel::vfs::filesystem::inode_ptr const & backing_inode) + -> kstd::result<boot_sector> + { + auto boot_sector = fat32::boot_sector{}; + if (auto read_result = backing_inode->read(kstd::raw_bytes(boot_sector), constants::boot_sector_offset); + !read_result) + { + return kstd::failure(read_result.error()); + } + + if (boot_sector.boot_signature != constants::boot_signature) + { + return kstd::failure(errc::invalid_boot_signature); + } + + return boot_sector; + } - if (!read_result) + //! Derive the location of the file allocation table and the data region from the boot sector. + //! + //! @param state The driver state whose boot sector to use and whose layout fields to fill. + //! @return Nothing on success, an error if the boot sector describes an impossible layout. + [[nodiscard]] auto compute_layout(driver_state & state) -> kstd::result<void> { - return kstd::failure(read_result.error()); + auto const & boot_sector = state.boot_sector; + + auto const bytes_per_sector = boot_sector.bytes_per_sector; + auto const sectors_per_cluster = boot_sector.sectors_per_cluster; + auto const total_sectors = boot_sector.total_sectors_32 != 0 ? std::uint64_t{boot_sector.total_sectors_32} + : std::uint64_t{boot_sector.total_sectors_16}; + auto const fat_sectors = std::uint64_t{boot_sector.number_of_fats} * boot_sector.fat_size_32; + auto const data_start_sector = boot_sector.reserved_sector_count + fat_sectors; + + if (bytes_per_sector < constants::min_bytes_per_sector || bytes_per_sector > constants::max_bytes_per_sector || + !std::has_single_bit(bytes_per_sector) || !std::has_single_bit(sectors_per_cluster) || + boot_sector.reserved_sector_count == 0 || fat_sectors == 0 || data_start_sector >= total_sectors) + { + return kstd::failure(errc::invalid_boot_sector); + } + + auto const cluster_count = (total_sectors - data_start_sector) / sectors_per_cluster; + auto const fat_capacity = + std::uint64_t{boot_sector.fat_size_32} * bytes_per_sector / constants::fat_entry_size.value; + + if (cluster_count == 0 || cluster_count + constants::first_data_cluster > fat_capacity) + { + return kstd::failure(errc::invalid_boot_sector); + } + + state.sector_size = kstd::bytes{bytes_per_sector}; + state.cluster_size = state.sector_size * sectors_per_cluster; + state.fat_start_sector = boot_sector.reserved_sector_count; + state.data_start_sector = static_cast<std::uint32_t>(data_start_sector); + state.cluster_count = static_cast<std::uint32_t>(cluster_count); + + return {}; } + } // namespace - if (boot_sector.boot_signature != constants::boot_signature) + auto filesystem::probe(inode_ptr const & inode) const -> kstd::result<std::uint32_t> + { + auto const boot_sector = read_boot_sector(inode); + if (!boot_sector) { - return kstd::failure(errc::invalid_boot_signature); + return kstd::failure(boot_sector.error()); } - print_boot_sector(boot_sector); + print_boot_sector(*boot_sector); return 0; } - auto filesystem::mount(inode_ptr const &) -> kstd::result<mount_result> + auto filesystem::mount(inode_ptr const & backing_inode) -> kstd::result<mount_result> { - auto root = kstd::make_shared<inode>(); - return mount_result{root, nullptr}; + if (!backing_inode) + { + return kstd::failure(vfs::errc::invalid_inode); + } + + auto const driver_state = kstd::make_shared<fat32::driver_state>(); + driver_state->backing_inode = backing_inode; + + auto const boot_sector = read_boot_sector(backing_inode); + if (!boot_sector) + { + return kstd::failure(boot_sector.error()); + } + driver_state->boot_sector = *boot_sector; + + if (auto layout_result = compute_layout(*driver_state); !layout_result) + { + return kstd::failure(layout_result.error()); + } + + auto const root_cluster = std::uint32_t{driver_state->boot_sector.root_cluster}; + if (!is_valid_cluster(root_cluster, *driver_state)) + { + return kstd::failure(errc::invalid_cluster); + } + + auto root = kstd::make_shared<inode>(root_cluster, constants::attribute_directory); + return mount_result{root, driver_state}; } auto filesystem::lookup(inode_ptr const &, std::string_view, driver_data_ptr) const -> kstd::result<inode_ptr> diff --git a/kernel/kernel/filesystems/fat32/filesystem.hpp b/kernel/kernel/filesystems/fat32/filesystem.hpp index 54c8035c..a392d0fd 100644 --- a/kernel/kernel/filesystems/fat32/filesystem.hpp +++ b/kernel/kernel/filesystems/fat32/filesystem.hpp @@ -24,6 +24,8 @@ namespace kernel::filesystems::fat32 { constexpr kstd::bytes inline boot_sector_offset = kstd::bytes{0}; 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; } // namespace constants //! The File Allocation Table 32 Filesystem (fat32) diff --git a/kernel/kernel/filesystems/fat32/inode.cpp b/kernel/kernel/filesystems/fat32/inode.cpp index 993256df..20e9ae48 100644 --- a/kernel/kernel/filesystems/fat32/inode.cpp +++ b/kernel/kernel/filesystems/fat32/inode.cpp @@ -8,11 +8,17 @@ #include <kstd/units.hpp> #include <cstddef> +#include <cstdint> #include <span> #include <utility> namespace kernel::filesystems::fat32 { + inode::inode(std::uint32_t first_cluster, std::uint8_t attributes) + : m_first_cluster(first_cluster) + , m_attributes(attributes) + {} + auto inode::read(std::span<std::byte>, kstd::bytes) const -> kstd::result<kstd::bytes> { return kstd::bytes{}; @@ -25,7 +31,7 @@ namespace kernel::filesystems::fat32 auto inode::is_directory() const -> bool { - return true; + return (m_attributes & constants::attribute_directory) != 0; } auto inode::read_directory(kapi::filesystem::directory_cursor position, @@ -34,4 +40,9 @@ namespace kernel::filesystems::fat32 { return std::pair{0, position}; } + + auto inode::first_cluster() const -> std::uint32_t + { + return m_first_cluster; + } } // namespace kernel::filesystems::fat32 diff --git a/kernel/kernel/filesystems/fat32/inode.hpp b/kernel/kernel/filesystems/fat32/inode.hpp index 3f9ae37e..87485ffb 100644 --- a/kernel/kernel/filesystems/fat32/inode.hpp +++ b/kernel/kernel/filesystems/fat32/inode.hpp @@ -12,14 +12,25 @@ #include <kstd/vector.hpp> #include <cstddef> +#include <cstdint> #include <span> #include <utility> namespace kernel::filesystems::fat32 { - //! An inode in the fat32 filesystem. + namespace constants + { + constexpr std::uint8_t inline attribute_directory = 0x10; + } // namespace constants + struct inode : kernel::vfs::inode { + //! Create a fat32 inode. + //! + //! @param first_cluster The first cluster of the inode's data. + //! @param attributes The attributes of the directory entry describing the inode. + explicit inode(std::uint32_t first_cluster, std::uint8_t attributes); + [[nodiscard]] auto read(std::span<std::byte> buffer, kstd::bytes offset) const -> kstd::result<kstd::bytes> override; @@ -31,6 +42,15 @@ namespace kernel::filesystems::fat32 [[nodiscard]] auto read_directory(kapi::filesystem::directory_cursor position, std::span<kapi::filesystem::directory_entry> entries) const -> kstd::result<std::pair<std::size_t, kapi::filesystem::directory_cursor>> override; + + //! Get the first cluster of the inode's data. + //! + //! @return The first cluster number. + [[nodiscard]] auto first_cluster() const -> std::uint32_t; + + private: + std::uint32_t m_first_cluster{}; + std::uint8_t m_attributes{}; }; } // namespace kernel::filesystems::fat32 diff --git a/kernel/kernel/main.cpp b/kernel/kernel/main.cpp index 15952547..fb709688 100644 --- a/kernel/kernel/main.cpp +++ b/kernel/kernel/main.cpp @@ -1,6 +1,9 @@ #include <kernel/devices/init.hpp> #include <kernel/devices/storage.hpp> #include <kernel/drivers/init.hpp> +#include <kernel/filesystems/fat32/driver_state.hpp> +#include <kernel/filesystems/fat32/file_allocation_table.hpp> +#include <kernel/filesystems/fat32/inode.hpp> #include <kernel/memory.hpp> #include <kernel/vfs.hpp> @@ -14,12 +17,14 @@ #include <kapi/system.hpp> #include <kstd/format.hpp> +#include <kstd/memory.hpp> #include <kstd/print.hpp> #include <kstd/system_error.hpp> #include <kstd/units.hpp> #include <kstd/vector.hpp> #include <cstddef> +#include <cstdint> #include <ranges> #include <string_view> @@ -38,6 +43,64 @@ auto run_demo_fat32() -> void { kapi::system::panic("[OS:DEM] failed to mount /dev/ram3 on /entrance", result.error()); } + + auto entrance = kernel::vfs::vfs::get().open("/entrance"); + if (!entrance) + { + kapi::system::panic("[OS:DEM] failed to open /entrance", entrance.error()); + } + + auto const root = kstd::static_pointer_cast<kernel::filesystems::fat32::inode>((*entrance)->inode()); + auto const state = kstd::static_pointer_cast<kernel::filesystems::fat32::driver_state>(root->driver_state().lock()); + + kstd::println("[OS:DEM] FAT starts at sector {}, data region starts at sector {}, {} clusters of {} bytes", + state->fat_start_sector, state->data_start_sector, state->cluster_count, state->cluster_size); + + auto const root_chain = kernel::filesystems::fat32::cluster_chain(root->first_cluster(), *state); + if (!root_chain) + { + kapi::system::panic("[OS:DEM] failed to read the root directory cluster chain", root_chain.error()); + } + + kstd::println("[OS:DEM] root directory starts at cluster {} and spans {} cluster(s):", root->first_cluster(), + root_chain->size()); + for (auto const cluster : *root_chain) + { + kstd::println("[OS:DEM] cluster {} at byte offset {}", cluster, + kernel::filesystems::fat32::cluster_offset(cluster, *state)); + } + + constexpr auto demo_cluster_count = std::uint32_t{4}; + kstd::println("[OS:DEM] reading the FAT entries of the first {} data clusters:", demo_cluster_count); + for (auto cluster = kernel::filesystems::fat32::constants::first_data_cluster; + cluster < kernel::filesystems::fat32::constants::first_data_cluster + demo_cluster_count; ++cluster) + { + auto const entry = kernel::filesystems::fat32::read_fat_entry(cluster, *state); + if (!entry) + { + kstd::println("[OS:DEM] cluster {} -> {}", cluster, entry.error()); + continue; + } + + switch (entry->type) + { + case kernel::filesystems::fat32::fat_entry_type::free: + kstd::println("[OS:DEM] cluster {} -> free", cluster); + break; + case kernel::filesystems::fat32::fat_entry_type::reserved: + kstd::println("[OS:DEM] cluster {} -> reserved", cluster); + break; + case kernel::filesystems::fat32::fat_entry_type::allocated: + kstd::println("[OS:DEM] cluster {} -> next cluster {}", cluster, entry->value); + break; + case kernel::filesystems::fat32::fat_entry_type::bad_cluster: + kstd::println("[OS:DEM] cluster {} -> bad cluster", cluster); + break; + case kernel::filesystems::fat32::fat_entry_type::end_of_chain: + kstd::println("[OS:DEM] cluster {} -> end of chain ({:#010X})", cluster, entry->value); + break; + } + } } auto run_demo() -> void |
