diff options
Diffstat (limited to 'include/iprt/formats/fat.h')
-rw-r--r-- | include/iprt/formats/fat.h | 749 |
1 files changed, 749 insertions, 0 deletions
diff --git a/include/iprt/formats/fat.h b/include/iprt/formats/fat.h new file mode 100644 index 00000000..7addb0e5 --- /dev/null +++ b/include/iprt/formats/fat.h @@ -0,0 +1,749 @@ +/* $Id: fat.h $ */ +/** @file + * IPRT, File Allocation Table (FAT). + */ + +/* + * Copyright (C) 2017-2019 Oracle Corporation + * + * This file is part of VirtualBox Open Source Edition (OSE), as + * available from http://www.virtualbox.org. This file is free software; + * you can redistribute it and/or modify it under the terms of the GNU + * General Public License (GPL) as published by the Free Software + * Foundation, in version 2 as it comes in the "COPYING" file of the + * VirtualBox OSE distribution. VirtualBox OSE is distributed in the + * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind. + * + * The contents of this file may alternatively be used under the terms + * of the Common Development and Distribution License Version 1.0 + * (CDDL) only, as it comes in the "COPYING.CDDL" file of the + * VirtualBox OSE 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. + */ + +#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 */ + |