// FAT private implementation model shared by the driver's translation units. #pragma once #include #include "fat.h" #include "fat_disk.h" #define FAT_PATH_CACHE_SLOTS 64u #define FAT_PATH_CACHE_MAX 512u #define FAT_CHAIN_CACHE_SLOTS 16u #define FAT_WRITE_RUN_MAX_SECTORS 128u #define FAT_READ_RUN_MAX_SECTORS 512u #define FAT_MAX_LFN 256 #ifndef FAT_DEBUG #define FAT_DEBUG 0 #endif #define FatDebugPrint(...) do { if (FAT_DEBUG) DbgPrint(__VA_ARGS__); } while (0) typedef struct FAT_PATH_CACHE_ENTRY { bool Valid; uint64_t Generation; uint32_t Hash; size_t PathLength; char Path[FAT_PATH_CACHE_MAX]; uint32_t Cluster; uint32_t Size; uint8_t Attr; uint64_t DirentLba; uint32_t DirentOffset; } FAT_PATH_CACHE_ENTRY; typedef struct FAT_CHAIN_CACHE_ENTRY { bool Valid; uint32_t LogicalStart; uint32_t PhysicalStart; uint32_t Length; uint32_t NextCluster; } FAT_CHAIN_CACHE_ENTRY; struct FAT_VOL_S { FAT_VARIANT Variant; uint8_t DriveIndex; uint64_t PartitionLba; uint64_t PartitionSize; uint32_t BytesPerSector; uint32_t SectorsPerCluster; uint32_t BytesPerCluster; uint32_t ReservedSectors; uint32_t NumFats; uint32_t FatSize; uint32_t RootCluster; uint32_t RootEntryCount; uint32_t RootDirSectors; uint64_t RootDirStart; uint64_t DataStart; uint32_t TotalClusters; uint32_t NextFreeHint; SPINLOCK PathCacheLock; uint64_t PathCacheGeneration; IO_FILESYSTEM_STATS Stats; FAT_PATH_CACHE_ENTRY PathCache[FAT_PATH_CACHE_SLOTS]; IO_VOLUME* Volume; LIST_ENTRY MountLink; }; typedef struct FAT_FILE { uint32_t StartCluster; uint32_t FileSize; FAT_VOL* Vol; uint64_t DirentLba; uint32_t DirentOffset; SPINLOCK ChainCacheLock; uint32_t ChainCacheClock; FAT_CHAIN_CACHE_ENTRY ChainCache[FAT_CHAIN_CACHE_SLOTS]; } FAT_FILE; typedef struct FAT_ENCODED_TIME { uint16_t Date; uint16_t Time; uint8_t CreateTimeTenth; } FAT_ENCODED_TIME; typedef struct FAT_DIRENT_UPDATE { uint32_t Flags; uint32_t Size; uint32_t FirstCluster; FAT_ENCODED_TIME Timestamp; } FAT_DIRENT_UPDATE; #define FAT_DIRENT_UPDATE_SIZE 0x00000001u #define FAT_DIRENT_UPDATE_FIRST_CLUSTER 0x00000002u #define FAT_DIRENT_UPDATE_CREATE_TIME 0x00000004u #define FAT_DIRENT_UPDATE_WRITE_TIME 0x00000008u #define FAT_DIRENT_UPDATE_ACCESS_DATE 0x00000010u KSTATUS FatReadSectors(FAT_VOL* volume, uint64_t lba, uint32_t count, void* buffer); KSTATUS FatWriteSectors(FAT_VOL* volume, uint64_t lba, uint32_t count, const void* buffer); const char* FatVariantName(FAT_VARIANT variant); uint32_t FatEocMark(FAT_VOL* volume); bool FatIsDataCluster(FAT_VOL* volume, uint32_t cluster); uint32_t FatDirentFirstCluster(FAT_VOL* volume, const DIRENT* dirent); void FatSetDirentFirstCluster(FAT_VOL* volume, DIRENT* dirent, uint32_t cluster); bool FatIsFixedRoot(FAT_VOL* volume, uint32_t dirCluster); bool FatDirectoryFirstSegment(FAT_VOL* volume, uint32_t dirCluster, uint32_t* cursorOut, uint64_t* lbaOut, uint32_t* sectorsOut); bool FatDirectoryNextSegment(FAT_VOL* volume, uint32_t dirCluster, uint32_t* cursorInOut, uint64_t* lbaOut, uint32_t* sectorsOut); uint64_t FatClusterToLba(FAT_VOL* volume, uint32_t cluster); uint32_t FatEntry(FAT_VOL* volume, uint32_t cluster); KSTATUS FatWriteEntry(FAT_VOL* volume, uint32_t cluster, uint32_t value); void FatFlushCache(FAT_VOL* volume); uint32_t FatAllocClusterEx(FAT_VOL* volume, bool zeroCluster); uint32_t FatAllocCluster(FAT_VOL* volume); uint32_t FatAppendClusterEx(FAT_VOL* volume, uint32_t lastCluster, bool zeroCluster); uint32_t FatAppendCluster(FAT_VOL* volume, uint32_t lastCluster); uint32_t FatGetChainEnd(FAT_VOL* volume, uint32_t start, uint32_t* countOut); void FatFreeClusterChain(FAT_VOL* volume, uint32_t start); void FatQueryEncodedTime(FAT_ENCODED_TIME* out); void FatDecodeDateTime(uint16_t date, uint16_t time, uint8_t createTenth, SYS_SYSTEM_TIME* out); void FatDecodeAccessDate(uint16_t date, SYS_SYSTEM_TIME* out); KSTATUS FatDirentUpdateMetadata(FAT_VOL* volume, uint64_t lba, uint32_t offset, const FAT_DIRENT_UPDATE* update); KSTATUS FatDirentUpdateSize(FAT_VOL* volume, uint64_t lba, uint32_t offset, uint32_t size); KSTATUS FatDirentUpdateFirstCluster(FAT_VOL* volume, uint64_t lba, uint32_t offset, uint32_t cluster); void FatLfnAppend(char* lfn, const LFN_ENTRY* entry); void FatPathCacheInvalidate(FAT_VOL* volume); void FatStatsAddReadRun(FAT_VOL* volume, uint32_t sectors, uint32_t merges); void FatFileInitChainCache(FAT_FILE* file); void FatFileInvalidateChainCache(FAT_FILE* file); uint32_t FatResolveFileCluster(FAT_FILE* file, uint32_t logicalIndex); bool FatBuildReadRun(FAT_FILE* file, uint32_t logicalIndex, uint32_t startCluster, uint32_t maxSectors, uint32_t* runSectorsOut, uint32_t* nextClusterOut); KSTATUS FatLookupPathV(FAT_VOL* volume, SYS_STRING_VIEW path, uint32_t* clusterOut, uint32_t* sizeOut, uint8_t* attrOut, uint64_t* direntLbaOut, uint32_t* direntOffsetOut); KSTATUS FatTraverseV(FAT_VOL* volume, SYS_STRING_VIEW path, uint32_t* clusterOut, uint32_t* sizeOut); KSTATUS FatResolveParentForMutation(FAT_VOL* volume, SYS_STRING_VIEW path, uint32_t* parentClusterOut, SYS_STRING_VIEW* nameOut); KSTATUS FatCreateDirent(FAT_VOL* volume, SYS_STRING_VIEW path, uint8_t attr, uint32_t firstCluster, uint32_t size, uint64_t* direntLbaOut, uint32_t* direntOffsetOut); KSTATUS FatInitializeDirectoryCluster(FAT_VOL* volume, uint32_t dirCluster, uint32_t parentCluster); KSTATUS FatDirectoryIsEmpty(FAT_VOL* volume, uint32_t dirCluster, bool* emptyOut); KSTATUS FatDeleteDirentRunV(FAT_VOL* volume, uint32_t parentCluster, SYS_STRING_VIEW name); void FatCacheInvalidate(void); void FatCacheInvalidateVolume(FAT_VOL* volume);