Skip to content
FreeDOSDeep Dive Published Updated 7 min readViews unavailable

FAT12 and FAT16 Internals: The Filesystem Behind FreeDOS

A forensic guide to FreeDOS FAT12, FAT16 and FAT32 layout, cluster typing, directory and VFAT entries, allocation chains, mirrors, corruption, and recovery.

FreeDOS reads and writes FAT12, FAT16, and FAT32. A FAT volume combines boot metadata, one or more File Allocation Tables, directories, and a cluster-addressed data area. Its allocation table acts like an array-backed linked list: a directory entry names the first cluster, and each FAT entry identifies the next cluster or a terminal state. The model is simple, but safe interpretation depends on exact cluster-count rules and on-disk offsets.

The volume begins with a BIOS Parameter Block

The volume boot sector contains executable boot code plus a BIOS Parameter Block. Core BPB fields describe bytes per sector, sectors per cluster, reserved sectors, FAT count, FAT size, root-entry count, media descriptor, total sectors, geometry, and hidden sectors.

FAT32 extends that record with a 32-bit FAT size, flags, root-directory starting cluster, FSInfo sector, and backup boot-sector location. FreeDOS’s bpb structure exposes those distinctions directly. A tool must select the correct field when a legacy 16-bit size is zero; blindly reading one layout as another produces wrong offsets.

On FAT12 and FAT16, the usual region order is reserved sectors, FAT copies, a fixed root-directory region, then cluster data. FAT32 places its root directory in a normal cluster chain, so there is no equivalent fixed root-directory array between FATs and data.

Cluster count determines the FAT type

The label text embedded in a boot sector is not authoritative. The Microsoft FAT specification and FreeDOS constants classify by the count of data clusters: fewer than 4,085 is FAT12; 4,085 through 65,524 is FAT16; 65,525 and above is FAT32 within supported limits.

That rule avoids circular assumptions about FAT entry width. An implementation first computes data sectors from the BPB, divides by sectors per cluster, and uses the result to determine the FAT type. Formatting near a threshold is discouraged because buggy readers historically used off-by-one formulas.

FAT32 entries occupy 32 bits on disk, but only the low 28 bits belong to the cluster value; the upper four are reserved and must be preserved appropriately. Describing FAT32 as offering a full 32-bit cluster number is inaccurate.

FreeDOS source defines 4,085 and 65,525 as its transition constants and reserves special values for bad and end-of-chain markers. Not every bit pattern is an allocatable cluster.

The FAT maps each file’s cluster chain

Cluster numbers begin at 2. Entries zero and one are reserved. A normal file may have a chain such as:

Directory start = 5
FAT[5] = 9
FAT[9] = 10
FAT[10] = end-of-chain

The file’s logical bytes occupy clusters 5, 9, and 10 in that order. A zero FAT entry represents a free cluster; a bad-cluster marker prevents allocation; a range near the maximum marks end of chain.

A reader must stop according to the current FAT type’s marker range, reject cluster numbers outside the data area, and detect loops. Following a corrupt chain forever or reading a reserved cluster as data can hang a utility or disclose unrelated file contents.

The last cluster is only partially used when file size is not a multiple of cluster size. Those unused bytes are allocation slack and may retain old data. Forensic tools distinguish logical file length from allocated cluster bytes for that reason.

Directory entries are fixed 32-byte records

A classic short-name directory entry contains an 8-byte base name, 3-byte extension, attribute byte, timestamps and dates, high and low words of the first cluster where applicable, and a 32-bit file size. FreeDOS’s struct dirent and DIRENT_SIZE define that layout.

Attributes include read-only, hidden, system, volume label, directory, and archive. The first byte also has special meanings for unused and deleted entries. Deletion normally marks the directory slot and releases the cluster chain; it does not immediately overwrite every old data byte.

The 32-bit size field limits an ordinary FAT file to at most 4,294,967,295 bytes at the format level. DOS programs and kernels may impose lower signed-offset or API constraints. Kernel 2044 explicitly tightened writes crossing the 4 GiB boundary to avoid wraparound rather than pretending a classic API can represent larger files safely.

FAT12/16 root directories have a fixed capacity

The FAT12/16 BPB reserves a fixed number of root entries when the volume is formatted. Once those slots are consumed, creating another root file can fail even when data clusters remain free. Subdirectories occupy cluster chains and can grow by allocating clusters.

FAT32 removes that particular root limit by storing the root as a cluster chain starting at BPB_RootClus. It does not eliminate all directory or implementation limits, and it does not make a FAT32 disk readable by software compiled only for FAT12/16.

This is one reason the filesystem type and target software must be chosen before formatting. Changing a partition label or BPB text does not convert the allocation structure.

VFAT long names use extra directory slots

Classic DOS exposes 8.3 names. VFAT stores a long Unicode name in special directory entries with attribute 0Fh, followed by the associated short entry. Each long-name slot carries up to 13 UTF-16 code units, an ordinal, and a checksum tied to the generated 8.3 alias.

Legacy code that does not understand VFAT should skip entries with the long-name attribute and continue using the short alias. A long-name-aware implementation reassembles slots in order and verifies the checksum. Orphaned or inconsistent slots should not be trusted merely because they contain readable characters.

FreeDOS’s core source defines the on-disk LFN structure and recognizes the attribute, but long-filename services are a separate API issue. Kernel documentation describes programs such as DOSLFN hooking INT 21h to provide long-name functionality. FAT32 support in KERNEL.SYS does not by itself prove that every application receives long filenames.

Multiple FATs are redundancy, not journaling

Most volumes store two FAT copies. That can help when one table has a localized read error, but DOS does not gain transactional consistency from duplication. A crash or buggy writer can update both copies incorrectly, or leave them different without enough information to know which represents the intended chain.

FAT32 flags can disable mirroring and select an active FAT. A repair tool must honor those flags instead of assuming copy zero always wins. Copying one table over another without analyzing directory sizes, chain validity, cross-links, and media errors can destroy the better evidence.

There is no journal recording an atomic sequence of directory, FAT, and data updates. Power loss between them can create lost clusters, cross-linked files, an incorrect size, or a chain that ends early.

Fragmentation and slack follow from allocation

Files need not occupy contiguous clusters. As files grow and free space becomes scattered, a chain can jump across the volume. On spinning disks that increases seeks; on flash and emulated media the performance effect differs, but corruption analysis still must follow the chain rather than assume physical adjacency.

Large clusters reduce FAT size and allow larger volumes with a fixed number of entries, but waste more space for many small files. A one-byte file consumes a full cluster. Cluster size is therefore a compatibility and capacity decision, not a performance slider to maximize blindly.

Defragmentation rewrites allocation and directory metadata extensively. It should never be the first response to suspected corruption, failing media, or an unverified backup.

Recovery starts with an image, not CHKDSK /F

Read-only inspection with CHKDSK drive: can report structure, but any repair mode mutates metadata. Before allowing repairs, capture a sector-for-sector image from the healthiest available reader, record its hash, preserve the original, and work on a copy.

Cross-links require deciding which file owns shared clusters. Lost chains may become recovered fragments without original names. A second FAT and backup boot sector are evidence sources, not automatic truth. Compare them with directory entries, expected file sizes, and known-good copies.

Never run FORMAT to “repair” a mount failure. Formatting creates new filesystem metadata and can overwrite the structures needed for recovery. Likewise, partitioning tools address a layer outside the FAT volume and should not be used until the partition boundaries are established independently.

FAT remains valuable because its structures are compact and documented, not because it is immune to ambiguity. FreeDOS’s own headers show the rules directly: cluster thresholds, reserved markers, BPB variants, 32-byte directory entries, LFN slots, and mirror flags. Respecting those details is what turns a simple mental model into a safe implementation.

Related:

Sources:

Comments