# How to determine the width of a FAT

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.)

## Overview and rationale

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:

TypeMeaning
"`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
0x00000002–0x00000FF62–4086FAT12
0x00000FF7–0x0000FFF64087–65526FAT16
0x0000FFF7–0x0FFFFFF665527–268435446FAT32

## Detailed algorithm

1. Read the volume's boot block, (volume-relative) block number 0.

2. 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.

3. If the filesystem type field is "`FAT12   `", "`FAT16   `", or "`FAT32   `" 6, then that's the width of the FAT. You're done.

4. 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.

5. Calculate the FAT width from the `ClusterCount` using the table. You're done.

6. 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.

7. If the filesystem type field is "`FAT12   `", "`FAT16   `", or "`FAT32   `" 6, then that's the width of the FAT. You're done.

8. 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.

9. Calculate the FAT width from the `ClusterCount` using the table. You're done.

10. 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.

11. Calculate the FAT width from the `ClusterCount` using the table. You're done.

## Notes

1. 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").

2. 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.

3. 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
0x00000002–0x00000FF52–4085FAT12
0x00000FF6–0x0000FFF54086–65525FAT16
0x0000FFF6–0x0FFFFFF565526–268435445FAT32

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!

4. 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.

5. 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.

6. 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.

7. 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.

© Copyright 2006–2006 Jonathan de Boyne Pollard. "Moral" rights asserted.
Permission is hereby granted to copy and to distribute this web page in its original, unmodified form as long as its last modification datestamp is preserved.