summaryrefslogtreecommitdiffstats
path: root/include/iprt/formats/fat.h
blob: d55c09577929968edcf28ebc57e4dc0d1e5cac24 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
/* $Id: fat.h $ */
/** @file
 * IPRT, File Allocation Table (FAT).
 */

/*
 * Copyright (C) 2017-2022 Oracle and/or its affiliates.
 *
 * This file is part of VirtualBox base platform packages, as
 * available from https://www.virtualbox.org.
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation, in version 3 of the
 * License.
 *
 * This program is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, see <https://www.gnu.org/licenses>.
 *
 * The contents of this file may alternatively be used under the terms
 * of the Common Development and Distribution License Version 1.0
 * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
 * in the VirtualBox distribution, in which case the provisions of the
 * CDDL are applicable instead of those of the GPL.
 *
 * You may elect to license modified versions of this file under the
 * terms and conditions of either the GPL or the CDDL or both.
 *
 * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
 */

#ifndef IPRT_INCLUDED_formats_fat_h
#define IPRT_INCLUDED_formats_fat_h
#ifndef RT_WITHOUT_PRAGMA_ONCE
# pragma once
#endif

#include <iprt/types.h>
#include <iprt/assertcompile.h>


/** @defgroup grp_rt_formats_fat    File Allocation Table (FAT) structures and definitions
 * @ingroup grp_rt_formats
 * @{
 */


/** @name FAT Media byte values
 * @remarks This isn't as simple as it's made out to be here!
 * @{ */
#define FATBPB_MEDIA_FLOPPY_8           UINT8_C(0xe5)
#define FATBPB_MEDIA_FLOPPY_5_DOT_25    UINT8_C(0xed)
#define FATBPB_MEDIA_FLOPPY_3_DOT_5     UINT8_C(0xf0)
/* incomplete, figure out as needed... */

/** Checks if @a a_bMedia is a valid media byte. */
#define FATBPB_MEDIA_IS_VALID(a_bMedia) (   (uint8_t)(a_bMedia) >= 0xf8 \
                                         || (uint8_t)(a_bMedia) == 0xf0 \
                                         || (uint8_t)(a_bMedia) == 0xf4 /* obscure - msdos 2.11 */ \
                                         || (uint8_t)(a_bMedia) == 0xf5 /* obscure - msdos 2.11 */ \
                                         || (uint8_t)(a_bMedia) == 0xed /* obscure - tandy 2000 */ \
                                         || (uint8_t)(a_bMedia) == 0xe5 /* obscure - tandy 2000 */ )
/** @} */

/** Checks if @a a_bFatId is a valid FAT ID byte.
 * @todo uncertain whether 0xf4 and 0xf5 should be allowed here too. */
#define FAT_ID_IS_VALID(a_bFatId) (   (uint8_t)(a_bFatId) >= 0xf8 \
                                   || (uint8_t)(a_bFatId) == 0xf0 \
                                   || (uint8_t)(a_bFatId) == 0xf4 /* obscure - msdos 2.11 */ \
                                   || (uint8_t)(a_bFatId) == 0xf5 /* obscure - msdos 2.11 */ \
                                   || (uint8_t)(a_bFatId) == 0xed /* obscure, tandy 2000 */ \
                                   || (uint8_t)(a_bFatId) == 0xe5 /* obscure, tandy 2000 */ )

/**
 * The DOS 2.0 BIOS parameter block (BPB).
 *
 * This was the first DOS version with a BPB.
 */
#pragma pack(1)
typedef struct FATBPB20
{
    /** 0x0b / 0x00: The sector size in bytes. */
    uint16_t        cbSector;
    /** 0x0d / 0x02: Number of sectors per cluster. */
    uint8_t         cSectorsPerCluster;
    /** 0x0e / 0x03: Number of reserved sectors before the first FAT. */
    uint16_t        cReservedSectors;
    /** 0x10 / 0x05: Number of FATs. */
    uint8_t         cFats;
    /** 0x11 / 0x06: Max size of the root directory (0 for FAT32). */
    uint16_t        cMaxRootDirEntries;
    /** 0x13 / 0x08: Total sector count, zero if 32-bit count is used. */
    uint16_t        cTotalSectors16;
    /** 0x15 / 0x0a: Media ID. */
    uint8_t         bMedia;
    /** 0x16 / 0x0b: Number of sectors per FAT (0 for FAT32). */
    uint16_t        cSectorsPerFat;
} FATBPB20;
#pragma pack()
AssertCompileSize(FATBPB20, 0xd);
/** Pointer to a DOS 2.0 BPB. */
typedef FATBPB20 *PFATBPB20;
/** Pointer to a const DOS 2.0 BPB. */
typedef FATBPB20 const *PCFATBPB20;


/**
 * The DOS 3.0 BPB changes that survived.
 */
#pragma pack(1)
typedef struct FATBPB30CMN
{
    /** DOS v2.0 BPB.   */
    FATBPB20        Bpb20;
    /** 0x18 / 0x0d: Sectors per track. Zero means reserved and not used. */
    uint16_t        cSectorsPerTrack;
    /** 0x1a / 0x0f: Number of heads. Zero means reserved and not used. */
    uint16_t        cTracksPerCylinder;
} FATBPB30CMN;
#pragma pack()
AssertCompileSize(FATBPB30CMN, 0x11);

/**
 * The DOS 3.0 BPB.
 */
#pragma pack(1)
typedef struct FATBPB30
{
    /** DOS v3.0 BPB bits that survived.   */
    FATBPB30CMN     Core30;
    /** 0x1c / 0x11: Number of hidden sectors preceeding the volume. This is zero
     * on unpartitioned media. */
    uint16_t        cHiddenSectors;
} FATBPB30;
#pragma pack()
AssertCompileSize(FATBPB30, 0x13);
/** Pointer to a DOS 3.0 BPB. */
typedef FATBPB30 *PFATBPB30;
/** Pointer to a const DOS 3.0 BPB. */
typedef FATBPB30 const *PCFATBPB30;

/**
 * The DOS 3.0 BPB, flattened structure.
 */
#pragma pack(1)
typedef struct FATBPB30FLAT
{
    /** @name New in DOS 2.0
     * @{ */
    /** 0x0b / 0x00: The sector size in bytes. */
    uint16_t        cbSector;
    /** 0x0d / 0x02: Number of sectors per cluster. */
    uint8_t         cSectorsPerCluster;
    /** 0x0e / 0x03: Number of reserved sectors before the first FAT. */
    uint16_t        cReservedSectors;
    /** 0x10 / 0x05: Number of FATs. */
    uint8_t         cFats;
    /** 0x11 / 0x06: Max size of the root directory (0 for FAT32). */
    uint16_t        cMaxRootDirEntries;
    /** 0x13 / 0x08: Total sector count, zero if 32-bit count is used. */
    uint16_t        cTotalSectors16;
    /** 0x15 / 0x0a: Media ID. */
    uint8_t         bMedia;
    /** 0x16 / 0x0b: Number of sectors per FAT (0 for FAT32). */
    uint16_t        cSectorsPerFat;
    /** @} */
    /** @name New in DOS 3.0
     * @{  */
    /** 0x18 / 0x0d: Sectors per track. Zero means reserved and not used. */
    uint16_t        cSectorsPerTrack;
    /** 0x1a / 0x0f: Number of heads. Zero means reserved and not used. */
    uint16_t        cTracksPerCylinder;
    /** 0x1c / 0x11: Number of hidden sectors preceeding the volume. This is zero
     * on unpartitioned media. */
    uint16_t        cHiddenSectors;
    /** @} */
} FATBPB30FLAT;
#pragma pack()
AssertCompileSize(FATBPB30FLAT, 0x13);
/** Pointer to a flattened DOS 3.0 BPB. */
typedef FATBPB30FLAT *PFATBPB30FLAT;
/** Pointer to a const flattened DOS 3.0 BPB. */
typedef FATBPB30FLAT const *PCFATBPB30FLAT;


/**
 * The DOS 3.2 BPB.
 */
#pragma pack(1)
typedef struct FATBPB32
{
    /** DOS v3.0 BPB.   */
    FATBPB30        Bpb30;
    /** 0x1e / 0x13: Number of sectors, including the hidden ones.  This is ZERO
     * in DOS 3.31+. */
    uint16_t        cAnotherTotalSectors;
} FATBPB32;
#pragma pack()
AssertCompileSize(FATBPB32, 0x15);
/** Pointer to a DOS 3.2 BPB. */
typedef FATBPB32 *PFATBPB32;
/** Pointer to const a DOS 3.2 BPB. */
typedef FATBPB32 const *PCFATBPB32;

/**
 * The DOS 3.2 BPB, flattened structure.
 */
#pragma pack(1)
typedef struct FATBPB32FLAT
{
    /** @name New in DOS 2.0
     * @{ */
    /** 0x0b / 0x00: The sector size in bytes. */
    uint16_t        cbSector;
    /** 0x0d / 0x02: Number of sectors per cluster. */
    uint8_t         cSectorsPerCluster;
    /** 0x0e / 0x03: Number of reserved sectors before the first FAT. */
    uint16_t        cReservedSectors;
    /** 0x10 / 0x05: Number of FATs. */
    uint8_t         cFats;
    /** 0x11 / 0x06: Max size of the root directory (0 for FAT32). */
    uint16_t        cMaxRootDirEntries;
    /** 0x13 / 0x08: Total sector count, zero if 32-bit count is used. */
    uint16_t        cTotalSectors16;
    /** 0x15 / 0x0a: Media ID. */
    uint8_t         bMedia;
    /** 0x16 / 0x0b: Number of sectors per FAT (0 for FAT32). */
    uint16_t        cSectorsPerFat;
    /** @} */
    /** @name New in DOS 3.0
     * @{  */
    /** 0x18 / 0x0d: Sectors per track. Zero means reserved and not used. */
    uint16_t        cSectorsPerTrack;
    /** 0x1a / 0x0f: Number of heads. Zero means reserved and not used. */
    uint16_t        cTracksPerCylinder;
    /** 0x1c / 0x11: Number of hidden sectors preceeding the volume. This is zero
     * on unpartitioned media. */
    uint16_t        cHiddenSectors;
    /** @} */
    /** @name New in DOS 3.2
     * @{  */
    /** 0x1e / 0x13: Number of sectors, including the hidden ones.  This is ZERO
     * in DOS 3.31+. */
    uint16_t        cAnotherTotalSectors;
    /** @} */
} FATBPB32FLAT;
#pragma pack()
AssertCompileSize(FATBPB32FLAT, 0x15);
/** Pointer to a flattened DOS 3.2 BPB. */
typedef FATBPB32FLAT *PFATBPB32FLAT;
/** Pointer to a const flattened DOS 3.2 BPB. */
typedef FATBPB32FLAT const *PCFATBPB32FLAT;


/**
 * The DOS 3.31 BPB.
 */
#pragma pack(1)
typedef struct FATBPB331
{
    /** DOS v3.0 BPB bits that survived.   */
    FATBPB30CMN     Core30;
    /** 0x1c / 0x11: Number of hidden sectors preceeding the volume.  This is zero
     * on unpartitioned media.  Values higher than 65535 are complicated due to
     * the field overlapping FATBPB32::cAnotherTotalSectors */
    uint32_t        cHiddenSectors;
    /** 0x20 / 0x15: Total logical sectors.  Used if count >= 64K, otherwise
     *  FATBPB20::cTotalSectors16 is used.  Zero if 64-bit value used with FAT32. */
    uint32_t        cTotalSectors32;
} FATBPB331;
#pragma pack()
AssertCompileSize(FATBPB331, 0x19);
/** Pointer to a DOS 3.31 BPB. */
typedef FATBPB331 *PFATBPB331;
/** Pointer to a const DOS 3.31 BPB. */
typedef FATBPB331 const *PCFATBPB331;

/**
 * The DOS 3.31 BPB, flattened structure.
 */
#pragma pack(1)
typedef struct FATBPB331FLAT
{
    /** @name New in DOS 2.0
     * @{ */
    /** 0x0b / 0x00: The sector size in bytes. */
    uint16_t        cbSector;
    /** 0x0d / 0x02: Number of sectors per cluster. */
    uint8_t         cSectorsPerCluster;
    /** 0x0e / 0x03: Number of reserved sectors before the first FAT (0 for
     *  NTFS). */
    uint16_t        cReservedSectors;
    /** 0x10 / 0x05: Number of FATs (0 for NTFS). */
    uint8_t         cFats;
    /** 0x11 / 0x06: Max size of the root directory (0 for FAT32 & NTFS). */
    uint16_t        cMaxRootDirEntries;
    /** 0x13 / 0x08: Total sector count, zero if 32-bit count is used (and for
     * NTFS). */
    uint16_t        cTotalSectors16;
    /** 0x15 / 0x0a: Media ID. */
    uint8_t         bMedia;
    /** 0x16 / 0x0b: Number of sectors per FAT (0 for FAT32 & NTFS). */
    uint16_t        cSectorsPerFat;
    /** @} */
    /** @name New in DOS 3.0
     * @{ */
    /** 0x18 / 0x0d: Sectors per track. Zero means reserved and not used. */
    uint16_t        cSectorsPerTrack;
    /** 0x1a / 0x0f: Number of heads. Zero means reserved and not used. */
    uint16_t        cTracksPerCylinder;
    /** @} */
    /** @name New in DOS 3.31
     * @{ */
    /** 0x1c / 0x11: Number of hidden sectors preceeding the volume.  This is zero
     * on unpartitioned media.  Values higher than 65535 are complicated due to
     * the field overlapping FATBPB32::cAnotherTotalSectors */
    uint32_t        cHiddenSectors;
    /** 0x20 / 0x15: Total logical sectors.  Used if count >= 64K, otherwise
     * FATBPB20::cTotalSectors16 is used.  Zero if 64-bit value used with FAT32.
     * (Zero for NTFS). */
    uint32_t        cTotalSectors32;
    /** @} */
} FATBPB331FLAT;
#pragma pack()
AssertCompileSize(FATBPB331FLAT, 0x19);
/** Pointer to a flattened DOS 3.31 BPB. */
typedef FATBPB331FLAT *PFATBPB331FLAT;
/** Pointer to a const flattened DOS 3.31 BPB. */
typedef FATBPB331FLAT const *PCFATBPB331FLAT;


/**
 * Extended BIOS parameter block (EBPB).
 */
#pragma pack(1)
typedef struct FATEBPB
{
    /** The BPB.  */
    FATBPB331FLAT   Bpb;

    /** 0x24 / 0x19: BIOS INT13 pysical drive number. */
    uint8_t         bInt13Drive;
    /** 0x25 / 0x1a: Reserved. NT used bit 0 for indicating dirty FS, and bit 1
     * for surface scan. */
    uint8_t         bReserved;
    /** 0x26 / 0x1b: Extended boot signature, FATEBPB_SIGNATURE or
     * FATEBPB_SIGNATURE_OLD. */
    uint8_t         bExtSignature;
    /** 0x27 / 0x1c: The volume serial number. */
    uint32_t        uSerialNumber;
    /** 0x2b / 0x20: The volume label (space padded).
     * @remarks Not available with FATEBPB_SIGNATURE_OLD  */
    char            achLabel[11];
    /** 0x36 / 0x2b: The file system type (space padded).
     * @remarks Not available with FATEBPB_SIGNATURE_OLD  */
    char            achType[8];
} FATEBPB;
#pragma pack()
AssertCompileSize(FATEBPB, 0x33);
/** Pointer to an extended BIOS parameter block. */
typedef FATEBPB *PFATEBPB;
/** Pointer to a const extended BIOS parameter block. */
typedef FATEBPB const *PCFATEBPB;

/** FATEBPB::bExtSignature value. */
#define FATEBPB_SIGNATURE       UINT8_C(0x29)
/** FATEBPB::bExtSignature value used by OS/2 1.0-1.1 and PC DOS 3.4.  These
 * does not have the volume and file system type. */
#define FATEBPB_SIGNATURE_OLD   UINT8_C(0x28)

/**FATEBPB::achType value for FAT12. */
#define FATEBPB_TYPE_FAT12      "FAT12   "
/**FATEBPB::achType value for FAT16. */
#define FATEBPB_TYPE_FAT16      "FAT16   "
/**FATEBPB::achType value for FAT12/FAT16. */
#define FATEBPB_TYPE_FAT        "FAT32   "


/**
 * FAT32 Extended BIOS parameter block (EBPB).
 */
#pragma pack(1)
typedef struct FAT32EBPB
{
    /** The BPB.  */
    FATBPB331FLAT   Bpb;

    /** 0x24 / 0x19: Number of sectors per FAT.
     * @note To avoid confusion with the FATEBPB signature, values which result in
     *       0x00280000 or 0x00290000 when masked by 0x00ff0000 must not be used. */
    uint32_t        cSectorsPerFat32;
    /** 0x28 / 0x1d: Flags pertaining to FAT mirroring and other stuff. */
    uint16_t        fFlags;
    /** 0x2a / 0x1f: FAT32 version number (FAT32EBPB_VERSION_0_0). */
    uint16_t        uVersion;
    /** 0x2c / 0x21: Cluster number of the root directory. */
    uint32_t        uRootDirCluster;
    /** 0x30 / 0x25: Logical sector number of the information sector. */
    uint16_t        uInfoSectorNo;
    /** 0x32 / 0x27: Logical sector number of boot sector copy. */
    uint16_t        uBootSectorCopySectorNo;
    /** 0x34 / 0x29: Reserved, zero (or 0xf6) filled, preserve. */
    uint8_t         abReserved[12];

    /** 0x40 / 0x35: BIOS INT13 pysical drive number
     * @remarks Same as FATEBPB::bInt13Drive. */
    uint8_t         bInt13Drive;
    /** 0x41 / 0x36: Reserved.
     * @remarks Same as FATEBPB::bReserved. */
    uint8_t         bReserved;
    /** 0x42 / 0x37: Extended boot signature (FATEBPB_SIGNATURE, or
     *  FATEBPB_SIGNATURE_OLD in some special cases).
     * @remarks Same as FATEBPB::bExtSignature. */
    uint8_t         bExtSignature;
    /** 0x43 / 0x38: The volume serial number.
     * @remarks Same as FATEBPB::uSerialNumber. */
    uint32_t        uSerialNumber;
    /** 0x47 / 0x3c: The volume label (space padded).
     * @remarks Not available with FATEBPB_SIGNATURE_OLD
     * @remarks Same as FATEBPB::achLabel. */
    char            achLabel[11];
    /** 0x52 / 0x47: The file system type (space padded), or 64-bit logical sector
     * count if both other count fields are zero.  In the latter case, the type is
     * moved to the OEM name field (FATBOOTSECTOR::achOemName).
     *
     * @remarks Not available with FATEBPB_SIGNATURE_OLD
     * @remarks Same as FATEBPB::achType. */
    union
    {
        /** Type string variant.  */
        char        achType[8];
        /** Total sector count if 4G or higher. */
        uint64_t    cTotalSectors64;
    } u;
} FAT32EBPB;
#pragma pack()
AssertCompileSize(FAT32EBPB, 0x4f);
/** Pointer to a FAT32 extended BIOS parameter block. */
typedef FAT32EBPB *PFAT32EBPB;
/** Pointer to a const FAT32 extended BIOS parameter block. */
typedef FAT32EBPB const *PCFAT32EBPB;

/** FAT32 version 0.0 (FAT32EBPB::uVersion). */
#define FAT32EBPB_VERSION_0_0   UINT16_C(0x0000)


/**
 * NTFS extended BIOS parameter block (NTFSEBPB).
 */
#pragma pack(1)
typedef struct NTFSEBPB
{
    /** The BPB.  */
    FATBPB331FLAT   Bpb;

    /** 0x24 / 0x19: BIOS INT13 pysical drive number.
     * @note Same location as FATEBPB::bInt13Drive. */
    uint8_t         bInt13Drive;
    /** 0x25 / 0x1a: Reserved / flags */
    uint8_t         bReserved;
    /** 0x26 / 0x1b: Extended boot signature (NTFSEBPB_SIGNATURE).
     * @note Same location as FATEBPB::bExtSignature. */
    uint8_t         bExtSignature;
    /** 0x27 / 0x1c: Reserved   */
    uint8_t         bReserved2;

    /** 0x28 / 0x1d: Number of sectors. */
    uint64_t        cSectors;
    /** 0x30 / 0x25: Logical cluster number of the master file table (MFT).   */
    uint64_t        uLcnMft;
    /** 0x38 / 0x2d: Logical cluster number of the MFT mirror. */
    uint64_t        uLcnMftMirror;
    /** 0x40 / 0x35: Logical clusters per file record segment.
     * This is a shift count if negative.  */
    int8_t          cClustersPerMftRecord;
    /** 0x41 / 0x36: Reserved. */
    uint8_t         abReserved3[3];
    /** 0x44 / 0x39: The default logical clusters count per index node.
     * This is a shift count if negative.  */
    int8_t          cClustersPerIndexNode;
    /** 0x45 / 0x3a: Reserved. */
    uint8_t         abReserved4[3];
    /** 0x48 / 0x3d: Volume serial number.
     * @note This is larger than the the FAT serial numbers. */
    uint64_t        uSerialNumber;
    /** 0x50 / 0x45: Checksum. */
    uint32_t        uChecksum;
} NTFSEBPB;
#pragma pack()
AssertCompileSize(NTFSEBPB, 0x49);
/** Pointer to a NTFS extended BIOS parameter block. */
typedef NTFSEBPB *PNTFSEBPB;
/** Pointer to a const NTFS extended BIOS parameter block. */
typedef NTFSEBPB const *PCNTFSEBPB;

/** NTFS EBPB signature (NTFSEBPB::bExtSignature). */
#define NTFSEBPB_SIGNATURE   UINT8_C(0x80)


/**
 * FAT boot sector layout.
 */
#pragma pack(1)
typedef struct FATBOOTSECTOR
{
    /** 0x000: DOS 2.0+ jump sequence. */
    uint8_t         abJmp[3];
    /** 0x003: OEM name (who formatted this volume). */
    char            achOemName[8];
    /** 0x00b: The BIOS parameter block.
     * This varies a lot in size. */
    union
    {
        FATBPB20        Bpb20;
        FATBPB30FLAT    Bpb30;
        FATBPB32FLAT    Bpb32;
        FATBPB331FLAT   Bpb331;
        FATEBPB         Ebpb;
        FAT32EBPB       Fat32Ebpb;
        NTFSEBPB        Ntfs;
    } Bpb;
    /** 0x05a: Bootloader code/data/stuff. */
    uint8_t             abStuff[0x1a3];
    /** 0x1fd: Old drive number location (DOS 3.2-3.31). */
    uint8_t             bOldInt13Drive;
    /** 0x1fe: DOS signature (FATBOOTSECTOR_SIGNATURE). */
    uint16_t            uSignature;
} FATBOOTSECTOR;
#pragma pack()
AssertCompileSize(FATBOOTSECTOR, 0x200);
/** Pointer to a FAT boot sector. */
typedef FATBOOTSECTOR *PFATBOOTSECTOR;
/** Pointer to a const FAT boot sector. */
typedef FATBOOTSECTOR const *PCFATBOOTSECTOR;

/** Boot sector signature (FATBOOTSECTOR::uSignature). */
#define FATBOOTSECTOR_SIGNATURE     UINT16_C(0xaa55)



/**
 * FAT32 info sector (follows the boot sector).
 */
typedef struct FAT32INFOSECTOR
{
    /** 0x000: Signature \#1 (FAT32INFOSECTOR_SIGNATURE_1). */
    uint32_t        uSignature1;
    /** Reserved, should be zero. */
    uint8_t         abReserved1[0x1E0];
    /** 0x1e4: Signature \#1 (FAT32INFOSECTOR_SIGNATURE_2). */
    uint32_t        uSignature2;
    /** 0x1e8: Last known number of free clusters (informational). */
    uint32_t        cFreeClusters;
    /** 0x1ec: Last allocated cluster number (informational).  This could be used as
     * an allocation hint when searching for a free cluster. */
    uint32_t        cLastAllocatedCluster;
    /** 0x1f0: Reserved, should be zero, preserve. */
    uint8_t         abReserved2[12];
    /** 0x1fc: Signature \#3 (FAT32INFOSECTOR_SIGNATURE_3). */
    uint32_t        uSignature3;
} FAT32INFOSECTOR;
AssertCompileSize(FAT32INFOSECTOR, 0x200);
/** Pointer to a FAT32 info sector. */
typedef FAT32INFOSECTOR *PFAT32INFOSECTOR;
/** Pointer to a const FAT32 info sector. */
typedef FAT32INFOSECTOR const *PCFAT32INFOSECTOR;

#define FAT32INFOSECTOR_SIGNATURE_1     UINT32_C(0x41615252)
#define FAT32INFOSECTOR_SIGNATURE_2     UINT32_C(0x61417272)
#define FAT32INFOSECTOR_SIGNATURE_3     UINT32_C(0xaa550000)


/** @name Special FAT cluster numbers and limits.
 * @{ */
#define FAT_FIRST_DATA_CLUSTER          2                       /**< The first data cluster. */

#define FAT_MAX_FAT12_TOTAL_CLUSTERS    UINT32_C(0x00000ff6)    /**< Maximum number of clusters in a 12-bit FAT . */
#define FAT_MAX_FAT16_TOTAL_CLUSTERS    UINT32_C(0x0000fff6)    /**< Maximum number of clusters in a 16-bit FAT . */
#define FAT_MAX_FAT32_TOTAL_CLUSTERS    UINT32_C(0x0ffffff6)    /**< Maximum number of clusters in a 32-bit FAT . */

#define FAT_LAST_FAT12_DATA_CLUSTER     UINT32_C(0x00000ff5)    /**< The last possible data cluster for FAT12. */
#define FAT_LAST_FAT16_DATA_CLUSTER     UINT32_C(0x0000fff5)    /**< The last possible data cluster for FAT16. */
#define FAT_LAST_FAT32_DATA_CLUSTER     UINT32_C(0x0ffffff5)    /**< The last possible data cluster for FAT32. */

#define FAT_MAX_FAT12_DATA_CLUSTERS     UINT32_C(0x00000ff4)    /**< Maximum number of data clusters for FAT12. */
#define FAT_MAX_FAT16_DATA_CLUSTERS     UINT32_C(0x0000fff4)    /**< Maximum number of data clusters for FAT16. */
#define FAT_MAX_FAT32_DATA_CLUSTERS     UINT32_C(0x0ffffff4)    /**< Maximum number of data clusters for FAT32. */

#define FAT_MIN_FAT12_DATA_CLUSTERS     UINT32_C(0x00000001)    /**< Maximum number of data clusters for FAT12. */
#define FAT_MIN_FAT16_DATA_CLUSTERS     UINT32_C(0x00000ff5)    /**< Maximum number of data clusters for FAT16. */
#define FAT_MIN_FAT32_DATA_CLUSTERS     UINT32_C(0x0000fff5)    /**< Maximum number of data clusters for FAT32. */

#define FAT_FIRST_FAT12_EOC             UINT32_C(0x00000ff8)    /**< The first end-of-file-cluster number for FAT12. */
#define FAT_FIRST_FAT16_EOC             UINT32_C(0x0000fff8)    /**< The first end-of-file-cluster number for FAT16. */
#define FAT_FIRST_FAT32_EOC             UINT32_C(0x0ffffff8)    /**< The first end-of-file-cluster number for FAT32. */
/** @} */


/**
 * FAT directory entry.
 */
typedef struct FATDIRENTRY
{
    /** 0x00: The directory entry name.
     * First character serves as a flag to indicate deleted or not. */
    uint8_t         achName[8+3];
    /** 0x0b: Attributes (FAT_ATTR_XXX). */
    uint8_t         fAttrib;
    /** 0x0c: NT case flags (FATDIRENTRY_CASE_F_XXX). */
    uint8_t         fCase;
    /** 0x0d: Birth milliseconds (DOS 7.0+ w/VFAT). */
    uint8_t         uBirthCentiseconds;
    /** 0x0e: Birth time (DOS 7.0+ w/VFAT). */
    uint16_t        uBirthTime;
    /** 0x10: Birth date (DOS 7.0+ w/VFAT). */
    uint16_t        uBirthDate;
    /** 0x12: Access date (DOS 7.0+ w/ACCDATA in Config.sys). */
    uint16_t        uAccessDate;
    union
    {
        /** 0x14: High cluster word for FAT32.   */
        uint16_t    idxClusterHigh;
        /** 0x14: Index of extended attributes (FAT16/FAT12). */
        uint16_t    idxEAs;
    } u;
    /** 0x16: Modify time (PC-DOS 1.1+, MS-DOS 1.20+).  */
    uint16_t        uModifyTime;
    /** 0x18: Modify date. */
    uint16_t        uModifyDate;
    /** 0x1a: The data cluster index. */
    uint16_t        idxCluster;
    /** 0x1c: The file size. */
    uint32_t        cbFile;
} FATDIRENTRY;
AssertCompileSize(FATDIRENTRY, 0x20);
AssertCompileMemberOffset(FATDIRENTRY, fAttrib, 0x0b);
AssertCompileMemberOffset(FATDIRENTRY, fCase, 0x0c);
AssertCompileMemberOffset(FATDIRENTRY, uBirthCentiseconds, 0x0d);
AssertCompileMemberOffset(FATDIRENTRY, uBirthTime, 0x0e);
AssertCompileMemberOffset(FATDIRENTRY, uBirthDate, 0x10);
AssertCompileMemberOffset(FATDIRENTRY, uAccessDate, 0x12);
AssertCompileMemberOffset(FATDIRENTRY, u, 0x14);
AssertCompileMemberOffset(FATDIRENTRY, uModifyTime, 0x16);
AssertCompileMemberOffset(FATDIRENTRY, uModifyDate, 0x18);
AssertCompileMemberOffset(FATDIRENTRY, idxCluster, 0x1a);
AssertCompileMemberOffset(FATDIRENTRY, cbFile, 0x1c);
/** Pointer to a FAT directory entry. */
typedef FATDIRENTRY *PFATDIRENTRY;
/** Pointer to a FAT directory entry. */
typedef FATDIRENTRY const *PCFATDIRENTRY;


/** @name FAT_ATTR_XXX - FATDIRENTRY::fAttrib flags.
 * @{ */
#define FAT_ATTR_READONLY           UINT8_C(0x01)
#define FAT_ATTR_HIDDEN             UINT8_C(0x02)
#define FAT_ATTR_SYSTEM             UINT8_C(0x04)
#define FAT_ATTR_VOLUME             UINT8_C(0x08)
#define FAT_ATTR_DIRECTORY          UINT8_C(0x10)
#define FAT_ATTR_ARCHIVE            UINT8_C(0x20)
#define FAT_ATTR_DEVICE             UINT8_C(0x40)
#define FAT_ATTR_RESERVED           UINT8_C(0x80)
#define FAT_ATTR_NAME_SLOT          UINT8_C(0x0f) /**< Special attribute value for FATDIRNAMESLOT. */
/** @} */

/** @name FATDIRENTRY_CASE_F_XXX - FATDIRENTRY::fCase flags.
 * @{ */
/** Lower cased base name (first 8 chars). */
#define FATDIRENTRY_CASE_F_LOWER_BASE   UINT8_C(0x08)
/** Lower cased filename extension (last 3 chars). */
#define FATDIRENTRY_CASE_F_LOWER_EXT    UINT8_C(0x10)
/** @} */

/** @name FATDIRENTRY_CH0_XXX - FATDIRENTRY::achName[0]
 * @{ */
/** Deleted entry. */
#define FATDIRENTRY_CH0_DELETED         UINT8_C(0xe5)
/** End of used directory entries (MS-DOS 1.25+, PC-DOS 2.0+). */
#define FATDIRENTRY_CH0_END_OF_DIR      UINT8_C(0x00)
/** The special dot or dot-dot dir aliases (MS-DOS 1.40+, PC-DOS 2.0+).
 * @remarks 0x2e is the ascii table entry of the '.' character.  */
#define FATDIRENTRY_CH0_DOT_ALIAS       UINT8_C(0x2e)
/** Escaped 0xe5 leadcharacter (DOS 3.0+). */
#define FATDIRENTRY_CH0_ESC_E5          UINT8_C(0x05)
/** @} */


/**
 * FAT directory alias name slot.
 *
 * Each slot holds 13 UTF-16 (/ UCS-2) characters, so it takes 20 slots to cover
 * a 255 character long name.
 */
#pragma pack(1)
typedef struct FATDIRNAMESLOT
{
    /** The slot sequence number. */
    uint8_t         idSlot;
    /** The first 5 name chars.
     * @remarks misaligned  */
    RTUTF16         awcName0[5];
    /** Attributes (FAT_ATTR_XXX). */
    uint8_t         fAttrib;
    /** Always zero. */
    uint8_t         fZero;
    /** Alias checksum. */
    uint8_t         bChecksum;
    /** The next 6 name chars. */
    RTUTF16         awcName1[6];
    /** Always zero (usually cluster entry). */
    uint16_t        idxZero;
    /** The next 2 name chars. */
    RTUTF16         awcName2[2];
} FATDIRNAMESLOT;
#pragma pack()
AssertCompileSize(FATDIRNAMESLOT, 0x20);
/** Pointer to a FAT directory entry. */
typedef FATDIRNAMESLOT *PFATDIRNAMESLOT;
/** Pointer to a FAT directory entry. */
typedef FATDIRNAMESLOT const *PCFATDIRNAMESLOT;

/** Slot ID flag indicating that it's the first slot. */
#define FATDIRNAMESLOT_FIRST_SLOT_FLAG  UINT8_C(0x40)
/** Highest slot ID recognized.  This allows for 260 characters, however many
 * implementation limits it to 255 or 250. */
#define FATDIRNAMESLOT_HIGHEST_SLOT_ID  UINT8_C(0x14)
/** Max number of slots recognized.  (This is the same as the higest slot ID
 * because the 0 isn't a valid ID.) */
#define FATDIRNAMESLOT_MAX_SLOTS        FATDIRNAMESLOT_HIGHEST_SLOT_ID
/** Number of UTF-16 units per slot. */
#define FATDIRNAMESLOT_CHARS_PER_SLOT   (5 + 6 + 2)



/**
 * FAT directory entry union.
 */
typedef union FATDIRENTRYUNION
{
    /** Regular entry view. */
    FATDIRENTRY     Entry;
    /** Name slot view. */
    FATDIRNAMESLOT  Slot;
} FATDIRENTRYUNION;
AssertCompileSize(FATDIRENTRYUNION, 0x20);
/** Pointer to a FAT directory entry union. */
typedef FATDIRENTRYUNION *PFATDIRENTRYUNION;
/** Pointer to a const FAT directory entry union. */
typedef FATDIRENTRYUNION const *PCFATDIRENTRYUNION;

/** @} */

#endif /* !IPRT_INCLUDED_formats_fat_h */