I'm writing a embedded FAT32 driver. I have issues.
I fill my Kingston DTR30G2 up to 1GB with zeros and plug it into a Windows 7 box, and format it as FAT32. Then, on my Linux box, I dump 1GB of the flash to file and open it in a hex editor and get the following values:
uint16_t BPB_ResvdSecCnt = 32 at offset 0xE
uint8_t BPB_SecPerClus = 8 at offset 0xD
uint8_t BPB_NumFATs = 2 at offset 0x10
Next, I look at the total number of sectors in the FAT32 volume ID:
uint32_t DskSize = 30734336 at offset 0x20
It's the same as Linux reports:
thinkpad :: ~ % cat /sys/block/sdb/sdb1/size
30734336
This is all within spec of FAT32. Now, let's look at the FAT Table sector size on the drive at offset 0x24. It's 29951
sectors. That is not in spec of FAT32. Official Microsoft documents declare the following equation:
RootDirSectors = ((BPB_RootEntCnt * 32) + (BPB_BytsPerSec – 1)) / BPB_BytsPerSec;
TmpVal1 = DskSize – (BPB_ResvdSecCnt + RootDirSectors);
TmpVal2 = (256 * BPB_SecPerClus) + BPB_NumFATs;
TmpVal2 = TmpVal2 / 2;
FATSz = (TMPVal1 + (TmpVal2 – 1)) / TmpVal2;
Where RootDirSectors
is constantly 0 for FAT32 as it is specified in the FAT32 documents:
Note that on a FAT32 volume the BPB_RootEntCnt value is always 0, so on a FAT32 volume RootDirSectors is always 0.
So this gives:
TmpVal1 = DskSize – BPB_ResvdSecCnt;
TmpVal2 = (256 * BPB_SecPerClus) + BPB_NumFATs;
TmpVal2 = TmpVal2 / 2;
FATSz = (TMPVal1 + (TmpVal2 – 1)) / TmpVal2;
Now, I implemented this:
int main(void) {
uint32_t DskSize = 30734336;
uint32_t FATSz;
uint16_t BPB_ResvdSecCnt = 32;
uint8_t BPB_SecPerClus = 8;
uint8_t BPB_NumFATs = 2;
uint32_t RootDirSectors = 0;
uint32_t TmpVal1 = DskSize - (BPB_ResvdSecCnt + RootDirSectors);
uint32_t TmpVal2 = (256 * BPB_SecPerClus) + BPB_NumFATs;
TmpVal2 = TmpVal2 / 2;
FATSz = (TmpVal1 + (TmpVal2 - 1)) / TmpVal2;
printf("%d\n", FATSz);
}
This code snippet gives 29985
sectors as the FAT size.
EDIT:
mkfs.fat 3.0.28
on Linux, when used with the following settings:
mkfs.fat /dev/sdb1 -S 512 -s 8 -F 32
Gives a FAT Table size of 29956
. Now, I have 3 different numbers of the same file system on the same partition.
- FAT32 Spec:
29985
- Windows 7:
29951
- mkfs.fat:
29956
Who should I now trust? The specification or the implementation. Why are the numbers off by 34
sectors?