Difference between revisions of "Unit FATFS"

From Ultibo.org
Jump to: navigation, search
Line 332: Line 332:
 
| <code>fatLowercaseChars:set of Byte = [$61..$7A];</code>
 
| <code>fatLowercaseChars:set of Byte = [$61..$7A];</code>
 
| 97..122 (These dont account for the code page)
 
| 97..122 (These dont account for the code page)
 +
|-
 +
|}
 +
</div></div>
 +
<br />
 +
<div class="toccolours mw-collapsible mw-collapsed" style="border: 1; font-family: arial; padding-top: 20px; padding-bottom: 15px;">
 +
<div style="font-size: 14px; padding-left: 12px;">'''FATFS params table''' <code> fatParams* </code></div>
 +
<div class="mw-collapsible-content" style="text-align: left; padding-left: 5px;">
 +
{| class="wikitable" style="font-size: 14px; background: white;"
 +
|-
 +
|colspan="2"|Used for FAT entry block loading
 +
|-
 +
|colspan="2"|&nbsp;
 +
|-
 +
| <code>fatMaxParams = 11;</code>
 +
| style="width: 50%;"|&nbsp;
 +
|-
 +
| <code>fatParams:array[0..fatMaxParams] of TFATParams = (</code>
 +
| &nbsp;
 +
|-
 +
|colspan="2"|''SectorSize,FATType,BlockShiftCount,EntriesPerBlock,SectorsPerBlock''
 +
|-
 +
|colspan="2"|''FAT12''
 +
|-
 +
| <code>(SectorSize:512; FATType:ftFAT12; BlockShiftCount:10; EntriesPerBlock:1024; SectorsPerBlock:3),</code>
 +
| &nbsp;
 +
|-
 +
| <code>(SectorSize:1024; FATType:ftFAT12; BlockShiftCount:11 ;EntriesPerBlock:2048; SectorsPerBlock:3),</code>
 +
| &nbsp;
 +
|-
 +
| <code>(SectorSize:2048; FATType:ftFAT12; BlockShiftCount:12; EntriesPerBlock:4096; SectorsPerBlock:3),</code>
 +
| &nbsp;
 +
|-
 +
| <code>(SectorSize:4096; FATType:ftFAT12; BlockShiftCount:13; EntriesPerBlock:8192; SectorsPerBlock:3),</code>
 +
| &nbsp;
 +
|-
 +
|colspan="2"|''FAT16''
 +
|-
 +
| <code>(SectorSize:512; FATType:ftFAT16; BlockShiftCount:10; EntriesPerBlock:1024; SectorsPerBlock:4),</code>
 +
| &nbsp;
 +
|-
 +
| <code>(SectorSize:1024; FATType:ftFAT16; BlockShiftCount:11; EntriesPerBlock:2048; SectorsPerBlock:4),</code>
 +
| &nbsp;
 +
|-
 +
| <code>(SectorSize:2048; FATType:ftFAT16; BlockShiftCount:12; EntriesPerBlock:4096; SectorsPerBlock:4),</code>
 +
| &nbsp;
 +
|-
 +
| <code>(SectorSize:4096 ;FATType:ftFAT16 ;BlockShiftCount:13; EntriesPerBlock:8192; SectorsPerBlock:4),</code>
 +
| &nbsp;
 +
|-
 +
|colspan="2"|''FAT32''
 +
|-
 +
| <code>(SectorSize:512; FATType:ftFAT32; BlockShiftCount:10; EntriesPerBlock:1024; SectorsPerBlock:8),</code>
 +
| &nbsp;
 +
|-
 +
| <code>(SectorSize:1024; FATType:ftFAT32; BlockShiftCount:11; EntriesPerBlock:2048; SectorsPerBlock:8),</code>
 +
| &nbsp;
 +
|-
 +
| <code>(SectorSize:2048; FATType:ftFAT32; BlockShiftCount:12; EntriesPerBlock:4096; SectorsPerBlock:8),</code>
 +
| &nbsp;
 +
|-
 +
| <code>(SectorSize:4096; FATType:ftFAT32; BlockShiftCount:13; EntriesPerBlock:8192; SectorsPerBlock:8));</code>
 +
| &nbsp;
 +
|-
 +
|}
 +
</div></div>
 +
<br />
 +
<div class="toccolours mw-collapsible mw-collapsed" style="border: 1; font-family: arial; padding-top: 20px; padding-bottom: 15px;">
 +
<div style="font-size: 14px; padding-left: 12px;">'''FATFS geometry tables''' <code> fat12Geometry* </code></div>
 +
<div class="mw-collapsible-content" style="text-align: left; padding-left: 5px;">
 +
{| class="wikitable" style="font-size: 14px; background: white;"
 +
|-
 +
|colspan="2"|Used for FAT formatting (Floppy Disk only)
 +
|-
 +
|colspan="2"|&nbsp;
 +
|-
 +
| <code>fat12MaxGeometry = 4;</code>
 +
| style="width: 50%;"|&nbsp;
 +
|-
 +
| <code>fat12Geometry:array[0..fat12MaxGeometry] of TFATGeometry = (</code>
 +
| &nbsp;
 +
|-
 +
|colspan="2"|''FloppyType,SectorsPerFat,SectorsPerCluster,RootEntryCount,MediaId''
 +
|-
 +
| <code>(FloppyType:ft360K; SectorsPerFat:2; SectorsPerCluster:2; RootEntryCount:112; MediaId:$FD),</code>
 +
| &nbsp;
 +
|-
 +
| <code>(FloppyType:ft12M;SectorsPerFat:7;SectorsPerCluster:1;RootEntryCount:224;MediaId:$F9),</code>
 +
| &nbsp;
 +
|-
 +
| <code>(FloppyType:ft720K; SectorsPerFat:3; SectorsPerCluster:2; RootEntryCount:112; MediaId:$F9),</code>
 +
| &nbsp;
 +
|-
 +
| <code>(FloppyType:ft144M; SectorsPerFat:9; SectorsPerCluster:1; RootEntryCount:224; MediaId:$F0),</code>
 +
| &nbsp;
 +
|-
 +
| <code>(FloppyType:ft288M; SectorsPerFat:9; SectorsPerCluster:2; RootEntryCount:240; MediaId:$F0));</code>
 +
| &nbsp;
 +
|-
 +
|}
 +
</div></div>
 +
<br />
 +
<div class="toccolours mw-collapsible mw-collapsed" style="border: 1; font-family: arial; padding-top: 20px; padding-bottom: 15px;">
 +
<div style="font-size: 14px; padding-left: 12px;">'''FATFS cluster size tables''' <code> fat_ClusterSize* </code></div>
 +
<div class="mw-collapsible-content" style="text-align: left; padding-left: 5px;">
 +
{| class="wikitable" style="font-size: 14px; background: white;"
 +
|-
 +
|colspan="2"|Used for FAT formatting (Fixed Disk only)
 +
|-
 +
|colspan="2"|&nbsp;
 +
|-
 +
| <code>fat12MaxClusterSize = 2;</code>
 +
| style="width: 50%;"|&nbsp;
 +
|-
 +
| <code>fat12ClusterSize:array[0..fat12MaxClusterSize] of TFATClusterSize = (</code>
 +
| &nbsp;
 +
|-
 +
|colspan="2"|''SectorCount,SectorsPerCluster''
 +
|-
 +
| <code>(SectorCount:6; SectorsPerCluster:0),</code>
 +
| up to 3 KB, the 0 value for SectorsPerCluster trips an error (Not possible due to 512 Root entries)
 +
|-
 +
| <code>(SectorCount:798; SectorsPerCluster:0),</code>
 +
| up to 399 KB, the 0 value for SectorsPerCluster trips an error
 +
|-
 +
| <code>(SectorCount:32623; SectorsPerCluster:8),</code>
 +
| up to 15.9 MB, 4k cluster
 +
|-
 +
| <code>(SectorCount:$FFFFFFFF; SectorsPerCluster:0));</code>
 +
| greater than 15.9 MB, 0 value for SectorsPerCluster trips an error
 +
|-
 +
|colspan="2"|See FAT12 Notes for Min/Max and Values
 +
|-
 +
|colspan="2"|&nbsp;
 +
|-
 +
| <code>fat16MaxClusterSize = 8;</code>
 +
| &nbsp;
 +
|-
 +
| <code>fat16ClusterSize:array[0..fat16MaxClusterSize] of TFATClusterSize = (</code>
 +
| &nbsp;
 +
|-
 +
|colspan="2"|''SectorCount,SectorsPerCluster''
 +
|-
 +
| <code>(SectorCount:8400; SectorsPerCluster:0),</code>
 +
| up to 4.1 MB, the 0 value for SectorsPerCluster trips an error
 +
|-
 +
| <code>(SectorCount:32680; SectorsPerCluster:2),</code>
 +
| up to 16 MB, 1k cluster
 +
|-
 +
| <code>(SectorCount:262144; SectorsPerCluster:4),</code>
 +
| up to 128 MB, 2k cluster
 +
|-
 +
| <code>(SectorCount:524288; SectorsPerCluster:8),</code>
 +
| up to 256 MB, 4k cluster
 +
|-
 +
| <code>(SectorCount:1048576; SectorsPerCluster:16),</code>
 +
| up to 512 MB, 8k cluster
 +
|-
 +
|colspan="2"|The entries after this point are not used unless FAT16 is forced
 +
|-
 +
| <code>(SectorCount:2097152; SectorsPerCluster:32),</code>
 +
| up to 1 GB, 16k cluster
 +
|-
 +
| <code>(SectorCount:4194304; SectorsPerCluster:64),</code>
 +
| up to 2 GB, 32k cluster
 +
|-
 +
| <code>(SectorCount:8388608; SectorsPerCluster:128),</code>
 +
| up to 4 GB, 64k cluster
 +
|-
 +
| <code>(SectorCount:$FFFFFFFF;SectorsPerCluster:0));</code>
 +
| greater than 4 GB, 0 value for SectorsPerCluster trips an error
 +
|-
 +
|colspan="2"|&nbsp;
 +
|-
 +
| <code>fat32MaxClusterSize = 5;</code>
 +
| &nbsp;
 +
|-
 +
| <code>fat32ClusterSize:array[0..fat32MaxClusterSize] of TFATClusterSize = (</code>
 +
| &nbsp;
 +
|-
 +
|colspan="2"|''SectorCount,SectorsPerCluster''
 +
|-
 +
| <code>(SectorCount:66600; SectorsPerCluster:0),</code>
 +
| up to 32.5 MB, the 0 value for SectorsPerCluster trips an error
 +
|-
 +
| <code>(SectorCount:532480 ;SectorsPerCluster:1),</code>
 +
| up to 260 MB, .5k cluster
 +
|-
 +
|colspan="2"|The entries before this point are not used unless FAT32 is forced
 +
|-
 +
| <code>(SectorCount:16777216; SectorsPerCluster:8),</code>
 +
| up to 8 GB, 4k cluster
 +
|-
 +
| <code>(SectorCount:33554432; SectorsPerCluster:16),</code>
 +
| up to 16 GB, 8k cluster
 +
|-
 +
| <code>(SectorCount:67108864; SectorsPerCluster:32),</code>
 +
| up to 32 GB, 16k cluster
 +
|-
 +
| <code>(SectorCount:$FFFFFFFF; SectorsPerCluster:64));</code>
 +
| greater than 32 GB, 32k cluster
 +
|-
 +
|}
 +
</div></div>
 +
<br />
 +
<div class="toccolours mw-collapsible mw-collapsed" style="border: 1; font-family: arial; padding-top: 20px; padding-bottom: 15px;">
 +
<div style="font-size: 14px; padding-left: 12px;">'''FATFS partition types''' <code> fatPartitionType* </code></div>
 +
<div class="mw-collapsible-content" style="text-align: left; padding-left: 5px;">
 +
{| class="wikitable" style="font-size: 14px; background: white;"
 +
|-
 +
| <code>fatMaxPartitionType = 5;</code>
 +
| style="width: 50%;"|&nbsp;
 +
|-
 +
| <code>fatPartitionType:array[0..fatMaxPartitionType] of TFATPartitionType = (</code>
 +
| &nbsp;
 +
|-
 +
|colspan="2"|''Excluded,Extended,SectorCount,PartitionId,LBAType''
 +
|-
 +
|colspan="2"|''Extended Partitions''
 +
|-
 +
| <code>(Excluded:False; Extended:True; SectorCount:$FFFFFFFF ;PartitionId:pidExtended; LBAType:pidExtLBA),</code>
 +
| any size, Extended
 +
|-
 +
|colspan="2"|Primary and Logical Partitions
 +
|-
 +
|colspan="2"|''Unused''
 +
|-
 +
| <code>(Excluded:False; Extended:False; SectorCount:798; PartitionId:pidUnused; LBAType:pidUnused),</code>
 +
| up to 399 KB, Unused (Unused type trips an error)
 +
|-
 +
|colspan="2"|''FAT12''
 +
|-
 +
| <code>(Excluded:False; Extended:False; SectorCount:32680; PartitionId:pidFAT12; LBAType:pidFAT12),</code>
 +
| up to 16 MB, FAT12
 +
|-
 +
|colspan="2"|''FAT16''
 +
|-
 +
| <code>(Excluded:False; Extended:False; SectorCount:65360; PartitionId:pidFAT16; LBAType:pidFAT16LBA),</code>
 +
| up to 32 MB, FAT16
 +
|-
 +
| <code>(Excluded:False; Extended:False; SectorCount:1048576; PartitionId:pidFAT16HUGE; LBAType:pidFAT16LBA),</code>
 +
| up to 512 MB, FAT16 HUGE
 +
|-
 +
|colspan="2"|''FAT32''
 +
|-
 +
| <code>(Excluded:False; Extended:False; SectorCount:$FFFFFFFF; PartitionId:pidFAT32; LBAType:pidFAT32LBA));</code>
 +
| above 512 MB, FAT32
 
|-
 
|-
 
|}
 
|}

Revision as of 02:48, 30 May 2017

Return to Unit Reference


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



FATFS specific 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
 
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)


FATFS params table 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));  


FATFS geometry tables 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));  


FATFS cluster size tables 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


FATFS partition types 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



FAT recognizer

TFATRecognizer = class(TRecognizer)

constructor Create(ADriver:TFileSysDriver);  
private
FCaseFlags:Boolean;  
FLongNames:Boolean;  
FOemConvert:Boolean;  
FNumericTail:Boolean;  
 
function CheckLBA:Boolean;  
function CheckFAT32:Boolean;  
function CheckBootSector(ABootSector:PBootSector; const AStartSector:Int64; ASectorCount:LongWord):Boolean;  
protected
function GetName:String; override;  
public
property CaseFlags:Boolean read FCaseFlags write FCaseFlags;  
property LongNames:Boolean read FLongNames write FLongNames;  
property OemConvert:Boolean read FOemConvert write FOemConvert;  
property NumericTail:Boolean read FNumericTail write FNumericTail;  
 
function RecognizePartitionId(APartitionId:Byte):Boolean; override;  
function RecognizeBootSector(ABootSector:PBootSector; const AStartSector,ASectorCount:Int64):Boolean; override;  
 
function RecognizePartition(APartition:TDiskPartition):Boolean; override;  
function RecognizeVolume(AVolume:TDiskVolume):Boolean; override;  
function MountVolume(AVolume:TDiskVolume; ADrive:TDiskDrive):Boolean; override;  

FAT partitioner

TFATPartitioner = class(TDiskPartitioner)

constructor Create(ADriver:TFileSysDriver; ARecognizer:TRecognizer);  
protected
function CheckLogical(ADevice:TDiskDevice; AParent:TDiskPartition; APartitionId:Byte):Boolean; override;  
function CheckExtended(ADevice:TDiskDevice; AParent:TDiskPartition; APartitionId:Byte):Boolean; override;  
 
function GetPartitionId(ADevice:TDiskDevice; AParent:TDiskPartition; AStart,ACount:LongWord; APartitionId:Byte):Byte; override;  
 
function InitPartition(ADevice:TDiskDevice; AParent:TDiskPartition; AStart,ACount:LongWord; APartitionId:Byte):Boolean; override;  
public
function AcceptPartition(ADevice:TDiskDevice; APartition,AParent:TDiskPartition; APartitionId:Byte):Boolean; override;  

FAT formatter

TFATFormatter = class(TDiskFormatter)

private
function CheckDevice(AVolume:TDiskVolume; ADrive:TDiskDrive; AFloppyType:TFloppyType):Boolean;  
function CheckPartition(AVolume:TDiskVolume; ADrive:TDiskDrive; AFileSysType:TFileSysType):Boolean;  
 
function GetPartitionId(AVolume:TDiskVolume; ADrive:TDiskDrive; AFATType:TFATType):Byte;  
function UpdatePartitionId(AVolume:TDiskVolume; ADrive:TDiskDrive; AFATType:TFATType):Boolean;  
 
function GetSectorsPerCluster(AVolume:TDiskVolume; ADrive:TDiskDrive; AFloppyType:TFloppyType; AFileSysType:TFileSysType; ABootSector:PBootSector; var AFATType:TFATType):LongWord;  
 
function GetSectorsPerFat(AVolume:TDiskVolume; ADrive:TDiskDrive; AFATType:TFATType; ABootSector:PBootSector):LongWord;  
 
function CreateBootSector(AVolume:TDiskVolume; ADrive:TDiskDrive; AFATType:TFATType; ABootSector:PBootSector):Boolean;  
function WriteBootSector(AVolume:TDiskVolume; ADrive:TDiskDrive; AFATType:TFATType; ABootSector:PBootSector):Boolean;  
function WriteFatTable(AVolume:TDiskVolume; ADrive:TDiskDrive; AFATType:TFATType; ABootSector:PBootSector):Boolean;  
function WriteRootDirectory(AVolume:TDiskVolume; ADrive:TDiskDrive; AFATType:TFATType; ABootSector:PBootSector):Boolean;  
 
function CreateInfoSector(AVolume:TDiskVolume; ADrive:TDiskDrive; AFATType:TFATType; ABootSector:PBootSector; AInfoSector:PFATInfoSector):Boolean;  
function WriteInfoSector(AVolume:TDiskVolume; ADrive:TDiskDrive; AFATType:TFATType; ABootSector:PBootSector; AInfoSector:PFATInfoSector):Boolean;  
public
function AcceptVolume(AVolume:TDiskVolume; AFloppyType:TFloppyType; AFileSysType:TFileSysType):Boolean; override;  
function FormatVolume(AVolume:TDiskVolume; AFloppyType:TFloppyType; AFileSysType:TFileSysType):Boolean; override;  

FAT defragger

TFATDefragger = class(TDiskDefragger)

private
 
public
 

FAT repairer

TFATRepairer = class(TDiskRepairer)

private
 
public
 

FAT file system

TFATFileSystem = class(TFileSystem)

constructor Create(ADriver:TFileSysDriver; AVolume:TDiskVolume; ADrive:TDiskDrive);  
destructor Destroy; override;  
private
FFATType:TFATType;  
FCaseFlags:Boolean; Allow writing entries with the Lowercase Flags set (Reading is always supported)
FVolumeFlags:LongWord; Volume Dirty/Error flags
 
FEndOfFile:LongWord;  
FEndOfCluster:LongWord;  
FFreeCluster:LongWord;  
FBadCluster:LongWord;  
FMediaCluster:LongWord;  
FStartCluster:LongWord;  
 
FHardError:LongWord;  
FCleanShutdown:LongWord;  
FReservedBits:LongWord;  
 
FNumberOfFats:Word; Usually 2
FSectorsPerFat:LongWord;  
FSectorsPerCluster:LongWord; Usually 1,2,4,8,16,32,64,128 etc
 
FReservedSectors:LongWord;  
 
FRootEntryCount:LongWord; Number of Directory entries in Root Directory
FRootSectorCount:LongWord; Number of Sectors occupied by Root Directory
FRootStartSector:LongWord; First Sector of Root Directory (Relative to StartSector)
 
FInfoSector:LongWord; Relative to StartSector
FInfoBackup:LongWord; Relative to StartSector
 
FRootStartCluster:LongWord; First Cluster of Root Directory
 
FActiveFat:Word; Zero based number of active FAT (Always 0 for FAT12/16)
FFatMirroring:Boolean; FAT Mirroring Enabled if True (Always True for FAT12/16)
 
FEntriesPerSector:LongWord; Number of Directory entries in a Sector
FEntriesPerCluster:LongWord; Number of Directory entries in a Cluster
 
FEntriesPerBlock:LongWord; Number of FAT entries per Block
FSectorsPerBlock:LongWord; Number of Sectors per Block of FAT entries
 
FBlockShiftCount:Word; Shift count for Cluster <-> BlockNo
FSectorShiftCount:Word; Shift count for Sector <-> Cluster
FClusterShiftCount:Word; Shift count for Cluster <-> Bytes
 
FDataStartSector:LongWord; First Sector of First Data Cluster (Relative to StartSector)
FDataClusterCount:LongWord; Number of usable data clusters
FTotalClusterCount:LongWord; Total number of clusters including reserved clusters
 
FLastFreeCluster:LongWord; Or $FFFFFFFF if not known
FFreeClusterCount:LongWord; Or $FFFFFFFF if not known
 
FClusterSize:LongWord; Size of a Cluster in Bytes (Max 65536 > Word)
 
FNameBuffer:Pointer; Buffer for long name handling
FNameLock:TMutexHandle; Lock for name buffer
 
FReadBuffer:Pointer; Buffer for partial cluster entry reads (Cluster size)
FReadLock:TMutexHandle; Lock for read buffer
 
FWriteBuffer:Pointer; Buffer for partial cluster entry writes (Cluster size)
FWriteLock:TMutexHandle; Lock for write buffer
 
FClusterBuffer:Pointer; Buffer of exactly cluster size
FClusterLock:TMutexHandle; Lock for cluster buffer
 
function NameLock:Boolean;  
function NameUnlock:Boolean;  
 
function ReadLock:Boolean;  
function ReadUnlock:Boolean;  
 
function WriteLock:Boolean;  
function WriteUnlock:Boolean;  
 
function ClusterLock:Boolean;  
function ClusterUnlock:Boolean;  
 
function GetHardError:Boolean;  
procedure SetHardError(AValue:Boolean);  
 
function GetCleanShutdown:Boolean;  
procedure SetCleanShutdown(AValue:Boolean);  
 
function GetVolumeFlags:LongWord;  
function SetVolumeFlags(AFlags:LongWord):Boolean;  
 
function FillCluster(ACluster:LongWord; AValue:Byte):Boolean;  
 
function ReadCluster(ACluster:LongWord; var ABuffer):Boolean;  
function WriteCluster(ACluster:LongWord; const ABuffer):Boolean;  
 
function GetNextFreeCluster:LongWord;  
function GetFreeClusterCount:LongWord;  
 
function SetNextFreeCluster(ACluster:LongWord):Boolean;  
function SetFreeClusterCount(ACount:LongWord):Boolean;  
 
function GetStartCluster(AEntry:TDiskEntry):LongWord;  
function GetParentCluster(AParent:TDiskEntry):LongWord;  
function CheckClusterBlock(ACluster,ANext:LongWord):Boolean;  
 
function GetNextChainCluster(AParent:LongWord):LongWord;  
function GetLastChainCluster(AParent:LongWord):LongWord;  
function GetChainClusterCount(AParent:LongWord):LongWord;  
 
function GetCluster(ACluster:LongWord):LongWord;  
function SetCluster(ACluster,AValue:LongWord;ACommit:Boolean):Boolean;  
 
function AllocCluster(AParent:LongWord; var ACluster:LongWord; ACount:LongWord):Boolean;  
function ReleaseCluster(AParent,ACluster:LongWord):Boolean;  
 
function CheckDirectoryRoot(AParent:TDiskEntry):Boolean;  
function CheckDirectoryStart(AParent:TDiskEntry):Boolean;  
 
function GetFirstDirectorySector(AParent:TDiskEntry; var ASector:LongWord):Boolean;  
function GetNextDirectorySector(AParent:TDiskEntry; var ASector:LongWord; AWrite:Boolean):Boolean;  
function GetDirectorySectorCount(AParent:TDiskEntry; AWrite:Boolean):LongWord;  
function GetDirectorySectorOffset(AParent:TDiskEntry):LongWord;  
 
function AllocDirectory(AParent:TDiskEntry; ACount:Byte; var AOffset,ASector:LongWord):Boolean;  
function ReleaseDirectory(AParent:TDiskEntry; ACount:Byte; AOffset,ASector:LongWord):Boolean;  
 
function GetBlockShiftCount(ASize:Word;AType:TFATType):Word;  
function GetSectorShiftCount(ASectorsPerCluster:LongWord):Word;  
function GetClusterShiftCount(AClusterSize:LongWord):Word;  
 
function GetEntriesPerBlock(ASize:Word; AType:TFATType):LongWord;  
function GetSectorsPerBlock(ASize:Word; AType:TFATType):LongWord;  
 
procedure ReadConvert(ADirectory:PFATDirectory);  
procedure WriteConvert(ADirectory:PFATDirectory);  
 
function NameToEntry(AName:Pointer; AEntry:TFATDiskEntry; AShort:Boolean):Boolean;  
function EntryToName(AEntry:TFATDiskEntry; AName:Pointer; AShort:Boolean):Boolean;  
 
function BufferToName(ABuffer:Pointer ;var AName:String):Boolean;  
function NameToBuffer(const AName:String; ABuffer:Pointer):Boolean;  
 
function DirectoryToBuffer(ADirectory,ABuffer:Pointer; ACount,AChecksum:Byte; ALast:Boolean):Boolean;  
function BufferToDirectory(ABuffer,ADirectory:Pointer; ACount,AChecksum:Byte; ALast:Boolean):Boolean;  
 
function DirectoryToEntry(ADirectory:Pointer; AEntry:TFATDiskEntry; AShort:Boolean):Boolean;  
function EntryToDirectory(AEntry:TFATDiskEntry; ADirectory:Pointer; AShort:Boolean):Boolean;  
 
function FATTypeToFileSysType(AFATType:TFATType):TFileSysType;  
protected
function LoadMaxFile:Integer; override;  
function LoadMaxPath:Integer; override;  
function LoadAttributes:LongWord; override;  
function LoadMaxAttributes:LongWord; override;  
function LoadSystemName:String; override;  
function LoadVolumeName:String; override;  
function LoadVolumeSerial:LongWord; override;  
function LoadFileSysType:TFileSysType; override;  
 
function SetVolumeName(const AName:String):Boolean;  
function SetVolumeSerial(ASerial:LongWord):Boolean;  
 
function ReadEntry(AParent,AEntry:TDiskEntry; var ABuffer; const AStart:Int64; ACount:LongWord; var AOffset,AValue:LongWord):Integer; override;  
function WriteEntry(AParent,AEntry:TDiskEntry; const ABuffer; const AStart:Int64; ACount:LongWord; var AOffset,AValue:LongWord):Integer; override;  
 
function LoadTables:Boolean; override;  
function LoadBlocks:Boolean; override;  
function LoadEntries(AParent:TDiskEntry):Boolean; override;  
 
function LoadTable(ATableNo:LongWord):Boolean; override;  
function LoadBlock(ABlockNo:LongWord):Boolean; override;  
function LoadEntry(AParent:TDiskEntry; ABuffer:Pointer; var ABlockOffset,AEntryOffset,ABlockSector,AEntrySector:LongWord):Boolean; Not override
function LoadLong(AParent:TDiskEntry; ABuffer:Pointer; var ABlockOffset,AEntryOffset,ABlockSector,AEntrySector:LongWord):Boolean; Not override
 
function AddEntry(AParent:TDiskEntry; const AName:String; AAttributes:LongWord; AReference:Boolean):TDiskEntry; override;  
function AddEntryEx(AParent:TDiskEntry; const AName,AAltName:String; AAttributes:LongWord; AReference:Boolean):TDiskEntry; override;  
function RemoveEntry(AParent,AEntry:TDiskEntry):Boolean; override;  
function RenameEntry(AParent,AEntry:TDiskEntry; const AName:String):Boolean; override;  
function RenameEntryEx(AParent,AEntry:TDiskEntry; const AAltName:String):Boolean; override;  
function MoveEntry(ASource,ADest,AEntry:TDiskEntry):Boolean; override;  
 
function SetBlock(ABlock:TDiskBlock):Boolean; override;  
function SetEntry(AParent,AEntry:TDiskEntry):Boolean; override;  
function SetLong(AParent,AEntry:TDiskEntry):Boolean; {Not override}  
 
function SizeEntry(AParent,AEntry:TDiskEntry; const ASize:Int64):Boolean; override;  
 
function GetBlock(ABlockNo:LongWord):TDiskBlock; override;  
function GetBlockEx(ABlockNo:LongWord; AWrite:Boolean):TDiskBlock; override;  
 
function CheckName(const AName:String):Boolean; override;  
function CountName(const AName:String):Byte;  
function CompareName(const AName,AMatch:String; AWildcard:Boolean):Boolean; override;  
function ChecksumName(AEntry:TDiskEntry):Byte;  
function GenerateName(AParent,AEntry:TDiskEntry; const AName:String):String;  
 
function GetNameFlags(const AName:String):LongWord;  
function CheckFlagName(const AName:String):Boolean;  
 
function ValidateName(AName:Pointer):Boolean;  
function ValidateDirectory(ADirectory:Pointer):Boolean;  
public
property CaseFlags:Boolean read FCaseFlags write FCaseFlags;  
property OemConvert:Boolean read FOemConvert write FOemConvert;  
property NumericTail:Boolean read FNumericTail write FNumericTail;  
 
property ReadOnly:Boolean read FReadOnly write FReadOnly;  
property LongNames:Boolean read FLongNames write FLongNames;  
property CasePreserved:Boolean read FCasePreserved write FCasePreserved;  
property UnicodeNames:Boolean read FUnicodeNames write FUnicodeNames;  
 
property HardError:Boolean read GetHardError write SetHardError;  
property CleanShutdown:Boolean read GetCleanShutdown write SetCleanShutdown;  
 
function FileSystemInit:Boolean; override;  
 
function MountFileSystem:Boolean; override;  
function DismountFileSystem:Boolean; override;  
function InitializeFileSystem(ASectorsPerCluster:LongWord; AFileSysType:TFileSysType):Boolean; override;  
 
function GetDriveLabel:String; override;  
function SetDriveLabel(const ALabel:String):Boolean; override;  
function SetDriveSerial(ASerial:LongWord):Boolean; override;  
 
function GetDriveFreeSpaceEx:Int64; override;  
function GetDriveTotalSpaceEx:Int64; override;  

FAT disk table

TFATDiskTable = class(TDiskTable)

Note: Represents a FAT table.
 
private
FStartSector:LongWord;  
FSectorCount:LongWord;  
public
property StartSector:LongWord read FStartSector write FStartSector;  
property SectorCount:LongWord read FSectorCount write FSectorCount;  

FAT disk block

TFATDiskBlock = class(TDiskBlock)

Note: Represents a block of FAT entries.
 
constructor Create(ALocalLock:TMutexHandle);  
destructor Destroy; override;  
private
FBlockBuffer:Pointer;  
FBlockSector:LongWord; Relative to the StartSector in Table
FSectorCount:LongWord;  
public
property BlockBuffer:Pointer read FBlockBuffer write FBlockBuffer;  
property BlockSector:LongWord read FBlockSector write FBlockSector;  
property SectorCount:LongWord read FSectorCount write FSectorCount;  

FAT disk entry

TFATDiskEntry = class(TDiskEntry)

Note: Represents a FAT directory entry.
 
private
FEntryCount:Byte; Always 1 if short name only
FNameOffset:LongWord; Same as EntryOffset if short name only
FNameSector:LongWord; Same as EntrySector if short name only
FEntryOffset:LongWord;  
FEntrySector:LongWord;  
FStartCluster:LongWord;  
public
property EntryCount:Byte read FEntryCount write FEntryCount;  
property NameOffset:LongWord read FNameOffset write FNameOffset;  
property NameSector:LongWord read FNameSector write FNameSector;  
property EntryOffset:LongWord read FEntryOffset write FEntryOffset;  
property EntrySector:LongWord read FEntrySector write FEntrySector;  
property StartCluster:LongWord read FStartCluster write FStartCluster;  
 
property StartSector:LongWord read FStartCluster write FStartCluster;  


Public variables


None defined

Function declarations



Initialization functions

procedure FATFSInit;
Description: To be documented
Note None documented


procedure FATFSQuit;
Description: To be documented
Note None documented


FATFS helper functions

function FATTypeToString(AType:TFATType):String;
Description: To be documented
Note None documented


Return to Unit Reference