exFAT 文件系统规范

1 简介

exFAT 文件系统是 FAT32 文件系统系列中的 FAT32 的继任者。 此规范介绍 exFAT 文件系统,并提供实现 exFAT 文件系统所需的所有信息。

1.1 设计目标

exFAT 文件系统有三个中心设计目标, (请参阅以下) 的列表。

  1. 保留基于 FAT 的文件系统的简单性。

    基于 FAT 的文件系统的两个优势是它们的相对简单性和易于实现。 在前身的精神下,实施者应该发现 exFAT 相对简单且易于实现。

  2. 启用非常大的文件和存储设备。

    exFAT 文件系统使用 64 位来描述文件大小,从而启用依赖于非常大文件的应用程序。 exFAT 文件系统还允许群集大小达 32MB,从而有效地启用非常大的存储设备。

  3. 将扩展性纳入未来创新。

    exFAT 文件系统将扩展性纳入其设计,使文件系统能够跟上存储和使用情况变化的创新步伐。

1.2 特定术语

在此规范的上下文中,某些术语 (请参阅 表 1) 具有 exFAT 文件系统设计和实现的特定含义。

具有非常具体含义的术语的表 1 定义

条款 定义
此规范使用术语“应”来描述强制行为。
建议值 此规范使用术语“应”来描述强烈建议的行为,但不强制行为。
五月 此规范使用术语“may”来描述可选行为。
必需 此术语描述实现应修改的字段或结构,并解释为此规范所描述的字段或结构。
可选 此术语描述实现可能或可能不支持的字段或结构。 如果实现支持给定的可选字段或结构,应对其进行修改,并将字段或结构解释为此规范。
Undefined 此术语描述实现可以根据需要修改的字段或结构内容 (,即在设置周围的字段或结构时,) 明确为零,不得解释为保留任何特定含义。
预留

此术语介绍实现的字段或结构内容:

  1. 应初始化为零,不应用于任何目的

  2. 不应解释,除非计算校验和

  3. 应在修改周围字段或结构的操作之间保留

1.3 常见首字母缩略词全文

此规范使用个人计算机行业的缩写词 (请参阅 表 2) 。

表 2 常见首字母缩略词全文

首字母缩写词 全文
ASCII 美国信息交换标准代码
BIOS 基本输入输出系统
CPU 中央处理单元
exFAT 可扩展文件分配表
FAT 文件分配表
FAT12 文件分配表,12 位群集索引
FAT16 文件分配表,16 位群集索引
FAT32 文件分配表,32 位群集索引
GPT GUID 分区表
GUID 全局唯一标识符 (请参阅 第 10.1 节)
INT 中断
MBR 主启动记录
texFAT 事务安全 exFAT
UTC 协调世界时

1.4 默认字段和结构限定符

此规范中的字段和结构具有以下限定符, (请参阅以下) 的列表,除非另有说明。

  1. 未签名

  2. 使用十进制表示法描述值,否则未指出;此规范使用帖子修复字母“h”来表示十六进制数字,并将 GUID 括在大括号中

  3. 采用小端格式

  4. 不需要字符串的 null 终止字符

1.5 Windows CE 和 TexFAT

TexFAT 是 exFAT 的扩展,用于在基本文件系统之上添加事务安全的操作语义。 TexFAT 由Windows CE使用。 TexFAT 需要使用两个 FAT 和分配位图,以便在事务中使用。 它还定义了多个其他结构,包括填充描述符和安全描述符。

2 卷结构

卷是存储和检索用户数据所需的所有文件系统结构和数据空间集。 所有 exFAT 卷都包含四个区域, (请参阅 表 3) 。

表 3 卷结构

子区域名称

Offset

(扇区)

大小

(扇区)

注释
主启动区域
主启动扇区 0 1 此子区域是必需的, 第 3.1 节 定义其内容。
主扩展启动扇区 1 8 此子区域是必需的, 第 3.2 节) 定义其内容。
主 OEM 参数 9 1 此子区域是必需的, 第 3.3 节 定义其内容。
主保留 10 1 此子区域是必需的,并且保留其内容。
主启动校验和 11 1 此子区域是必需的, 第 3.4 节 定义其内容。
备份启动区域
备份启动扇区 12 1 此子区域是必需的, 第 3.1 节 定义其内容。
备份扩展启动扇区 13 8 此子区域是必需的, 第 3.2 节 定义其内容。
备份 OEM 参数 21 1 此子区域是必需的, 第 3.3 节 定义其内容。
保留备份 22 1 此子区域是必需的,并且保留其内容。
备份启动校验和 23 1 此子区域是必需的, 第 3.4 节 定义其内容。
FAT 区域
FAT 对齐方式 24 FatOffset – 24

此子区域是必需的,并且其内容(如果有)未定义。

注意:Main 和 备份 Boot Sectors 都包含 FatOffset 字段。

第一个 FAT FatOffset FatLength

此子区域是必需的, 第 4.1 节 定义其内容。

注意:主和备份启动扇区均包含 FatOffset 和 FatLength 字段。

第二个 FAT FatOffset + FatLength FatLength * (NumberOfFats – 1)

此子区域是必需的, 第 4.1 节 定义其内容(如果有)。

注意:Main 和 备份 Boot 扇区均包含 FatOffset、FatLength 和 NumberOfFats 字段。 NumberOfFats 字段只能保存值 1 和 2。

数据区域
群集堆对齐 FatOffset + FatLength * NumberOfFats ClusterHeapOffset – (FatOffset + FatLength * NumberOfFats)

此子区域是必需的,并且其内容(如果有)未定义。

注意:主和备份启动扇区都包含 FatOffset、FatLength、NumberOfFats 和 ClusterHeapOffset 字段。 NumberOfFats 字段的有效值为 1 和 2。

群集堆 ClusterHeapOffset ClusterCount * 2SectorsPerClusterShift

此子区域是必需的, 第 5.1 节 定义其内容。

注意:Main 和 备份 启动扇区均包含 ClusterHeapOffset、ClusterCount 和 SectorsPerClusterShift 字段。

多余的空间 ClusterHeapOffset + ClusterCount * 2SectorsPerClusterShift VolumeLength – (ClusterHeapOffset + ClusterCount * 2SectorsPerClusterShift)

此子区域是必需的,并且其内容(如果有)未定义。

注意:Main 和 备份 启动扇区都包含 ClusterHeapOffset、ClusterCount、SectorsPerClusterShift 和 VolumeLength 字段。

3 个主要和备份启动区域

主启动区域提供所有必要的引导带式指令、标识信息和文件系统参数,使实现能够执行以下操作:

  1. 从 exFAT 卷启动计算机系统。

  2. 将卷上的文件系统标识为 exFAT。

  3. 发现 exFAT 文件系统结构的位置。

备份启动区域是主启动区域的备份。 当主启动区域处于不一致状态时,它有助于恢复 exFAT 卷。 除了更新启动带式指令等不频繁的情况外,实现不应修改备份启动区域的内容。

3.1 主和备份启动扇区子区域

主启动扇区包含用于从 exFAT 卷进行启动绑带的代码,以及描述卷结构的基本 exFAT 参数的代码, (请参阅 表 4) 。 BIOS、MBR 或其他启动带代理可能会检查此扇区,并可能加载和执行其中包含的任何启动带式指令。

备份启动扇区是主启动扇区的备份,其结构相同, (请参阅表 4) 。 备份启动扇区可能有助于恢复操作;但是,实现应将 VolumeFlags 和 PercentInUse 字段的内容视为过时。

在使用 Main 或 备份 Boot 扇区的内容之前,实现应通过验证其各自的 Boot Checksum 并确保其所有字段在其有效值范围内来验证其内容。

虽然初始格式操作将初始化 Main 和 备份 Boot 扇区的内容,但实现可以更新这些扇区 (,并根据需要更新各自的启动校验和) 。 但是,实现可能会更新 VolumeFlags 或 PercentInUse 字段,而无需更新各自的启动校验和, (校验和专门排除这两个字段) 。

表 4 主和备份启动扇区结构

字段名称

Offset

(字节)

大小

(字节)

注释
JumpBoot 0 3 此字段是必需的, 第 3.1.1 节 定义其内容。
FileSystemName 3 8 此字段是必需的, 第 3.1.2 节 定义其内容。
MustBeZero 11 53 此字段是必需的, 第 3.1.3 节 定义其内容。
PartitionOffset 64 8 此字段是必需的, 第 3.1.4 节 定义其内容。
VolumeLength 72 8 此字段是必需的, 第 3.1.5 节 定义其内容。
FatOffset 80 4 此字段是必需的, 第 3.1.6 节 定义其内容。
FatLength 84 4 此字段是必需的, 第 3.1.7 节 定义其内容。
ClusterHeapOffset 88 4 此字段是必需的, 第 3.1.8 节 定义其内容。
ClusterCount 92 4 此字段是必需的, 第 3.1.9 节 定义其内容。
FirstClusterOfRootDirectory 96 4 此字段是必需的, 第 3.1.10 节 定义其内容。
VolumeSerialNumber 100 4 此字段是必需的, 第 3.1.11 节 定义其内容。
FileSystemRevision 104 2 此字段是必需的, 第 3.1.12 节 定义其内容。
VolumeFlags 106 2 此字段是必需的, 第 3.1.13 节 定义其内容。
BytesPerSectorShift 108 1 此字段是必需的, 第 3.1.14 节 定义其内容。
SectorsPerClusterShift 109 1 此字段是必需的, 第 3.1.15 节 定义其内容。
NumberOfFats 110 1 此字段是必需的, 第 3.1.16 节 定义其内容。
DriveSelect 111 1 此字段是必需的, 第 3.1.17 节 定义其内容。
PercentInUse 112 1 此字段是必需的, 第 3.1.18 节 定义其内容。
预留 113 7 此字段是必需的,其内容是保留的。
BootCode 120 390 此字段是必需的, 第 3.1.19 节 定义其内容。
BootSignature 510 2 此字段是必需的, 第 3.1.20 节 定义其内容。
ExcessSpace 512 2BytesPerSectorShift – 512

此字段是必需的,并且其内容(如果有)未定义。

注意:主扇区和备份启动扇区均包含 BytesPerSectorShift 字段。

3.1.1 JumpBoot 字段

JumpBoot 字段应包含个人计算机中常见的 CPU 的跳转指令,在执行时,“跳转”CPU 以在 BootCode 字段中执行启动带式指令。

此字段的有效值为 (低阶字节到高阶字节的顺序,) EBh 76h 90h。

3.1.2 FileSystemName 字段

FileSystemName 字段应包含卷上的文件系统的名称。

此字段的有效值为 ASCII 字符“EXFAT”,其中包含三个尾随空格。

3.1.3 MustBeZero 字段

MustBeZero 字段应直接与打包的 BIOS 参数块在 FAT12/16/32 卷上使用的字节范围相对应。

此字段的有效值为 0,这有助于防止 FAT12/16/32 实现错误地装载 exFAT 卷。

3.1.4 PartitionOffset 字段

PartitionOffset 字段应描述承载给定 exFAT 卷的分区的媒体相对扇区偏移量。 此字段有助于在个人计算机上使用扩展 INT 13h 从卷启动带。

此字段的所有可能值都有效;但是,值 0 表示实现应忽略此字段。

3.1.5 VolumeLength 字段

VolumeLength 字段应描述扇区中给定 exFAT 卷的大小。

此字段的有效值范围应为:

  • 至少 220/ 2BytesPerSectorShift,这可确保最小卷不超过 1MB

  • 最多 264- 1,此字段可以描述的最大值。

    但是,如果多余的空间子区域的大小为 0,则此字段的最大值为 ClusterHeapOffset + (232- 11) * 2SectorsPerClusterShift

3.1.6 FatOffset 字段

FatOffset 字段应描述第一个 FAT 的卷相对扇区偏移量。 此字段使实现能够将第一个 FAT 与基础存储介质的特征保持一致。

此字段的有效值范围应为:

  • 至少 24 个,这占主启动和备份启动区域消耗的扇区

  • 大多数 ClusterHeapOffset - (FatLength * NumberOfFats) ,它占群集堆消耗的扇区

3.1.7 FatLength 字段

FatLength 字段应描述每个 FAT 表的长度(以扇区为单位) (卷最多可以包含两个 FAT) 。

此字段的有效值范围应为:

  • 至少 (ClusterCount + 2) * 22/ 2BytesPerSectorShiftrounded 到最接近的整数,这可确保每个 FAT 有足够的空间来描述群集堆中的所有群集

  • 最多 (ClusterHeapOffset - FatOffset) /NumberOfFats 向下舍入到最接近的整数,这可确保群集堆之前存在 FAT

此字段可能包含超出其下限 (的值,如上述) 所述,使第二个 FAT(如果存在)也与基础存储介质的特征保持一致。 超出 FAT 本身需要的内容(如果有)的内容是未定义的。

3.1.8 ClusterHeapOffset 字段

ClusterHeapOffset 字段应描述群集堆的卷相对扇区偏移量。 此字段使实现能够将群集堆与基础存储介质的特征保持一致。

此字段的有效值范围应为:

  • 至少 FatOffset + FatLength * NumberOfFats,以考虑上述所有区域消耗的扇区

  • 最多 232- 1 或 VolumeLength - (ClusterCount * 2SectorsPerClusterShift) ,无论计算的计算大小都更少

3.1.9 ClusterCount 字段

ClusterCount 字段应描述群集堆包含的群集数。

此字段的有效值应小于以下内容:

  • (VolumeLength - ClusterHeapOffset) / 2SectorsPerClusterShiftrounded 到最接近的整数,这正是群集堆的开头与卷末尾之间的群集数

  • 232- 11,这是 FAT 可以描述的最大群集数

ClusterCount 字段的值确定 FAT 的最小大小。 为了避免非常大的 FAT,实现可以通过通过 SectorsPerClusterShift 字段) 增加群集大小 (来控制群集堆中的群集数。 此规范建议群集堆中不超过 224- 2 个群集。 但是,实现应能够处理群集堆中最多 232- 11 个群集的卷。

3.1.10 FirstClusterOfRootDirectory 字段

FirstClusterOfRootDirectory 字段应包含根目录第一个群集的群集索引。 实现应尽一切努力将根目录的第一个群集置于群集中的第一个非坏群集中,群集使用分配位图和上写表。

此字段的有效值范围应为:

  • 至少 2,群集堆中第一个群集的索引

  • 大多数 ClusterCount + 1,群集堆中最后一个群集的索引

3.1.11 VolumeSerialNumber 字段

VolumeSerialNumber 字段应包含唯一的序列号。 这有助于实现区分不同的 exFAT 卷。 实现应结合 exFAT 卷的格式设置日期和时间来生成序列号。 合并日期和时间形成序列号的机制特定于实现。

此字段的所有可能值都有效。

3.1.12 FileSystemRevision 字段

FileSystemRevision 字段应描述给定卷上 exFAT 结构的主要和次要修订号。

高阶字节是主要修订号,低阶字节是次要修订号。 例如,如果高顺序字节包含值 01h,如果低顺序字节包含值 05h,则 FileSystemRevision 字段描述修订号 1.05。 同样,如果高阶字节包含值 0Ah,如果低阶字节包含值 0Fh,则 FileSystemRevision 字段描述修订号 10.15。

此字段的有效值范围应为:

  • 对于低阶字节,至少为 0,对于高阶字节,至少为 1

  • 对于低阶字节,最多为 99,对于高阶字节,为 99

此规范描述的 exFAT 的修订号为 1.00。 此规范的实现应装载具有主要修订号 1 的任何 exFAT 卷,并且不得将任何 exFAT 卷装载到任何其他主要修订号。 实现应遵循次要修订号,不得执行操作或创建给定次要修订号相应规范中未描述的任何文件系统结构。

3.1.13 VolumeFlags 字段

VolumeFlags 字段应包含指示 exFAT 卷上各种文件系统结构状态的标志, (请参阅 表 5) 。

在计算其各自的主启动或备份启动区域校验和时,实现不应包含此字段。 引用备份启动扇区时,实现应将此字段视为过时。

表 5 VolumeFlags 字段结构

字段名称

Offset

(位)

大小

(位)

注释
ActiveFat 0 1 此字段是必需的, 第 3.1.13.1 节 定义其内容。
VolumeDirty 1 1 此字段是必需的, 第 3.1.13.2 节 定义其内容。
MediaFailure 2 1 此字段是必需的, 第 3.1.13.3 节 定义其内容。
ClearToZero 3 1 此字段是必需的, 第 3.1.13.4 节 定义其内容。
保留 4 12 此字段是必需的,并且保留其内容。
3.1.13.1 ActiveFat 字段

ActiveFat 字段应描述哪些 FAT 和分配位图处于活动状态 (,实现应使用) ,如下所示:

  • 0,这意味着第一个 FAT 和第一个分配位图处于活动状态

  • 1,这意味着第二个 FAT 和第二个分配位图处于活动状态,并且仅当 NumberOfFats 字段包含值 2 时,才可能

实现应将非活动 FAT 和分配位图视为过时。 只有 TexFAT 感知实现才能切换活动 FAT 和分配位图, (请参阅 第 7.1 节) 。

3.1.13.2 VolumeDirty 字段

VolumeDirty 字段应描述卷是否脏,如下所示:

  • 0,这意味着卷可能处于一致状态

  • 1,这意味着卷可能处于不一致状态

实现在遇到文件系统元数据不一致时,应将此字段的值设置为 1,它们不会解析。 如果装载卷时,此字段的值为 1,则只有解析文件系统元数据不一致性的实现才能将此字段的值清除为 0。 只有在确保文件系统处于一致状态后,此类实现才会将此字段的值清除为 0。

如果装载卷时,此字段的值为 0,则实现应在更新文件系统元数据之前将此字段设置为 1,并将此字段清除为 0,类似于 第 8.1 节中所述的建议写入顺序。

3.1.13.3 MediaFailure Field

MediaFailure 字段应描述实现是否已发现媒体故障,如下所示:

  • 0,这意味着托管媒体未报告故障,或者 FAT 中已记录任何已知故障为“坏”群集

  • 1,这意味着托管媒体 (报告失败,即读取或写入操作失败)

实现应在以下情况下将此字段设置为 1:

  1. 托管媒体无法尝试访问卷中的任何区域

  2. 实现已用尽访问重试算法(如果有)

如果装载卷时,此字段的值为 1,则实现会扫描整个卷中的媒体故障,并将所有故障记录为 FAT (中的“坏”群集,否则,) 可能会将此字段的值清除为 0。

3.1.13.4 ClearToZero 字段

ClearToZero 字段在此规范中没有意义。

此字段的有效值为:

  • 0,没有任何特定含义

  • 1,这意味着实现应在修改任何文件系统结构、目录或文件之前将此字段清除为 0

3.1.14 BytesPerSectorShift 字段

BytesPerSectorShift 字段应描述每个扇区表示为 log2 (N) 的字节数,其中 N 是每个扇区字节数。 例如,对于每个扇区 512 字节,此字段的值为 9。

此字段的有效值范围应为:

  • ) 至少 9 个 (扇区大小为 512 字节,这是 exFAT 卷可能的最大扇区

  • ) 最多 12 个 (扇区大小为 4096 字节,这是个人计算机中常见的 CPU 内存页大小

3.1.15 SectorsPerClusterShift 字段

“SectorsPerClusterShift”字段应描述表示为 log2 (N) 的每个群集的扇区数,其中 N 是每个群集的扇区数。 例如,对于每个群集 8 个扇区,此字段的值为 3。

此字段的有效值范围应为:

  • 每个群集至少 0 (1 个扇区) ,这是可能的最小群集

  • 最多 25 - BytesPerSectorShift,计算结果为 32MB 的群集大小

3.1.16 NumberOfFats 字段

NumberOfFats 字段应描述卷包含的 FAT 数和分配位图的数量。

此字段的有效值范围应为:

  • 1,表示卷仅包含第一个 FAT 和 First 分配位图

  • 2,指示卷包含第一个 FAT、第二个 FAT、第一个分配位图和第二个分配位图:此值仅适用于 TexFAT 卷

3.1.17 DriveSelect 字段

DriveSelect 字段应包含扩展的 INT 13h 驱动器号,这有助于在个人计算机上使用扩展 INT 13h 从此卷启动带。

此字段的所有可能值都有效。 以前基于 FAT 的文件系统中的类似字段经常包含值 80h。

3.1.18 PercentInUse 字段

PercentInUse 字段应描述已分配的群集堆中的群集百分比。

此字段的有效值范围应为:

  • 在 0 到 100 之间(包括 0 到 100 之间)(即群集堆中已分配的群集的百分比)向下舍入到最接近的整数

  • 完全 FFh,它指示群集堆中已分配群集的百分比不可用

实现应更改此字段的值,以反映群集堆中群集分配的更改,或者将其更改为 FFh。

在计算其各自的主启动或备份启动区域校验和时,实现不应包含此字段。 引用备份启动扇区时,实现应将此字段视为过时。

3.1.19 BootCode 字段

BootCode 字段应包含启动带式指令。 实现可以使用启动带式计算机系统所需的 CPU 指令填充此字段。 不提供启动带指令的实现应将此字段中的每个字节初始化为 F4h, (个人计算机中常见的 CPU 的停止指令) 作为格式操作的一部分。

3.1.20 BootSignature 字段

BootSignature 字段应描述给定扇区的意图是否为启动扇区。

此字段的有效值为 AA55h。 此字段中的任何其他值使其各自的启动扇区失效。 实现应在根据相应启动扇区的任何其他字段之前验证此字段的内容。

3.2 主和备份扩展启动扇区子区域

主扩展启动扇区的每个扇区具有相同的结构:但是,每个扇区可以保存不同的启动带式指令, (请参阅表 6) 。 启动带代理(如主启动扇区中的启动带式指令、备用 BIOS 实现或嵌入式系统的固件)可能会加载这些扇区并执行它们所包含的指令。

备份扩展启动扇区是主扩展启动扇区备份,并且具有相同的结构, (请参阅表 6) 。

在执行 Main 或 备份 扩展启动扇区的说明之前,实现应通过确保每个扇区的 ExtendedBootSignature 字段包含其规定的值来验证其内容。

虽然初始格式操作将初始化 Main 和 备份 扩展启动扇区的内容,但实现可以更新这些扇区 (,并根据需要更新各自的启动校验和) 。

表 6 扩展启动扇区结构

字段名称

Offset

(字节)

大小

(字节)

注释
ExtendedBootCode 0 2BytesPerSectorShift – 4

此字段是必需的, 第 3.2.1 节 定义其内容。

注意:主和备份启动扇区都包含 BytesPerSectorShift 字段。

ExtendedBootSignature 2BytesPerSectorShift – 4 4

此字段是必需的, 第 3.2.2 节 定义其内容。

注意:主和备份启动扇区都包含 BytesPerSectorShift 字段。

3.2.1 ExtendedBootCode 字段

ExtendedBootCode 字段应包含启动带式指令。 实现可以使用启动带式计算机系统所需的 CPU 指令填充此字段。 不提供启动带指令的实现应将此字段中的每个字节初始化为 00 小时,作为其格式操作的一部分。

3.2.2 ExtendedBootSignature Field

ExtendedBootSignature 字段应描述给定扇区的意图是否为扩展启动扇区。

此字段的有效值为 AA550000h。 此字段中的任何其他值使其各自的 Main 或 备份 扩展启动扇区失效。 实现应在根据相应扩展启动扇区的任何其他字段之前验证此字段的内容。

3.3 主和备份 OEM 参数子区域

主 OEM 参数子区域包含 10 个参数结构,这些结构可能包含制造商特定的信息, (请参阅 表 7) 。 每个十个参数结构派生自泛型参数模板, (请参阅 第 3.3.2 节) 。 制造商可以从泛型参数模板派生其自己的自定义参数结构。 此规范本身定义了两个参数结构:Null 参数 (请参阅 第 3.3.3 节) 和 Flash 参数 (请参阅 第 3.3.4 节) 。

备份 OEM 参数是主 OEM 参数的备份,并且具有相同的结构, (请参阅表 7) 。

在使用 Main 或 备份 OEM 参数的内容之前,实现应通过验证各自的启动校验和来验证其内容。

制造商应使用自己的自定义参数结构(如果有)和任何其他参数结构填充 Main 和 备份 OEM 参数。 后续格式操作应保留 Main 和 备份 OEM 参数的内容。

实现可以根据 (更新 Main 和 备份 OEM 参数,并更新各自的启动校验和) 。

表 7 OEM 参数结构

字段名称

Offset

(字节)

大小

(字节)

注释
Parameters[0] 0 48 此字段是必需的, 第 3.3.1 节 定义其内容。

.

.

.

.

.

.

.

.

.

.

.

.

Parameters[9] 432 48 此字段是必需的, 第 3.3.1 节 定义其内容。
预留 480 2BytesPerSectorShift – 480

此字段是必需的,并且保留其内容。

注意:主和备份启动扇区都包含 BytesPerSectorShift 字段。

3.3.1 参数[0] ...Parameters[9]

此数组中的每个 Parameters 字段都包含一个参数结构,该结构派生自泛型参数模板 (请参阅 第 3.3.2 节) 。 任何未使用的参数字段应描述为包含 Null 参数结构, (请参阅 第 3.3.3 节) 。

3.3.2 通用参数模板

泛型参数模板提供参数结构的基本定义, (请参阅 表 8) 。 所有参数结构都派生自此模板。 必须支持此泛型参数模板。

表 8 泛型参数模板

字段名称

Offset

(字节)

大小

(字节)

注释
ParametersGuid 0 16 此字段是必需的, 第 3.3.2.1 节 定义其内容。
CustomDefined 16 32 此字段是必需的,并且派生自此模板的结构定义其内容。
3.3.2.1 ParametersGuid 字段

ParametersGuid 字段应描述 GUID,该 GUID 确定给定参数结构的其余部分的布局。

此字段的所有可能值都有效;但是,制造商应使用 GUID 生成工具(如GuidGen.exe)从此模板派生自定义参数结构时选择 GUID。

3.3.3 Null 参数

Null 参数结构派生自泛型参数模板 (请参阅 第 3.3.2 节) ,并描述未使用的参数字段, (请参阅 表 9) 。 创建或更新 OEM 参数结构时,实现应使用 Null 参数结构填充未使用的 Parameters 字段。 此外,在创建或更新 OEM 参数结构时,实现应合并数组末尾的 Null 参数结构,从而将所有其他 Parameters 结构保留在 OEM 参数结构的开头。

必须支持 Null 参数结构。

表 9 Null 参数结构

字段名称

Offset

(字节)

大小

(字节)

注释
ParametersGuid 0 16 此字段是必需的, 第 3.3.3.1 节 定义其内容。
预留 16 32 此字段是必需的,并且保留其内容。
3.3.3.1 ParametersGuid 字段

ParametersGuid 字段应符合泛型参数模板提供的定义, (请参阅 第 3.3.2.1 节) 。

此字段的有效值为 GUID 表示法 {00000000-0000-0000-0000-000000000000}。

3.3.4 闪存参数

Flash 参数结构派生自泛型参数模板, (请参阅 第 3.3.2 节) ,其中包含闪存媒体 (的参数,请参阅 表 10) 。 基于闪存的存储设备的制造商可能会填充参数字段, (最好使用此参数结构) Parameters[0] 字段。 实现可以使用 Flash 参数结构中的信息来优化读取/写入期间的访问操作,以及文件系统结构在媒体格式设置时保持一致。

对 Flash 参数结构的支持是可选的。

表 10 闪存参数结构

字段名称

Offset

(字节)

大小

(字节)

注释
ParametersGuid 0 16 此字段是必需的, 第 3.3.4.1 节 定义其内容。
EraseBlockSize 16 4 此字段是必需的, 第 3.3.4.2 节 定义其内容。
PageSize 20 4 此字段是必需的, 第 3.3.4.3 节 定义其内容。
SpareSectors 24 4 此字段是必需的, 第 3.3.4.4 节 定义其内容。
RandomAccessTime 28 4 此字段是必需的, 第 3.3.4.5 节 定义其内容。
ProgrammingTime 32 4 此字段是必需的, 第 3.3.4.6 节 定义其内容。
ReadCycle 36 4 此字段是必需的, 第 3.3.4.7 节 定义其内容。
WriteCycle 40 4 此字段是必需的, 第 3.3.4.8 节 定义其内容。
预留 44 4 此字段是必需的,其内容是保留的。

除 ParametersGuid 字段外,所有 Flash Parameters 字段的所有可能值都是有效的。 但是,值 0 表示字段实际上毫无意义 (实现应忽略给定字段) 。

3.3.4.1 ParametersGuid 字段

ParametersGuid 字段应符合泛型参数模板中提供的定义, (请参阅 第 3.3.2.1 节) 。

此字段的有效值为 {0A0C7E46-3399-4021-90C8-FA6D389C4BA2}。

3.3.4.2 EraseBlockSize 字段

EraseBlockSize 字段应描述闪存介质擦除块的大小(以字节为单位)。

3.3.4.3 PageSize 字段

PageSize 字段应描述闪存媒体页面的大小(以字节为单位)。

3.3.4.4 备用对象字段

SpareSectors 字段应描述闪存媒体对其内部稀疏操作可用的扇区的数量。

3.3.4.5 RandomAccessTime 字段

RandomAccessTime 字段应描述闪存介质的平均随机访问时间(以纳米秒为单位)。

3.3.4.6 编程时间字段

ProgrammingTime 字段应以纳米秒为单位描述闪存介质的平均编程时间。

3.3.4.7 ReadCycle 字段

ReadCycle 字段应以纳米秒为单位描述闪存介质的平均读取周期时间。

3.3.4.8 WriteCycle 字段

WriteCycle 字段应以纳秒为单位描述平均写入周期时间。

3.4 主和备份启动校验和子区域

Main 和 备份 Boot Checksum 分别包含其各自启动区域中所有其他子区域内容的四字节校验和的重复模式。 校验和计算不应在其各自的启动扇区中包含 VolumeFlags 和 PercentInUse 字段, (请参阅 图 1) 。 四字节校验和的重复模式从头到尾填充其各自的启动校验和子区域。

在使用 Main 或 备份 Boot 区域中任何其他子区域的内容之前,实现应通过验证其各自的 Boot Checksum 来验证其内容。

虽然初始格式操作将使用重复校验和模式填充 Main 和 备份 Boot Checksum,但实现应更新这些扇区,因为其各自的启动区域中的其他扇区的内容会发生变化。

图 1 启动校验和计算

UInt32 BootChecksum
(
    UCHAR  * Sectors,        // points to an in-memory copy of the 11 sectors
    USHORT   BytesPerSector
)
{
    UInt32 NumberOfBytes = (UInt32)BytesPerSector * 11;
    UInt32 Checksum = 0;
    UInt32 Index;

    for (Index = 0; Index < NumberOfBytes; Index++)
    {
        if ((Index == 106) || (Index == 107) || (Index == 112))
        {
            continue;
        }
        Checksum = ((Checksum&1) ? 0x80000000 : 0) + (Checksum>>1) + (UInt32)Sectors[Index];
    }

    return Checksum;
}

4 文件分配表区域

文件分配表 (FAT) 区域最多可以包含两个 FAT,一个位于第一个 FAT 子区域中,另一个位于第二个 FAT 子区域中。 NumberOfFats 字段描述此区域包含的 FAT 数。 NumberOfFats 字段的有效值为 1 和 2。 因此,第一个 FAT 子区域始终包含 FAT。 如果 NumberOfFats 字段为 2,则第二个 FAT 子区域也包含 FAT。

VolumeFlags 字段的 ActiveFat 字段描述哪些 FAT 处于活动状态。 只有主启动扇区中的 VolumeFlags 字段是最新的。 实现应将不处于活动状态的 FAT 视为过时。 使用非活动 FAT 并在 FAT 之间切换是特定于实现的。

4.1 第一个和第二个 FAT 子区域

FAT 应描述群集堆中的群集链 (请参阅 表 11) 。 群集链是一系列群集,提供用于记录文件、目录和其他文件系统结构内容的空间。 FAT 表示群集链作为群集索引的单独链接列表。 除了前两个条目外,FAT 中的每个条目都表示一个群集。

表 11 文件分配表结构

字段名称

Offset

(字节)

大小

(字节)

注释
FatEntry[0] 0 4 此字段是必需的, 第 4.1.1 节 定义其内容。
FatEntry[1] 4 4 此字段是必需的, 第 4.1.2 节 定义其内容。
FatEntry[2] 8 4 此字段是必需的, 第 4.1.3 节 定义其内容。

.

.

.

.

.

.

.

.

.

.

.

.

FatEntry[ClusterCount+1] (ClusterCount + 1) * 4 4

此字段是必需的, 第 4.1.3 节 定义其内容。

ClusterCount + 1 永远不能超过 FFFFFFF6h。

注意:主和备份启动扇区均包含 ClusterCount 字段。

ExcessSpace (ClusterCount + 2) * 4 (FatLength * 2BytesPerSectorShift) – ( (ClusterCount + 2) * 4)

此字段是必需的,并且其内容(如果有)未定义。

注意:Main 和 备份 启动扇区均包含 ClusterCount、FatLength 和 BytesPerSectorShift 字段。

4.1.1 FatEntry[0] 字段

FatEntry[0] 字段应描述第一个字节中的媒体类型, (最低顺序字节) ,并将 FFh 包含在其余三个字节中。

媒体类型 (第一个字节) 应为 F8h。

4.1.2 FatEntry[1] 字段

FatEntry[1] 字段仅存在,因为历史优先级,并且不描述任何感兴趣的内容。

此字段的有效值为 FFFFFFFFh。 实现应将此字段初始化为其规定的值,不应将此字段用于任何目的。 实现不应解释此字段,并且应跨修改周围字段的操作保留其内容。

4.1.3 FatEntry[2] ...FatEntry[ClusterCount+1] 字段

此数组中的每个 FatEntry 字段应表示群集堆中的群集。 FatEntry[2] 表示群集堆中的第一个群集,FatEntry[ClusterCount+1] 表示群集堆中的最后一个群集。

这些字段的有效值范围应为:

  • 介于 2 和 ClusterCount + 1 之间,包括指向给定群集链中的下一个 FatEntry;给定的 FatEntry 不应指向给定群集链中前面的任何 FatEntry

  • 完全 FFFFFFF7h,它将给定 FatEntry 的相应群集标记为“bad”

  • 完全是 FFFFFFFFh,它将给定的 FatEntry 的相应群集标记为群集链的最后一个群集;这是任何给定群集链的最后一个 FatEntry 的唯一有效值

5 数据区域

数据区域包含群集堆,它为文件系统结构、目录和文件提供托管空间。

5.1 群集堆子区域

群集堆的结构非常简单, (请参阅 表 12) ;每个连续的扇区系列描述一个群集,因为 SectorsPerClusterShift 字段定义。 重要的是,群集堆的第一个群集具有索引 2,它直接对应于 FatEntry[2] 的索引。

在 exFAT 卷中,分配位图 (请参阅 第 7.1.5 节) 维护所有群集的分配状态记录。 这与 exFAT 的前任 (FAT12、FAT16 和 FAT32) 有很大区别,其中 FAT 维护了群集堆中所有群集的分配状态记录。

表 12 群集堆结构

字段名称

Offset

(扇区)

大小

(扇区)

注释
Cluster[2] ClusterHeapOffset 2SectorsPerClusterShift

此字段是必需的, 第 5.1.1 节 定义其内容。

注意:主和备份启动扇区都包含 ClusterHeapOffset 和 SectorsPerClusterShift 字段。

.

.

.

.

.

.

.

.

.

.

.

.

Cluster[ClusterCount+1] ClusterHeapOffset + (ClusterCount – 1) * 2SectorsPerClusterShift 2SectorsPerClusterShift

此字段是必需的, 第 5.1.1 节 定义其内容。

注意:Main 和 备份 Boot 扇区都包含 ClusterCount、ClusterHeapOffset 和 SectorsPerClusterShift 字段。

5.1.1 群集[2] ...Cluster[ClusterCount+1] 字段

此数组中的每个群集字段都是一系列连续扇区,其大小由 SectorsPerClusterShift 字段定义。

6 目录结构

exFAT 文件系统使用目录树方法来管理群集堆中存在的文件系统结构和文件。 目录在目录树中的父级和子级之间具有一对多关系。

FirstClusterOfRootDirectory 字段引用的目录是目录树的根目录。 所有其他目录以单向链接的方式从根目录降序。

每个目录由一系列目录条目组成, (请参阅 表 13) 。

一个或多个目录条目合并到一个目录条目集中,用于描述感兴趣的内容,例如文件系统结构、子目录或文件。

表 13 目录结构

字段名称

Offset

(字节)

大小

(字节)

注释
DirectoryEntry[0] 0 32 此字段是必需的, 第 6.1 节 定义其内容。

.

.

.

.

.

.

.

.

.

.

.

.

DirectoryEntry[N–1] (N – 1) * 32 32

此字段是必需的, 第 6.1 节 定义其内容。

N,DirectoryEntry 字段数,是包含给定目录的群集链的大小(以字节为单位),除以 DirectoryEntry 字段的大小,32 字节。

6.1 DirectoryEntry[0] ...DirectoryEntry[N--1]

此数组中的每个 DirectoryEntry 字段都派生自 Generic DirectoryEntry 模板, (请参阅 第 6.2 节) 。

6.2 Generic DirectoryEntry 模板

Generic DirectoryEntry 模板为目录条目提供基本定义, (请参阅 表 14) 。 所有目录条目结构都派生自此模板,只有 Microsoft 定义的目录条目结构有效, (exFAT 没有针对制造商定义的目录条目结构的预配,但第 7.8 节和第 7.9 节) 中定义除外。 必须解释 Generic DirectoryEntry 模板。

表 14 Generic DirectoryEntry 模板

字段名称

Offset

(字节)

大小

(字节)

注释
EntryType 0 1 此字段是必需的, 第 6.2.1 节 定义其内容。
CustomDefined 1 19 此字段是必需的,并且派生自此模板的结构可以定义其内容。
FirstCluster 20 4 此字段是必需的, 第 6.2.2 节 定义其内容。
DataLength 24 8 此字段是必需的, 第 6.2.3 节 定义其内容。

6.2.1 EntryType 字段

EntryType 字段具有三种使用模式,字段的值定义 (请参阅下面的列表) 。

  • 00h,这是目录结束标记,并适用以下条件:

    • 给定 DirectoryEntry 中的所有其他字段实际上都保留

    • 给定目录中的所有后续目录条目也是目录末尾标记

    • 目录结束标记仅在目录条目集外部有效

    • 实现可能根据需要覆盖目录结束标记

  • 在 01h 和 7Fh 之间(包括 7Fh),这是未使用的目录条目标记,并适用以下条件:

    • 给定 DirectoryEntry 中的所有其他字段实际上未定义

    • 未使用的目录条目仅在目录条目集之外有效

    • 实现可能根据需要覆盖未使用的目录条目

    • 此值范围对应于 InUse 字段 (请参阅包含值 0 的部分 6.2.1.4)

  • 介于 81h 和 FFh 之间,这是常规目录条目,满足以下条件:

    • EntryType 字段的内容 (请参阅 表 15) 确定 DirectoryEntry 结构的其余部分的布局

    • 此值范围(仅此值范围)在目录条目集中有效

    • 此值范围直接对应于 InUse 字段 (请参阅 包含值 1 的第 6.2.1.4 节)

若要防止修改 InUse 字段 (请参阅 第 6.2.1.4 节) 错误地导致目录结束标记,值为 80h 无效。

表 15 泛型 EntryType 字段结构

字段名称

Offset

(位)

大小

(位)

注释
TypeCode 0 5 此字段是必需的, 第 6.2.1.1 节 定义其内容。
TypeImportance 5 1 此字段是必需的, 第 6.2.1.2 节 定义其内容。
TypeCategory 6 1 此字段是必需的, 第 6.2.1.3 节 定义其内容。
InUse 7 1 此字段是必需的, 第 6.2.1.4 节 定义其内容。
6.2.1.1 TypeCode 字段

TypeCode 字段部分描述给定目录条目的特定类型。 此字段以及 TypeImportance 和 TypeCategory 字段 (分别看到 第 6.2.1.2节和第 6.2.1.3 节,分别) 唯一标识给定目录条目的类型。

此字段的所有可能值都有效,除非 TypeImportance 和 TypeCategory 字段都包含值 0;在这种情况下,此字段的值 0 无效。

6.2.1.2 TypeImportance 字段

TypeImportance 字段应描述给定目录条目的重要性。

此字段的有效值应为:

6.2.1.3 TypeCategory 字段

TypeCategory 字段应描述给定目录条目的类别。

此字段的有效值应为:

  • 0,这意味着给定的目录条目是主要 (请参阅 第 6.3 节)

  • 1,这意味着给定的目录条目是辅助目录 (请参阅 第 6.4 节)

6.2.1.4 InUse 字段

InUse 字段应描述是否使用给定的目录条目。

此字段的有效值应为:

  • 0,这意味着给定的目录条目未使用;这意味着给定结构实际上是未使用的目录条目

  • 1,这意味着给定的目录条目正在使用中;这意味着给定的结构是常规目录条目

6.2.2 FirstCluster 字段

FirstCluster 字段应包含与给定目录条目关联的群集堆中分配的第一个群集的索引。

此字段的有效值范围应为:

  • 完全为 0,这意味着不存在群集分配

  • 介于 2 和 ClusterCount + 1 之间,这是有效群集索引的范围

如果群集分配与派生结构不兼容,则从此模板派生的结构可以重新定义 FirstCluster 和 DataLength 字段。

6.2.3 DataLength 字段

DataLength 字段描述关联群集分配包含的数据的大小(以字节为单位)。

此字段的有效值范围为:

  • 至少 0;如果 FirstCluster 字段包含值 0,则此字段的唯一有效值为 0

  • 大多数 ClusterCount * 2SectorsPerClusterShift* 2BytesPerSectorShift

如果派生自此模板的结构不能用于派生结构,则如果无法为派生结构重新定义 FirstCluster 和 DataLength 字段。

6.3 通用主 DirectoryEntry 模板

目录条目集中的第一个目录条目应为主目录条目。 目录条目集中的所有后续目录条目(如果有)应为辅助目录条目, (请参阅 第 6.4) 节

必须能够解释泛型主 DirectoryEntry 模板。

所有主目录条目结构派生自泛型主 DirectoryEntry 模板 (请参阅 表 16) ,该表派生自 Generic DirectoryEntry 模板 (请参阅 第 6.2 节) 。

表 16 泛型主 DirectoryEntry 模板

字段名称

Offset

(字节)

大小

(字节)

注释
EntryType 0 1 此字段是必需的, 第 6.3.1 节 定义其内容。
SecondaryCount 1 1 此字段是必需的, 第 6.3.2 节 定义其内容。
SetChecksum 2 2 此字段是必需的, 第 6.3.3 节 定义其内容。
GeneralPrimaryFlags 4 2 此字段是必需的, 第 6.3.4 节 定义其内容。
CustomDefined 6 14 此字段是必需的,并且派生自此模板的结构定义其内容。
FirstCluster 20 4 此字段是必需的, 第 6.3.5 节 定义其内容。
DataLength 24 8 此字段是必需的, 第 6.3.6 节 定义其内容。

6.3.1 EntryType 字段

EntryType 字段应符合 Generic DirectoryEntry 模板中提供的定义, (请参阅 第 6.2.1 节) 。

6.3.1.1 TypeCode 字段

TypeCode 字段应符合 Generic DirectoryEntry 模板中提供的定义, (请参阅 第 6.2.1.1 节) 。

6.3.1.2 TypeImportance 字段

TypeImportance 字段应符合 Generic DirectoryEntry 模板中提供的定义, (请参阅 第 6.2.1.2 节) 。

6.3.1.2.1 关键主目录条目

关键主目录条目包含对正确管理 exFAT 卷至关重要的信息。 只有根目录包含关键主目录条目, (文件目录条目是例外,请参阅 第 7.4 节) 。

关键主目录条目的定义与主要 exFAT 修订号相关。 实现应支持所有关键主目录条目,并且只记录此规范定义的关键主目录条目结构。

6.3.1.2.2 良性主目录条目

良性主目录条目包含可用于管理 exFAT 卷的其他信息。 任何目录可能包含良性主目录条目。

良性主目录条目的定义与次要 exFAT 修订号相关。 支持此规范或任何后续规范的任何良性主目录条目是可选的。 无法识别的良性主目录条目将整个目录条目集呈现为无法识别 (超出适用目录条目模板的定义) 。

6.3.1.3 TypeCategory 字段

TypeCategory 字段应符合 Generic DirectoryEntry 模板中提供的定义, (请参阅 第 6.2.1.3 节) 。

对于此模板,此字段的有效值应为 0。

6.3.1.4 InUse 字段

InUse 字段应符合 Generic DirectoryEntry 模板中提供的定义, (请参阅 第 6.2.1.4 节) 。

6.3.2 SecondaryCount 字段

SecondaryCount 字段应描述紧跟给定主目录条目的辅助目录条目数。 这些辅助目录条目以及给定的主目录条目构成目录条目集。

此字段的有效值范围应为:

  • 至少 0,这意味着此主目录条目是目录条目集中的唯一条目

  • 最多 255 个,这意味着接下来的 255 个目录条目和此主目录条目构成目录条目集

从此模板派生的关键主目录条目结构可以重新定义 SecondaryCount 和 SetChecksum 字段。

6.3.3 SetChecksum 字段

SetChecksum 字段应包含给定目录条目集中所有目录条目的校验和。 但是,校验和排除此字段 (请参阅 图 2) 。 实现应在使用给定目录条目集中的任何其他目录条目之前验证此字段的内容是否有效。

从此模板派生的关键主目录条目结构可以重新定义 SecondaryCount 和 SetChecksum 字段。

图 2 EntrySetChecksum 计算

UInt16 EntrySetChecksum
(
    UCHAR * Entries,       // points to an in-memory copy of the directory entry set
    UCHAR   SecondaryCount
)
{
    UInt16 NumberOfBytes = ((UInt16)SecondaryCount + 1) * 32;
    UInt16 Checksum = 0;
    UInt16 Index;

    for (Index = 0; Index < NumberOfBytes; Index++)
    {
        if ((Index == 2) || (Index == 3))
        {
            continue;
        }
        Checksum = ((Checksum&1) ? 0x8000 : 0) + (Checksum>>1) +  (UInt16)Entries[Index];
    }
    return Checksum;
}

6.3.4 GeneralPrimaryFlags Field

GeneralPrimaryFlags 字段包含标志 (请参阅 表 17) 。

从此模板派生的关键主目录条目结构可能会重新定义此字段。

表 17 Generic GeneralPrimaryFlags 字段结构

字段名称

Offset

(位)

大小

(位)

注释
可能分配 0 1 此字段是必需的, 第 6.3.4.1 节 定义其内容。
NoFatChain 1 1 此字段是必需的, 第 6.3.4.2 节 定义其内容。
CustomDefined 2 14 此字段是必需的,派生自此模板的结构可以定义此字段。
6.3.4.1 可能分配字段

“可能分配”字段应描述给定目录条目是否可以在群集堆中分配。

此字段的有效值应为:

  • 0,这意味着群集的关联分配是不可能的,FirstCluster 和 DataLength 字段实际上是未定义的 (结构,派生自此模板的结构可能会重新定义这些字段)

  • 1,这意味着群集的关联分配是可能的,FirstCluster 和 DataLength 字段的定义

6.3.4.2 NoFatChain 字段

NoFatChain 字段应指示活动 FAT 是否描述给定分配的群集链。

此字段的有效值应为:

  • 0,这意味着分配群集链的相应 FAT 条目有效,实现应解释它们:如果“分配可能”字段包含值 0,或者“分配可能”字段包含值 1 且 FirstCluster 字段包含值 0,则此字段的唯一有效值为 0

  • 1,这意味着关联的分配是一个连续的群集系列:群集的相应 FAT 条目无效,实现不应解释它们:实现可以使用以下公式计算关联的分配的大小:DataLength/ (2SectorsPerClusterShift* 2BytesPerSectorShift) 向上舍入到最接近的整数

如果从此模板派生的关键主目录条目结构重新定义 GeneralPrimaryFlags 字段,则任何关联的分配群集链的相应 FAT 条目都有效。

6.3.5 FirstCluster 字段

FirstCluster 字段应符合 Generic DirectoryEntry 模板中提供的定义, (请参阅 第 6.2.2 节) 。

如果 NoFatChain 位为 1,则 FirstCluster 必须指向群集堆中的有效群集。

从此模板派生的关键主目录条目结构可能会重新定义 FirstCluster 和 DataLength 字段。 派生自此模板的其他结构只有在“分配可能”字段包含值 0 时,才能重新定义 FirstCluster 和 DataLength 字段。

6.3.6 DataLength 字段

DataLength 字段应符合 Generic DirectoryEntry 模板中提供的定义, (请参阅 第 6.2.3 节) 。

如果 NoFatChain 位为 1,则 DataLength 不得为零。 如果 FirstCluster 字段为零,则 DataLength 也必须为零。

从此模板派生的关键主目录条目结构可能会重新定义 FirstCluster 和 DataLength 字段。 派生自此模板的其他结构只有在“分配可能”字段包含值 0 时,才能重新定义 FirstCluster 和 DataLength 字段。

6.4 通用辅助目录Entry 模板

辅助目录条目的核心用途是提供有关目录条目集的其他信息。 必须能够解释泛型辅助 DirectoryEntry 模板。

关键和良性辅助目录条目的定义与次要 exFAT 修订号相关。 对此规范或后续规范的任何关键或良性辅助目录条目的支持是可选的。

所有辅助目录条目结构都派生自泛型辅助 DirectoryEntry 模板 (请参阅 表 18) ,该表派生自 Generic DirectoryEntry 模板, (请参阅 第 6.2 节) 。

表 18 Generic Secondary DirectoryEntry 模板

字段名称

Offset

(字节)

大小

(字节)

注释
EntryType 0 1 此字段是必需的, 第 6.4.1 节 定义其内容。
GeneralSecondaryFlags 1 1 此字段是必需的, 第 6.4.2 节 定义其内容。
CustomDefined 2 18 此字段是必需的,并且派生自此模板的结构定义其内容。
FirstCluster 20 4 此字段是必需的, 第 6.4.3 节 定义其内容。
DataLength 24 8 此字段是必需的, 第 6.4.4 节 定义其内容。

6.4.1 EntryType 字段

EntryType 字段应符合 Generic DirectoryEntry 模板中提供的定义, (请参阅 第 6.2.1 节)

6.4.1.1 TypeCode 字段

TypeCode 字段应符合 Generic DirectoryEntry 模板中提供的定义, (请参阅 第 6.2.1.1 节) 。

6.4.1.2 TypeImportance 字段

TypeImportance 字段应符合 Generic DirectoryEntry 模板中提供的定义, (请参阅 第 6.2.1.2 节) 。

6.4.1.2.1 关键辅助目录条目

关键辅助目录条目包含的信息对于正确管理其包含目录条目集至关重要。 尽管对任何特定关键辅助目录条目的支持是可选的,但无法识别的关键目录项条目会将整个目录条目集呈现为无法识别 (超出适用目录条目模板定义) 。

但是,如果目录项集包含实现无法识别的至少一个关键辅助目录条目,则实现最多应解释目录条目集中目录条目的模板,而不是与目录条目集中任何目录条目关联的数据包含 (文件目录条目是一个例外, 请参阅 第 7.4 节) 。

6.4.1.2.2 良性辅助目录条目

良性辅助目录条目包含其他信息,这些信息可能有助于管理其包含的目录条目集。 支持任何特定的良性辅助目录条目是可选的。 无法识别的良性辅助目录条目不会将整个目录条目集呈现为无法识别。

实现可能会忽略它无法识别的任何良性辅助条目。

6.4.1.3 TypeCategory 字段

TypeCategory 字段应符合 Generic DirectoryEntry 模板中提供的定义, (请参阅 第 6.2.1.3 节) 。

对于此模板,此字段的有效值为 1。

6.4.1.4 InUse 字段

InUse 字段应符合 Generic DirectoryEntry 模板中提供的定义, (请参阅 第 6.2.1.4 节) 。

6.4.2 GeneralSecondaryFlags Field

GeneralSecondaryFlags 字段包含标志 (请参阅 表 19) 。

表 19 泛型 GeneralSecondaryFlags 字段结构

字段名称

Offset

(位)

大小

(位)

注释
可能分配 0 1 此字段是必需的, 第 6.4.2.1 节 定义其内容。
NoFatChain 1 1 此字段是必需的, 第 6.4.2.2 节 定义其内容。
CustomDefined 2 6 此字段是必需的,派生自此模板的结构可以定义此字段。
6.4.2.1 分配可能字段

“分配可能”字段应具有与泛型主 DirectoryEntry 模板中同名字段的定义, (请参阅 第 6.3.4.1 节) 。

6.4.2.2 NoFatChain 字段

NoFatChain 字段应具有与泛型主 DirectoryEntry 模板中同名字段的定义, (请参阅 第 6.3.4.2 节) 。

6.4.3 FirstCluster 字段

FirstCluster 字段应符合 Generic DirectoryEntry 模板中提供的定义, (请参阅 第 6.2.2 节) 。

如果 NoFatChain 位为 1,则 FirstCluster 必须指向群集堆中的有效群集。

6.4.4 DataLength 字段

DataLength 字段应符合 Generic DirectoryEntry 模板中提供的定义, (请参阅 第 6.2.3 节) 。

如果 NoFatChain 位为 1,则 DataLength 不得为零。 如果 FirstCluster 字段为零,则 DataLength 也必须为零。

7 目录条目定义

exFAT 文件系统的修订版 1.00 定义了以下目录条目:

7.1 分配位图目录条目

在 exFAT 文件系统中,FAT 不描述群集的分配状态;而是分配位图。 群集堆中存在分配位图 (请参阅 第 7.1.5 节) ,并在根目录中具有相应的关键主目录条目, (请参阅 表 20) 。

NumberOfFats 字段确定根目录中的有效分配位图目录条目数。 如果 NumberOfFats 字段包含值 1,则分配位图目录条目的唯一有效数为 1。 此外,仅当它描述第一个分配位图 (请参阅 第 7.1.2.1 节) 时,一个分配位图目录条目才有效。 如果 NumberOfFats 字段包含值 2,则分配位图目录条目的唯一有效数目为 2。 此外,仅当两个分配位图目录条目描述第一个分配位图时,两个分配位图目录条目才有效,另一个条目描述第二个分配位图。

表 20 分配位图 DirectoryEntry 结构

字段名称

Offset

(字节)

大小

(字节)

注释
EntryType 0 1 此字段是必需的, 第 7.1.1 节 定义其内容。
BitmapFlags 1 1 此字段是必需的, 第 7.1.2 节 定义其内容。
保留 2 18 此字段是必需的,并且保留其内容。
FirstCluster 20 4 此字段是必需的, 第 7.1.3 节 定义其内容。
DataLength 24 8 此字段是必需的, 第 7.1.4 节 定义其内容。

7.1.1 EntryType 字段

EntryType 字段应符合泛型主 DirectoryEntry 模板中提供的定义, (请参阅 第 6.3.1 节) 。

7.1.1.1 TypeCode 字段

TypeCode 字段应符合泛型主 DirectoryEntry 模板中提供的定义, (请参阅 第 6.3.1.1 节) 。

对于分配位图目录条目,此字段的有效值为 1。

7.1.1.2 TypeImportance 字段

TypeImportance 字段应符合泛型主 DirectoryEntry 模板中提供的定义, (请参阅 第 6.3.1.2 节) 。

对于分配位图目录条目,此字段的有效值为 0。

7.1.1.3 TypeCategory 字段

TypeCategory 字段应符合泛型主目录模板中提供的定义, (请参阅 第 6.3.1.3 节) 。

7.1.1.4 InUse 字段

InUse 字段应符合泛型主目录Entry 模板中提供的定义, (请参阅 第 6.3.1.4 节) 。

7.1.2 BitmapFlags 字段

BitmapFlags 字段包含标志 (请参阅 表 21) 。

表 21 BitmapFlags 字段结构

字段名称

Offset

(位)

大小

(位)

注释
BitmapIdentifier 0 1 此字段是必需的, 第 7.1.2.1 节 定义其内容。
保留 1 7 此字段是必需的,其内容是保留的。
7.1.2.1 BitmapIdentifier 字段

BitmapIdentifier 字段应指示给定目录条目描述的分配位图。 实现应将第一个分配位图与第一个 FAT 结合使用,并将第二个分配位图与第二个 FAT 结合使用。 ActiveFat 字段描述哪些 FAT 和分配位图处于活动状态。

此字段的有效值应为:

  • 0,这意味着给定的目录条目描述了第一个分配位图

  • 1,这意味着给定的目录条目描述第二个分配位图,并且仅当 NumberOfFats 包含值 2 时,才可能

7.1.3 FirstCluster 字段

FirstCluster 字段应符合泛型 Primary DirectoryEntry 模板中提供的定义, (请参阅 第 6.3.5 节) 。

此字段包含群集链的第一个群集的索引,如 FAT 所述,该索引承载分配位图。

7.1.4 DataLength 字段

DataCluster 字段应符合泛型主目录Entry 模板中提供的定义, (请参阅 第 6.3.6 节) 。

7.1.5 分配位图

分配位图记录群集堆中的群集的分配状态。 分配位图中的每个位都指示其相应的群集是否可用于分配。

分配位图表示从最低到最高索引的群集 (请参阅 表 22) 。 出于历史原因,第一个群集具有索引 2。 注意:位图中的第一位是第一个字节的最低顺序位。

表 22 分配位图结构

字段名称

Offset

(位)

大小

(位)

注释
BitmapEntry[2] 0 1 此字段是必需的, 第 7.1.5.1 节 定义其内容。

.

.

.

.

.

.

.

.

.

.

.

.

BitmapEntry[ClusterCount+1] ClusterCount - 1 1

此字段是必需的, 第 7.1.5.1 节 定义其内容。

注意:主和备份启动扇区均包含 ClusterCount 字段。

预留 ClusterCount (DataLength * 8) – ClusterCount

此字段是必需的,并且保留其内容(如果有)。

注意:主和备份启动扇区均包含 ClusterCount 字段。

7.1.5.1 BitmapEntry[2] ...BitmapEntry[ClusterCount+1] 字段

此数组中的每个 BitmapEntry 字段表示群集堆中的群集。 BitmapEntry[2] 表示群集堆中的第一个群集,BitmapEntry[ClusterCount+1] 表示群集堆中的最后一个群集。

这些字段的有效值应为:

  • 0,其中将相应的群集描述为可用于分配

  • 1,其中将相应群集描述为不能用于分配 (群集分配可能已使用相应的群集,或者活动 FAT 可能会将相应的群集描述为错误的)

7.2 大小写表目录条目

Up-case 表定义从小写字符到大写字符的转换。 这一点很重要,因为文件名目录条目 (请参阅使用 Unicode 字符的第 7.7 节) ,并且 exFAT 文件系统不区分大小写且保留大小写。 群集堆中存在案例表 (请参阅 第 7.2.5 节) ,并在根目录中具有相应的关键主目录条目, (请参阅 表 23) 。 有效数量的 Up-case 表目录条目为 1。

由于 Up-case Table 与文件名之间的关系,实现不应修改 Up-case 表(格式操作的结果除外)。

表 23 Up-case Table DirectoryEntry 结构

字段名称

Offset

(字节)

大小

(字节)

注释
EntryType 0 1 此字段是必需的, 第 7.2.1 节 定义其内容。
Reserved1 1 3 此字段是必需的,其内容是保留的。
TableChecksum 4 4 此字段是必需的, 第 7.2.2 节 定义其内容。
Reserved2 8 12 此字段是必需的,其内容是保留的。
FirstCluster 20 4 此字段是必需的, 第 7.2.3 节 定义其内容。
DataLength 24 8 此字段是必需的, 第 7.2.4 节 定义其内容。

7.2.1 EntryType 字段

EntryType 字段应符合泛型主 DirectoryEntry 模板中提供的定义, (请参阅 第 6.3.1 节) 。

7.2.1.1 TypeCode 字段

TypeCode 字段应符合泛型主目录Entry 模板中提供的定义, (请参阅 第 6.3.1.1 节) 。

对于 Up-case Table 目录条目,此字段的有效值为 2。

7.2.1.2 TypeImportance 字段

TypeImportance 字段应符合泛型主 DirectoryEntry 模板中提供的定义, (请参阅 第 6.3.1.2 节) 。

对于 Up-case Table 目录条目,此字段的有效值为 0。

7.2.1.3 TypeCategory 字段

TypeCategory 字段应符合泛型主目录模板中提供的定义, (请参阅 第 6.3.1.3 节) 。

7.2.1.4 InUse 字段

InUse 字段应符合泛型主目录Entry 模板中提供的定义, (请参阅 第 6.3.1.4 节) 。

7.2.2 TableChecksum 字段

TableChecksum 字段包含 Up-case Table (校验和,FirstCluster 和 DataLength 字段描述) 。 实现应在使用 Up-case Table 之前验证此字段的内容是否有效。

图 3 TableChecksum 计算

UInt32 TableChecksum
(
    UCHAR  * Table,    // points to an in-memory copy of the up-case table
    UInt64   DataLength
)
{
    UInt32 Checksum = 0;
    UInt64 Index;

    for (Index = 0; Index < DataLength; Index++)
    {
        Checksum = ((Checksum&1) ? 0x80000000 : 0) + (Checksum>>1) + (UInt32)Table[Index];
    }

    return Checksum;
}

7.2.3 FirstCluster 字段

FirstCluster 字段应符合泛型 Primary DirectoryEntry 模板中提供的定义, (请参阅 第 6.3.5 节) 。

此字段包含群集链的第一个群集的索引,如 FAT 所述,该索引承载了 Up-case 表。

7.2.4 DataLength 字段

DataCluster 字段应符合泛型主目录Entry 模板中提供的定义, (请参阅 第 6.3.6 节) 。

7.2.5 大小写表

一个大小写表是一系列 Unicode 字符映射。 字符映射由 2 字节字段组成,上写表中字段的索引表示要上写的 Unicode 字符,以及表示上写 Unicode 字符的 2 字节字段。

前 128 个 Unicode 字符具有强制映射, (请参阅 表 24) 。 对于前 128 个 Unicode 字符中的任何一个,具有任何其他字符映射的 Up-case 表无效。

仅支持强制映射范围内的字符的实现可能会忽略上写表其余部分的映射。 此类实现仅在通过文件名目录条目创建或重命名 (文件时,才应使用强制映射范围中的字符,请参阅 第 7.7 节) 。 在对现有文件名进行大小写时,此类实现不得从非强制映射范围起写字符,但在生成的大小写文件名中保留它们不变, (这是部分上写) 。 比较文件名时,此类实现应仅将与非强制映射范围中的 Unicode 字符比较的名称不同的文件名视为等效项。 虽然此类文件名仅可能等效,但此类实现无法确保完全采用大小写的文件名不会与比较下的名称发生冲突。

表 24 必需前 128 个事例表条目

表索引 + 0 + 1 + 2 + 3 + 4 + 5 + 6 + 7
0000h 0000h 0001h 0002h 0003h 0004h 0005h 0006h 0007h
0008h 0008h 0009h 000Ah 000Bh 000Ch 000Dh 000Eh 000Fh
0010h 0010h 0011h 0012h 0013h 0014h 0015h 0016h 0017h
0018h 0018h 0019h 001Ah 001Bh 001Ch 001Dh 001Eh 001Fh
0020h 0020h 0021h 0022h 0023h 0024h 0025h 0026h 0027h
0028h 0028h 0029h 002Ah 002Bh 002Ch 002Dh 002Eh 002Fh
0030h 0030h 0031h 0032h 0033h 0034h 0035h 0036h 0037h
0038h 0038h 0039h 003Ah 003Bh 003Ch 003Dh 003Eh 003Fh
0040h 0040h 0041h 0042h 0043h 0044h 0045h 0046h 0047h
0048h 0048h 0049h 004Ah 004Bh 004Ch 004Dh 004Eh 004Fh
0050h 0050h 0051h 0052h 0053h 0054h 0055h 0056h 0057h
0058h 0058h 0059h 005Ah 005Bh 005Ch 005Dh 005Eh 005Fh
0060h 0060h 0041h 0042h 0043h 0044h 0045h 0046h 0047h
0068h 0048h 0049h 004Ah 004Bh 004Ch 004Dh 004Eh 004Fh
0070h 0050h 0051h 0052h 0053h 0054h 0055h 0056h 0057h
0078h 0058h 0059h 005Ah 007Bh 007Ch 007Dh 007Eh 007Fh

(注意:具有非标识上例映射的条目采用粗体)

格式化卷时,实现可以使用标识映射压缩以压缩格式生成大写表,因为 Unicode 字符空间的大部分概念都不是大小写 (,这意味着“小写”和“大写”字符等效) 。 实现通过将一系列标识映射与值 FFFFh 后跟的标识映射数来压缩起例表。

例如,实现可能表示前 100 个 (64 小时) 字符映射,其中包含压缩大小写表的以下 8 个条目:

FFFFh, 0061h, 0041h, 0042h, 0043h

前两个条目表示前 97 (61 小时) 字符, (从 0000h 到 0060h) 具有标识映射。 后续字符 0061h 到 0063h,分别映射到字符 0041h 到 0043h。

在格式化卷时提供压缩大小写表的功能是可选的。 但是,必须解释未压缩表和压缩大小写表的功能。 TableChecksum 字段的值始终符合卷上存在的情况,该表可能采用压缩格式或未压缩格式。

格式化卷时,实现应以压缩格式记录建议的事例表, (请参阅 表 25) ,其中 TableChecksum 字段的值为 E619D30Dh。

如果实现定义了自己的大小写表(压缩或未压缩),则该表应涵盖从字符代码 0000h 到 FFFFh(含) )的完整 Unicode 字符范围 (。