After NTFS and EXFAT now some FAT32 fun. The FORMAT
and DISKPART
tools on Windows NT have some limitations, therefore I created rexxfat.rex for experiments with disk image files and the FAT file system. In essence rexxfat can create a VFD image for a given number of sectors, example:
c:\etc\bin>rexxfat 4194304
1: 32264 * 2 FAT32 sectors; 7 + 0 SYS; 1 * 4129769 data: 4129769
2: 16257 * 2 FAT32 sectors; 8 + 0 SYS; 2 * 2080891 data: 4161782
3: 8161 * 2 FAT32 sectors; 10 + 0 SYS; 4 * 1044493 data: 4177972
4: 4089 * 2 FAT32 sectors; 14 + 0 SYS; 8 * 523264 data: 4186112
5: 2047 * 2 FAT32 sectors; 18 + 0 SYS; 16 * 261887 data: 4190192
6: 1024 * 2 FAT32 sectors; 32 + 0 SYS; 32 * 131007 data: 4192224
7: 128 * 2 FAT16 sectors; 1 + 127 SYS; 128 * 32765 data: 4193920
Pick 1..7 to create c:\etc\bin\rexxfat.vfd with 4194304 sectors
FAT16 cluster size 128 (hex. 80h) might be a bad idea for ancient tools. On the other hand FAT32 is not supported by ancient DOS versions up to MS DOS 6.22 or PC DOS 7.
FAT12 and FAT16 have a static root directory in the system area. For FAT32 the root directory is a dynamic part of the data area typically starting in the first data cluster. Consequently FAT12 and FAT16 never require unused sectors at the end of the data area, e.g., if a given cluster size cs=2**n
yields u=1…cs-1 unused data sectors, then the data area can be reduced by u sectors, and the root directory can be increased by u sectors. rexxfat uses a default minimum of 6 sectors for the root directory, for sector size 512 that allows a minimum of 96 root directory entries.
For FAT32 any unused sectors are added to the reserved sectors at the begin of the system area. Normally FAT32 has 12 or more reserved sectors consisting of four sets:
- 00..02 Three boot sectors (01 is actually used as FSinfo)
- 03..05 Three unused sectors (nulls, no magic 55AAh)
- 06..08 Three backup boot sectors (the FSinfo pointer in 06 is 01, not 07)
- 09..11 Three or more unused sectors
Fortunately this madness can be trimmed, for starters zero or more unused reserved sectors in the last set are good enough. It is also possible to move the backup boot sectors from 06..08 to 03..05, simply modify the backup pointer in 00 and its backup.
There be dragons: If sector 00 is unreadable the backup pointer is also unreadable, and tools trying to fix or bypass this issue would assume that 06 is the backup. It is still possible to use 03..05 as official backup and keep 06 as unofficial third backup. For many purposes that should be good enough, with one notable exception: FAT32 boot code for MS DOS 7 (Windows 95, 98, ME) actually uses the third boot sector, and the Windows NT master boot code assumes that the backup boot sectors for FAT32 partitions start in relative sector 06. Obviously this cannot work as expected if MS DOS 7 backup boot code expected in sector 08 only exists in sector 05.
Fast forward, this is 2011, I've never used MS DOS 7, the dummy boot code in rexxfat consists of two bytes CD18h (INT 18h), and this works for all sector sizes in sectors 00, 03, or even 06. There is an option to enforce a classic layout with 9 or more reserved sectors.
For my purposes the odd layout with only 7 reserved sectors is better, adding one sector for the MBR yields 8, and removable media typically consists of 8×x sectors: No stupid gaps between the MBR and the FAT32 partition, and also no unused sectors after this partition or at its end. DISKPART
and similar tools would skip 63-1 or 2048-1 sectors between MBR and partition, but for removable media with only one partition this is unnecessary: If some decent MBR code can load sector 63 or 2048 it can also load sector 1. There is no "second track" beginning in sector 63, and the new MS Vista alignment on MB boundaries (2048) is nice if you need to find a lost partition on a huge disk, but not required.
To create a VHD image instead of a VFD with rexxfat specify a negative total sector number as argument. One sector is used as MBR, the rest is used for the FAT partition. If the sector size is 512 a classic fixed VHD footer (511 bytes) is added. Sadly fixed VHDs cannot be created as NTFS sparse files, and also do not allow other sector sizes (128, 256, 1024, 2048, or 4096). Here's the checkmbr output for a VHD with 66558 sectors:
...\bin\rexxfat.vhd (assuming geometry CHS 11093 1 6) id. [16F4-1407]
MBR CHS 0 0 1 at 0, end 0 0 1, size 1
1: 0C: CHS 0 0 2 at 1, end 11092 0 6, size 66557 FAT32
2: 00: CHS 0 0 0 at 0, end 0 0 0, size 0 unused
3: 00: CHS 0 0 0 at 0, end 0 0 0, size 0 unused
4: 00: CHS 0 0 0 at 0, end 0 0 0, size 0 unused
total 66558
FAT32 CHS 0 0 2 at 1, end 11092 0 6, size 66557
boot CHS 0 0 2 at 1, end 0 0 4, size 3
backup CHS 0 0 5 at 4, end 1 0 1, size 3 boot
rest CHS 1 0 2 at 7, end 1 0 2, size 1 boot
FAT32 CHS 1 0 3 at 8, end 86 0 4, size 512 #1
FAT32 CHS 86 0 5 at 520, end 171 0 6, size 512 #2
data CHS 172 0 1 at 1032, end 11092 0 6, size 65526
[16F4-1408] (cluster size 1, number 65526) total 66557
This is work in progress, the pseudo-geometry in the VHD footer fits into 28=16+4+8 bits for ATA, but an incomplete last cylinder in a geometry with 24=10+8+6 bits for INT 13h would be better for less than 16515072=1024×256×63 sectors. After all there are no cylinders in a VHD image, and the checkmbr output is designed for INT 13h CHS tuples in MBRs, not for ATA CHS tuples in VHDs.