Unit FATFS
Return to Unit Reference
Contents
Description
Ultibo FAT12/16/32/exFAT Interface unit
Notes:
Based on information from numerous sources, primarily the document fatgen103.pdf from Microsoft. FAT Disk Blocks are based on reading a group of sectors into a block at once. The BlockNo of each block is therefore the FAT entry no of the first FAT in the block.
The use of IsEightDotThree and GenerateShortName(Ex) from the UltiboUtils unit should be replaced by internal routines optimised for maximum performance. All Block and Entry Offsets have been expanded to 32bit to avoid 16bit overflow on 64K clusters.
Constants
fat*
fatFAT12 = 0;
|
|
fatFAT16 = 1;
|
|
fatFAT32 = 2;
|
|
fatDotName = '.';
|
|
fatDotDotName = '..';
|
|
fatNameCount = 8;
|
|
fatExtCount = 3;
|
|
fatLabelMask = '*';
|
|
fatLabelCount = 11;
|
|
fatOemName = 'MSWIN4.1';
|
|
fatDefaultName = 'NO NAME';
|
|
fatFlagNone = $00;
|
|
fatFlagName = $08;
|
|
fatFlagExt = $10;
|
|
fatFlagBoth = $18;
|
|
lfnMaxName = 2048;
|
Buffer size for lfn handling |
lfnMaxAlias = 999999;
|
Max number of lfn aliases (ie ~999999) |
lfnMaxNameAlias = 4;
|
|
lfnMaxHashAlias = 999;
|
|
lfnMaxHashShift = 16;
|
|
fatMaxFileSize = 4294967295;
|
Max size in bytes of a File (4GB) |
fatMaxDirectorySize = 2097152;
|
Max size in bytes of a Directory (2MB = 65536 * 32) |
fatMinClusterSize = 512;
|
|
fatMaxClusterSize = 65536;
|
|
fat12MinClusters = 3;
|
|
fat16MinClusters = 4085;
|
Smallest Number of Clusters on a FAT16 volume, is FAT12 if less |
fat32MinClusters = 65525;
|
Smallest Number of Clusters on a FAT32 volume, is FAT16 if less |
fat12MinSectors = 6;
|
Number of Sectors at which we cannot create a FAT12 (Not possible due to 512 Root entries) |
fat12MinSectors = 798;
|
Number of Sectors at which we cannot create a FAT12 |
fat12MaxSectors = 32623;
|
Number of Sectors at which we insist on creating FAT16 |
fat16MinSectors = 8400;
|
Number of Sectors at which we cannot create a FAT16 |
fat16MaxSectors = 1048576;
|
Number of Sectors at which we insist on creating FAT32 |
fat32MinSectors = 66600;
|
Number of Sectors at which we cannot create a FAT32 |
fat32MaxSectors = $FFFFFFFF;
|
No limit on maximum size of a FAT32 |
Note: In FAT12 EOC will be >= $0FF0 due to Media ID on Floppy | |
fat12EndOfFile = $0FF0;
|
Some Code sets values from $0FF0 - $0FFF as EOF |
fat12EndOfFile = $0FF8;
|
Some Code sets values from $0FF8 - $0FFF as EOF |
fat12EndOfCluster = $0FFF;
|
EOF Mark, Check for >= $0FF0 - See Above |
fat12FreeCluster = $0000;
|
Available for Use |
fat12BadCluster = $0FF7;
|
Bad Cluster Mark - Do Not Use |
fat12MediaCluster = $0F00;
|
First Cluster - $0F00 + MediaID from BPB Usually $0FF8 |
fat12Reserved0 = $0FF0;
|
Reserved Cluster Nos - Do Not Use (Due to Media ID on Floppy) |
fat12Reserved1 = $0FF1;
|
|
fat12Reserved2 = $0FF2;
|
|
fat12Reserved3 = $0FF3;
|
|
fat12Reserved4 = $0FF4;
|
|
fat12Reserved5 = $0FF5;
|
|
fat12Reserved6 = $0FF6;
|
|
fat16EndOfFile = $FFF8;
|
Some Code sets values from $FFF8 - $FFFF as EOF |
fat16EndOfCluster = $FFFF;
|
EOF Mark, Check for >= $FFF8 - See Above |
fat16FreeCluster = $0000;
|
Available for Use |
fat16BadCluster = $FFF7;
|
Bad Cluster Mark - Do Not Use |
fat16MediaCluster = $FF00;
|
First Cluster - $FF00 + MediaID from BPB Usually $FFF8 |
fat32EndOfFile = $0FFFFFF8;
|
Some Code sets values from $0FFFFFF8 - $0FFFFFFF as EOF |
fat32EndOfCluster = $0FFFFFFF;
|
EOF Mark, Check for >= $0FFFFFF8 - See Above |
fat32FreeCluster = $00000000;
|
Available for Use |
fat32BadCluster = $0FFFFFF7;
|
Bad Cluster Mark - Do Not Use |
fat32MediaCluster = $0FFFFF00;
|
First Cluster - $0FFFFF00 + MediaID from BPB Usually $0FFFFFF8 |
fat16CleanShutdown = $8000;
|
Second Cluster - EndOfCluster + Bits |
fat16HardError = $4000;
|
Second Cluster - EndOfCluster + Bits |
fat32CleanShutdown = $08000000;
|
Second Cluster - EndOfCluster + Bits |
fat32HardError = $04000000;
|
Second Cluster - EndOfCluster + Bits |
fat32ReservedBits = $F0000000;
|
Bits 31-29 must be preserved on FAT32 |
fatBootSector = 0;
|
|
fatFreeCluster = 0;
|
|
fatStartCluster = 2;
|
Lowest allocatable cluster number |
fatUnevenCluster = $00000001;
|
|
fatUnknownCluster = $FFFFFFFF;
|
|
fatEntryFree = $E5;
|
|
fatEntryFreeAll = $00;
|
|
fatEntrySpecial = $05;
|
If real first char is $E5 |
fatEntryPadding = $20;
|
Padded with spaces (32) |
fatEntrySize = 32;
|
Size of a FAT Directory Entry (or LFNDirectoryEntry) |
lfnEntryMax= $3F;
|
Maximum count of an LFN entry |
lfnEntryLast = $40;
|
Marker for LFN last entry |
lfnEntryMask = $BF;
|
Mask for LFN entry count |
lfnEntryChars = 13;
|
Number of characters per LFN entry |
lfnEntryNull = $0000;
|
Null terminator on LFN when applicable |
lfnEntryPadding = $FFFF;
|
Empty LFN chars padded with (65535) |
lfnAttributeMask = (faReadOnly or faHidden or faSysFile or faVolumeID);
|
Not Used - See faLongName |
fatBootSignature = $29;
|
|
fat32LeadSignature = $41615252;
|
RRaA |
fat32StructSignature = $61417272;
|
rrAa |
fat32TrailSignature = $AA550000;
|
Standard Boot Sector signature |
fatDotChar:Byte = $2E;
|
Checked separately from Invalid chars due to . and .. entries |
fatSpaceChar:Byte = $20;
|
|
fatBaseChars:set of Byte = [$00..$19];
|
0..31 (Dont include $20 as that is checked separately) |
fatInvalidChars:set of Byte = [$22,$2A,$2B,$2C,$2F,$3A,$3B,$3C,$3D,$3E,$3F,$5B,$5C,$5D,$7C];
|
34,42,43,44,47,58,59,60,61,62,63,91,92,93,124 (Dont include $2E as that is checked separately) |
fatLowercaseChars:set of Byte = [$61..$7A];
|
97..122 (These dont account for the code page) |
fatParams*
Used for FAT entry block loading | |
fatMaxParams = 11;
|
|
fatParams:array[0..fatMaxParams] of TFATParams = (
|
|
SectorSize,FATType,BlockShiftCount,EntriesPerBlock,SectorsPerBlock | |
FAT12 | |
(SectorSize:512; FATType:ftFAT12; BlockShiftCount:10; EntriesPerBlock:1024; SectorsPerBlock:3),
|
|
(SectorSize:1024; FATType:ftFAT12; BlockShiftCount:11 ;EntriesPerBlock:2048; SectorsPerBlock:3),
|
|
(SectorSize:2048; FATType:ftFAT12; BlockShiftCount:12; EntriesPerBlock:4096; SectorsPerBlock:3),
|
|
(SectorSize:4096; FATType:ftFAT12; BlockShiftCount:13; EntriesPerBlock:8192; SectorsPerBlock:3),
|
|
FAT16 | |
(SectorSize:512; FATType:ftFAT16; BlockShiftCount:10; EntriesPerBlock:1024; SectorsPerBlock:4),
|
|
(SectorSize:1024; FATType:ftFAT16; BlockShiftCount:11; EntriesPerBlock:2048; SectorsPerBlock:4),
|
|
(SectorSize:2048; FATType:ftFAT16; BlockShiftCount:12; EntriesPerBlock:4096; SectorsPerBlock:4),
|
|
(SectorSize:4096 ;FATType:ftFAT16 ;BlockShiftCount:13; EntriesPerBlock:8192; SectorsPerBlock:4),
|
|
FAT32 | |
(SectorSize:512; FATType:ftFAT32; BlockShiftCount:10; EntriesPerBlock:1024; SectorsPerBlock:8),
|
|
(SectorSize:1024; FATType:ftFAT32; BlockShiftCount:11; EntriesPerBlock:2048; SectorsPerBlock:8),
|
|
(SectorSize:2048; FATType:ftFAT32; BlockShiftCount:12; EntriesPerBlock:4096; SectorsPerBlock:8),
|
|
(SectorSize:4096; FATType:ftFAT32; BlockShiftCount:13; EntriesPerBlock:8192; SectorsPerBlock:8));
|
fat12Geometry*
Used for FAT formatting (Floppy Disk only) | |
fat12MaxGeometry = 4;
|
|
fat12Geometry:array[0..fat12MaxGeometry] of TFATGeometry = (
|
|
FloppyType,SectorsPerFat,SectorsPerCluster,RootEntryCount,MediaId | |
(FloppyType:ft360K; SectorsPerFat:2; SectorsPerCluster:2; RootEntryCount:112; MediaId:$FD),
|
|
(FloppyType:ft12M;SectorsPerFat:7;SectorsPerCluster:1;RootEntryCount:224;MediaId:$F9),
|
|
(FloppyType:ft720K; SectorsPerFat:3; SectorsPerCluster:2; RootEntryCount:112; MediaId:$F9),
|
|
(FloppyType:ft144M; SectorsPerFat:9; SectorsPerCluster:1; RootEntryCount:224; MediaId:$F0),
|
|
(FloppyType:ft288M; SectorsPerFat:9; SectorsPerCluster:2; RootEntryCount:240; MediaId:$F0));
|
fat_ClusterSize*
Used for FAT formatting (Fixed Disk only) | |
fat12MaxClusterSize = 2;
|
|
fat12ClusterSize:array[0..fat12MaxClusterSize] of TFATClusterSize = (
|
|
SectorCount,SectorsPerCluster | |
(SectorCount:6; SectorsPerCluster:0),
|
up to 3 KB, the 0 value for SectorsPerCluster trips an error (Not possible due to 512 Root entries) |
(SectorCount:798; SectorsPerCluster:0),
|
up to 399 KB, the 0 value for SectorsPerCluster trips an error |
(SectorCount:32623; SectorsPerCluster:8),
|
up to 15.9 MB, 4k cluster |
(SectorCount:$FFFFFFFF; SectorsPerCluster:0));
|
greater than 15.9 MB, 0 value for SectorsPerCluster trips an error |
See FAT12 Notes for Min/Max and Values | |
fat16MaxClusterSize = 8;
|
|
fat16ClusterSize:array[0..fat16MaxClusterSize] of TFATClusterSize = (
|
|
SectorCount,SectorsPerCluster | |
(SectorCount:8400; SectorsPerCluster:0),
|
up to 4.1 MB, the 0 value for SectorsPerCluster trips an error |
(SectorCount:32680; SectorsPerCluster:2),
|
up to 16 MB, 1k cluster |
(SectorCount:262144; SectorsPerCluster:4),
|
up to 128 MB, 2k cluster |
(SectorCount:524288; SectorsPerCluster:8),
|
up to 256 MB, 4k cluster |
(SectorCount:1048576; SectorsPerCluster:16),
|
up to 512 MB, 8k cluster |
The entries after this point are not used unless FAT16 is forced | |
(SectorCount:2097152; SectorsPerCluster:32),
|
up to 1 GB, 16k cluster |
(SectorCount:4194304; SectorsPerCluster:64),
|
up to 2 GB, 32k cluster |
(SectorCount:8388608; SectorsPerCluster:128),
|
up to 4 GB, 64k cluster |
(SectorCount:$FFFFFFFF;SectorsPerCluster:0));
|
greater than 4 GB, 0 value for SectorsPerCluster trips an error |
fat32MaxClusterSize = 5;
|
|
fat32ClusterSize:array[0..fat32MaxClusterSize] of TFATClusterSize = (
|
|
SectorCount,SectorsPerCluster | |
(SectorCount:66600; SectorsPerCluster:0),
|
up to 32.5 MB, the 0 value for SectorsPerCluster trips an error |
(SectorCount:532480 ;SectorsPerCluster:1),
|
up to 260 MB, .5k cluster |
The entries before this point are not used unless FAT32 is forced | |
(SectorCount:16777216; SectorsPerCluster:8),
|
up to 8 GB, 4k cluster |
(SectorCount:33554432; SectorsPerCluster:16),
|
up to 16 GB, 8k cluster |
(SectorCount:67108864; SectorsPerCluster:32),
|
up to 32 GB, 16k cluster |
(SectorCount:$FFFFFFFF; SectorsPerCluster:64));
|
greater than 32 GB, 32k cluster |
fatPartitionType*
fatMaxPartitionType = 5;
|
|
fatPartitionType:array[0..fatMaxPartitionType] of TFATPartitionType = (
|
|
Excluded,Extended,SectorCount,PartitionId,LBAType | |
Extended Partitions | |
(Excluded:False; Extended:True; SectorCount:$FFFFFFFF ;PartitionId:pidExtended; LBAType:pidExtLBA),
|
any size, Extended |
Primary and Logical Partitions | |
Unused | |
(Excluded:False; Extended:False; SectorCount:798; PartitionId:pidUnused; LBAType:pidUnused),
|
up to 399 KB, Unused (Unused type trips an error) |
FAT12 | |
(Excluded:False; Extended:False; SectorCount:32680; PartitionId:pidFAT12; LBAType:pidFAT12),
|
up to 16 MB, FAT12 |
FAT16 | |
(Excluded:False; Extended:False; SectorCount:65360; PartitionId:pidFAT16; LBAType:pidFAT16LBA),
|
up to 32 MB, FAT16 |
(Excluded:False; Extended:False; SectorCount:1048576; PartitionId:pidFAT16HUGE; LBAType:pidFAT16LBA),
|
up to 512 MB, FAT16 HUGE |
FAT32 | |
(Excluded:False; Extended:False; SectorCount:$FFFFFFFF; PartitionId:pidFAT32; LBAType:pidFAT32LBA));
|
above 512 MB, FAT32 |
Type definitions
FATFS specific types
TFATType = (ftNONE,ftFAT12,ftFAT16,ftFAT32);
|
FATFS params
TFATParams = record
Note: (Not Packed) Block values for various Sector sizes. | |
SectorSize:Word;
|
|
FATType:TFATType;
|
|
BlockShiftCount:Word;
|
|
EntriesPerBlock:LongWord;
|
|
SectorsPerBlock:LongWord;
|
FATFS geometry
TFATGeometry = record
Note: (Not Packed) FAT12 values for various Floppy Types. | |
FloppyType:TFloppyType;
|
|
SectorsPerFat:LongWord;
|
|
SectorsPerCluster:LongWord;
|
|
RootEntryCount:LongWord;
|
|
MediaId:Byte;
|
FATFS cluster size
TFATClusterSize = record
Note: (Not Packed) Sectors per Cluster for various disk sizes (Fixed Disk only). | |
SectorCount:LongWord;
|
Based on 512 bytes per sector only |
SectorsPerCluster:LongWord;
|
FATFS partition type
TFATPartitionType = record
Note: (Not Packed) Partition Type for various disk sizes (Fixed Disk only). | |
Excluded:Boolean;
|
Entry is excluded from FAT Partition Type check |
Extended:Boolean;
|
|
SectorCount:LongWord;
|
Based on 512 bytes per sector only |
PartitionId:Byte;
|
|
LBAType:Byte;
|
FATFS name
PFATName = ^TFATName;
TFATName = packed record
Note: 11 Bytes | |
Name:array[0..7] of Char;
|
File Name |
Ext:array[0..2] of Char;
|
File Extension |
FATSFS directory
PFATDirectory = ^TFATDirectory;
TFATDirectory = packed record
Note: 32 Bytes | |
Name:array[0..7] of Char;
|
File Name |
Ext:array[0..2] of Char;
|
File Extension |
Attribute:Byte;
|
File Attributes - See Standard Values |
Reserved:Byte;
|
Always 0 (See below) |
CaseFlags:Byte;
|
Set to $08 if Name, $10 if Extension or $18 if both |
CreateTimeMsecs:Byte;
|
|
CreateTime:Word;
|
|
CreateDate:Word;
|
|
LastAccessDate:Word;
|
|
FirstClusterHigh:Word;
|
High word of the start cluster (FAT32 Only) |
WriteTime:Word;
|
|
WriteDate:Word;
|
|
FirstClusterLow:Word;
|
Low Word of Start Cluster all versions |
Length:LongWord;
|
LFN directory
PLFNDirectory = ^TLFNDirectory;
TLFNDirectory = packed record
Note: 32 Bytes | |
Order:Byte;
|
Bit 6 = 1 if last LFN in chain, Bits 5-0 = Order of LFN chunks for this File |
Name1:array[0..4] of WideChar;
|
First 5 Characters in this chunk |
Attribute:Byte;
|
Always 0Fh - Volume, System, Hidden, ReadOnly |
FileType:Byte;
|
Usually 00h |
Checksum:Byte;
|
Checksum calculated on 8.3 name |
Name2:array[0..5] of WideChar;
|
Next 6 Characters in this chunk |
Reserved:Word;
|
Always 0000h - FirstCluster in Standard Entry |
Name3:array[0..1] of WideChar;
|
Next 2 Characters in this chunk |
FATFS info sector
PFATInfoSector = ^TFATInfoSector;
TFATInfoSector = packed record
LeadSignature:LongWord;
|
Signature "RRaA" or 41615252h |
Reserved1:array[0..479] of Byte;
|
Always 0 |
StructureSignature:LongWord;
|
Signature "rrAa" or 61417272h |
FreeClusterCount:LongWord;
|
Free Clusters $FFFFFFFF if unknown |
LastFreeCluster:LongWord;
|
Most recently allocated cluster $FFFFFFFF if unknown |
Reserved2:array[0..11] of Byte;
|
Always 0 |
TrailSignature:LongWord;
|
Signature AA550000h |
Class definitions
FATFS specific classes
TFATRecognizer = class(TRecognizer)
|
TFATPartitioner = class(TDiskPartitioner)
|
TFATFormatter = class(TDiskFormatter)
|
TFATDefragger = class(TDiskDefragger)
|
TFATRepairer = class(TDiskRepairer)
|
TFATFileSystem = class(TFileSystem)
|
TFATDiskTable = class(TDiskTable)
|
TFATDiskBlock = class(TDiskBlock)
|
TFATDiskEntry = class(TDiskEntry)
|
Public variables
None defined
Function declarations
Initialization functions
procedure FATFSInit;
Note | None documented |
---|
procedure FATFSQuit;
Note | None documented |
---|
FATFS helper functions
function FATTypeToString(AType:TFATType):String;
Note | None documented |
---|
Return to Unit Reference