You've come to this page because you've asked a question similar to
I have a disc volume that I know to be formatted with the FAT filesystem. But I don't know what bit-width of file allocation table (i.e. FAT12, FAT16, or FAT32) was used. How do I determine the bit-width of the FAT?
This is the Frequently Given Answer to that question. (Please note that it is not the answer to the different question of how to determine whether a volume is formatted with the FAT filesystem.)
You read (volume-relative) block 0 of the volume; determine what type of BIOS Parameter Block (BPB) is in that block1; and use the contents of the various fields in the BPB to determine what the software that formatted the volume in the first place thought was the FAT width — first by inspecting the filesystem type field and (if that fails) by calculating the number of clusters in the volume that the BPB says there are and working out the smallest FAT width that can contain that number of clusters.
The basis of this algorithm is that when formatting FAT volumes, format softwares record the FAT width that they have used in the filesystem type field. If they don't record the FAT width, the assumption is that they use the standard algorithm for picking a FAT width based upon the number of clusters in the volume, and haven't allowed the user to specify a different FAT width2.
The relevant values of the filesystem type field are:
Type | Meaning |
---|---|
"FAT " |
FAT volume (width unspecified by the filesystem type) |
"FAT12 " |
FAT volume with 12-bit FATs |
"FAT16 " |
FAT volume with 16-bit FATs |
"FAT32 " |
FAT volume with 32-bit FATs |
The formulae for calculating the number of clusters (that the software that formatted the volume thought that there were, and that thus used to determine what FAT width to employ) are as follows:
SectorsInRootDirectory = (BPB.RootDirectoryEntries * 32 + BPB.BytesPerSector - 1) / BPB.BytesPerSector DataStart = BPB.ReservedSectors + BPB.FATs * SectorsPerFAT + SectorsInRootDirectory ClusterCount = 2 + (SectorsInVolume - DataStart) / BPB.SectorsPerCluster
The values for SectorsPerFAT
and SectorsInVolume
are
calculated in a manner that is specific to each type of BPB.
The standard algorithm for picking a FAT width based upon the cluster count is a simple table:
ClusterCount3 | Consequent FAT width | |
---|---|---|
Hexadecimal | Decimal | |
0x00000002–0x00000FF6 | 2–4086 | FAT12 |
0x00000FF7–0x0000FFF6 | 4087–65526 | FAT16 |
0x0000FFF7–0x0FFFFFF6 | 65527–268435446 | FAT32 |
Read the volume's boot block, (volume-relative) block number 0.
Inspect the
version 7.0 BPB's
signature byte at offset 0x42 and the version 7.0 BPB's filesystem type
field at offsets 0x52–0x59;. If the signature is not the value 0x28
or the value 0x29, or the filesystem type field is not
"FAT
,
"FAT12
",
"FAT16
", or
"FAT32
" 4,
then this is not a version 7.0 BPB for a FAT
volume5. Go to step #6.
If the filesystem type field is "FAT12
",
"FAT16
", or "FAT32
"
6, then that's the width of the FAT. You're
done.
Calculate SectorsPerFAT
and SectorsInVolume
values, for employing in the aforementioned formulae, using the fields in
the version 7.0 BPB. There are two fields for each value, one 16-bit and
one 32-bit. The rule is that the 16-bit fields take precedence over the
32-bit fields unless they have the value zero.
Calculate the FAT width from the ClusterCount
using the table.
You're done.
Inspect the
version 4.0 BPB's
signature byte at offset 0x26 and the version 4.0 BPB's filesystem type
field at offsets 0x36–0x3d;. If the signature is not the value 0x28
or the value 0x29, or the filesystem type field is not
"FAT
,
"FAT12
",
"FAT16
", or
"FAT32
" 4,
then this is not a version 4.0 BPB for a FAT
volume5. Go to step #10.
If the filesystem type field is "FAT12
",
"FAT16
", or "FAT32
"
6, then that's the width of the FAT. You're
done.
Calculate SectorsPerFAT
and SectorsInVolume
values, for employing in the aforementioned formulae, using the fields in
the version 4.0 BPB. There are two fields for the
SectorsInVolume
value, one 16-bit and one 32-bit. The rule
is that the 16-bit field takes precedence over the 32-bit field
unless it has the value zero.
Calculate the FAT width from the ClusterCount
using the table.
You're done.
There's no detectable BPB signature. So just assume that the boot block contains a version 3.4 BPB7.
Calculate SectorsPerFAT
and SectorsInVolume
values, for employing in the aforementioned formulae, using the fields in
the version 3.4 BPB. There are two fields for the
SectorsInVolume
value, one 16-bit and one 32-bit. The rule
is that the 16-bit field takes precedence over the 32-bit field
unless it has the value zero.
Calculate the FAT width from the ClusterCount
using the table.
You're done.
There's a misconception that "only FAT32 can have a version 7.0 BPB". That's simply untrue. It may be a BPB type that in the wild is generally only used on volumes that are formatted as FAT32. But there's nothing inherent in a version 7.0 BPB that prevents its use on FAT16 or FAT12 volumes (or even on HPFS or EXT2 volumes, for that matter). Indeed, a version 7.0 BPB brings some useful augmentations to FAT12 and FAT16 volumes: a backup boot sector, a variable-size and variable-position root directory, and a superblock (a.k.a. "filesystem information sector").
The implication is that any formatting software that allows the user to explicitly specify the FAT width, overriding the standard algorithm for choosing a FAT width, must record the width used in the filesystem type field.
These are the numbers from the widely circulated Microsoft EFI FAT32 specification document. They are the same as the numbers in the footnote to Microsoft's Knowledgebase Article #67321, and are a consequence of the fact that the final 9 cluster number values, for each size of FAT, are reserved values (on that size of FAT) that are unavailable for use as real cluster numbers, but that instead indicate bad clusters and the ends of cluster chains.
The "msdos" filesystem driver for Linux agrees with these numbers. The FAT filesystem driver in FreeDOS does not, however. It instead uses:
ClusterCount | Consequent FAT width | |
---|---|---|
Hexadecimal | Decimal | |
0x00000002–0x00000FF5 | 2–4085 | FAT12 |
0x00000FF6–0x0000FFF5 | 4086–65525 | FAT16 |
0x0000FFF6–0x0FFFFFF5 | 65526–268435445 | FAT32 |
Its author claims to have obtained these numbers from "MS docs", although xe provides no clue as to what documents these actually are — no such documents from Microsoft have yet turned up. It is ironic that the FreeDOS filesystem driver author complains in a comment in the source code that another set of numbers would make more sense. (The actual filesystem driver itself does not consider cluster numbers 0x00000FF6 and 0x0000FFF6 to be reserved cluster numbers.) The more sensible numbers are the very ones used by the Linux FAT filesystem driver and specified by the aforementioned Microsoft documentation!
It is important that you check the entire contents of the field, including the space padding. Checking just the first 3 characters is not enough.
Unfortunately, due to a very poor piece of design on Microsoft's and IBM's parts, the signature fields of the various types of BPB are not in the same place. So the signature byte in one kind of BPB is an entirely different field in another kind of BPB. This has the unfortunate consequence that checking the signature bytes by themselves is not sufficient. A valid signature byte for one kind of BPB could exist simply as a byproduct of another kind of BPB just happening to have the right values in its fields.
The solution to this is to effectively extend the signature field, making it
less likely that it will be accidentially duplicated by another type of BPB.
Since we already know that the volume is formatted with the FAT
filesystem, we know that (as a consequence) the filesystem type fields of the
BPBs will contain one of the strings
"FAT
",
"FAT12
",
"FAT16
", or
"FAT32
". If it were any other string (such as
"HPFS
" or
"NTFS
") then we wouldn't have determined
that this was a FAT volume in the first place. Therefore we extend the
"signature" to comprise a combination of the real signature byte and the
filesystem type field. Each kind of BPB is only recognized if it has one of
the correct compound signatures. This results in a 9 byte signature
for BPBs of other types to accidentally get right, rather than a 1 byte
signature.
Design tip: For variant records, always locate your signature fields at the same byte offset into the record.
Some Microsoft documentation states that you should not rely upon the width given in the filesystem type field. The reasoning given for this is fallacious, however. The reasoning given is that the field is not trustworthy, since some softwares have been known to write an incorrect type when formatting FAT volumes. But softwares have been known to write incorrect values into other fields. (Indeed, one of Microsoft's own operating systems is notorious for not writing several BPB fields properly.) The filesystem type field is not inherently less trustworthy on these grounds than any other field of the BPB is, including (ironically) the fields that Microsoft says to use instead.
Conversely, if you trust the software that formatted the volume in the first
place to have written the BPB correctly, you trust it in particular to have
written the BPB's filesystem type field correctly. If it wrote
"FAT16
", it clearly believed that it
was creating a FAT formatted volume with 16-bit file allocation tables.
There's no reason not to take it at its word.
The only case for which further action is required is thus when the software
that formatted the volume didn't record the FAT width that it was using, i.e.
where it just wrote "FAT
" in the
filesystem type field.
If we didn't already know that this was a FAT volume, we couldn't make the assumption that there was a version 3.4 BPB. But we've already determined beforehand that this is a FAT volume. (The algorithm for determining the filesystem type of the volume will not have determined the type of a volume that lacks a version 4.0 BPB, a version 7.0 BPB, or a version 8.0 BPB. But the type may have been specified manually.)
In theory, this algorithm doesn't support very old media written by exceedingly old versions of MS/PC-DOS, which won't have BPBs at all. To support such media involves now proceeding to work out the FAT size based upon the type and capacity of the disc drive. In practice, that's not a major concern nowadays, over two decades after those versions of MS/PC-DOS were superceded.