Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Extensible File Allocation Table (exFAT) file system format

The Extensible File Allocation Table (exFAT) file system format is a successor of the File Allocation Table (FAT) file system format.

Overview

An exFAT file system consists of:

  • Main boot region (11 sectors)
    • boot sector (or boot record)
    • 7 extended boot sectors; can contain a sector signature (“\x55\xaa”)
    • OEM parameters sector; can contain a sector signature (“\x55\xaa”)
    • Reserved sector; can contain a sector signature (“\x55\xaa”)
    • boot checksum sector
  • Backup boot region (11 sectors)
    • boot sector (or boot record)
    • 7 extended boot sectors; can contain a sector signature (“\x55\xaa”)
    • OEM parameters sector; can contain a sector signature (“\x55\xaa”)
    • Reserved sector; can contain a sector signature (“\x55\xaa”)
    • boot checksum sector
  • File Allocation Table region
    • Aligment padding
    • First cluster block allocation tables
    • Zero or more backup block allocation tables
  • Data region
    • Aligment padding
    • Cluster heap
    • File and directory data

Characteristics

CharacteristicsDescription
Byte orderlittle-endian
Date and time valuesFAT date and time, in local time with UTC offset
Character stringsUCS-2 little-endian, which allows for unpaired Unicode surrogates such as "U+d800" and "U+dc00"

Boot record

The boot record is stored in the first sector of the volume.

The boot record is at least 512 bytes in size and consists of:

OffsetSizeValueDescription
03"\xeb\x76\x90"Boot entry point (JMP +120, NOP)
38"EXFAT\x20\x20\x20"File system signature (or OEM name)
11530Unknown (reserved), which must be 0
648Partition offset
728Total number of sectors
804Cluster block allocation table start sector
844Cluster block allocation table size, in number of sectors, which must be non 0
884Cluster heap start sector
924Number of clusters
964Root directory start cluster
1004Volume serial number
1041Format revision minor number
10511Format revision major number
1062Volume flags
1081Bytes per sector, which is stored as 2^n, for example 9 is 2^9 = 512. The bytes per sector value must be 512, 1024, 2048 or 4096
1091Sectors per cluster block, which is stored as 2^n, for example 3 is 2^3 = 8. The sectors per cluster block must be 1 upto 32M (2^25)
1101Number of cluster block allocation tables
1111Drive number
1121Unknown (percent in use), which contains the percentage of allocated cluster blocks in the cluster heap of 0xff if not available
1137Unknown (reserved)
120390Used for boot code
5102"\x55\xaa"Sector signature

Volume flags

ValueIdentifierDescription
0x0001ActiveFatActive FAT, where 0 represents the first FAT
0x0002VolumeDirtyIs dirty
0x0004MediaFailureHas media failures
0x0008ClearToZeroMust be cleared
0xfff0Unknown (reserved)

Boot checksum sector

The boot checksum sector is at least 512 bytes in size and consists of:

OffsetSizeValueDescription
04Boot checksum
44Copy of boot checksum
84Copy of boot checksum
124Copy of boot checksum
16496Unknown (empty values)
checksum = 0

for index in range(0, 11 * bytes_per_sector):
    # Ignore the volume flags and percent in use values.
    if index in (106, 107, 112):
        continue

    carry = 0x80000000 if (checksum & 1) else 0
    checksum = carry + (checksum >> 1) + sectors[index]
    checksum &= 0xFFFFFFFF

Cluster block allocation table

A cluster block allocation table consists of:

  • One ore more cluster block allocation table entries

Cluster block allocation table entry

A cluster block allocation table entry is 32 bits in size and consists of:

OffsetSizeValueDescription
032 bitsData cluster number

Where the data cluster number has the following meanings:

Value(s)Description
0x00000000Unused (free) cluster
0x00000001Unknown (invalid)
0x00000002 - 0xffffffefUsed cluster
0xfffffff0 - 0xfffffff6Reserved
0xfffffff7Bad cluster
0xfffffff8 - 0xffffffffEnd of cluster chain

Cluster heap

A cluster heap consists of:

  • One ore more sector allocation table entries

Sector allocation table entry

A sector allocation table entry is 32 bits in size and consists of:

OffsetSizeValueDescription
032 bitsData sector number

Directory

A directory consists of:

  • Zero or more directory entries
  • Terminator directory entry

Directory entry

A directory entry is 32 bytes in size and consists of:

OffsetSizeValueDescription
01Entry type
11Entry flags
119Entry data
204Data start cluster
248Data size

Directory entry type

OffsetSizeValueDescription
0.05 bitsType type code
0.51 bitIs non-critical (also referred to as type importance)
0.61 bitIs secondary entry (also referred to as type category)
0.71 bitIn use
ValueDescription
0x00Terminator directory entry
0x01 - 0x7fUnused
0x80Invalid
0x81 - 0xffUsed
Directory entry type codes
ValueDescription
Critical and primary
0x81Allocation bitmap
0x82Case folding mappings
0x83Volume label
0x85File entry
Non-critical and primary
0xa0Volume identifier
0xa1TexFAT padding
Critical and secondary
0xc0Data stream
0xc1File (entry) name
Non-critical and secondary
0xe0Vendor extension
0xe1Vendor allocation

Directory entry flags

OffsetSizeValueDescription
0.01 bitUnknown (AllocationPossible)
0.11 bitContinuous allocation (NoFatChain), if set do not use the cluster block allocation table
0.26 bitsUnknown
offset = ( ( cluster_block_number - 2 ) * cluster_block_size ) + cluster_chain_offset
Allocation bitmap record
OffsetSizeValueDescription
010x81Entry type
11Bitmap flags
2180Unknown (Reserved)
204Data start cluster
248Data size
Allocation bitmap flags
OffsetSizeValueDescription
0.01 bitUnknown (BitmapIdentifier)
0.17 bitsUnknown (reserved)
Case folding mappings record
OffsetSizeValueDescription
010x82Entry type
130Unknown (Reserved)
44Checksum of the case folding mappings data
8120Unknown (Reserved)
204Data start cluster
248Data size
Volume label record
OffsetSizeValueDescription
010x83Entry type
11Name size, in number of characters
222Name string, which contains an UCS-2 little-endian string without an end-of-string character
2480Unknown (Reserved)

Note that the volume label record should only be stored in the first and/or second directory entry of the root directory.

File entry record
OffsetSizeValueDescription
010x85Entry type
11Entry flags
22Entry set checksum
42File attribute flags
620Unknown (Reserved)
82Creation time
102Creation date
122Last modification time
142Last modification date
162Last access time
182Last access date
201Creation time fraction of seconds, which contains fraction of 2-seconds in 10 ms intervals
211Last modification time fraction of seconds, which contains fraction of 2-seconds in 10 ms intervals
221Creation time UTC offset, which contains number of 15 minute intervals of the time relative to UTC, where an MSB of 1 indicates the offset is valid (and 0 invalid)
231Last modification time UTC offset, which contains number of 15 minute intervals of the time relative to UTC, where an MSB of 1 indicates the offset is valid (and 0 invalid)
241Last access time UTC offset, which contains number of 15 minute intervals of the time relative to UTC, where an MSB of 1 indicates the offset is valid (and 0 invalid)
2570Unknown (Reserved)
Volume identifier record
OffsetSizeValueDescription
010xa0Entry type
11Entry flags
22Entry set checksum
42Unknown (Flags)
616Volume identifier, which contains a GUID
22100Unknown (Reserved)
Data stream record
OffsetSizeValueDescription
010xc0Entry type
11Entry flags
210Unknown (Reserved)
31Name size, in number of characters
42Name hash
620Unknown (Reserved)
88Valid data size
1640Unknown (Reserved)
204Data start cluster
248Data size
File name record
OffsetSizeValueDescription
010xc1Entry type
11Entry flags
230Name string, which contains an UCS-2 little-endian string without an end-of-string character

File attribute flags

ValueDescription
0x0001Read-only
0x0002Hidden
0x0004System
0x0008Is volume label
0x0010Is directory
0x0020Archive
0x0040Is device
0x0080Unused (reserved)

Checksum

The checksum calculation uses Rotate Right by 1 (ROR1).

checksum = 0

for byte_value in data:
    msb = 0x80000000 if (checksum & 1) else 0
    checksum = (msb + (checksum >> 1) + byte_value) & 0xffffffff

References