Skip to content

Commit

Permalink
Make the FAT media descriptor match everywhere.
Browse files Browse the repository at this point in the history
In a FAT12 or FAT16 filesystem, the first entry's first byte must
match the media descriptor given in the BPB (BIOS Parameter Block,
part of the boot sector).  This gives a kind of check of the disk
geometry: on an unpartitioned disk (like a floppy or ZIP disk), the
BPB can be read with the wrong geometry, but to properly locate the
FAT, the geometry must be correct.

Many OSs don't check that these match, but a few do, such as FreeBSD
(both in the kernel msdos filesystem driver, and in fsck_msdosfs).  If
they don't match, the mount will fail with an unhelpful error message.

Previously, the media descriptor was 0xf8 in the BPB, but 0xf0 in the
FAT.  This patch changes them to 0xf0 everywhere.

There were different values used for different disk geometries before
disk addressing was reformed in the 90s, but since then only 0xf0 and
0xf8 are in common use.  Typically, 0xf0 is used for a filesystem
within an unpartitioned medium (such as a floppy disk), and 0xf8 is
used for a filesystem within a partition (such as a hard disk).

Since the UF2 bootloader emulates an unpartitioned removable medium,
0xf0 seemed appropriate.

See also the description of the media descriptor, offset 0x15, at
https://en.wikipedia.org/w/index.php?title=Design_of_the_FAT_file_system&oldid=920681387#BIOS_Parameter_Block
particularly the last few paragraphs which note that it must match the
FAT ID.
  • Loading branch information
piquan committed Oct 28, 2019
1 parent 765e915 commit 84c32dc
Showing 1 changed file with 3 additions and 3 deletions.
6 changes: 3 additions & 3 deletions src/fat.c
Original file line number Diff line number Diff line change
Expand Up @@ -115,11 +115,11 @@ static const FAT_BootBlock BootBlock = {
.FATCopies = 2,
.RootDirectoryEntries = (ROOT_DIR_SECTORS * DIRENTRIES_PER_SECTOR),
.TotalSectors16 = NUM_FAT_BLOCKS - 2,
.MediaDescriptor = 0xF8,
.MediaDescriptor = 0xf0, // typical for unpartitioned disks
.SectorsPerFAT = SECTORS_PER_FAT,
.SectorsPerTrack = 1,
.Heads = 1,
.PhysicalDriveNum = 0x80, // to match MediaDescriptor of 0xF8
.PhysicalDriveNum = 0x00, // to match MediaDescriptor of 0xf0
.ExtendedBootSig = 0x29,
.VolumeSerialNumber = 0x00420042,
.VolumeLabel = VOLUME_LABEL,
Expand Down Expand Up @@ -152,7 +152,7 @@ void read_block(uint32_t block_no, uint8_t *data) {
sectionIdx -= SECTORS_PER_FAT; // second FAT is same as the first...
#if USE_FAT
if (sectionIdx == 0) {
data[0] = 0xf0;
data[0] = 0xf0; // must match MediaDescriptor
// WARNING -- code presumes only one NULL .content for .UF2 file
// and all non-NULL .content fit in one sector
// and requires it be the last element of the array
Expand Down

0 comments on commit 84c32dc

Please sign in to comment.